diff --git a/.github/workflows/codeowner-self-approval.yml b/.github/workflows/codeowner-self-approval.yml index bd4d3182682..149213effc5 100644 --- a/.github/workflows/codeowner-self-approval.yml +++ b/.github/workflows/codeowner-self-approval.yml @@ -13,7 +13,7 @@ permissions: jobs: approve: - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 # Only run if the PR author enabled auto-merge, not someone else. # Also run if a new approval was created, as this affects whether we can # auto-approve. There is a risk of infinite loops here, though -- when we diff --git a/Common/TableProducer/centralityTable.cxx b/Common/TableProducer/centralityTable.cxx index 439ed0aad29..6b18bcf6882 100644 --- a/Common/TableProducer/centralityTable.cxx +++ b/Common/TableProducer/centralityTable.cxx @@ -249,18 +249,21 @@ struct CentralityTable { /* check the previous run number */ auto bc = collision.bc_as(); if (bc.runNumber() != mRunNumber) { + mRunNumber = bc.runNumber(); // mark that this run has been attempted already regardless of outcome LOGF(debug, "timestamp=%llu", bc.timestamp()); TList* callst = nullptr; if (ccdbConfig.reconstructionPass.value == "") { - callst = ccdb->getForTimeStamp(ccdbConfig.ccdbPath, bc.timestamp()); + callst = ccdb->getForRun(ccdbConfig.ccdbPath, bc.runNumber()); } else if (ccdbConfig.reconstructionPass.value == "metadata") { std::map metadata; metadata["RecoPassName"] = metadataInfo.get("RecoPassName"); - callst = ccdb->getSpecific(ccdbConfig.ccdbPath, bc.timestamp(), metadata); + LOGF(info, "Loading CCDB for reconstruction pass (from metadata): %s", metadataInfo.get("RecoPassName")); + callst = ccdb->getSpecificForRun(ccdbConfig.ccdbPath, bc.runNumber(), metadata); } else { std::map metadata; metadata["RecoPassName"] = ccdbConfig.reconstructionPass.value; - callst = ccdb->getSpecific(ccdbConfig.ccdbPath, bc.timestamp(), metadata); + LOGF(info, "Loading CCDB for reconstruction pass (from provided argument): %s", ccdbConfig.reconstructionPass.value); + callst = ccdb->getSpecificForRun(ccdbConfig.ccdbPath, bc.runNumber(), metadata); } Run2V0MInfo.mCalibrationStored = false; @@ -350,15 +353,11 @@ struct CentralityTable { LOGF(fatal, "Calibration information from CL1 multiplicity for run %d corrupted", bc.runNumber()); } } - if (Run2V0MInfo.mCalibrationStored || Run2V0AInfo.mCalibrationStored || Run2SPDTksInfo.mCalibrationStored || Run2SPDClsInfo.mCalibrationStored || Run2CL0Info.mCalibrationStored || Run2CL1Info.mCalibrationStored) { - mRunNumber = bc.runNumber(); - } } else { if (!ccdbConfig.doNotCrashOnNull) { // default behaviour: crash LOGF(fatal, "Centrality calibration is not available in CCDB for run=%d at timestamp=%llu", bc.runNumber(), bc.timestamp()); } else { // only if asked: continue filling with non-valid values (105) LOGF(info, "Centrality calibration is not available in CCDB for run=%d at timestamp=%llu, will fill tables with dummy values", bc.runNumber(), bc.timestamp()); - mRunNumber = bc.runNumber(); } } } @@ -473,6 +472,7 @@ struct CentralityTable { /* check the previous run number */ auto bc = collision.template bc_as(); if (bc.runNumber() != mRunNumber) { + mRunNumber = bc.runNumber(); // mark that this run has been attempted already regardless of outcome LOGF(info, "timestamp=%llu, run number=%d", bc.timestamp(), bc.runNumber()); TList* callst = nullptr; // Check if the ccdb path is a root file @@ -485,15 +485,17 @@ struct CentralityTable { } } else { if (ccdbConfig.reconstructionPass.value == "") { - callst = ccdb->getForTimeStamp(ccdbConfig.ccdbPath, bc.timestamp()); + callst = ccdb->getForRun(ccdbConfig.ccdbPath, bc.runNumber()); } else if (ccdbConfig.reconstructionPass.value == "metadata") { std::map metadata; metadata["RecoPassName"] = metadataInfo.get("RecoPassName"); - callst = ccdb->getSpecific(ccdbConfig.ccdbPath, bc.timestamp(), metadata); + LOGF(info, "Loading CCDB for reconstruction pass (from metadata): %s", metadataInfo.get("RecoPassName")); + callst = ccdb->getSpecificForRun(ccdbConfig.ccdbPath, bc.runNumber(), metadata); } else { std::map metadata; metadata["RecoPassName"] = ccdbConfig.reconstructionPass.value; - callst = ccdb->getSpecific(ccdbConfig.ccdbPath, bc.timestamp(), metadata); + LOGF(info, "Loading CCDB for reconstruction pass (from provided argument): %s", ccdbConfig.reconstructionPass.value); + callst = ccdb->getSpecificForRun(ccdbConfig.ccdbPath, bc.runNumber(), metadata); } } @@ -555,13 +557,11 @@ struct CentralityTable { break; } } - mRunNumber = bc.runNumber(); } else { if (!ccdbConfig.doNotCrashOnNull) { // default behaviour: crash LOGF(fatal, "Centrality calibration is not available in CCDB for run=%d at timestamp=%llu", bc.runNumber(), bc.timestamp()); } else { // only if asked: continue filling with non-valid values (105) LOGF(info, "Centrality calibration is not available in CCDB for run=%d at timestamp=%llu, will fill tables with dummy values", bc.runNumber(), bc.timestamp()); - mRunNumber = bc.runNumber(); } } } diff --git a/Common/TableProducer/eventSelection.cxx b/Common/TableProducer/eventSelection.cxx index 9aa2a664544..440f18390c9 100644 --- a/Common/TableProducer/eventSelection.cxx +++ b/Common/TableProducer/eventSelection.cxx @@ -24,6 +24,7 @@ #include "DataFormatsParameters/GRPECSObject.h" #include "ITSMFTBase/DPLAlpideParam.h" #include "MetadataHelper.h" +#include "DataFormatsParameters/AggregatedRunInfo.h" #include "TH1D.h" @@ -36,8 +37,9 @@ MetadataHelper metadataInfo; // Metadata helper using BCsWithRun2InfosTimestampsAndMatches = soa::Join; using BCsWithRun3Matchings = soa::Join; using BCsWithBcSelsRun2 = soa::Join; -using BCsWithBcSelsRun3 = soa::Join; +using BCsWithBcSelsRun3 = soa::Join; using FullTracksIU = soa::Join; +const double bcNS = o2::constants::lhc::LHCBunchSpacingNS; struct BcSelectionTask { Produces bcsel; @@ -259,24 +261,12 @@ struct BcSelectionTask { mITSROFrameEndBorderMargin = confITSROFrameEndBorderMargin < 0 ? par->fITSROFrameEndBorderMargin : confITSROFrameEndBorderMargin; mTimeFrameStartBorderMargin = confTimeFrameStartBorderMargin < 0 ? par->fTimeFrameStartBorderMargin : confTimeFrameStartBorderMargin; mTimeFrameEndBorderMargin = confTimeFrameEndBorderMargin < 0 ? par->fTimeFrameEndBorderMargin : confTimeFrameEndBorderMargin; - // access orbit-reset timestamp - auto ctpx = ccdb->getForTimeStamp>("CTP/Calib/OrbitReset", ts); - int64_t tsOrbitReset = (*ctpx)[0]; // us - // access TF duration, start-of-run and end-of-run timestamps from ECS GRP - std::map metadata; - metadata["runNumber"] = Form("%d", run); - auto grpecs = ccdb->getSpecific("GLO/Config/GRPECS", ts, metadata); - uint32_t nOrbitsPerTF = grpecs->getNHBFPerTF(); // assuming 1 orbit = 1 HBF; nOrbitsPerTF=128 in 2022, 32 in 2023 - int64_t tsSOR = grpecs->getTimeStart(); // ms - // calculate SOR orbit - int64_t orbitSOR = (tsSOR * 1000 - tsOrbitReset) / o2::constants::lhc::LHCOrbitMUS; - // adjust to the nearest TF edge - orbitSOR = orbitSOR / nOrbitsPerTF * nOrbitsPerTF + par->fTimeFrameOrbitShift; - // first bc of the first orbit (should coincide with TF start) - bcSOR = orbitSOR * o2::constants::lhc::LHCMaxBunches; + + auto runInfo = o2::parameters::AggregatedRunInfo::buildAggregatedRunInfo(o2::ccdb::BasicCCDBManager::instance(), run); + // first bc of the first orbit + bcSOR = runInfo.orbitSOR * o2::constants::lhc::LHCMaxBunches; // duration of TF in bcs - nBCsPerTF = nOrbitsPerTF * o2::constants::lhc::LHCMaxBunches; - LOGP(info, "tsOrbitReset={} us, SOR = {} ms, orbitSOR = {}, nBCsPerTF = {}", tsOrbitReset, tsSOR, orbitSOR, nBCsPerTF); + nBCsPerTF = runInfo.orbitsPerTF * o2::constants::lhc::LHCMaxBunches; } } @@ -454,6 +444,7 @@ struct EventSelectionTask { Configurable confTimeRangeVetoOnCollStandard{"TimeRangeVetoOnCollStandard", 10, "Exclusion of a collision if there are other collisions nearby, +/- us"}; Configurable confTimeRangeVetoOnCollNarrow{"TimeRangeVetoOnCollNarrow", 4, "Exclusion of a collision if there are other collisions nearby, +/- us"}; Configurable confUseWeightsForOccupancyVariable{"UseWeightsForOccupancyEstimator", 1, "Use or not the delta-time weights for the occupancy estimator"}; + Configurable confSigmaBCforHighPtTracks{"confSigmaBCforHighPtTracks", 4, "Custom sigma (in bcs) for collisions with high-pt tracks"}; Partition tracklets = (aod::track::trackType == static_cast(o2::aod::track::TrackTypeEnum::Run2Tracklet)); @@ -480,6 +471,40 @@ struct EventSelectionTask { 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) + { + 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 * 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 = pow((it->second - zVtxCol) / zVtxSigma, 2) + pow((it->first - meanBC) / sigmaBC, 2.); + if (chi2 < bestChi2) { + bestChi2 = chi2; + bestGlobalBC = it->first; + } + } + + return bestGlobalBC; + } + void init(InitContext&) { if (metadataInfo.isFullyDefined()) { // Check if the metadata is initialized (only if not forced from the workflow configuration) @@ -501,7 +526,6 @@ struct EventSelectionTask { } } - // ccdb->setURL("http://ccdb-test.cern.ch:8080"); ccdb->setURL("http://alice-ccdb.cern.ch"); ccdb->setCaching(true); ccdb->setLocalObjectValidityChecking(); @@ -517,7 +541,7 @@ struct EventSelectionTask { evsel.reserve(collisions.size()); } - void processRun2(aod::Collision const& col, BCsWithBcSelsRun2 const&, aod::Tracks const&, aod::FV0Cs const&) + void processRun2(aod::Collision const& col, BCsWithBcSelsRun2 const&, FullTracksIU const&, aod::FV0Cs const&) { auto bc = col.bc_as(); EventSelectionParams* par = ccdb->getForTimeStamp("EventSelection/EventSelectionParams", bc.timestamp()); @@ -589,58 +613,42 @@ struct EventSelectionTask { } PROCESS_SWITCH(EventSelectionTask, processRun2, "Process Run2 event selection", true); - Preslice perCollision = aod::track::collisionId; - void processRun3(aod::Collisions const& cols, FullTracksIU const& tracks, BCsWithBcSelsRun3 const& bcs, aod::FT0s const&) + Partition pvTracks = ((aod::track::flags & (uint32_t)o2::aod::track::PVContributor) == (uint32_t)o2::aod::track::PVContributor); + void processRun3(aod::Collisions const& cols, FullTracksIU const&, BCsWithBcSelsRun3 const& bcs, aod::FT0s const&) { int run = bcs.iteratorAt(0).runNumber(); // extract bc pattern from CCDB for data or anchored MC only if (run != lastRun && run >= 500000) { lastRun = run; + auto runInfo = o2::parameters::AggregatedRunInfo::buildAggregatedRunInfo(o2::ccdb::BasicCCDBManager::instance(), run); + // 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; + // colliding bc pattern int64_t ts = bcs.iteratorAt(0).timestamp(); auto grplhcif = ccdb->getForTimeStamp("GLO/Config/GRPLHCIF", ts); bcPatternB = grplhcif->getBunchFilling().getBCPattern(); - - // - EventSelectionParams* par = ccdb->getForTimeStamp("EventSelection/EventSelectionParams", ts); - // access orbit-reset timestamp - auto ctpx = ccdb->getForTimeStamp>("CTP/Calib/OrbitReset", ts); - int64_t tsOrbitReset = (*ctpx)[0]; // us - // access TF duration, start-of-run timestamp from ECS GRP - std::map metadata; - metadata["runNumber"] = Form("%d", run); - auto grpecs = ccdb->getSpecific("GLO/Config/GRPECS", ts, metadata); - uint32_t nOrbitsPerTF = grpecs->getNHBFPerTF(); // assuming 1 orbit = 1 HBF; nOrbitsPerTF=128 in 2022, 32 in 2023 - int64_t tsSOR = grpecs->getTimeStart(); // ms - // calculate SOR orbit - int64_t orbitSOR = (tsSOR * 1000 - tsOrbitReset) / o2::constants::lhc::LHCOrbitMUS; - // adjust to the nearest TF edge - orbitSOR = orbitSOR / nOrbitsPerTF * nOrbitsPerTF + par->fTimeFrameOrbitShift; - // first bc of the first orbit (should coincide with TF start) - bcSOR = orbitSOR * o2::constants::lhc::LHCMaxBunches; - // duration of TF in bcs - nBCsPerTF = nOrbitsPerTF * o2::constants::lhc::LHCMaxBunches; } - // create maps from globalBC to bc index for TVX or FT0-OR fired bcs - // to be used for closest TVX (FT0-OR) searches + // create maps from globalBC to bc index for TVX-fired bcs + // to be used for closest TVX searches std::map mapGlobalBcWithTVX; - std::map mapGlobalBcWithTOR; + std::map mapGlobalBcVtxZ; for (auto& bc : bcs) { int64_t globalBC = bc.globalBC(); // skip non-colliding bcs for data and anchored runs if (run >= 500000 && bcPatternB[globalBC % o2::constants::lhc::LHCMaxBunches] == 0) { continue; } - if (bc.selection_bit(kIsBBT0A) || bc.selection_bit(kIsBBT0C)) { - mapGlobalBcWithTOR[globalBC] = bc.globalIndex(); - } if (bc.selection_bit(kIsTriggerTVX)) { mapGlobalBcWithTVX[globalBC] = bc.globalIndex(); + mapGlobalBcVtxZ[globalBC] = bc.has_ft0() ? bc.ft0().posZ() : 0; } } // protection against empty FT0 maps - if (mapGlobalBcWithTOR.size() == 0 || mapGlobalBcWithTVX.size() == 0) { + if (mapGlobalBcWithTVX.size() == 0) { LOGP(error, "FT0 table is empty or corrupted. Filling evsel table with dummy values"); for (auto& col : cols) { auto bc = col.bc_as(); @@ -653,88 +661,139 @@ struct EventSelectionTask { } return; } - - std::vector vFoundBCindex(cols.size(), -1); // indices of found bcs - 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 - - // for the occupancy study - std::vector vFoundGlobalBC(cols.size(), 0); // global BCs for collisions std::vector vTracksITS567perColl(cols.size(), 0); // counter of tracks per found bc for occupancy studies std::vector vIsFullInfoForOccupancy(cols.size(), 0); // info for occupancy in +/- windows is available (i.e. a given coll is not too close to the TF borders) const float timeWinOccupancyCalcMinNS = confTimeIntervalForOccupancyCalculationMin * 1e3; // ns const float timeWinOccupancyCalcMaxNS = confTimeIntervalForOccupancyCalculationMax * 1e3; // ns - // const double timeWinOccupancyExclusionRangeNS = confExclusionIntervalForOccupancyCalculation * 1e3; // ns - const double bcNS = o2::constants::lhc::LHCBunchSpacingNS; - - // loop to find nearest bc with FT0 entry -> foundBC index + std::vector vIsVertexITSTPC(cols.size(), 0); // at least one of vertex contributors is ITS-TPC track + std::vector vIsVertexTOFmatched(cols.size(), 0); // at least one of vertex contributors is matched to TOF + std::vector vIsVertexTRDmatched(cols.size(), 0); // at least one of vertex contributors is matched to TRD + + std::vector vCollisionsPerBc(bcs.size(), 0); // counter of collisions per found bc for pileup checks + std::vector vFoundBCindex(cols.size(), -1); // indices of found bcs + std::vector vFoundGlobalBC(cols.size(), 0); // global BCs for collisions + + std::vector vIsVertexTOF(cols.size(), 0); + std::vector vIsVertexTRD(cols.size(), 0); + std::vector vIsVertexTPC(cols.size(), 0); + std::vector vIsVertexHighPtTPC(cols.size(), 0); + std::vector vNcontributors(cols.size(), 0); + std::vector vWeightedTimesTPCnoTOFnoTRD(cols.size(), 0); + std::vector vWeightedSigmaTPCnoTOFnoTRD(cols.size(), 0); + + // temporary vectors to find tracks with median time + std::vector vTrackTimesTOF; + std::vector vTrackTimesTRDnoTOF; + + // first loop to match collisions to TVX for (auto& col : cols) { + int32_t colIndex = col.globalIndex(); auto bc = col.bc_as(); - int64_t meanBC = bc.globalBC(); - const double bcNS = o2::constants::lhc::LHCBunchSpacingNS; - int64_t deltaBC = std::ceil(col.collisionTimeRes() / bcNS * 4); - - // count tracks of different types - int nITS567cls = 0; - int nITSTPCtracks = 0; - int nTOFtracks = 0; - int nTRDtracks = 0; - double timeFromTOFtracks = 0; - auto tracksGrouped = tracks.sliceBy(perCollision, col.globalIndex()); - for (auto& track : tracksGrouped) { - if (!track.isPVContributor()) { - continue; - } - nITSTPCtracks += track.hasITS() && track.hasTPC(); - nTOFtracks += track.hasTOF(); - nTRDtracks += track.hasTRD(); - // calculate average time using TOF tracks - if (track.hasTOF()) { - timeFromTOFtracks += track.trackTime(); - } + int64_t globalBC = bc.globalBC(); + int64_t 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 (auto& track : colPvTracks) { + float trackTime = track.trackTime(); if (track.itsNCls() >= 5) - nITS567cls++; + 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++; + } + } } - LOGP(debug, "nContrib={} nITSTPCtracks={} nTOFtracks={} nTRDtracks={}", col.numContrib(), nITSTPCtracks, nTOFtracks, nTRDtracks); - - if (nTOFtracks > 0) { - meanBC += TMath::FloorNint(timeFromTOFtracks / nTOFtracks / bcNS); // assign collision bc using TOF-matched tracks - deltaBC = 4; // use precise bc from TOF tracks with +/-4 bc margin - } else if (nITSTPCtracks > 0) { - deltaBC += 30; // extend deltaBC for collisions built with ITS-TPC tracks only + vWeightedTimesTPCnoTOFnoTRD[colIndex] = sumW > 0 ? sumTime / sumW : 0; + vWeightedSigmaTPCnoTOFnoTRD[colIndex] = sumW > 0 ? sqrt(1. / sumW) : 0; + vNcontributors[colIndex] = colPvTracks.size(); + int nPvTracksTOF = vTrackTimesTOF.size(); + int nPvTracksTRDnoTOF = vTrackTimesTRDnoTOF.size(); + // collision type + vIsVertexTOF[colIndex] = nPvTracksTOF > 0; + vIsVertexTRD[colIndex] = nPvTracksTRDnoTOF > 0; + vIsVertexTPC[colIndex] = nPvTracksTPCnoTOFnoTRD > 0; + vIsVertexHighPtTPC[colIndex] = nPvTracksHighPtTPCnoTOFnoTRD > 0; + + int64_t foundGlobalBC = 0; + int32_t foundBCindex = -1; + + if (nPvTracksTOF > 0) { + // for collisions with TOF tracks: + // take bc corresponding to TOF track with median time + int64_t tofGlobalBC = globalBC + TMath::Nint(getMedian(vTrackTimesTOF) / bcNS); + std::map::iterator it = mapGlobalBcWithTVX.find(tofGlobalBC); + if (it != mapGlobalBcWithTVX.end()) { + foundGlobalBC = it->first; + foundBCindex = it->second; + } + } else if (nPvTracksTPCnoTOFnoTRD == 0 && nPvTracksTRDnoTOF > 0) { + // for collisions with TRD tracks but without TOF or ITSTPC-only tracks: + // take bc corresponding to TRD track with median time + int64_t trdGlobalBC = globalBC + TMath::Nint(getMedian(vTrackTimesTRDnoTOF) / bcNS); + std::map::iterator it = mapGlobalBcWithTVX.find(trdGlobalBC); + if (it != mapGlobalBcWithTVX.end()) { + foundGlobalBC = it->first; + foundBCindex = it->second; + } + } else if (nPvTracksHighPtTPCnoTOFnoTRD > 0) { + // for collisions with high-pt ITSTPC-nonTOF-nonTRD tracks + // search in 3*confSigmaBCforHighPtTracks range (3*4 bcs by default) + int64_t meanBC = globalBC + TMath::Nint(sumHighPtTime / sumHighPtW / bcNS); + int64_t bestGlobalBC = findBestGlobalBC(meanBC, confSigmaBCforHighPtTracks, vNcontributors[colIndex], col.posZ(), mapGlobalBcVtxZ); + if (bestGlobalBC > 0) { + foundGlobalBC = bestGlobalBC; + foundBCindex = mapGlobalBcWithTVX[bestGlobalBC]; + } } - int64_t minBC = meanBC - deltaBC; - int64_t maxBC = meanBC + deltaBC; + // 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; - int32_t indexClosestTVX = findClosest(meanBC, mapGlobalBcWithTVX); - int64_t tvxBC = bcs.iteratorAt(indexClosestTVX).globalBC(); - if (tvxBC >= minBC && tvxBC <= maxBC) { // closest TVX within search region - bc.setCursor(indexClosestTVX); - } else { // no TVX within search region, searching for TOR = T0A | T0C - int32_t indexClosestTOR = findClosest(meanBC, mapGlobalBcWithTOR); - int64_t torBC = bcs.iteratorAt(indexClosestTOR).globalBC(); - if (torBC >= minBC && torBC <= maxBC) { - bc.setCursor(indexClosestTOR); - } - } - int32_t foundBC = bc.globalIndex(); + // erase found global BC with TVX from the pool of bcs for the next loop over low-pt TPCnoTOFnoTRD collisions + if (foundBCindex >= 0) + mapGlobalBcVtxZ.erase(foundGlobalBC); + } + + // second loop to match remaining low-pt TPCnoTOFnoTRD collisions + for (auto& col : cols) { int32_t colIndex = col.globalIndex(); - LOGP(debug, "foundBC = {} globalBC = {}", foundBC, bc.globalBC()); - vFoundBCindex[colIndex] = foundBC; - vIsVertexITSTPC[colIndex] = nITSTPCtracks > 0; - vIsVertexTOFmatched[colIndex] = nTOFtracks > 0; - vIsVertexTRDmatched[colIndex] = nTRDtracks > 0; - vCollisionsPerBc[foundBC]++; - vTracksITS567perColl[colIndex] = nITS567cls; - vFoundGlobalBC[colIndex] = bc.globalBC(); - - // check that this collision has full information inside the time window (taking into account TF borders) - int64_t bcInTF = (bc.globalBC() - bcSOR) % nBCsPerTF; - vIsFullInfoForOccupancy[colIndex] = ((bcInTF - 300) * bcNS > -timeWinOccupancyCalcMinNS) && ((nBCsPerTF - 4000 - bcInTF) * bcNS > timeWinOccupancyCalcMaxNS) ? true : false; + if (vIsVertexTPC[colIndex] > 0 && vIsVertexTOF[colIndex] == 0 && vIsVertexHighPtTPC[colIndex] == 0) { + float weightedTime = vWeightedTimesTPCnoTOFnoTRD[colIndex]; + float weightedSigma = vWeightedSigmaTPCnoTOFnoTRD[colIndex]; + auto bc = col.bc_as(); + int64_t globalBC = bc.globalBC(); + int64_t meanBC = globalBC + TMath::Nint(weightedTime / bcNS); + int64_t bestGlobalBC = findBestGlobalBC(meanBC, weightedSigma / bcNS, 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 in time range for occupancy calculation @@ -817,7 +876,7 @@ struct EventSelectionTask { int nITS567tracksInTimeBins[nTimeIntervals] = {}; int nITS567tracksForVetoStandard = 0; // to veto events with nearby collisions int nITS567tracksForVetoNarrow = 0; // to veto events with nearby collisions (narrower range) - for (int iCol = 0; iCol < vAssocToThisCol.size(); iCol++) { + for (uint32_t iCol = 0; iCol < vAssocToThisCol.size(); iCol++) { int thisColIndex = vAssocToThisCol[iCol]; if (thisColIndex == colIndex) // skip the same collision continue; diff --git a/Common/TableProducer/multiplicityExtraTable.cxx b/Common/TableProducer/multiplicityExtraTable.cxx index 6a6bc1a76a8..216a1b7acc6 100644 --- a/Common/TableProducer/multiplicityExtraTable.cxx +++ b/Common/TableProducer/multiplicityExtraTable.cxx @@ -41,6 +41,15 @@ struct MultiplicityExtraTable { Configurable minFT0CforBCTable{"minFT0CforBCTable", 25.0f, "Minimum FT0C amplitude to fill BC table to reduce data"}; Configurable saveOnlyBCsWithCollisions{"saveOnlyBCsWithCollisions", true, "save only BCs with collisions in them"}; + Configurable bcTableFloatPrecision{"bcTableFloatPrecision", 0.1, "float precision in bc table for data reduction"}; + + float tru(float value) + { + if (bcTableFloatPrecision < 1e-4) + return value; // make sure nothing bad happens in case zero (best precision) + return bcTableFloatPrecision * std::round(value / bcTableFloatPrecision) + 0.5f * bcTableFloatPrecision; + }; + // needed for downscale unsigned int randomSeed = 0; @@ -231,9 +240,10 @@ struct MultiplicityExtraTable { bc2mult(bc2multArray[bc.globalIndex()]); multBC( - multFT0A, multFT0C, posZFT0, posZFT0valid, multFV0A, - multFDDA, multFDDC, multZNA, multZNC, multZEM1, - multZEM2, multZPA, multZPC, Tvx, isFV0OrA, + tru(multFT0A), tru(multFT0C), + tru(posZFT0), posZFT0valid, tru(multFV0A), + tru(multFDDA), tru(multFDDC), tru(multZNA), tru(multZNC), tru(multZEM1), + tru(multZEM2), tru(multZPA), tru(multZPC), Tvx, isFV0OrA, multFV0TriggerBits, multFT0TriggerBits, multFDDTriggerBits, multBCTriggerMask, collidingBC, bc.flags()); } diff --git a/Common/TableProducer/multiplicityTable.cxx b/Common/TableProducer/multiplicityTable.cxx index 5b7d69c4fc8..08b3852e65a 100644 --- a/Common/TableProducer/multiplicityTable.cxx +++ b/Common/TableProducer/multiplicityTable.cxx @@ -379,15 +379,17 @@ struct MultiplicityTable { if (bc.runNumber() != mRunNumber) { mRunNumber = bc.runNumber(); // mark this run as at least tried if (ccdbConfig.reconstructionPass.value == "") { - lCalibObjects = ccdb->getForTimeStamp(ccdbConfig.ccdbPath, bc.timestamp()); + lCalibObjects = ccdb->getForRun(ccdbConfig.ccdbPath, mRunNumber); } else if (ccdbConfig.reconstructionPass.value == "metadata") { std::map metadata; metadata["RecoPassName"] = metadataInfo.get("RecoPassName"); - lCalibObjects = ccdb->getSpecific(ccdbConfig.ccdbPath, bc.timestamp(), metadata); + LOGF(info, "Loading CCDB for reconstruction pass (from metadata): %s", metadataInfo.get("RecoPassName")); + lCalibObjects = ccdb->getSpecificForRun(ccdbConfig.ccdbPath, mRunNumber, metadata); } else { std::map metadata; metadata["RecoPassName"] = ccdbConfig.reconstructionPass.value; - lCalibObjects = ccdb->getSpecific(ccdbConfig.ccdbPath, bc.timestamp(), metadata); + LOGF(info, "Loading CCDB for reconstruction pass (from provided argument): %s", ccdbConfig.reconstructionPass.value); + lCalibObjects = ccdb->getSpecificForRun(ccdbConfig.ccdbPath, mRunNumber, metadata); } if (lCalibObjects) { diff --git a/Common/TableProducer/trackPropagation.cxx b/Common/TableProducer/trackPropagation.cxx index ac8a4e60e0e..ab8e3bf33fb 100644 --- a/Common/TableProducer/trackPropagation.cxx +++ b/Common/TableProducer/trackPropagation.cxx @@ -123,9 +123,6 @@ struct TrackPropagation { trackTunerObj.getDcaGraphs(); trackTunedTracks->SetTitle(outputStringParams.c_str()); trackTunedTracks->GetXaxis()->SetBinLabel(1, "all tracks"); - trackTunedTracks->GetXaxis()->SetBinLabel(2, "tracks tuned (no negative detXY)"); - trackTunedTracks->GetXaxis()->SetBinLabel(3, "untouched tracks due to negative detXY"); - trackTunedTracks->GetXaxis()->SetBinLabel(4, "original detXY<0"); } } diff --git a/DPG/Tasks/AOTTrack/qaImpPar.cxx b/DPG/Tasks/AOTTrack/qaImpPar.cxx index eb2b8e20521..338f1e1c06c 100644 --- a/DPG/Tasks/AOTTrack/qaImpPar.cxx +++ b/DPG/Tasks/AOTTrack/qaImpPar.cxx @@ -112,6 +112,7 @@ struct QaImpactPar { Configurable keepAllTracksPVrefit{"keepAllTracksPVrefit", false, "Keep all tracks for PV refit (for debug)"}; Configurable use_customITSHitMap{"use_customITSHitMap", false, "Use custom ITS hitmap selection"}; Configurable customITShitmap{"customITShitmap", 0, "Custom ITS hitmap (consider the binary representation)"}; + Configurable customITShitmap_exclude{"customITShitmap_exclude", 0, "Custom ITS hitmap of layers to be excluded (consider the binary representation)"}; Configurable n_customMinITShits{"n_customMinITShits", 0, "Minimum number of layers crossed by a track among those in \"customITShitmap\""}; Configurable custom_forceITSTPCmatching{"custom_forceITSTPCmatching", false, "Consider or not only ITS-TPC macthed tracks when using custom ITS hitmap"}; @@ -135,9 +136,9 @@ struct QaImpactPar { /// Histogram registry (from o2::framework) HistogramRegistry histograms{"HistogramsImpParQA"}; - bool isPIDPionApplied = ((nSigmaTPCPionMin > -10.001 && nSigmaTPCPionMax < 10.001) || (nSigmaTOFPionMin > -10.001 && nSigmaTOFPionMax < 10.001)); - bool isPIDKaonApplied = ((nSigmaTPCKaonMin > -10.001 && nSigmaTPCKaonMax < 10.001) || (nSigmaTOFKaonMin > -10.001 && nSigmaTOFKaonMax < 10.001)); - bool isPIDProtonApplied = ((nSigmaTPCProtonMin > -10.001 && nSigmaTPCProtonMax < 10.001) || (nSigmaTOFProtonMin > -10.001 && nSigmaTOFProtonMax < 10.001)); + bool isPIDPionApplied; + bool isPIDKaonApplied; + bool isPIDProtonApplied; // Needed for PV refitting Service ccdb; @@ -239,7 +240,7 @@ struct QaImpactPar { // } mRunNumber = -1; - /// Custom cut selection objects + /// Custom cut selection objects - ITS layers that must be present std::set set_customITShitmap; // = {}; if (use_customITSHitMap) { for (int index_ITSlayer = 0; index_ITSlayer < 7; index_ITSlayer++) { @@ -258,6 +259,24 @@ struct QaImpactPar { selector_ITShitmap.SetRequireHitsInITSLayers(n_customMinITShits, set_customITShitmap); } + /// Custom cut selection objects - ITS layers that must be absent + std::set set_customITShitmap_exclude; // = {}; + if (use_customITSHitMap) { + for (int index_ITSlayer = 0; index_ITSlayer < 7; index_ITSlayer++) { + if ((customITShitmap_exclude & (1 << index_ITSlayer)) > 0) { + set_customITShitmap_exclude.insert(static_cast(index_ITSlayer)); + } + } + LOG(info) << "### customITShitmap_exclude: " << customITShitmap_exclude; + LOG(info) << "### set_customITShitmap_exclude.size(): " << set_customITShitmap_exclude.size(); + LOG(info) << "### ITS layers to be excluded: "; + for (std::set::iterator it = set_customITShitmap_exclude.begin(); it != set_customITShitmap_exclude.end(); it++) { + LOG(info) << "Layer " << static_cast(*it) << " "; + } + LOG(info) << "############"; + + selector_ITShitmap.SetRequireNoHitsInITSLayers(set_customITShitmap_exclude); + } // tracks const AxisSpec trackPtAxis{binningPt, "#it{p}_{T} (GeV/#it{c})"}; @@ -303,14 +322,17 @@ struct QaImpactPar { histograms.add("Reco/h4ImpParPulls", "", kTHnSparseD, {trackPtAxis, trackImpParRPhiPullsAxis, trackEtaAxis, trackPhiAxis, trackPDGAxis, trackChargeAxis, axisVertexNumContrib, trackIsPvContrib}); histograms.add("Reco/h4ImpParZPulls", "", kTHnSparseD, {trackPtAxis, trackImpParZPullsAxis, trackEtaAxis, trackPhiAxis, trackPDGAxis, trackChargeAxis, axisVertexNumContrib, trackIsPvContrib}); } + isPIDPionApplied = ((nSigmaTPCPionMin > -10.001 && nSigmaTPCPionMax < 10.001) || (nSigmaTOFPionMin > -10.001 && nSigmaTOFPionMax < 10.001)); if (isPIDPionApplied) { histograms.add("Reco/h4ImpPar_Pion", "", kTHnSparseD, {trackPtAxis, trackImpParRPhiAxis, trackEtaAxis, trackPhiAxis, trackPDGAxis, trackChargeAxis, axisVertexNumContrib, trackIsPvContrib}); histograms.add("Reco/h4ImpParZ_Pion", "", kTHnSparseD, {trackPtAxis, trackImpParZAxis, trackEtaAxis, trackPhiAxis, trackPDGAxis, trackChargeAxis, axisVertexNumContrib, trackIsPvContrib}); } + isPIDKaonApplied = ((nSigmaTPCKaonMin > -10.001 && nSigmaTPCKaonMax < 10.001) || (nSigmaTOFKaonMin > -10.001 && nSigmaTOFKaonMax < 10.001)); if (isPIDKaonApplied) { histograms.add("Reco/h4ImpPar_Kaon", "", kTHnSparseD, {trackPtAxis, trackImpParRPhiAxis, trackEtaAxis, trackPhiAxis, trackPDGAxis, trackChargeAxis, axisVertexNumContrib, trackIsPvContrib}); histograms.add("Reco/h4ImpParZ_Kaon", "", kTHnSparseD, {trackPtAxis, trackImpParZAxis, trackEtaAxis, trackPhiAxis, trackPDGAxis, trackChargeAxis, axisVertexNumContrib, trackIsPvContrib}); } + isPIDProtonApplied = ((nSigmaTPCProtonMin > -10.001 && nSigmaTPCProtonMax < 10.001) || (nSigmaTOFProtonMin > -10.001 && nSigmaTOFProtonMax < 10.001)); if (isPIDProtonApplied) { histograms.add("Reco/h4ImpPar_Proton", "", kTHnSparseD, {trackPtAxis, trackImpParRPhiAxis, trackEtaAxis, trackPhiAxis, trackPDGAxis, trackChargeAxis, axisVertexNumContrib, trackIsPvContrib}); histograms.add("Reco/h4ImpParZ_Proton", "", kTHnSparseD, {trackPtAxis, trackImpParZAxis, trackEtaAxis, trackPhiAxis, trackPDGAxis, trackChargeAxis, axisVertexNumContrib, trackIsPvContrib}); diff --git a/EventFiltering/macros/checkBCrangesSkimming.C b/EventFiltering/macros/checkBCrangesSkimming.C index 3dea4c56318..bd6d39b41fb 100644 --- a/EventFiltering/macros/checkBCrangesSkimming.C +++ b/EventFiltering/macros/checkBCrangesSkimming.C @@ -10,13 +10,14 @@ // or submit itself to any jurisdiction. // O2 includes -#include -#include -#include #include #include -#include #include +#include +#include +#include +#include +#include #include "CommonDataFormat/InteractionRecord.h" #include "CommonDataFormat/IRFrame.h" @@ -24,9 +25,7 @@ using o2::InteractionRecord; using o2::dataformats::IRFrame; // Set the bit of trigger which need to be checked -const ULong64_t Trigger0BIT = BIT(61); -const ULong64_t Trigger1BIT = 0; -const ULong64_t bcDiffTolerance = 100; +const ULong64_t bcDiffTolerance = 0; const char outputFileName[15] = "output.root"; struct bcTuple { @@ -40,6 +39,7 @@ struct bcTuple { }; struct selectedFrames : public IRFrame { + selectedFrames(ULong64_t bcAO2D, ULong64_t bcEvSel, const IRFrame& frame) : IRFrame(frame), bcAO2D(bcAO2D), bcEvSel(bcEvSel), triMask{0, 0}, selMask{0, 0} {} selectedFrames(ULong64_t bcAO2D, ULong64_t bcEvSel, ULong64_t triMask[2], ULong64_t selMask[2], const IRFrame& frame) : IRFrame(frame), bcAO2D(bcAO2D), bcEvSel(bcEvSel), triMask{triMask[0], triMask[1]}, selMask{selMask[0], selMask[1]} {} ULong64_t triMask[2]{0ull}, selMask[2]{0ull}, bcAO2D, bcEvSel; int numSameTriggerInNearbyBCs = 0; // related to bcDiffTolerance @@ -58,20 +58,32 @@ int DoBCSubraction(ULong64_t bc1, ULong64_t bc2) } } +int DoBCSubraction(selectedFrames bc1, selectedFrames bc2) +{ + if (bc1.getMin() > bc2.getMax()) { + return DoBCSubraction(bc1.getMin().toLong(), bc2.getMax().toLong()); + } else if (bc1.getMax() < bc2.getMin()) { + return DoBCSubraction(bc1.getMax().toLong(), bc2.getMin().toLong()); + } else { + return 0; + } +} + bool isClose(selectedFrames a, selectedFrames b, ULong64_t bcDiffTolerance) { - if (a.getMin() > b.getMax() + bcDiffTolerance || a.getMax() < b.getMin() - bcDiffTolerance) + if (a.getMin() > b.getMax() + bcDiffTolerance || a.getMax() + bcDiffTolerance < b.getMin()) return false; else return true; } -std::vector getSelectedFrames(TFile& file, ULong64_t trigger0Bit, ULong64_t trigger1Bit) +std::vector> getFrames(std::unique_ptr& file, int trgIDStart, int N) { - std::vector selectedFrames; ULong64_t bcAO2D{0ull}, bcEvSel{0ull}, triMask[2]{0ull}, selMask[2]{0ull}; - for (auto key : *file.GetListOfKeys()) { - auto dir = dynamic_cast(file.Get(key->GetName())); + std::vector> frames; + frames.resize(N); + for (auto key : *file->GetListOfKeys()) { + auto dir = dynamic_cast(file->Get(key->GetName())); if (!dir) { continue; } @@ -96,18 +108,36 @@ std::vector getSelectedFrames(TFile& file, ULong64_t trigger0Bit if (!selMask[0] && !selMask[1]) { continue; } - if (selMask[0] & trigger0Bit || selMask[1] & trigger1Bit) { - InteractionRecord irstart, irend; - irstart.setFromLong(std::min(bcAO2D, bcEvSel)); - irend.setFromLong(std::max(bcAO2D, bcEvSel)); - IRFrame frame(irstart, irend); - selectedFrames.push_back({bcAO2D, bcEvSel, triMask, selMask, frame}); + for (int trgID = trgIDStart; trgID < trgIDStart + N; trgID++) { + ULong64_t trigger0Bit = 0, trigger1Bit = 0; + if (trgID < 64) { + trigger0Bit = BIT(trgID); + } else { + trigger1Bit = BIT(trgID - 64); + } + if (selMask[0] & trigger0Bit || selMask[1] & trigger1Bit) { + InteractionRecord irstart, irend; + irstart.setFromLong(std::min(bcAO2D, bcEvSel)); + irend.setFromLong(std::max(bcAO2D, bcEvSel)); + IRFrame frame(irstart, irend); + int index = trgID - trgIDStart; + frames[index].push_back({bcAO2D, bcEvSel, triMask, selMask, frame}); + } } } } - return selectedFrames; + + return frames; +} + +std::vector getSelectedFrames(std::unique_ptr& file, int trgID) +{ + auto frames = getFrames(file, trgID, 1); + return frames[0]; } +// Check how many other triggers are in a compatible BC window with the current one +// Ideally, most of triggers are singles (num = 1), which means none of others is in the same window void checkNearbyBCs(std::vector& frames, ULong64_t bcDiffTolerance) { std::sort(frames.begin(), frames.end(), [](const selectedFrames& a, const selectedFrames& b) { @@ -138,27 +168,163 @@ void checkNearbyBCs(std::vector& frames, ULong64_t bcDiffToleran } } -// Calulate the ratio of duplicate triggers -void checkDuplicateTriggerAndBCs(std::string AnaFileName = "AnalysisResults.root", std::string originalFileName = "bcRanges_fullrun.root", std::string skimmedFileName = "bcRanges_fullrun_skimmed.root") +// Get RunNumber +std::string getRunNumber(std::string fileName) { - - // Get RunNumber std::string runNumber = ""; std::regex re("/5[0-9]*"); std::smatch match; - if (std::regex_search(originalFileName, match, re)) { + if (std::regex_search(fileName, match, re)) { // Remove the leading '/' runNumber = match.str().substr(1); } + return runNumber; +} + +// Detailed checks for specific trigger +void checkBCForSelectedTrg(std::vector& originalFrames, std::vector& skimmedFrames, string runNumber, string triggerLabel) +{ + + TH1D hTriggerCounter("hTriggerCounter", (runNumber + " " + triggerLabel + ";;Total number of trigger").data(), 2, -0.5, 1.5); + hTriggerCounter.GetXaxis()->SetBinLabel(1, "Original"); + hTriggerCounter.GetXaxis()->SetBinLabel(2, "Skimmed"); + TH1D hBCDiffAO2D("hBCDiffAO2D", (runNumber + " " + triggerLabel + ";;#DeltaBC_{AO2D} between paired singles").data(), 201, -100.5, 100.5); + TH1D hBCDiffEvSel("hBCDiffEvSel", (runNumber + " " + triggerLabel + ";;#DeltaBC_{EvSel} between paired singles").data(), 201, -100.5, 100.5); + + TH1D hBCOriginal("hBCOriginal", (runNumber + " " + triggerLabel + " Original;;Trigger counts").data(), 4, -0.5, 3.5); + hBCOriginal.GetXaxis()->SetBinLabel(1, "Total"); + hBCOriginal.GetXaxis()->SetBinLabel(2, "Same AO2D BC"); + hBCOriginal.GetXaxis()->SetBinLabel(3, "Same EvSel BC"); + hBCOriginal.GetXaxis()->SetBinLabel(4, "Same Both BC"); + TH1D hBCSkimmed("hBCSkimmed", (runNumber + " " + triggerLabel + " Skimmed;;Trigger counts").data(), 4, -0.5, 3.5); + hBCSkimmed.GetXaxis()->SetBinLabel(1, "Total"); + hBCSkimmed.GetXaxis()->SetBinLabel(2, "Same AO2D BC"); + hBCSkimmed.GetXaxis()->SetBinLabel(3, "Same EvSel BC"); + hBCSkimmed.GetXaxis()->SetBinLabel(4, "Same Both BC"); - // Checks for BC difference between original and skimming data, and the ratio of triggers which have BCdiff==0 - TH1D hPairedNumCounterTotal("hPairedNumCounterTotal", "hPairedNumCounterTotal", 10, -0.5, 9.5); - TH1D hBCDiffAO2DTotal("hBCDiffAO2DTotal", "hBCDiffAO2DTotal", 201, -100.5, 100.5); - TH1D hBCDiffEvSelTotal("hBCDiffEvSelTotal", "hBCDiffEvSelTotal", 201, -100.5, 100.5); + TH1D hPairedNumCounter("hPairedNumCounter", (runNumber + " " + triggerLabel + ";;Number of matched triggers in skimmed data").data(), 10, -0.5, 9.5); + + checkNearbyBCs(originalFrames, bcDiffTolerance); + checkNearbyBCs(skimmedFrames, bcDiffTolerance); + + std::vector bcSet; + int firstID = 0; + for (auto frame : originalFrames) { + hTriggerCounter.Fill(0); + hBCOriginal.Fill(0); + //------------------------------ Check if there are triggers which have same BC, time-consuming! ------------------------------------------------------- + auto p1 = std::find_if(bcSet.begin(), bcSet.end(), [&](const auto& val) { return val.bcAO2D == frame.bcAO2D; }); + if (p1 != bcSet.end()) { + hBCOriginal.Fill(1); + } + auto p2 = std::find_if(bcSet.begin(), bcSet.end(), [&](const auto& val) { return val.bcEvSel == frame.bcEvSel; }); + if (p2 != bcSet.end()) { + hBCOriginal.Fill(2); + } + bcTuple currentBC(frame.bcAO2D, frame.bcEvSel); + auto p3 = std::find(bcSet.begin(), bcSet.end(), currentBC); + if (p3 == bcSet.end()) { + bcSet.push_back(currentBC); + } else { + hBCOriginal.Fill(3); + } + //------------------------------------------------------------------------------------- + + if (frame.GetNum() != 1) { + continue; // Only check singles + } + std::vector skimmedbcs; + int n = 0; + bool isFirst = true; + for (int i = firstID; i < skimmedFrames.size(); i++) { + auto& skimmedFrame = skimmedFrames[i]; + if (skimmedFrame.getMin() > frame.getMax()) { + break; + } + if (skimmedFrame.GetNum() != 1) { + continue; // Only check singles + } + if (isClose(frame, skimmedFrame, bcDiffTolerance)) { + bool found = frame.selMask[0] & skimmedFrame.selMask[0] || frame.selMask[1] & skimmedFrame.selMask[1]; + if (found) { + skimmedbcs.push_back({skimmedFrame.bcAO2D, skimmedFrame.bcEvSel}); + n++; + } + } else { + if (isFirst) { + firstID = i; + } + } + } + if (n == 0) { + // std::cout << "Trigger not found!!!" << std::endl; + } else if (n == 1) { + hBCDiffAO2D.Fill(DoBCSubraction(frame.bcAO2D, skimmedbcs[0].bcAO2D)); + hBCDiffEvSel.Fill(DoBCSubraction(frame.bcEvSel, skimmedbcs[0].bcEvSel)); + } + hPairedNumCounter.Fill(n); + } + + //------------------------------ Check if there are triggers which have same BC, time-consuming! ------------------------------------------------------- + bcSet.clear(); + for (auto& skimmedFrame : skimmedFrames) { + hTriggerCounter.Fill(1); + hBCSkimmed.Fill(0); + auto p1 = std::find_if(bcSet.begin(), bcSet.end(), [&](const auto& val) { return val.bcAO2D == skimmedFrame.bcAO2D; }); + if (p1 != bcSet.end()) { + hBCSkimmed.Fill(1); + } + auto p2 = std::find_if(bcSet.begin(), bcSet.end(), [&](const auto& val) { return val.bcEvSel == skimmedFrame.bcEvSel; }); + if (p2 != bcSet.end()) { + hBCSkimmed.Fill(2); + } + bcTuple currentBC(skimmedFrame.bcAO2D, skimmedFrame.bcEvSel); + auto p3 = std::find(bcSet.begin(), bcSet.end(), currentBC); + if (p3 == bcSet.end()) { + bcSet.push_back(currentBC); + } else { + hBCSkimmed.Fill(3); + } + } + //------------------------------------------------------------------------------------- + + TFile fout(outputFileName, "UPDATE"); + fout.cd(); + TDirectory* dir1 = fout.GetDirectory(runNumber.data()); + if (!dir1) { + dir1 = fout.mkdir(runNumber.data()); + } + dir1->cd(); + TDirectory* dir2 = dir1->GetDirectory(triggerLabel.data()); + if (!dir2) { + dir2 = dir1->mkdir(triggerLabel.data()); + } + dir2->cd(); + + hTriggerCounter.Write(); + hBCOriginal.Write(); + hBCSkimmed.Write(); + hBCDiffAO2D.Write(); + hBCDiffEvSel.Write(); + hPairedNumCounter.Write(); + fout.Close(); +} + +// Detailed checks for specific trigger +void checkBCForSelectedTrg(std::string AnaFileName = "AnalysisResults.root", std::string originalFileName = "bcRanges_fullrun.root", std::string skimmedFileName = "bcRanges_fullrun_skimmed.root", int triggerID = 1, bool useAlien = true) +{ + + string runNumber = getRunNumber(originalFileName); + if (useAlien) { + TGrid::Connect("alien://"); + AnaFileName = "alien://" + AnaFileName; + originalFileName = "alien://" + originalFileName; + skimmedFileName = "alien://" + skimmedFileName; + } // Readin labels - TFile AnaFile(AnaFileName.c_str(), "READ"); - TH1* hist0 = dynamic_cast(AnaFile.Get("central-event-filter-task/scalers/mFiltered;1")); + std::unique_ptr AnaFile{TFile::Open(AnaFileName.c_str(), "READ")}; + TH1* hist0 = dynamic_cast(AnaFile->Get("central-event-filter-task/scalers/mFiltered;1")); std::vector labels; std::vector binNum; for (int i = 1; i <= hist0->GetNbinsX(); i++) { @@ -168,29 +334,69 @@ void checkDuplicateTriggerAndBCs(std::string AnaFileName = "AnalysisResults.root binNum.push_back(i); } } - AnaFile.Close(); + AnaFile->Close(); + std::string triggerLabel = labels[triggerID]; - TFile originalFile(originalFileName.c_str(), "READ"); - TFile skimmedFile(skimmedFileName.c_str(), "READ"); - std::vector sel_labels; - std::vector numOriginal, numSkimmed, numOriginalSingle, numSkimmedSingle, numOriginalDouble, numSkimmedDouble, numOriginalMultiple, numSkimmedMultiple; - std::vector numpair, numpairedBCAO2D, numpairedBCEvSel, maxDeltaBCAO2D, maxDeltaBCEvSel; - for (int i = 0; i < labels.size(); i++) { - // std::cout << "i:" << i << std::endl; - ULong64_t trigger0Bit = 0, trigger1Bit = 0; - int triggerBit = binNum[i] - 2; - if (triggerBit < 64) { - trigger0Bit = BIT(triggerBit); - } else { - trigger1Bit = BIT(triggerBit - 64); + std::unique_ptr originalFile{TFile::Open(originalFileName.c_str(), "READ")}; + std::unique_ptr skimmedFile{TFile::Open(skimmedFileName.c_str(), "READ")}; + auto originalFrames = getSelectedFrames(originalFile, triggerID); + auto skimmedFrames = getSelectedFrames(skimmedFile, triggerID); + originalFile->Close(); + skimmedFile->Close(); + + checkBCForSelectedTrg(originalFrames, skimmedFrames, runNumber, triggerLabel); +} + +// Calulate the ratio of duplicate triggers +void checkBCrangesSkimming(std::string AnaFileName = "AnalysisResults.root", std::string originalFileName = "bcRanges_fullrun.root", std::string skimmedFileName = "bcRanges_fullrun_skimmed.root", bool useAlien = true) +{ + + string runNumber = getRunNumber(originalFileName); + if (useAlien) { + TGrid::Connect("alien://"); + AnaFileName = "alien://" + AnaFileName; + originalFileName = "alien://" + originalFileName; + skimmedFileName = "alien://" + skimmedFileName; + } + + // Readin labels + std::unique_ptr AnaFile{TFile::Open(AnaFileName.c_str(), "READ")}; + TH1* hist0 = dynamic_cast(AnaFile->Get("central-event-filter-task/scalers/mFiltered;1")); + std::vector labels; + std::vector binNum; + for (int i = 1; i <= hist0->GetNbinsX(); i++) { + std::string label = hist0->GetXaxis()->GetBinLabel(i); + if (label != "Total number of events" && label != "Filtered events") { + labels.push_back(label); + binNum.push_back(i); + // std::cout << i - 2 << ": " << label << std::endl; } + } + AnaFile->Close(); + + // Due to potential selection on triggers, histograms should be created later + // for example: skip triggers which have no enrties + std::vector sel_labels; + std::vector numOriginal, numSkimmed, numOriginalSingle, numSkimmedSingle, numOriginalDouble, numSkimmedDouble, numOriginalMultiple, numSkimmedMultiple, numCloseSkimmed; + std::vector numpair, numpairedBCAO2D, numpairedBCEvSel; + std::vector avgDeltaBCAO2D, avgDeltaBCEvSel, avgDeltaBC, rmsDeltaBCAO2D, rmsDeltaBCEvSel, rmsDeltaBC; + std::vector avgNumPairedTrigger, rmsNumPairedTrigger; + + std::unique_ptr originalFile{TFile::Open(originalFileName.c_str(), "READ")}; + std::unique_ptr skimmedFile{TFile::Open(skimmedFileName.c_str(), "READ")}; + std::vector> originalAllFrames = getFrames(originalFile, 0, labels.size()); + std::vector> skimmedAllFrames = getFrames(skimmedFile, 0, labels.size()); + for (int trgID = 0; trgID < labels.size(); trgID++) { // Caculate singles, doubles, and multiples + int noriginal{0}, nskimmed{0}, noriginalsingle{0}, nskimmedsingle{0}, noriginaldouble{0}, nskimmeddouble{0}, noriginalmultiple{0}, nskimmedmultiple{0}; + // Caculate mean and rms of diff BC + TH1D hDiffBCAO2DCount("hDiffBCAO2DCount", "hDiffBCAO2DCount", 21, -10.5, 10.5); + TH1D hDiffBCEvSelCount("hDiffBCEvSelCount", "hDiffBCEvSelCount", 21, -10.5, 10.5); + TH1D hDiffBCCount("hDiffBCCount", "hDiffBCCount", 21, -10.5, 10.5); + TH1D hNumPairedTriggerCount("hNumPairedTriggerCount", "hNumPairedTriggerCount", 10, -0.5, 9.5); // For Original dataset - std::vector bcSet; - std::vector bcFullSet; - int noriginal{0}, nskimmed{0}, noriginalsingle{0}, nskimmedsingle{0}, noriginaldouble{0}, nskimmeddouble{0}, noriginalmultiple{0}, nskimmedmultiple{0}, maxdiffBCAO2D{0}, maxdiffBCEvSel{0}; - auto originalFrames = getSelectedFrames(originalFile, trigger0Bit, trigger1Bit); - checkNearbyBCs(originalFrames, bcDiffTolerance); + auto& originalFrames = originalAllFrames[trgID]; + checkNearbyBCs(originalFrames, bcDiffTolerance); // include sorting noriginal = originalFrames.size(); for (auto originalFrame : originalFrames) { if (originalFrame.GetNum() == 0) { @@ -204,8 +410,8 @@ void checkDuplicateTriggerAndBCs(std::string AnaFileName = "AnalysisResults.root } } // For skimmed dataset - auto skimmedFrames = getSelectedFrames(skimmedFile, trigger0Bit, trigger1Bit); - checkNearbyBCs(skimmedFrames, bcDiffTolerance); + auto& skimmedFrames = skimmedAllFrames[trgID]; + checkNearbyBCs(skimmedFrames, bcDiffTolerance); // include sorting nskimmed = skimmedFrames.size(); for (auto& skimmedFrame : skimmedFrames) { if (skimmedFrame.GetNum() == 0) { @@ -219,344 +425,233 @@ void checkDuplicateTriggerAndBCs(std::string AnaFileName = "AnalysisResults.root } } - sel_labels.push_back(labels[i]); - numOriginal.push_back(noriginal); - numOriginalSingle.push_back(noriginalsingle); - numOriginalDouble.push_back(noriginaldouble); - numOriginalMultiple.push_back(noriginalmultiple); - numSkimmed.push_back(nskimmed); - numSkimmedSingle.push_back(nskimmedsingle); - numSkimmedDouble.push_back(nskimmeddouble); - numSkimmedMultiple.push_back(nskimmedmultiple); - // Check BC differences - int npair{0}, npairedBCAO2D{0}, npairedBCEvSel{0}, maxdeltaBCAO2D{0}, maxdeltaBCEvSel{0}; + int npair{0}, npairedBCAO2D{0}, npairedBCEvSel{0}, ncloseskimmed{0}, maxdeltaBCAO2D{0}, maxdeltaBCEvSel{0}; int firstID = 0; for (auto frame : originalFrames) { - if (frame.selMask[0] & trigger0Bit || frame.selMask[1] & trigger1Bit) { - // std::cout << "------------------------------------------------" << std::endl; - if (frame.GetNum() != 1) { + if (frame.GetNum() != 1) { + continue; // Only check singles + } + std::vector skimmedbcs; + int n = 0; + bool isFirst = true; + for (int i = firstID; i < skimmedFrames.size(); i++) { + auto& skimmedFrame = skimmedFrames[i]; + if (skimmedFrame.getMin() > frame.getMax()) { + break; + } + if (skimmedFrame.GetNum() != 1) { continue; // Only check singles } - std::vector skimmedbcs; - int n = 0; - bool isFirst = true; - for (int i = firstID; i < skimmedFrames.size(); i++) { - auto& skimmedFrame = skimmedFrames[i]; - if (skimmedFrame.getMin() > frame.getMax()) { - break; - } - if (skimmedFrame.GetNum() != 1) { - continue; // Only check singles + if (isClose(frame, skimmedFrame, bcDiffTolerance)) { + isFirst = false; + bool found = frame.selMask[0] & skimmedFrame.selMask[0] || frame.selMask[1] & skimmedFrame.selMask[1]; + if (found) { + InteractionRecord irstart, irend; + irstart.setFromLong(std::min(skimmedFrame.bcAO2D, skimmedFrame.bcEvSel)); + irend.setFromLong(std::max(skimmedFrame.bcAO2D, skimmedFrame.bcEvSel)); + IRFrame frame(irstart, irend); + skimmedbcs.push_back({skimmedFrame.bcAO2D, skimmedFrame.bcEvSel, frame}); + n++; } - if (isClose(frame, skimmedFrame, bcDiffTolerance)) { - isFirst = false; - bool found = frame.selMask[0] & skimmedFrame.selMask[0] || frame.selMask[1] & skimmedFrame.selMask[1]; - // found = found && (frame.bcAO2D == skimmedFrame.bcAO2D || frame.bcEvSel == skimmedFrame.bcEvSel); - if (found) { - skimmedbcs.push_back({skimmedFrame.bcAO2D, skimmedFrame.bcEvSel}); - n++; - } - } else { - if (isFirst) { - firstID = i; - } + } else { + if (isFirst) { + firstID = i; } } - if (n == 1) { - npair++; - int bcdiffAO2D = DoBCSubraction(frame.bcAO2D, skimmedbcs[0].bcAO2D); - int bcdiffEvSel = DoBCSubraction(frame.bcEvSel, skimmedbcs[0].bcEvSel); - hBCDiffAO2DTotal.Fill(bcdiffAO2D); - hBCDiffEvSelTotal.Fill(bcdiffEvSel); - maxdiffBCAO2D = std::max(std::abs(maxdiffBCAO2D), bcdiffAO2D); - maxdiffBCEvSel = std::max(std::abs(maxdiffBCEvSel), bcdiffEvSel); - if (frame.bcAO2D == skimmedbcs[0].bcAO2D) { - npairedBCAO2D++; - } - if (frame.bcEvSel == skimmedbcs[0].bcEvSel) { - npairedBCEvSel++; - } + } + if (n == 1) { + npair++; + int bcdiffAO2D = DoBCSubraction(frame.bcAO2D, skimmedbcs[0].bcAO2D); + int bcdiffEvSel = DoBCSubraction(frame.bcEvSel, skimmedbcs[0].bcEvSel); + hDiffBCAO2DCount.Fill(std::abs(bcdiffAO2D)); + hDiffBCEvSelCount.Fill(std::abs(bcdiffEvSel)); + hDiffBCCount.Fill(std::abs(DoBCSubraction(frame, skimmedbcs[0]))); + if (frame.bcAO2D == skimmedbcs[0].bcAO2D) { + npairedBCAO2D++; + } + if (frame.bcEvSel == skimmedbcs[0].bcEvSel) { + npairedBCEvSel++; } - hPairedNumCounterTotal.Fill(n); } + ncloseskimmed += n; + hNumPairedTriggerCount.Fill(n); + } + + // if (static_cast(ncloseskimmed) / noriginal > 0.95 || noriginal == 0) + if (noriginal == 0) { + // continue; } + sel_labels.push_back(labels[trgID]); + numOriginal.push_back(noriginal); + numOriginalSingle.push_back(noriginalsingle); + numOriginalDouble.push_back(noriginaldouble); + numOriginalMultiple.push_back(noriginalmultiple); + numSkimmed.push_back(nskimmed); + numSkimmedSingle.push_back(nskimmedsingle); + numSkimmedDouble.push_back(nskimmeddouble); + numSkimmedMultiple.push_back(nskimmedmultiple); + numpair.push_back(npair); numpairedBCAO2D.push_back(npairedBCAO2D); numpairedBCEvSel.push_back(npairedBCEvSel); - maxDeltaBCAO2D.push_back(maxdiffBCAO2D); - maxDeltaBCEvSel.push_back(maxdiffBCEvSel); + numCloseSkimmed.push_back(ncloseskimmed); + avgDeltaBCAO2D.push_back(hDiffBCAO2DCount.GetMean()); + avgDeltaBCEvSel.push_back(hDiffBCEvSelCount.GetMean()); + avgDeltaBC.push_back(hDiffBCCount.GetMean()); + rmsDeltaBCAO2D.push_back(hDiffBCAO2DCount.GetRMS()); + rmsDeltaBCEvSel.push_back(hDiffBCEvSelCount.GetRMS()); + rmsDeltaBC.push_back(hDiffBCCount.GetRMS()); + avgNumPairedTrigger.push_back(hNumPairedTriggerCount.GetMean()); + rmsNumPairedTrigger.push_back(hNumPairedTriggerCount.GetRMS()); } - originalFile.Close(); - skimmedFile.Close(); - - TH1D hOriginalTotal("hOriginalTotal", (runNumber + " AO2D Original;;Number of events").data(), sel_labels.size(), 0, sel_labels.size()); - TH1D hOriginalSingles("hOriginalSingles", (runNumber + " Original;;Number of Singles").data(), sel_labels.size(), 0, sel_labels.size()); - TH1D hOriginalSinglesRatio("hOriginalSinglesRatio", (runNumber + " Original;;Singles / Total").data(), sel_labels.size(), 0, sel_labels.size()); - TH1D hOriginalDoubles("hOriginalDoubles", (runNumber + " Original;;Number of Doubles").data(), sel_labels.size(), 0, sel_labels.size()); - TH1D hOriginalDoublesRatio("hOriginalDoublesRatio", (runNumber + " Original;;Doubles / Total").data(), sel_labels.size(), 0, sel_labels.size()); - TH1D hOriginalMultiples("hOriginalMultiples", (runNumber + " Original;;Number of Multiples").data(), sel_labels.size(), 0, sel_labels.size()); - TH1D hOriginalMultiplesRatio("hOriginalMultiplesRatio", (runNumber + " Original;;Multiples / Total").data(), sel_labels.size(), 0, sel_labels.size()); - - TH1D hSkimmedTotal("hSkimmedTotal", (runNumber + " AO2D Skimmed;;Number of events").data(), sel_labels.size(), 0, sel_labels.size()); - TH1D hSkimmedSingles("hSkimmedSingles", (runNumber + " Skimmed;;Number of Singles").data(), sel_labels.size(), 0, sel_labels.size()); - TH1D hSkimmedSinglesRatio("hSkimmedSinglesRatio", (runNumber + " Skimmed;;Singles / Total").data(), sel_labels.size(), 0, sel_labels.size()); - TH1D hSkimmedDoubles("hSkimmedDoubles", (runNumber + " Skimmed;;Number of Doubles").data(), sel_labels.size(), 0, sel_labels.size()); - TH1D hSkimmedDoublesRatio("hSkimmedDoublesRatio", (runNumber + " Skimmed;;Doubles / Total").data(), sel_labels.size(), 0, sel_labels.size()); - TH1D hSkimmedMultiples("hSkimmedMultiples", (runNumber + " Skimmed;;Number of Multiples").data(), sel_labels.size(), 0, sel_labels.size()); - TH1D hSkimmedMultiplesRatio("hSkimmedMultiplesRatio", (runNumber + " Skimmed;;Multiples / Total").data(), sel_labels.size(), 0, sel_labels.size()); - - TH1D hPairedBCAO2DRatio("hPairedBCAO2DRatio", (runNumber + " One-to-One Pairs;; Pairs with same BCAO2D / Total").data(), sel_labels.size(), 0, sel_labels.size()); - TH1D hPairedBCEvSelRatio("hPairedBCEvSelRatio", (runNumber + " One-to-One Pairs;; Pairs with same BCEvSel / Total").data(), sel_labels.size(), 0, sel_labels.size()); - TH1D hMaxDiffBCAO2D("hMaxDiffBCAO2D", (runNumber + " One-to-One Pairs;;|#DeltaBCAO2D|_{max}").data(), sel_labels.size(), 0, sel_labels.size()); - TH1D hMaxDiffBCEvSel("hMaxDiffBCEvSel", (runNumber + " One-to-One Pairs;;|#DeltaBCEvSel|_{max}").data(), sel_labels.size(), 0, sel_labels.size()); + originalFile->Close(); + skimmedFile->Close(); + + TH1D hOriginalTotal("hOriginalTotal", (runNumber + " Original;;Number of events").data(), sel_labels.size(), 0, sel_labels.size()); + TH1D hOriginalSingles("hOriginalSingles", (runNumber + " Original;;Number of singles").data(), sel_labels.size(), 0, sel_labels.size()); + TH1D hOriginalDoubles("hOriginalDoubles", (runNumber + " Original;;Number of doubles").data(), sel_labels.size(), 0, sel_labels.size()); + TH1D hOriginalMultiples("hOriginalMultiples", (runNumber + " Original;;Number of multiples").data(), sel_labels.size(), 0, sel_labels.size()); + + TH1D hSkimmedTotal("hSkimmedTotal", (runNumber + " Skimmed;;Number of events").data(), sel_labels.size(), 0, sel_labels.size()); + TH1D hSkimmedSingles("hSkimmedSingles", (runNumber + " Skimmed;;Number of singles").data(), sel_labels.size(), 0, sel_labels.size()); + TH1D hSkimmedDoubles("hSkimmedDoubles", (runNumber + " Skimmed;;Number of doubles").data(), sel_labels.size(), 0, sel_labels.size()); + TH1D hSkimmedMultiples("hSkimmedMultiples", (runNumber + " Skimmed;;Number of multiples").data(), sel_labels.size(), 0, sel_labels.size()); + + TH1D hTriggerPairsRatio("hTriggerPairsRatio", (runNumber + " Skimmed Efficiency;; Matched skimmed triggers / Original singles").data(), sel_labels.size(), 0, sel_labels.size()); // the ratio of triggers in skimmed dataset whose BC is compatible with original triggers to the number of original triggers, might be duplicate since we check it based on every trigger in unskimmed data + TH1D hTriggerSinglePairsRatio("hTriggerSinglePairsRatio", (runNumber + " Skimmed Efficiency;; One-to-one pairs / Original singles").data(), sel_labels.size(), 0, sel_labels.size()); // the ratio of 1-1 paired triggers to the number of original triggers + TH1D hPairsSameBCAO2DRatio("hPairsSameBCAO2DRatio", (runNumber + " One-to-one pairs;; Pairs with same BC_{AO2D} / Total").data(), sel_labels.size(), 0, sel_labels.size()); // In 1-1 pairs, the ratio of pairs who have same BCAO2D + TH1D hPairsSameBCEvSelRatio("hPairsSameBCEvSelRatio", (runNumber + " One-to-one pairs;; Pairs with same BC_{EvSel} / Total").data(), sel_labels.size(), 0, sel_labels.size()); // In 1-1 pairs, the ratio of pairs who have same BCEvSel + TH1D hDiffBCAO2D("hDiffBCAO2D", (runNumber + " One-to-one pairs;;#DeltaBC_{AO2D}").data(), sel_labels.size(), 0, sel_labels.size()); // difference in BCAO2D of 1-1 pairs + TH1D hDiffBCEvSel("hDiffBCEvSel", (runNumber + " One-to-one pairs;;#DeltaBC_{EvSel}").data(), sel_labels.size(), 0, sel_labels.size()); // difference in BCEvSel of 1-1 pairs + TH1D hDiffBC("hDiffBC", (runNumber + " One-to-one pairs;;#DeltaBC").data(), sel_labels.size(), 0, sel_labels.size()); // difference between the BC tuple, expected to be 0 if bcDiffTolerance = 0 + TH1D hNumPairsInSkimmed("hNumPairsInSkimmed", (runNumber + " number of matched triggers in skimmed data;;Matched trigger count").data(), sel_labels.size(), 0, sel_labels.size()); // number of triggers in skimmed data which are compatible in the BC ranges of singles in original selection for (int i = 0; i < sel_labels.size(); i++) { + // Original data hOriginalTotal.GetXaxis()->SetBinLabel(i + 1, sel_labels[i].c_str()); hOriginalSingles.GetXaxis()->SetBinLabel(i + 1, sel_labels[i].c_str()); + hOriginalDoubles.GetXaxis()->SetBinLabel(i + 1, sel_labels[i].c_str()); hOriginalMultiples.GetXaxis()->SetBinLabel(i + 1, sel_labels[i].c_str()); - hOriginalSinglesRatio.GetXaxis()->SetBinLabel(i + 1, sel_labels[i].c_str()); - hOriginalDoublesRatio.GetXaxis()->SetBinLabel(i + 1, sel_labels[i].c_str()); - hOriginalMultiplesRatio.GetXaxis()->SetBinLabel(i + 1, sel_labels[i].c_str()); hOriginalTotal.SetBinContent(i + 1, numOriginal[i]); + hOriginalTotal.SetBinError(i + 1, std::sqrt(numOriginal[i])); hOriginalSingles.SetBinContent(i + 1, numOriginalSingle[i]); + hOriginalSingles.SetBinError(i + 1, std::sqrt(numOriginalSingle[i])); hOriginalDoubles.SetBinContent(i + 1, numOriginalDouble[i]); + hOriginalDoubles.SetBinError(i + 1, std::sqrt(numOriginalDouble[i])); hOriginalMultiples.SetBinContent(i + 1, numOriginalMultiple[i]); - if (numOriginal[i] > 0) { - hOriginalSinglesRatio.SetBinContent(i + 1, static_cast(numOriginalSingle[i]) / numOriginal[i]); - hOriginalDoublesRatio.SetBinContent(i + 1, static_cast(numOriginalSingle[i]) / numOriginal[i]); - hOriginalMultiplesRatio.SetBinContent(i + 1, static_cast(numOriginalMultiple[i]) / numOriginal[i]); - } else { - hOriginalSinglesRatio.SetBinContent(i + 1, 0); - hOriginalDoublesRatio.SetBinContent(i + 1, 0); - hOriginalMultiplesRatio.SetBinContent(i + 1, 0); - } + hOriginalMultiples.SetBinError(i + 1, std::sqrt(numOriginalMultiple[i])); + // Skimmed data hSkimmedTotal.GetXaxis()->SetBinLabel(i + 1, sel_labels[i].c_str()); hSkimmedSingles.GetXaxis()->SetBinLabel(i + 1, sel_labels[i].c_str()); + hSkimmedDoubles.GetXaxis()->SetBinLabel(i + 1, sel_labels[i].c_str()); hSkimmedMultiples.GetXaxis()->SetBinLabel(i + 1, sel_labels[i].c_str()); - hSkimmedSinglesRatio.GetXaxis()->SetBinLabel(i + 1, sel_labels[i].c_str()); - hSkimmedDoublesRatio.GetXaxis()->SetBinLabel(i + 1, sel_labels[i].c_str()); - hSkimmedMultiplesRatio.GetXaxis()->SetBinLabel(i + 1, sel_labels[i].c_str()); hSkimmedTotal.SetBinContent(i + 1, numSkimmed[i]); + hSkimmedTotal.SetBinError(i + 1, std::sqrt(numSkimmed[i])); hSkimmedSingles.SetBinContent(i + 1, numSkimmedSingle[i]); + hSkimmedSingles.SetBinError(i + 1, std::sqrt(numSkimmedSingle[i])); hSkimmedDoubles.SetBinContent(i + 1, numSkimmedDouble[i]); + hSkimmedDoubles.SetBinError(i + 1, std::sqrt(numSkimmedDouble[i])); hSkimmedMultiples.SetBinContent(i + 1, numSkimmedMultiple[i]); - if (numSkimmed[i] > 0) { - hSkimmedSinglesRatio.SetBinContent(i + 1, static_cast(numSkimmedSingle[i]) / numSkimmed[i]); - hSkimmedDoublesRatio.SetBinContent(i + 1, static_cast(numSkimmedDouble[i]) / numSkimmed[i]); - hSkimmedMultiplesRatio.SetBinContent(i + 1, static_cast(numSkimmedMultiple[i]) / numSkimmed[i]); - } else { - hSkimmedSinglesRatio.SetBinContent(i + 1, 0); - hSkimmedDoublesRatio.SetBinContent(i + 1, 0); - hSkimmedMultiplesRatio.SetBinContent(i + 1, 0); - } + hSkimmedMultiples.SetBinError(i + 1, std::sqrt(numSkimmedMultiple[i])); + + // Pairs QA + hTriggerPairsRatio.GetXaxis()->SetBinLabel(i + 1, sel_labels[i].c_str()); + hTriggerSinglePairsRatio.GetXaxis()->SetBinLabel(i + 1, sel_labels[i].c_str()); + hPairsSameBCAO2DRatio.GetXaxis()->SetBinLabel(i + 1, sel_labels[i].c_str()); + hPairsSameBCEvSelRatio.GetXaxis()->SetBinLabel(i + 1, sel_labels[i].c_str()); + hDiffBCAO2D.GetXaxis()->SetBinLabel(i + 1, sel_labels[i].c_str()); + hDiffBCEvSel.GetXaxis()->SetBinLabel(i + 1, sel_labels[i].c_str()); + hDiffBC.GetXaxis()->SetBinLabel(i + 1, sel_labels[i].c_str()); + hNumPairsInSkimmed.GetXaxis()->SetBinLabel(i + 1, sel_labels[i].c_str()); - hPairedBCAO2DRatio.GetXaxis()->SetBinLabel(i + 1, sel_labels[i].c_str()); - hPairedBCEvSelRatio.GetXaxis()->SetBinLabel(i + 1, sel_labels[i].c_str()); if (numpair[i] > 0) { - hPairedBCAO2DRatio.SetBinContent(i + 1, static_cast(numpairedBCAO2D[i]) / numpair[i]); - hPairedBCEvSelRatio.SetBinContent(i + 1, static_cast(numpairedBCEvSel[i]) / numpair[i]); + hPairsSameBCAO2DRatio.SetBinContent(i + 1, static_cast(numpairedBCAO2D[i]) / numpair[i]); + hPairsSameBCEvSelRatio.SetBinContent(i + 1, static_cast(numpairedBCEvSel[i]) / numpair[i]); } - - hMaxDiffBCAO2D.GetXaxis()->SetBinLabel(i + 1, sel_labels[i].c_str()); - hMaxDiffBCEvSel.GetXaxis()->SetBinLabel(i + 1, sel_labels[i].c_str()); - hMaxDiffBCAO2D.SetBinContent(i + 1, maxDeltaBCAO2D[i]); - hMaxDiffBCEvSel.SetBinContent(i + 1, maxDeltaBCEvSel[i]); + hTriggerPairsRatio.SetBinContent(i + 1, numCloseSkimmed[i]); + hTriggerPairsRatio.SetBinError(i + 1, std::sqrt(numCloseSkimmed[i])); + hTriggerSinglePairsRatio.SetBinContent(i + 1, numpair[i]); + hTriggerSinglePairsRatio.SetBinError(i + 1, std::sqrt(numpair[i])); + hDiffBCAO2D.SetBinContent(i + 1, avgDeltaBCAO2D[i]); + hDiffBCAO2D.SetBinError(i + 1, rmsDeltaBCAO2D[i]); + hDiffBCEvSel.SetBinContent(i + 1, avgDeltaBCEvSel[i]); + hDiffBCEvSel.SetBinError(i + 1, rmsDeltaBCEvSel[i]); + hDiffBC.SetBinContent(i + 1, avgDeltaBC[i]); + hDiffBC.SetBinError(i + 1, rmsDeltaBC[i]); + hNumPairsInSkimmed.SetBinContent(i + 1, avgNumPairedTrigger[i]); + hNumPairsInSkimmed.SetBinError(i + 1, rmsNumPairedTrigger[i]); } + TH1D* hTriggerEff; // Ratio of the total number of triggers in skimmed data to that in original data + TH1D *hOriginalSinglesRatio, *hOriginalDoublesRatio, *hOriginalMultiplesRatio; + TH1D *hSkimmedSinglesRatio, *hSkimmedDoublesRatio, *hSkimmedMultiplesRatio; + + hTriggerEff = (TH1D*)hSkimmedTotal.Clone("hTriggerEff"); + hTriggerEff->SetTitle((runNumber + " skimmed efficiency;; Skimmed / Original").data()); + hTriggerEff->Divide(&hOriginalTotal); + hTriggerPairsRatio.Divide(&hOriginalSingles); + hTriggerSinglePairsRatio.Divide(&hOriginalSingles); + hOriginalSinglesRatio = (TH1D*)hOriginalSingles.Clone("hOriginalSinglesRatio"); + hOriginalSinglesRatio->SetTitle((runNumber + " Original;;Singles / Total").data()); + hOriginalSinglesRatio->Divide(&hOriginalTotal); + hOriginalDoublesRatio = (TH1D*)hOriginalDoubles.Clone("hOriginalDoublesRatio"); + hOriginalDoublesRatio->SetTitle((runNumber + " Original;;Doubles / Total").data()); + hOriginalDoublesRatio->Divide(&hOriginalTotal); + hOriginalMultiplesRatio = (TH1D*)hOriginalMultiples.Clone("hOriginalMultiplesRatio"); + hOriginalMultiplesRatio->SetTitle((runNumber + " Original;;Multiples / Total").data()); + hOriginalMultiplesRatio->Divide(&hOriginalTotal); + + hSkimmedSinglesRatio = (TH1D*)hSkimmedSingles.Clone("hSkimmedSinglesRatio"); + hSkimmedSinglesRatio->SetTitle((runNumber + " Skimmed;;Singles / Total").data()); + hSkimmedSinglesRatio->Divide(&hSkimmedTotal); + hSkimmedDoublesRatio = (TH1D*)hSkimmedDoubles.Clone("hSkimmedDoublesRatio"); + hSkimmedDoublesRatio->SetTitle((runNumber + " Skimmed;;Doubles / Total").data()); + hSkimmedDoublesRatio->Divide(&hSkimmedTotal); + hSkimmedMultiplesRatio = (TH1D*)hSkimmedMultiples.Clone("hSkimmedMultiplesRatio"); + hSkimmedMultiplesRatio->SetTitle((runNumber + " Skimmed;;Multiples / Total").data()); + hSkimmedMultiplesRatio->Divide(&hSkimmedTotal); + TFile fout(outputFileName, "UPDATE"); fout.cd(); + TDirectory* dir = fout.mkdir(runNumber.data()); + dir->cd(); + hTriggerEff->Write(); + hTriggerPairsRatio.Write(); + hTriggerSinglePairsRatio.Write(); + hDiffBCAO2D.Write(); + hDiffBCEvSel.Write(); + hNumPairsInSkimmed.Write(); + if (bcDiffTolerance > 0) { + hDiffBC.Write(); + } + TDirectory* dirextra = dir->mkdir("ExtraQA"); + dirextra->cd(); hOriginalTotal.Write(); hOriginalSingles.Write(); hOriginalDoubles.Write(); hOriginalMultiples.Write(); - hOriginalSinglesRatio.Write(); - hOriginalDoublesRatio.Write(); - hOriginalMultiplesRatio.Write(); + hOriginalSinglesRatio->Write(); + hOriginalDoublesRatio->Write(); + hOriginalMultiplesRatio->Write(); hSkimmedTotal.Write(); hSkimmedSingles.Write(); hSkimmedDoubles.Write(); hSkimmedMultiples.Write(); - hSkimmedSinglesRatio.Write(); - hSkimmedDoublesRatio.Write(); - hSkimmedMultiplesRatio.Write(); - hPairedNumCounterTotal.Write(); - hBCDiffAO2DTotal.Write(); - hBCDiffEvSelTotal.Write(); - hPairedBCAO2DRatio.Write(); - hPairedBCEvSelRatio.Write(); - hMaxDiffBCAO2D.Write(); - hMaxDiffBCEvSel.Write(); + hSkimmedSinglesRatio->Write(); + hSkimmedDoublesRatio->Write(); + hSkimmedMultiplesRatio->Write(); + hPairsSameBCAO2DRatio.Write(); + hPairsSameBCEvSelRatio.Write(); fout.Close(); -} - -// Detailed checks for specific trigger -void checkBCrangesSkimming(std::string originalFileName = "bcRanges_fullrun.root", std::string skimmedFileName = "bcRanges_fullrun_skimmed.root") -{ - //---------------------------------For specific trigger---------------------------------- - TH1D hTriggerCounter("hTriggerCounter", "hTriggerCounter", 3, 0.5, 3.5); - hTriggerCounter.GetXaxis()->SetBinLabel(1, "Original"); - hTriggerCounter.GetXaxis()->SetBinLabel(2, "Skimmed"); - TH1D hNumCounter("hNumCounter", "hNumCounter", 10, -0.5, 9.5); - TH1D hSinglePairCheck("hSinglePairCheck", "hSinglePairCheck", 4, 0.5, 4.5); - hSinglePairCheck.GetXaxis()->SetBinLabel(1, "Total"); - hSinglePairCheck.GetXaxis()->SetBinLabel(2, "Same AO2D BC"); - hSinglePairCheck.GetXaxis()->SetBinLabel(3, "Same EvSel BC"); - hSinglePairCheck.GetXaxis()->SetBinLabel(4, "Same Both BC"); - TH1D hMultiPairCheck("hMultiPairCheck", "hMultiPairCheck", 5, 0.5, 5.5); - hMultiPairCheck.GetXaxis()->SetBinLabel(1, "Total"); - hMultiPairCheck.GetXaxis()->SetBinLabel(2, "Total Pair"); - hMultiPairCheck.GetXaxis()->SetBinLabel(3, "Same AO2D BC"); - hMultiPairCheck.GetXaxis()->SetBinLabel(4, "Same EvSel BC"); - hMultiPairCheck.GetXaxis()->SetBinLabel(5, "Same Both BC"); - TH1D hBCDiffAO2D("hBCDiffAO2D", "hBCDiffAO2D", 2001, -1000.5, 1000.5); - TH1D hBCDiffEvSel("hBCDiffEvSel", "hBCDiffEvSel", 2001, -1000.5, 1000.5); - - TH1D hBCOriginal("hBCOriginal", "hBCOriginal", 4, 0.5, 4.5); - hBCOriginal.GetXaxis()->SetBinLabel(1, "Total"); - hBCOriginal.GetXaxis()->SetBinLabel(2, "Same AO2D BC"); - hBCOriginal.GetXaxis()->SetBinLabel(3, "Same EvSel BC"); - hBCOriginal.GetXaxis()->SetBinLabel(4, "Same Both BC"); - TH1D hBCSkimmed("hBCSkimmed", "hBCSkimmed", 4, 0.5, 4.5); - hBCSkimmed.GetXaxis()->SetBinLabel(1, "Total"); - hBCSkimmed.GetXaxis()->SetBinLabel(2, "Same AO2D BC"); - hBCSkimmed.GetXaxis()->SetBinLabel(3, "Same EvSel BC"); - hBCSkimmed.GetXaxis()->SetBinLabel(4, "Same Both BC"); - - auto t1 = std::chrono::steady_clock::now(); - TFile originalFile(originalFileName.c_str(), "READ"); - TFile skimmedFile(skimmedFileName.c_str(), "READ"); - auto originalFrames = getSelectedFrames(originalFile, Trigger0BIT, Trigger1BIT); - auto skimmedFrames = getSelectedFrames(skimmedFile, Trigger0BIT, Trigger1BIT); - originalFile.Close(); - skimmedFile.Close(); - auto t2 = std::chrono::steady_clock::now(); - int d1 = std::chrono::duration_cast(t2 - t1).count(); - std::cout << "Readin Time: " << d1 << std::endl; - - auto t3 = std::chrono::steady_clock::now(); - checkNearbyBCs(originalFrames, bcDiffTolerance); - checkNearbyBCs(skimmedFrames, bcDiffTolerance); - auto t4 = std::chrono::steady_clock::now(); - int d2 = std::chrono::duration_cast(t4 - t3).count(); - std::cout << "Sort Time: " << d2 << std::endl; - auto t5 = std::chrono::steady_clock::now(); - std::vector bcSet; - for (auto frame : originalFrames) { - if (frame.selMask[0] & Trigger0BIT || frame.selMask[1] & Trigger1BIT) { - hTriggerCounter.Fill(1); - hBCOriginal.Fill(1); - auto p1 = std::find_if(bcSet.begin(), bcSet.end(), [&](const auto& val) { return val.bcAO2D == frame.bcAO2D; }); - if (p1 != bcSet.end()) { - hBCOriginal.Fill(2); - } - auto p2 = std::find_if(bcSet.begin(), bcSet.end(), [&](const auto& val) { return val.bcEvSel == frame.bcEvSel; }); - if (p2 != bcSet.end()) { - hBCOriginal.Fill(3); - } - bcTuple currentBC(frame.bcAO2D, frame.bcEvSel); - auto p3 = std::find(bcSet.begin(), bcSet.end(), currentBC); - if (p3 == bcSet.end()) { - bcSet.push_back(currentBC); - } else { - hBCOriginal.Fill(4); - } - // std::cout << "------------------------------------------------" << std::endl; - if (frame.GetNum() != 1) { - continue; // Only check singles - } - std::vector skimmedbcs; - int n = 0; - for (auto& skimmedFrame : skimmedFrames) { - if (skimmedFrame.getMin() > frame.getMax()) { - break; - } - if (skimmedFrame.GetNum() != 1) { - continue; // Only check singles - } - if (isClose(frame, skimmedFrame, bcDiffTolerance)) { - bool found = frame.selMask[0] & skimmedFrame.selMask[0] || frame.selMask[1] & skimmedFrame.selMask[1]; - // found = found && (frame.bcAO2D == skimmedFrame.bcAO2D || frame.bcEvSel == skimmedFrame.bcEvSel); - if (found) { - skimmedbcs.push_back({skimmedFrame.bcAO2D, skimmedFrame.bcEvSel}); - n++; - } - } - } - if (n == 0) { - // std::cout << "Trigger not found!!!" << std::endl; - } else if (n == 1) { - hSinglePairCheck.Fill(1); - hBCDiffAO2D.Fill(DoBCSubraction(frame.bcAO2D, skimmedbcs[0].bcAO2D)); - hBCDiffEvSel.Fill(DoBCSubraction(frame.bcEvSel, skimmedbcs[0].bcEvSel)); - if (frame.bcAO2D == skimmedbcs[0].bcAO2D) { - hSinglePairCheck.Fill(2); - } - if (frame.bcEvSel == skimmedbcs[0].bcEvSel) { - hSinglePairCheck.Fill(3); - if (frame.bcAO2D == skimmedbcs[0].bcAO2D) { - hSinglePairCheck.Fill(4); - } - } - } else { - // std::cout << "Unexpected trigger!!! n=" << n << std::endl; - hMultiPairCheck.Fill(1); - for (auto skimmedbc : skimmedbcs) { - hMultiPairCheck.Fill(2); - if (frame.bcAO2D == skimmedbc.bcAO2D) { - hMultiPairCheck.Fill(3); - } - if (frame.bcEvSel == skimmedbc.bcEvSel) { - hMultiPairCheck.Fill(4); - if (frame.bcAO2D == skimmedbc.bcAO2D) { - hMultiPairCheck.Fill(5); - } - } - } - } - hNumCounter.Fill(n); - } - } - auto t6 = std::chrono::steady_clock::now(); - int d3 = std::chrono::duration_cast(t6 - t5).count(); - std::cout << "Search Time: " << d3 << std::endl; - - bcSet.clear(); - for (auto& skimmedFrame : skimmedFrames) { - if (skimmedFrame.selMask[0] & Trigger0BIT || skimmedFrame.selMask[1] & Trigger1BIT) { - hTriggerCounter.Fill(2); - hBCSkimmed.Fill(1); - auto p1 = std::find_if(bcSet.begin(), bcSet.end(), [&](const auto& val) { return val.bcAO2D == skimmedFrame.bcAO2D; }); - if (p1 != bcSet.end()) { - hBCSkimmed.Fill(2); - } - auto p2 = std::find_if(bcSet.begin(), bcSet.end(), [&](const auto& val) { return val.bcEvSel == skimmedFrame.bcEvSel; }); - if (p2 != bcSet.end()) { - hBCSkimmed.Fill(3); - } - bcTuple currentBC(skimmedFrame.bcAO2D, skimmedFrame.bcEvSel); - auto p3 = std::find(bcSet.begin(), bcSet.end(), currentBC); - if (p3 == bcSet.end()) { - bcSet.push_back(currentBC); - } else { - hBCSkimmed.Fill(4); - } + // Do checks for trigger + for (int trgID = 0; trgID < labels.size(); trgID++) { + if (trgID == 77 || trgID == 78 || trgID == 79) { + // checkBCForSelectedTrg(originalAllFrames[trgID], skimmedAllFrames[trgID], runNumber, labels[trgID]); } } - - TFile fout(outputFileName, "RECREATE"); - fout.cd(); - hTriggerCounter.Write(); - hBCOriginal.Write(); - hBCSkimmed.Write(); - hNumCounter.Write(); - hSinglePairCheck.Write(); - hBCDiffAO2D.Write(); - hBCDiffEvSel.Write(); - hMultiPairCheck.Write(); - fout.Close(); } diff --git a/EventFiltering/macros/uploadOTSobjects.C b/EventFiltering/macros/uploadOTSobjects.C index 132f1b618da..039840d34a5 100644 --- a/EventFiltering/macros/uploadOTSobjects.C +++ b/EventFiltering/macros/uploadOTSobjects.C @@ -16,6 +16,7 @@ #include #include #include +#include #include "TFile.h" #include "TGrid.h" @@ -26,16 +27,23 @@ #include "CCDB/BasicCCDBManager.h" #include "EventFiltering/ZorroHelper.h" +#include "CommonConstants/LHCConstants.h" -void uploadOTSobjects(std::string inputList, std::string passName, bool useAlien) +constexpr uint32_t chunkSize = 1000000; + +void uploadOTSobjects(std::string inputList, std::string passName, bool useAlien, bool chunkedProcessing) { const std::string kBaseCCDBPath = "Users/m/mpuccio/EventFiltering/OTS/"; std::string baseCCDBpath = passName.empty() ? kBaseCCDBPath : kBaseCCDBPath + passName + "/"; + if (chunkedProcessing) { + baseCCDBpath += "Chunked/"; + } if (useAlien) { TGrid::Connect("alien://"); } o2::ccdb::CcdbApi api; api.init("http://alice-ccdb.cern.ch"); + auto& ccdb = o2::ccdb::BasicCCDBManager::instance(); std::ifstream file(inputList.data()); std::string path; @@ -47,9 +55,11 @@ void uploadOTSobjects(std::string inputList, std::string passName, bool useAlien const int runNumber = std::stoi(runString); metadata["runNumber"] = runString; std::pair duration = o2::ccdb::BasicCCDBManager::getRunDuration(api, runNumber); - duration.first -= 10000; // subtract 3 minutes from the run start - duration.second += 180000; // add 3 minutes to the run duration + duration.first -= 60000; // subtract 1 minutes from the run start + duration.second += 60000; // add 1 minutes to the run duration std::cout << ">>> Begin - end timestamps for the upload: " << duration.first << " - " << duration.second << std::endl; + auto ctp = ccdb.getForTimeStamp>("CTP/Calib/OrbitReset", duration.first / 2 + duration.second / 2); + auto orbitResetTimestamp = (*ctp)[0]; path = useAlien ? "alien://" + path : path; std::unique_ptr scalersFile{TFile::Open((path + "/AnalysisResults_fullrun.root").data(), "READ")}; TH1* scalers = static_cast(scalersFile->Get("central-event-filter-task/scalers/mScalers")); @@ -85,13 +95,48 @@ void uploadOTSobjects(std::string inputList, std::string passName, bool useAlien } } } - api.storeAsTFileAny(&zorroHelpers, baseCCDBpath + "ZorroHelpers", metadata, duration.first, duration.second); + std::sort(zorroHelpers.begin(), zorroHelpers.end(), [](const ZorroHelper& a, const ZorroHelper& b) { + return a.bcAOD < b.bcAOD; + }); + if (!chunkedProcessing) { + api.storeAsTFileAny(&zorroHelpers, baseCCDBpath + "ZorroHelpers", metadata, duration.first, duration.second); + std::cout << std::endl; + } else { + uint32_t helperIndex{0}; + auto startTS = duration.first; + int64_t endTS = 0; + while (helperIndex < zorroHelpers.size()) { + std::vector chunk; + uint32_t endIndex = helperIndex + chunkSize; + while (true) { + if (endIndex >= zorroHelpers.size() - 2) { + endTS = duration.second; + chunk.insert(chunk.begin(), zorroHelpers.begin() + helperIndex, zorroHelpers.end()); + break; + } + auto bcEnd{zorroHelpers[endIndex].bcAOD > zorroHelpers[endIndex].bcEvSel ? zorroHelpers[endIndex].bcAOD : zorroHelpers[endIndex].bcEvSel}; + const auto& nextHelper = zorroHelpers[endIndex + 1]; + auto bcNext{nextHelper.bcAOD < nextHelper.bcEvSel ? nextHelper.bcAOD : nextHelper.bcEvSel}; + if (bcNext - bcEnd > 2001 / o2::constants::lhc::LHCBunchSpacingMUS) { /// ensure a gap of 2ms between chunks + chunk.insert(chunk.begin(), zorroHelpers.begin() + helperIndex, zorroHelpers.begin() + endIndex + 1); + endTS = (orbitResetTimestamp + int64_t(bcEnd * o2::constants::lhc::LHCBunchSpacingNS * 1e-3)) / 1000 + 1; + break; + } + bcEnd = nextHelper.bcAOD > nextHelper.bcEvSel ? nextHelper.bcAOD : nextHelper.bcEvSel; + endIndex++; + } + std::cout << ">>> Chunk " << helperIndex << " - " << helperIndex + chunk.size() << " : " << startTS << " - " << endTS << " \t" << (endTS - startTS) * 1.e-3 << std::endl; + api.storeAsTFileAny(&zorroHelpers, baseCCDBpath + "ZorroHelpers", metadata, startTS, endTS); + startTS = endTS + 1; + helperIndex += chunk.size(); + } + } } } -void uploadOTSobjects(std::string periodName) +void uploadOTSobjects(std::string periodName, bool chunkedProcessing) { int year = 2000 + std::stoi(periodName.substr(3, 2)); gSystem->Exec(Form("alien_find /alice/data/%i/%s/ ctf_skim_full/AnalysisResults_fullrun.root | sed 's:/AnalysisResults_fullrun\\.root::' > list_%s.txt", year, periodName.data(), periodName.data())); - uploadOTSobjects(Form("list_%s.txt", periodName.data()), "", true); + uploadOTSobjects(Form("list_%s.txt", periodName.data()), "", true, chunkedProcessing); } diff --git a/PWGCF/EbyEFluctuations/Tasks/FactorialMomentsTask.cxx b/PWGCF/EbyEFluctuations/Tasks/FactorialMomentsTask.cxx index f235859360a..c76556ec26f 100644 --- a/PWGCF/EbyEFluctuations/Tasks/FactorialMomentsTask.cxx +++ b/PWGCF/EbyEFluctuations/Tasks/FactorialMomentsTask.cxx @@ -16,6 +16,7 @@ #include #include #include +#include "TRandom.h" // O2 includes #include "Framework/AnalysisDataModel.h" #include "Framework/AnalysisTask.h" @@ -33,11 +34,11 @@ using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; struct FactorialMoments { - Configurable confEta{"centralEta", 0.8, "eta limit for tracks"}; + Configurable confEta{"centralEta", 0.9, "eta limit for tracks"}; Configurable confNumPt{"numPt", 1, "number of pT bins"}; Configurable confPtMin{"ptMin", 0.2f, "lower pT cut"}; Configurable confDCAxy{"dcaXY", 2.4f, "DCA xy cut"}; - Configurable confDCAz{"dcaZ", 3.2f, "DCA z cut"}; + Configurable confDCAz{"dcaZ", 2.0f, "DCA z cut"}; Configurable confMinTPCCls{"minTPCCls", 70.0f, "minimum number of TPC clusters"}; Configurable> confCentCut{"centLimits", {0, 5}, "centrality min and max"}; Configurable> confVertex{"vertexXYZ", {0.3f, 0.4f, 10.0f}, "vertex cuts"}; @@ -77,9 +78,11 @@ struct FactorialMoments { {"mChi2TPC", "chi2 TPC", {HistType::kTH1F, {{100, 0, 10}}}}, {"mChi2ITS", "chi2 ITS", {HistType::kTH1F, {{100, 0, 10}}}}, {"mChi2TRD", "chi2 TRD", {HistType::kTH1F, {{100, 0, 100}}}}, - {"mDCAxy", "DCA xy", {HistType::kTH1F, {{100, -0.8, 0.8}}}}, - {"mDCAx", "DCA z", {HistType::kTH1F, {{100, -2.0, 2.0}}}}, - {"mDCAxyPt", "DCA xy vs #pt;#pt;DCAxy", {HistType::kTH2F, {{100, 0, 20}, {100, -0.5, 0.5}}}}, + {"mDCAxy", "DCA xy", {HistType::kTH1F, {{500, -0.8, 0.8}}}}, + {"mDCAx", "DCA z", {HistType::kTH1F, {{500, -2.0, 2.0}}}}, + {"mDCAxyPt", "DCA xy vs #pt;#pt;DCAxy", {HistType::kTH2F, {{100, 0, 20}, {500, -0.5, 0.5}}}}, + {"mDCAxyPtbcut", "DCA xy vs #pt;#pt;DCAxycut", {HistType::kTH2F, {{100, 0, 20}, {500, -0.5, 0.5}}}}, + {"mDCAzPtbcut", "DCA z vs #pt;#pt;DCAzcut", {HistType::kTH2F, {{100, 0, 20}, {100, -2.0, 2.0}}}}, {"mDCAzPt", "DCA z vs #pt;#pt;DCAz", {HistType::kTH2F, {{100, 0, 20}, {100, -2.0, 2.0}}}}, {"mNSharedClsTPC", "shared clusters in TPC", {HistType::kTH1F, {{100, 0, 10}}}}, {"mCrossedRowsTPC", "crossedrows in TPC", {HistType::kTH1F, {{100, 0, 200}}}}, @@ -137,9 +140,16 @@ struct FactorialMoments { { for (auto iPt = 0; iPt < confNumPt; ++iPt) { if (track.pt() > confPtBins.value[2 * iPt] && track.pt() < confPtBins.value[2 * iPt + 1]) { + float iphi = track.phi(); + iphi = gRandom->Gaus(iphi, TMath::TwoPi()); + if (iphi < 0) { + iphi += TMath::TwoPi(); + } else if (iphi > TMath::TwoPi()) { + iphi -= TMath::TwoPi(); + } mHistArrQA[iPt * 4]->Fill(track.eta()); mHistArrQA[iPt * 4 + 1]->Fill(track.pt()); - mHistArrQA[iPt * 4 + 2]->Fill(track.phi()); + mHistArrQA[iPt * 4 + 2]->Fill(iphi); countTracks[iPt]++; for (auto iM = 0; iM < nBins; ++iM) { mHistArrReset[iPt * nBins + iM]->Fill(track.eta(), track.phi()); @@ -182,8 +192,9 @@ struct FactorialMoments { mBinConFinal[iPt * 6 + iOrder]->Fill(iM, binConEvent[iPt][iM]); } } // end of loop over M bins - } // end of loop over pT bins + } // end of loop over pT bins } + using TracksFMs = soa::Filtered>; void processRun3(soa::Filtered>::iterator const& coll, TracksFMs const& tracks) { @@ -217,41 +228,32 @@ struct FactorialMoments { fqEvent = {{{{{0, 0, 0, 0, 0, 0}}}}}; binConEvent = {{{0, 0, 0, 0, 0}}}; for (auto const& track : tracks) { - if (includeGlobalTracks && (!track.isGlobalTrack())) { - continue; - } - if (includeTPCTracks && (!track.hasTPC())) { - continue; - } - if (includeITSTracks && (!track.hasITS())) { - continue; + if (track.hasTPC()) { + histos.fill(HIST("mCollID"), track.collisionId()); + histos.fill(HIST("mEta"), track.eta()); + histos.fill(HIST("mPt"), track.pt()); + histos.fill(HIST("mPhi"), track.phi()); + histos.fill(HIST("mNFindableClsTPC"), track.tpcNClsFindable()); + histos.fill(HIST("mNClsTPC"), track.tpcNClsFound()); + histos.fill(HIST("mNClsITS"), track.itsNCls()); + histos.fill(HIST("mChi2TPC"), track.tpcChi2NCl()); + histos.fill(HIST("mChi2ITS"), track.itsChi2NCl()); + histos.fill(HIST("mChi2TRD"), track.trdChi2()); + histos.fill(HIST("mDCAxy"), track.dcaXY()); + histos.fill(HIST("mDCAx"), track.dcaZ()); + histos.fill(HIST("mDCAxyPt"), track.pt(), track.dcaXY()); + histos.fill(HIST("mDCAzPt"), track.pt(), track.dcaZ()); + histos.fill(HIST("mNSharedClsTPC"), track.tpcNClsShared()); + histos.fill(HIST("mCrossedRowsTPC"), track.tpcNClsCrossedRows()); + histos.fill(HIST("mNFinClsminusCRows"), track.tpcNClsFindableMinusCrossedRows()); + histos.fill(HIST("mNFractionShClsTPC"), track.tpcFractionSharedCls()); + histos.fill(HIST("mSharedClsvsPt"), track.pt(), track.tpcNClsShared()); + histos.fill(HIST("mSharedClsProbvsPt"), track.pt(), track.tpcFractionSharedCls() / track.tpcNClsCrossedRows()); + checkpT(track); } - if ((track.pt() < confPtMin) || (track.tpcNClsFindable() < confMinTPCCls)) { - continue; - } - histos.fill(HIST("mCollID"), track.collisionId()); - histos.fill(HIST("mEta"), track.eta()); - histos.fill(HIST("mPt"), track.pt()); - histos.fill(HIST("mPhi"), track.phi()); - histos.fill(HIST("mNFindableClsTPC"), track.tpcNClsFindable()); - histos.fill(HIST("mNClsTPC"), track.tpcNClsFound()); - histos.fill(HIST("mNClsITS"), track.itsNCls()); - histos.fill(HIST("mChi2TPC"), track.tpcChi2NCl()); - histos.fill(HIST("mChi2ITS"), track.itsChi2NCl()); - histos.fill(HIST("mChi2TRD"), track.trdChi2()); - histos.fill(HIST("mDCAxy"), track.dcaXY()); - histos.fill(HIST("mDCAx"), track.dcaZ()); - histos.fill(HIST("mDCAxyPt"), track.pt(), track.dcaXY()); - histos.fill(HIST("mDCAzPt"), track.pt(), track.dcaZ()); - histos.fill(HIST("mNSharedClsTPC"), track.tpcNClsShared()); - histos.fill(HIST("mCrossedRowsTPC"), track.tpcNClsCrossedRows()); - histos.fill(HIST("mNFinClsminusCRows"), track.tpcNClsFindableMinusCrossedRows()); - histos.fill(HIST("mNFractionShClsTPC"), track.tpcFractionSharedCls()); - histos.fill(HIST("mSharedClsvsPt"), track.pt(), track.tpcNClsShared()); - histos.fill(HIST("mSharedClsProbvsPt"), track.pt(), track.tpcFractionSharedCls() / track.tpcNClsCrossedRows()); - checkpT(track); } for (auto iPt = 0; iPt < confNumPt; ++iPt) { + // if (countTracks[iPt] > 0) if (countTracks[iPt] > 0) { mHistArrQA[iPt * 4 + 3]->Fill(countTracks[iPt]); } diff --git a/PWGCF/EbyEFluctuations/Tasks/MeanPtFlucIdentified.cxx b/PWGCF/EbyEFluctuations/Tasks/MeanPtFlucIdentified.cxx index b61c8de928d..5d0ed29cc60 100644 --- a/PWGCF/EbyEFluctuations/Tasks/MeanPtFlucIdentified.cxx +++ b/PWGCF/EbyEFluctuations/Tasks/MeanPtFlucIdentified.cxx @@ -29,33 +29,30 @@ #include "Common/DataModel/PIDResponse.h" #include "Common/DataModel/Multiplicity.h" #include "Common/DataModel/Centrality.h" +#include "Common/Core/RecoDecay.h" -#include "TDatabasePDG.h" -#include "TLorentzVector.h" +#include using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; +using namespace o2::constants::physics; using namespace std; -double massPi = TDatabasePDG::Instance()->GetParticle(211)->Mass(); -double massKa = TDatabasePDG::Instance()->GetParticle(321)->Mass(); -double massPr = TDatabasePDG::Instance()->GetParticle(2212)->Mass(); - struct meanPtFlucId { Configurable nPtBins{"nPtBins", 300, ""}; Configurable nPartBins{"nPartBins", 250, ""}; Configurable nCentBins{"nCentBins", 101, ""}; Configurable nEtaBins{"nEtaBins", 100, ""}; - Configurable nTpNBins{"nTpNBins", 200, ""}; - Configurable nTpDBins{"nTpDBins", 100, ""}; - Configurable cfgCutPtMax{"cfgCutPtMax", 2.0, "maximum pT"}; + Configurable nPhiBins{"nPhiBins", 100, ""}; + Configurable cfgCutPtMax{"cfgCutPtMax", 3.0, "maximum pT"}; Configurable cfgCutPtMin{"cfgCutPtMin", 0.15, "minimum pT"}; Configurable cfgCutEta{"cfgCutEta", 0.8, "Eta cut"}; Configurable cfgCutRap{"cfgCutRap", 0.5, "Rapidity Cut"}; Configurable cfgCutDcaXY{"cfgCutDcaXY", 0.12, "DCAxy cut"}; Configurable cfgCutDcaZ{"cfgCutDcaZ", 0.3, "DCAz cut"}; Configurable cfgCutPosZ{"cfgCutPosZ", 10.0, "cut for vertex Z"}; + Configurable cfgGammaCut{"cfgGammaCut", 0.003, "Gamma inv Mass Cut for electron-positron rejection"}; Configurable cfgCutNSigTpcEl{"cfgCutNSigTpcEl", 1.5, "TPC nSigma Electron veto cut"}; Configurable cfgCutNSigTofEl{"cfgCutNSigTofEl", 1.5, "TOF nSigma Electron veto cut"}; Configurable cfgCutNSig2{"cfgCutNSig2", 2.0, "nSigma cut (2)"}; @@ -63,25 +60,41 @@ struct meanPtFlucId { 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 cfgCutPiP1{"cfgCutPiP1", 0.65, "pion p cut-1"}; - Configurable cfgCutPiP2{"cfgCutPiP2", 0.75, "pion p cut-2"}; - Configurable cfgCutKaP1{"cfgCutKaP1", 0.50, "kaon p cut-1"}; - Configurable cfgCutKaP2{"cfgCutKaP2", 0.60, "kaon p cut-2"}; - Configurable cfgCutKaP3{"cfgCutKaP3", 1.60, "kaon p cut-3"}; - Configurable cfgCutPrP1{"cfgCutPrP1", 0.90, "proton p cut-1"}; - Configurable cfgCutPrP2{"cfgCutPrP2", 1.00, "proton p cut-2"}; - Configurable cfgSelPi{"cfgSelPi", true, "PID selection cut for Pions"}; - Configurable cfgSelKa{"cfgSelKa", true, "PID selection cut for Kaons"}; - Configurable cfgSelPr{"cfgSelPr", true, "PID selection cut for Protons"}; - Configurable cfgSelPiInnerParam{"cfgSelPiInnerParam", false, "PID selection cut for Pions by using Momentum at inner wall of the TPC"}; - Configurable cfgSelKaInnerParam{"cfgSelKaInnerParam", false, "PID selection cut for Kaons by using Momentum at inner wall of the TPC"}; - Configurable cfgSelPrInnerParam{"cfgSelPrInnerParam", false, "PID selection cut for Protons by using Momentum at inner wall of the TPC"}; + 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 cfgMcTpcShiftEl{"cfgMcTpcShiftEl", 0., "Electron Shift in TPC (MC data) "}; + Configurable cfgMcTpcShiftPi{"cfgMcTpcShiftPi", 0., "Pion Shift in TPC (MC data) "}; + Configurable cfgMcTpcShiftKa{"cfgMcTpcShiftKa", 0., "Kaon Shift in TPC (MC data) "}; + Configurable cfgMcTpcShiftPr{"cfgMcTpcShiftPr", 0., "Proton Shift in TPC (MC data) "}; + Configurable cfgInvMass{"cfgInvMass", true, "electron Inv Mass cut selection"}; + Configurable cfgSelORPi{"cfgSelORPi", true, "Low OR High momentum for Pions"}; + Configurable cfgSelORKa{"cfgSelORKa", true, "Low OR High momentum for Kaons"}; + Configurable cfgSelORPr{"cfgSelORPr", true, "Low OR High momentum for Protons"}; + Configurable cfgSelANDPi{"cfgSelANDPi", false, "Low AND High momentum for Pions"}; + Configurable cfgSelANDKa{"cfgSelANDKa", false, "Low AND High momentum for Kaons"}; + Configurable cfgSelANDPr{"cfgSelANDPr", false, "Low AND High momentum for Protons"}; + Configurable cfgSelLowPi{"cfgSelLowPi", true, "PID selection cut for Low momentum Pions"}; + Configurable cfgSelLowKa{"cfgSelLowKa", true, "PID selection cut for Low momentum Kaons"}; + Configurable cfgSelLowPr{"cfgSelLowPr", true, "PID selection cut for Low momentum Protons"}; + Configurable cfgSelHighPi{"cfgSelHighPi", true, "PID selection cut for High momentum Pions"}; + Configurable cfgSelHighKa{"cfgSelHighKa", true, "PID selection cut for High momentum Kaons"}; + Configurable cfgSelHighPr{"cfgSelHighPr", true, "PID selection cut for High momentum Protons"}; ConfigurableAxis multTPCBins{"multTPCBins", {150, 0, 150}, "TPC Multiplicity bins"}; ConfigurableAxis multFT0CBins{"multFT0CBins", {200, 0, 2000}, "Forward Multiplicity bins"}; - ConfigurableAxis multFT0CMCBins{"multFT0CMCBins", {250, 0, 250}, "Forward Multiplicity bins"}; // made change fore Gen + ConfigurableAxis multFT0CMCBins{"multFT0CMCBins", {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", {100, 0., 100.}, "nth moments bins"}; + ConfigurableAxis QnBins{"QnBins", {1000, 0., 100.}, "nth moments bins"}; + ConfigurableAxis TpNBins{"TpNBins", {300, 0., 3000.}, ""}; + ConfigurableAxis TpDBins{"TpDBins", {100, 0., 2000.}, ""}; using MyAllTracks = soa::Join ", kTH1D, {axisMeanPt}); @@ -320,18 +345,23 @@ struct meanPtFlucId { { if (std::abs(col.posZ()) > cfgCutPosZ) return false; + hist.fill(HIST("QA/after/counts_evSelCuts"), 1); if (!col.sel8()) return false; + hist.fill(HIST("QA/after/counts_evSelCuts"), 2); if (!col.selection_bit(o2::aod::evsel::kNoSameBunchPileup)) return false; + hist.fill(HIST("QA/after/counts_evSelCuts"), 3); if (!col.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV)) return false; + hist.fill(HIST("QA/after/counts_evSelCuts"), 4); if (!col.selection_bit(o2::aod::evsel::kIsVertexITSTPC)) return false; + hist.fill(HIST("QA/after/counts_evSelCuts"), 5); return true; } @@ -352,63 +382,116 @@ struct meanPtFlucId { if (track.sign() == 0) return false; - if (std::abs(track.dcaZ()) > cfgCutDcaZ) + if (std::fabs(track.dcaZ()) > cfgCutDcaZ) return false; - if (std::abs(track.dcaXY()) > cfgCutDcaXY) + if (std::fabs(track.dcaXY()) > cfgCutDcaXY) return false; return true; } - // Cuts to rejects the tracks + // Cuts to reject the tracks template bool rejectTracks(T const& track) { - if (track.tpcNSigmaEl() > -3. && track.tpcNSigmaEl() < 5. && std::abs(track.tpcNSigmaPi()) > 3 && std::abs(track.tpcNSigmaKa()) > 3 && std::abs(track.tpcNSigmaPr()) > 3) { + if ((track.tpcNSigmaEl() + cfgMcTpcShiftEl) > -3. && (track.tpcNSigmaEl() + cfgMcTpcShiftEl) < 5. && std::fabs(track.tpcNSigmaPi() + cfgMcTpcShiftPi) > 3 && std::fabs(track.tpcNSigmaKa() + cfgMcTpcShiftKa) > 3 && std::fabs(track.tpcNSigmaPr() + cfgMcTpcShiftPr) > 3) { return true; } + return false; } - // PID selection tpc (!tof) or (tof + tpc) - // PID selction cuts for Pions template - bool selPions(T const& track, double innerParam) + bool selElectrons(T const& track) { - if (track.pt() >= cfgCutPiPtMin && ((!track.hasTOF() && std::abs(track.tpcNSigmaEl()) > cfgCutNSigTpcEl && - ((std::abs(track.tpcNSigmaPi()) < cfgCutNSig3 && innerParam <= cfgCutPiP1) || (std::abs(track.tpcNSigmaPi()) < cfgCutNSig2 && innerParam > cfgCutPiP1 && innerParam <= cfgCutPiP2))) || - (track.hasTOF() && std::abs(track.tpcNSigmaPi()) < cfgCutNSig3 && std::abs(track.tofNSigmaEl()) > cfgCutNSigTofEl && (std::abs(track.tofNSigmaPi()) < cfgCutNSig3)))) { - if (abs(track.rapidity(massPi)) < cfgCutRap) + if (std::fabs(track.tpcNSigmaEl() + cfgMcTpcShiftEl) < cfgCutNSig3) { + return true; + } + + return false; + } + + // PID selction cuts for Low momentum Pions + template + bool selLowPi(T const& track, double p) + { + if (track.pt() >= cfgCutPiPtMin && std::fabs(track.tpcNSigmaKa() + cfgMcTpcShiftKa) > 3 && std::fabs(track.tpcNSigmaPr() + cfgMcTpcShiftPr) > 3 && track.p() <= cfgCutPiThrsldP && + ((std::fabs(track.tpcNSigmaPi() + cfgMcTpcShiftPi) < cfgCutNSig3 && p <= cfgCutPiP1) || + (std::fabs(track.tpcNSigmaPi() + cfgMcTpcShiftPi) < cfgCutNSig2 && p > cfgCutPiP1 && p <= cfgCutPiP2))) { + if (std::abs(track.rapidity(MassPiPlus)) < cfgCutRap) { return true; + } } return false; } - // PID selction cuts for Kaons + // PID selction cuts for Low momentum Kaons template - bool selKaons(T const& track, double innerParam) + bool selLowKa(T const& track, double p) { - if (track.pt() >= cfgCutKaPtMin && (((!track.hasTOF()) && std::abs(track.tpcNSigmaEl()) > cfgCutNSigTpcEl && - ((std::abs(track.tpcNSigmaKa()) < cfgCutNSig3 && innerParam <= cfgCutKaP1) || (std::abs(track.tpcNSigmaKa()) < cfgCutNSig2 && innerParam > cfgCutKaP1 && innerParam <= cfgCutKaP2))) || - (track.hasTOF() && std::abs(track.tpcNSigmaKa()) < cfgCutNSig3 && std::abs(track.tofNSigmaEl()) > cfgCutNSigTofEl && - ((std::abs(track.tofNSigmaKa()) < cfgCutNSig3 && track.p() <= cfgCutKaP3) || (std::abs(track.tofNSigmaKa()) < cfgCutNSig2 && track.p() > cfgCutKaP3))))) { - if (abs(track.rapidity(massKa)) < cfgCutRap) + if (track.pt() >= cfgCutKaPtMin && std::fabs(track.tpcNSigmaPi() + cfgMcTpcShiftPi) > 3 && std::fabs(track.tpcNSigmaPr() + cfgMcTpcShiftPr) > 3 && track.p() <= cfgCutKaThrsldP && + ((std::fabs(track.tpcNSigmaKa() + cfgMcTpcShiftKa) < cfgCutNSig3 && p <= cfgCutKaP1) || + (std::fabs(track.tpcNSigmaKa() + cfgMcTpcShiftKa) < cfgCutNSig2 && p > cfgCutKaP1 && p <= cfgCutKaP2))) { + if (std::abs(track.rapidity(MassKPlus)) < cfgCutRap) { return true; + } } return false; } - // PID selction cuts for Protons + // PID selction cuts for Low momentum Protons template - bool selProtons(T const& track, double innerParam) + bool selLowPr(T const& track, double p) { - if (track.pt() >= cfgCutPrPtMin && (((!track.hasTOF()) && std::abs(track.tpcNSigmaEl()) > cfgCutNSigTpcEl && - ((std::abs(track.tpcNSigmaPr()) < cfgCutNSig3 && innerParam <= cfgCutPrP1) || (std::abs(track.tpcNSigmaPr()) < cfgCutNSig2 && innerParam > cfgCutPrP1 && innerParam <= cfgCutPrP2))) || - (track.hasTOF() && std::abs(track.tpcNSigmaPr()) < cfgCutNSig3 && std::abs(track.tofNSigmaEl()) > cfgCutNSigTofEl && std::abs(track.tofNSigmaPr()) < cfgCutNSig3))) { - if (abs(track.rapidity(massPr)) < cfgCutRap) + if (track.pt() >= cfgCutPrPtMin && std::fabs(track.tpcNSigmaKa() + cfgMcTpcShiftKa) > 3 && std::fabs(track.tpcNSigmaPi() + cfgMcTpcShiftPi) > 3 && track.p() <= cfgCutPrThrsldP && + ((std::fabs(track.tpcNSigmaPr() + cfgMcTpcShiftPr) < cfgCutNSig3 && p <= cfgCutPrP1) || + (std::fabs(track.tpcNSigmaPr() + cfgMcTpcShiftPr) < cfgCutNSig2 && p > cfgCutPrP1 && p <= cfgCutPrP2))) { + if (std::abs(track.rapidity(MassProton)) < cfgCutRap) { return true; + } + } + + return false; + } + + // PID selction cuts for High momentum Protons + template + bool selHighPi(T const& track) + { + if (track.p() > cfgCutPiThrsldP && (track.hasTOF() && std::fabs(track.tpcNSigmaPi() + cfgMcTpcShiftPi) < cfgCutNSig3 && (std::fabs(track.tofNSigmaPi()) < cfgCutNSig3))) { + if (std::abs(track.rapidity(MassPiPlus)) < cfgCutRap) { + return true; + } + } + + return false; + } + + // PID selction cuts for High momentum Kaons + template + bool selHighKa(T const& track) + { + if (track.p() > cfgCutKaThrsldP && (track.hasTOF() && std::fabs(track.tpcNSigmaKa() + cfgMcTpcShiftKa) < cfgCutNSig3 && + ((std::fabs(track.tofNSigmaKa()) < cfgCutNSig3 && track.p() <= cfgCutKaP3) || + (std::fabs(track.tofNSigmaKa()) < cfgCutNSig2 && track.p() > cfgCutKaP3)))) { + if (std::abs(track.rapidity(MassKPlus)) < cfgCutRap) { + return true; + } + } + + return false; + } + + // PID selction cuts for High momentum Protons + template + bool selHighPr(T const& track) + { + if (track.p() > cfgCutPrThrsldP && (track.hasTOF() && std::fabs(track.tpcNSigmaPr() + cfgMcTpcShiftPr) < cfgCutNSig3 && std::fabs(track.tofNSigmaPr()) < cfgCutNSig3)) { + if (std::abs(track.rapidity(MassProton)) < cfgCutRap) { + return true; + } } return false; @@ -418,18 +501,22 @@ struct meanPtFlucId { template void FillBeforeQAHistos(T const& col, U const& tracks) { - for (auto& myTrack : tracks) { - hist.fill(HIST("QA/before/h_Eta"), myTrack.eta()); - hist.fill(HIST("QA/before/h_Pt"), myTrack.pt()); - hist.fill(HIST("QA/before/h2_PvsPinner"), myTrack.p(), myTrack.tpcInnerParam()); - hist.fill(HIST("QA/before/h2_Pt_Eta"), myTrack.eta(), myTrack.pt()); - hist.fill(HIST("QA/before/h_TPCChi2perCluster"), myTrack.tpcChi2NCl()); - hist.fill(HIST("QA/before/h_ITSChi2perCluster"), myTrack.itsChi2NCl()); - hist.fill(HIST("QA/before/h_crossedTPC"), myTrack.tpcNClsCrossedRows()); - hist.fill(HIST("QA/before/h_DcaXY"), myTrack.dcaXY()); - hist.fill(HIST("QA/before/h_DcaZ"), myTrack.dcaZ()); - hist.fill(HIST("QA/before/h2_DcaXY"), myTrack.pt(), myTrack.dcaXY()); - hist.fill(HIST("QA/before/h2_DcaZ"), myTrack.pt(), myTrack.dcaZ()); + for (auto& track : tracks) { + hist.fill(HIST("QA/before/h_Eta"), track.eta()); + hist.fill(HIST("QA/before/h_Phi"), track.phi()); + hist.fill(HIST("QA/before/h_Pt"), track.pt()); + hist.fill(HIST("QA/before/h2_PvsPinner"), track.p(), track.tpcInnerParam()); + hist.fill(HIST("QA/before/h2_Pt_Eta"), track.eta(), track.pt()); + hist.fill(HIST("QA/before/h_TPCChi2perCluster"), track.tpcChi2NCl()); + hist.fill(HIST("QA/before/h_ITSChi2perCluster"), track.itsChi2NCl()); + hist.fill(HIST("QA/before/h_crossedTPC"), track.tpcNClsCrossedRows()); + hist.fill(HIST("QA/before/h_DcaXY"), track.dcaXY()); + hist.fill(HIST("QA/before/h_DcaZ"), track.dcaZ()); + hist.fill(HIST("QA/before/h2_DcaXY"), track.pt(), track.dcaXY()); + hist.fill(HIST("QA/before/h2_DcaZ"), track.pt(), track.dcaZ()); + + if (track.hasTOF()) + hist.fill(HIST("QA/before/h2_PtofvsPinner"), track.p(), track.tpcInnerParam()); } hist.fill(HIST("QA/before/h_VtxZ"), col.posZ()); hist.fill(HIST("QA/before/h_Counts"), 2); @@ -473,6 +560,7 @@ struct meanPtFlucId { void FillChargedQAHistos(T const& track) { 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/h2_PvsPinner"), track.p(), track.tpcInnerParam()); hist.fill(HIST("QA/after/h2_Pt_Eta"), track.eta(), track.pt()); @@ -484,6 +572,9 @@ struct meanPtFlucId { hist.fill(HIST("QA/after/h_TPCChi2perCluster"), track.tpcChi2NCl()); hist.fill(HIST("QA/after/h_ITSChi2perCluster"), track.itsChi2NCl()); hist.fill(HIST("QA/after/h_crossedTPC"), track.tpcNClsCrossedRows()); + + if (track.hasTOF()) + hist.fill(HIST("QA/after/h2_PtofvsPinner"), track.p(), track.tpcInnerParam()); } // Fill before PID cut QA hist: @@ -519,19 +610,21 @@ struct meanPtFlucId { hist.fill(HIST("QA/Kaon/innerParam/before/h2_TpcTofNsigma"), track.tpcNSigmaKa(), track.tofNSigmaKa()); } - // Fill Proton QA hist: + // Fill after PID cut QA hist: template void FillIdParticleQAHistos(T const& track, double rap, double nSigmaTPC, double nSigmaTOF) { - hist.fill(HIST(dire[mode]) + HIST("h_Pt"), track.pt()); hist.fill(HIST(dire[mode]) + HIST("h_Eta"), track.eta()); + hist.fill(HIST(dire[mode]) + HIST("h_Phi"), track.phi()); hist.fill(HIST(dire[mode]) + HIST("h_rap"), rap); hist.fill(HIST(dire[mode]) + HIST("h2_Pt_rap"), rap, track.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"), track.pt(), track.dcaZ()); hist.fill(HIST(dire[mode]) + HIST("h2_DcaXY"), track.pt(), track.dcaXY()); + hist.fill(HIST(dire[mode]) + HIST("h2_Pt_Pinner"), track.tpcInnerParam(), track.pt()); + hist.fill(HIST(dire[mode]) + HIST("h2_P_Pinner"), track.tpcInnerParam(), track.p()); 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()); @@ -558,13 +651,28 @@ struct meanPtFlucId { hist.fill(HIST("QA/after/innerParam/h2_pvsm2"), track.mass() * track.mass(), track.tpcInnerParam()); } + template + void FillMCPIDHist(T const& track, int PID, int pdgCodePos, int pdgCodeNeg, int& N, double& Q1, double& Q2, double& Q3, double& Q4) + { + N++; + double pt = track.pt(); + moments(pt, Q1, Q2, Q3, Q4); + hist.fill(HIST(dire[mode]) + HIST("h_Pt"), track.pt()); + if (PID == pdgCodePos) { + hist.fill(HIST(dire[mode]) + HIST("h_PtPos"), track.pt()); + } + if (PID == pdgCodeNeg) { + hist.fill(HIST(dire[mode]) + HIST("h_PtNeg"), track.pt()); + } + } + // Moments Calculation: - void moments(double pt, double* Q1, double* Q2, double* Q3, double* Q4) + void moments(double pt, double& Q1, double& Q2, double& Q3, double& Q4) { - *Q1 += pt; - *Q2 += pt * pt; - *Q3 += pt * pt * pt; - *Q4 += pt * pt * pt * pt; + Q1 += pt; + Q2 += pt * pt; + Q3 += pt * pt * pt; + Q4 += pt * pt * pt * pt; } template @@ -628,6 +736,26 @@ struct meanPtFlucId { double pt_Pr = 0, Q1_Pr = 0, Q2_Pr = 0, Q3_Pr = 0, Q4_Pr = 0; double pt_Ka = 0, Q1_Ka = 0, Q2_Ka = 0, Q3_Ka = 0, Q4_Ka = 0; + array p1, p2; + double invMassGamma = 0.0; + + for (auto const& [trkEl, trkPos] : soa::combinations(soa::CombinationsFullIndexPolicy(tracks, tracks))) { + if (trkEl.index() == trkPos.index()) + continue; + + if (!selTrack(trkEl) || !selTrack(trkPos)) + continue; + + if (!selElectrons(trkEl) || !selElectrons(trkPos)) + continue; + + p1 = array{trkEl.px(), trkEl.py(), trkEl.pz()}; + p2 = array{trkPos.px(), trkPos.py(), trkPos.pz()}; + + invMassGamma = RecoDecay::m(array{p1, p2}, array{MassElectron, MassElectron}); + hist.fill(HIST("QA/after/h_invMass_gamma"), invMassGamma); + } + for (auto& track : tracks) { if (!selTrack(track)) { continue; @@ -639,16 +767,16 @@ struct meanPtFlucId { double nSigmaTOFPi = track.tofNSigmaPi(); double nSigmaTOFKa = track.tofNSigmaKa(); double nSigmaTOFPr = track.tofNSigmaPr(); - double rapPi = track.rapidity(massPi); - double rapKa = track.rapidity(massKa); - double rapPr = track.rapidity(massPr); + double rapPi = track.rapidity(MassPiPlus); + double rapKa = track.rapidity(MassKPlus); + double rapPr = track.rapidity(MassProton); double innerParam = track.tpcInnerParam(); if constexpr (DataFlag) { - if (std::abs(track.eta()) < 0.8) { + if (std::fabs(track.eta()) < 0.8) { Nch++; pt_ch = track.pt(); - moments(pt_ch, &Q1_ch, &Q2_ch, &Q3_ch, &Q4_ch); + moments(pt_ch, Q1_ch, Q2_ch, Q3_ch, Q4_ch); FillChargedQAHistos(track); } @@ -658,70 +786,166 @@ struct meanPtFlucId { return; } - // For Pions: - if (selPions(track, innerParam) == cfgSelPi) { - N_Pi++; - pt_Pi = track.pt(); - moments(pt_Pi, &Q1_Pi, &Q2_Pi, &Q3_Pi, &Q4_Pi); - FillIdParticleQAHistos(track, rapPi, nSigmaTPCPi, nSigmaTOFPi); + if (cfgInvMass == true && invMassGamma < cfgGammaCut) { + continue; } - // For Kaons: - if (selKaons(track, innerParam) == cfgSelKa) { - N_Ka++; - pt_Ka = track.pt(); - moments(pt_Ka, &Q1_Ka, &Q2_Ka, &Q3_Ka, &Q4_Ka); - FillIdParticleQAHistos(track, rapKa, nSigmaTPCKa, nSigmaTOFKa); + if (cfgSelORPi == true && cfgSelANDPi == false) { + if (selLowPi(track, innerParam) == cfgSelLowPi || selHighPi(track) == cfgSelHighPi) { + N_Pi++; + pt_Pi = track.pt(); + moments(pt_Pi, Q1_Pi, Q2_Pi, Q3_Pi, Q4_Pi); + FillIdParticleQAHistos(track, rapPi, nSigmaTPCPi, nSigmaTOFPi); + } + } else if (cfgSelORPi == false && cfgSelANDPi == true) { + if (selLowPi(track, innerParam) == cfgSelLowPi && selHighPi(track) == cfgSelHighPi) { + N_Pi++; + pt_Pi = track.pt(); + moments(pt_Pi, Q1_Pi, Q2_Pi, Q3_Pi, Q4_Pi); + FillIdParticleQAHistos(track, rapPi, nSigmaTPCPi, nSigmaTOFPi); + } + } + + if (cfgSelORKa == true && cfgSelANDKa == false) { + if (selLowKa(track, innerParam) == cfgSelLowKa || selHighKa(track) == cfgSelHighKa) { + N_Ka++; + pt_Ka = track.pt(); + moments(pt_Ka, Q1_Ka, Q2_Ka, Q3_Ka, Q4_Ka); + FillIdParticleQAHistos(track, rapKa, nSigmaTPCKa, nSigmaTOFKa); + } + } else if (cfgSelORKa == false && cfgSelANDKa == true) { + if (selLowKa(track, innerParam) == cfgSelLowKa && selHighKa(track) == cfgSelHighKa) { + N_Ka++; + pt_Ka = track.pt(); + moments(pt_Ka, Q1_Ka, Q2_Ka, Q3_Ka, Q4_Ka); + FillIdParticleQAHistos(track, rapKa, nSigmaTPCKa, nSigmaTOFKa); + } } - // For Protons: - if (selProtons(track, innerParam) == cfgSelPr) { - N_Pr++; - pt_Pr = track.pt(); - moments(pt_Pr, &Q1_Pr, &Q2_Pr, &Q3_Pr, &Q4_Pr); - FillIdParticleQAHistos(track, rapPr, nSigmaTPCPr, nSigmaTOFPr); + if (cfgSelORPr == true && cfgSelANDPr == false) { + if (selLowPr(track, innerParam) == cfgSelLowPr || selHighPr(track) == cfgSelHighPr) { + N_Pr++; + pt_Pr = track.pt(); + moments(pt_Pr, Q1_Pr, Q2_Pr, Q3_Pr, Q4_Pr); + FillIdParticleQAHistos(track, rapPr, nSigmaTPCPr, nSigmaTOFPr); + } + } else if (cfgSelORPr == false && cfgSelANDPr == true) { + if (selLowPr(track, innerParam) == cfgSelLowPr && selHighPr(track) == cfgSelHighPr) { + N_Pr++; + pt_Pr = track.pt(); + moments(pt_Pr, Q1_Pr, Q2_Pr, Q3_Pr, Q4_Pr); + FillIdParticleQAHistos(track, rapPr, nSigmaTPCPr, nSigmaTOFPr); + } } } else if constexpr (RecoFlag) { if (track.has_mcParticle() && track.mcParticle().isPhysicalPrimary()) { - if (std::abs(track.eta()) < 0.8) { + if (std::fabs(track.eta()) < 0.8) { Nch++; pt_ch = track.pt(); - moments(pt_ch, &Q1_ch, &Q2_ch, &Q3_ch, &Q4_ch); + moments(pt_ch, Q1_ch, Q2_ch, Q3_ch, Q4_ch); FillChargedQAHistos(track); } FillBeforePIDQAHistos(track); - if (rejectTracks(track)) + if (rejectTracks(track)) { return; + } + + if (cfgInvMass == true && invMassGamma < cfgGammaCut) { + continue; + } + + int PID = track.mcParticle().pdgCode(); + + if (cfgSelORPi == true && cfgSelANDPi == false) { + if (selLowPi(track, innerParam) == cfgSelLowPi || selHighPi(track) == cfgSelHighPi) { + hist.fill(HIST("QA/Pion/h_allPt"), track.pt()); + if (track.sign() > 0) + hist.fill(HIST("QA/Pion/h_allPtPos"), track.pt()); - if (selPions(track, innerParam) == cfgSelPi) { - hist.fill(HIST("QA/Reco/Pion/h_allPt"), track.pt()); - if (std::abs(track.mcParticle().pdgCode()) == 211) { - N_Pi++; - pt_Pi = track.pt(); - moments(pt_Pi, &Q1_Pi, &Q2_Pi, &Q3_Pi, &Q4_Pi); - FillIdParticleQAHistos(track, rapPi, nSigmaTPCPi, nSigmaTOFPi); + if (track.sign() < 0) + hist.fill(HIST("QA/Pion/h_allPtNeg"), track.pt()); + + if (std::abs(PID) == kPiPlus) { + FillIdParticleQAHistos(track, rapPi, nSigmaTPCPi, nSigmaTOFPi); + FillMCPIDHist(track, PID, kPiPlus, kPiMinus, N_Pi, Q1_Pi, Q2_Pi, Q3_Pi, Q4_Pi); + } + } + } else if (cfgSelORPi == false && cfgSelANDPi == true) { + if (selLowPi(track, innerParam) == cfgSelLowPi && selHighPi(track) == cfgSelHighPi) { + hist.fill(HIST("QA/Pion/h_allPt"), track.pt()); + if (track.sign() > 0) + hist.fill(HIST("QA/Pion/h_allPtPos"), track.pt()); + + if (track.sign() < 0) + hist.fill(HIST("QA/Pion/h_allPtNeg"), track.pt()); + + if (std::abs(PID) == kPiPlus) { + + FillIdParticleQAHistos(track, rapPi, nSigmaTPCPi, nSigmaTOFPi); + FillMCPIDHist(track, PID, kPiPlus, kPiMinus, N_Pi, Q1_Pi, Q2_Pi, Q3_Pi, Q4_Pi); + } } } - if (selKaons(track, innerParam) == cfgSelKa) { - hist.fill(HIST("QA/Reco/Kaon/h_allPt"), track.pt()); - if (std::abs(track.mcParticle().pdgCode()) == 321) { - N_Ka++; - pt_Ka = track.pt(); - moments(pt_Ka, &Q1_Ka, &Q2_Ka, &Q3_Ka, &Q4_Ka); - FillIdParticleQAHistos(track, rapKa, nSigmaTPCKa, nSigmaTOFKa); + if (cfgSelORKa == true && cfgSelANDKa == false) { + if (selLowKa(track, innerParam) == cfgSelLowKa || selHighKa(track) == cfgSelHighKa) { + hist.fill(HIST("QA/Kaon/h_allPt"), track.pt()); + if (track.sign() > 0) + hist.fill(HIST("QA/Kaon/h_allPtPos"), track.pt()); + + if (track.sign() < 0) + hist.fill(HIST("QA/Kaon/h_allPtNeg"), track.pt()); + + if (std::abs(PID) == kKPlus) { + FillIdParticleQAHistos(track, rapKa, nSigmaTPCKa, nSigmaTOFKa); + FillMCPIDHist(track, PID, kKPlus, kKMinus, N_Ka, Q1_Ka, Q2_Ka, Q3_Ka, Q4_Ka); + } + } + } else if (cfgSelORKa == false && cfgSelANDKa == true) { + if (selLowKa(track, innerParam) == cfgSelLowKa && selHighKa(track) == cfgSelHighKa) { + hist.fill(HIST("QA/Kaon/h_allPt"), track.pt()); + if (track.sign() > 0) + hist.fill(HIST("QA/Kaon/h_allPtPos"), track.pt()); + + if (track.sign() < 0) + hist.fill(HIST("QA/Kaon/h_allPtNeg"), track.pt()); + + if (std::abs(PID) == kKPlus) { + FillIdParticleQAHistos(track, rapKa, nSigmaTPCKa, nSigmaTOFKa); + FillMCPIDHist(track, PID, kKPlus, kKMinus, N_Ka, Q1_Ka, Q2_Ka, Q3_Ka, Q4_Ka); + } } } - if (selProtons(track, innerParam) == cfgSelPr) { - hist.fill(HIST("QA/Reco/Proton/h_allPt"), track.pt()); - if (std::abs(track.mcParticle().pdgCode()) == 2212) { - N_Pr++; - pt_Pr = track.pt(); - moments(pt_Pr, &Q1_Pr, &Q2_Pr, &Q3_Pr, &Q4_Pr); - FillIdParticleQAHistos(track, rapPr, nSigmaTPCPr, nSigmaTOFPr); + if (cfgSelORPr == true && cfgSelANDPr == false) { + if (selLowPr(track, innerParam) == cfgSelLowPr && selHighPr(track) == cfgSelHighPr) { + hist.fill(HIST("QA/Proton/h_allPt"), track.pt()); + if (track.sign() > 0) + hist.fill(HIST("QA/Proton/h_allPtPos"), track.pt()); + + if (track.sign() < 0) + hist.fill(HIST("QA/Proton/h_allPtNeg"), track.pt()); + + if (std::abs(PID) == kProton) { + FillIdParticleQAHistos(track, rapPr, nSigmaTPCPr, nSigmaTOFPr); + FillMCPIDHist(track, PID, kProton, kProtonBar, N_Pr, Q1_Pr, Q2_Pr, Q3_Pr, Q4_Pr); + } + } + } else if (cfgSelORPr == false && cfgSelANDPr == true) { + if (selLowPr(track, innerParam) == cfgSelLowPr && selHighPr(track) == cfgSelHighPr) { + hist.fill(HIST("QA/Proton/h_allPt"), track.pt()); + if (track.sign() > 0) + hist.fill(HIST("QA/Proton/h_allPtPos"), track.pt()); + + if (track.sign() < 0) + hist.fill(HIST("QA/Proton/h_allPtNeg"), track.pt()); + + if (std::abs(PID) == kProton) { + FillIdParticleQAHistos(track, rapPr, nSigmaTPCPr, nSigmaTOFPr); + FillMCPIDHist(track, PID, kProton, kProtonBar, N_Pr, Q1_Pr, Q2_Pr, Q3_Pr, Q4_Pr); + } } } } @@ -751,7 +975,7 @@ struct meanPtFlucId { FillHistos(col, tracks); } } - PROCESS_SWITCH(meanPtFlucId, process_Run3, "Process for Run3", false); + PROCESS_SWITCH(meanPtFlucId, process_Run3, "Process for Run3", true); void process_MCRecoRun3(MyMCCollisions::iterator const& col, aod::McCollisions const&, MyMCTracks const& tracks, aod::McParticles const&) { @@ -766,18 +990,18 @@ struct meanPtFlucId { FillHistos(col, tracks); } } - PROCESS_SWITCH(meanPtFlucId, process_MCRecoRun3, "process MC Reconstructed Run-3", true); + PROCESS_SWITCH(meanPtFlucId, process_MCRecoRun3, "process MC Reconstructed Run-3", false); void process_MCGen(soa::Join::iterator const& mccol, aod::McParticles const& McParticles) { int N_Pi = 0, N_Ka = 0, N_Pr = 0; int Nch = 0, NTPC = 0, N_FT0C = 0; double pt_ch = 0, Q1_ch = 0, Q2_ch = 0, Q3_ch = 0, Q4_ch = 0; - double pt_Pi = 0, Q1_Pi = 0, Q2_Pi = 0, Q3_Pi = 0, Q4_Pi = 0; - double pt_Pr = 0, Q1_Pr = 0, Q2_Pr = 0, Q3_Pr = 0, Q4_Pr = 0; - double pt_Ka = 0, Q1_Ka = 0, Q2_Ka = 0, Q3_Ka = 0, Q4_Ka = 0; + double Q1_Pi = 0, Q2_Pi = 0, Q3_Pi = 0, Q4_Pi = 0; + double Q1_Pr = 0, Q2_Pr = 0, Q3_Pr = 0, Q4_Pr = 0; + double Q1_Ka = 0, Q2_Ka = 0, Q3_Ka = 0, Q4_Ka = 0; - if (abs(mccol.posZ()) > cfgCutPosZ) + if (std::abs(mccol.posZ()) > cfgCutPosZ) return; for (auto& mcParticle : McParticles) { @@ -785,39 +1009,55 @@ struct meanPtFlucId { continue; auto charge = 0.; - auto* p = pdg->GetParticle(mcParticle.pdgCode()); - if (p != nullptr) { - charge = p->Charge(); + int PID = mcParticle.pdgCode(); + auto* pd = pdg->GetParticle(PID); + if (pd != nullptr) { + charge = pd->Charge(); } - if (std::abs(charge) < 1e-3) { - continue; // reject neutral particles in counters + if (std::fabs(charge) < 1e-3) { + continue; } - if (mcParticle.pt() > cfgCutPtMin && mcParticle.pt() < cfgCutPtMax && abs(mcParticle.y()) < cfgCutRap) { + if (mcParticle.pt() > cfgCutPtMin && mcParticle.pt() < cfgCutPtMax && std::abs(mcParticle.y()) < cfgCutRap) { Nch++; pt_ch = mcParticle.pt(); - moments(pt_ch, &Q1_ch, &Q2_ch, &Q3_ch, &Q4_ch); + moments(pt_ch, Q1_ch, Q2_ch, Q3_ch, Q4_ch); hist.fill(HIST("Gen/Charged/h_Pt"), mcParticle.pt()); - if (std::abs(mcParticle.pdgCode()) == 211 && mcParticle.pt() >= cfgCutPiPtMin) { - N_Pi++; - pt_Pi = mcParticle.pt(); - moments(pt_Pi, &Q1_Pi, &Q2_Pi, &Q3_Pi, &Q4_Pi); - hist.fill(HIST("Gen/Pion/h_Pt"), mcParticle.pt()); + if (std::abs(PID) == kPiPlus && mcParticle.pt() >= cfgCutPiPtMin) { + if (cfgSelORPi == true && cfgSelANDPi == false) { + if (mcParticle.p() <= cfgCutPiThrsldP || mcParticle.p() > cfgCutPiThrsldP) { + FillMCPIDHist(mcParticle, PID, kPiPlus, kPiMinus, N_Pi, Q1_Pi, Q2_Pi, Q3_Pi, Q4_Pi); + } + } else if (cfgSelORPi == false && cfgSelANDPi == true) { + if ((cfgSelLowPi == true && mcParticle.p() <= cfgCutPiThrsldP) && (cfgSelHighPi == true && mcParticle.p() > cfgCutPiThrsldP)) { + FillMCPIDHist(mcParticle, PID, kPiPlus, kPiMinus, N_Pi, Q1_Pi, Q2_Pi, Q3_Pi, Q4_Pi); + } + } } - if (std::abs(mcParticle.pdgCode()) == 321 && mcParticle.pt() >= cfgCutKaPtMin) { - N_Ka++; - pt_Ka = mcParticle.pt(); - moments(pt_Ka, &Q1_Ka, &Q2_Ka, &Q3_Ka, &Q4_Ka); - hist.fill(HIST("Gen/Kaon/h_Pt"), mcParticle.pt()); + if (std::abs(PID) == kKPlus && mcParticle.pt() >= cfgCutKaPtMin) { + if (cfgSelORPi == true && cfgSelANDPi == false) { + if ((cfgSelLowKa == true && mcParticle.p() <= cfgCutPiThrsldP) || (cfgSelHighKa == true && mcParticle.p() > cfgCutPiThrsldP)) { + FillMCPIDHist(mcParticle, PID, kKPlus, kKMinus, N_Ka, Q1_Ka, Q2_Ka, Q3_Ka, Q4_Ka); + } + } else if (cfgSelORKa == false && cfgSelANDKa == true) { + if ((cfgSelLowKa == true && mcParticle.p() <= cfgCutKaThrsldP) && (cfgSelHighKa == true && mcParticle.p() > cfgCutKaThrsldP)) { + FillMCPIDHist(mcParticle, PID, kKPlus, kKMinus, N_Ka, Q1_Ka, Q2_Ka, Q3_Ka, Q4_Ka); + } + } } - if (std::abs(mcParticle.pdgCode()) == 2212 && mcParticle.pt() >= cfgCutPrPtMin) { - N_Pr++; - pt_Pr = mcParticle.pt(); - moments(pt_Pr, &Q1_Pr, &Q2_Pr, &Q3_Pr, &Q4_Pr); - hist.fill(HIST("Gen/Proton/h_Pt"), mcParticle.pt()); + if (std::abs(PID) == kProton && mcParticle.pt() >= cfgCutPrPtMin) { + if (cfgSelORPr == true && cfgSelANDPr == false) { + if ((cfgSelLowPr == true && mcParticle.p() <= cfgCutPrThrsldP) || (cfgSelHighPr == true && mcParticle.p() > cfgCutPrThrsldP)) { + FillMCPIDHist(mcParticle, PID, kProton, kProtonBar, N_Pr, Q1_Pr, Q2_Pr, Q3_Pr, Q4_Pr); + } + } else if (cfgSelORPr == false && cfgSelANDPr == true) { + if ((cfgSelLowPr == true && mcParticle.p() <= cfgCutPrThrsldP) && (cfgSelHighPr == true && mcParticle.p() > cfgCutPrThrsldP)) { + FillMCPIDHist(mcParticle, PID, kProton, kProtonBar, N_Pr, Q1_Pr, Q2_Pr, Q3_Pr, Q4_Pr); + } + } } } } @@ -825,16 +1065,19 @@ struct meanPtFlucId { N_FT0C = mccol.multMCFT0C(); hist.fill(HIST("Gen/Counts"), 2); hist.fill(HIST("Gen/vtxZ"), mccol.posZ()); - hist.fill(HIST("Gen/NTPC"), NTPC); - hist.fill(HIST("Gen/NFT0C"), N_FT0C); - hist.fill(HIST("Gen/h2_NTPC_NFT0C"), N_FT0C, NTPC); + if (NTPC != 0) + hist.fill(HIST("Gen/NTPC"), NTPC); + if (N_FT0C != 0) + hist.fill(HIST("Gen/NFT0C"), N_FT0C); + if (NTPC != 0 && N_FT0C != 0) + hist.fill(HIST("Gen/h2_NTPC_NFT0C"), N_FT0C, NTPC); FillAnalysisHistos(NTPC, N_FT0C, Nch, Q1_ch, Q2_ch, Q3_ch, Q4_ch); FillAnalysisHistos(NTPC, N_FT0C, N_Pi, Q1_Pi, Q2_Pi, Q3_Pi, Q4_Pi); FillAnalysisHistos(NTPC, N_FT0C, N_Ka, Q1_Ka, Q2_Ka, Q3_Ka, Q4_Ka); FillAnalysisHistos(NTPC, N_FT0C, N_Pr, Q1_Pr, Q2_Pr, Q3_Pr, Q4_Pr); } - PROCESS_SWITCH(meanPtFlucId, process_MCGen, "process MC Generated", true); + PROCESS_SWITCH(meanPtFlucId, process_MCGen, "process MC Generated", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGCF/FemtoUniverse/TableProducer/femtoUniverseProducerTask.cxx b/PWGCF/FemtoUniverse/TableProducer/femtoUniverseProducerTask.cxx index f5d4445af0a..a0de6890b98 100644 --- a/PWGCF/FemtoUniverse/TableProducer/femtoUniverseProducerTask.cxx +++ b/PWGCF/FemtoUniverse/TableProducer/femtoUniverseProducerTask.cxx @@ -265,6 +265,8 @@ struct femtoUniverseProducerTask { Configurable ConfLooseTOFNSigmaValue{"ConfLooseTOFNSigmaValue", 10, "Value for the loose TOF N Sigma for Kaon PID."}; Configurable ConfInvMassLowLimitPhi{"ConfInvMassLowLimitPhi", 1.011, "Lower limit of the Phi invariant mass"}; // change that to do invariant mass cut Configurable ConfInvMassUpLimitPhi{"ConfInvMassUpLimitPhi", 1.027, "Upper limit of the Phi invariant mass"}; + Configurable ConfPtLowLimitPhi{"ConfPtLowLimitPhi", 0.8, "Lower limit of the Phi pT."}; + Configurable ConfPtHighLimitPhi{"ConfPtHighLimitPhi", 4.0, "Higher limit of the Phi pT."}; Configurable ConfNsigmaRejectPion{"ConfNsigmaRejectPion", 3.0, "Reject if particle could be a Pion combined nsigma value."}; Configurable ConfNsigmaRejectProton{"ConfNsigmaRejectProton", 3.0, "Reject if particle could be a Proton combined nsigma value."}; } ConfPhiSelection; @@ -324,31 +326,31 @@ struct femtoUniverseProducerTask { { if (mom < 0.3) { // 0.0-0.3 - if (TMath::Abs(nsigmaTPCK) < ConfPhiSelection.ConfLooseTPCNSigmaValue) { + if (TMath::Abs(nsigmaTPCK) < ConfPhiSelection.ConfLooseTPCNSigmaValue.value) { return true; } else { return false; } } else if (mom < 0.45) { // 0.30 - 0.45 - if (TMath::Abs(nsigmaTPCK) < ConfPhiSelection.ConfLooseTPCNSigmaValue) { + if (TMath::Abs(nsigmaTPCK) < ConfPhiSelection.ConfLooseTPCNSigmaValue.value) { return true; } else { return false; } } else if (mom < 0.55) { // 0.45-0.55 - if (TMath::Abs(nsigmaTPCK) < ConfPhiSelection.ConfLooseTPCNSigmaValue) { + if (TMath::Abs(nsigmaTPCK) < ConfPhiSelection.ConfLooseTPCNSigmaValue.value) { return true; } else { return false; } } else if (mom < 1.5) { // 0.55-1.5 (now we use TPC and TOF) - if ((TMath::Abs(nsigmaTOFK) < 3.0) && (TMath::Abs(nsigmaTPCK) < ConfPhiSelection.ConfLooseTPCNSigmaValue)) { + if ((TMath::Abs(nsigmaTOFK) < 3.0) && (TMath::Abs(nsigmaTPCK) < ConfPhiSelection.ConfLooseTPCNSigmaValue.value)) { return true; } else { return false; } } else if (mom > 1.5) { // 1.5 - - if ((TMath::Abs(nsigmaTOFK) < 2.0) && (TMath::Abs(nsigmaTPCK) < ConfPhiSelection.ConfLooseTPCNSigmaValue)) { + if ((TMath::Abs(nsigmaTOFK) < 2.0) && (TMath::Abs(nsigmaTPCK) < ConfPhiSelection.ConfLooseTPCNSigmaValue.value)) { return true; } else { return false; @@ -379,7 +381,7 @@ struct femtoUniverseProducerTask { return false; } } else if (mom < 1.5) { // 0.55-1.5 (now we use TPC and TOF) - if ((TMath::Abs(nsigmaTOFK) < ConfPhiSelection.ConfLooseTOFNSigmaValue) && (TMath::Abs(nsigmaTPCK) < 3.0)) { + if ((TMath::Abs(nsigmaTOFK) < ConfPhiSelection.ConfLooseTOFNSigmaValue.value) && (TMath::Abs(nsigmaTPCK) < 3.0)) { { return true; } @@ -387,7 +389,7 @@ struct femtoUniverseProducerTask { return false; } } else if (mom > 1.5) { // 1.5 - - if ((TMath::Abs(nsigmaTOFK) < ConfPhiSelection.ConfLooseTOFNSigmaValue) && (TMath::Abs(nsigmaTPCK) < 3.0)) { + if ((TMath::Abs(nsigmaTOFK) < ConfPhiSelection.ConfLooseTOFNSigmaValue.value) && (TMath::Abs(nsigmaTPCK) < 3.0)) { return true; } else { return false; @@ -400,16 +402,16 @@ struct femtoUniverseProducerTask { bool IsKaonRejected(float mom, float nsigmaTPCPr, float nsigmaTOFPr, float nsigmaTPCPi, float nsigmaTOFPi) { if (mom < 0.5) { - if (TMath::Abs(nsigmaTPCPi) < ConfPhiSelection.ConfNsigmaRejectPion) { + if (TMath::Abs(nsigmaTPCPi) < ConfPhiSelection.ConfNsigmaRejectPion.value) { return true; - } else if (TMath::Abs(nsigmaTPCPr) < ConfPhiSelection.ConfNsigmaRejectProton) { + } else if (TMath::Abs(nsigmaTPCPr) < ConfPhiSelection.ConfNsigmaRejectProton.value) { return true; } } if (mom > 0.5) { - if (TMath::Hypot(nsigmaTOFPi, nsigmaTPCPi) < ConfPhiSelection.ConfNsigmaRejectPion) { + if (TMath::Hypot(nsigmaTOFPi, nsigmaTPCPi) < ConfPhiSelection.ConfNsigmaRejectPion.value) { return true; - } else if (TMath::Hypot(nsigmaTOFPr, nsigmaTPCPr) < ConfPhiSelection.ConfNsigmaRejectProton) { + } else if (TMath::Hypot(nsigmaTOFPr, nsigmaTPCPr) < ConfPhiSelection.ConfNsigmaRejectProton.value) { return true; } else { return false; @@ -1245,7 +1247,7 @@ struct femtoUniverseProducerTask { continue; } // implementing PID cuts for phi children - if (ConfPhiSelection.ConfLooseTPCNSigma) { + if (ConfPhiSelection.ConfLooseTPCNSigma.value) { if (!(IsKaonNSigmaTPCLoose(p1.pt(), trackCuts.getNsigmaTPC(p1, o2::track::PID::Kaon), trackCuts.getNsigmaTOF(p1, o2::track::PID::Kaon)))) { continue; } @@ -1253,7 +1255,7 @@ struct femtoUniverseProducerTask { continue; } } - if (ConfPhiSelection.ConfLooseTOFNSigma) { + if (ConfPhiSelection.ConfLooseTOFNSigma.value) { if (!(IsKaonNSigmaTOFLoose(p1.pt(), trackCuts.getNsigmaTPC(p1, o2::track::PID::Kaon), trackCuts.getNsigmaTOF(p1, o2::track::PID::Kaon)))) { continue; } @@ -1297,7 +1299,7 @@ struct femtoUniverseProducerTask { } float phiPt = sumVec.Pt(); - if ((phiPt < 0.14) || (phiPt > 10.0)) { + if ((phiPt < ConfPhiSelection.ConfPtLowLimitPhi.value) || (phiPt > ConfPhiSelection.ConfPtHighLimitPhi.value)) { continue; } @@ -1309,7 +1311,7 @@ struct femtoUniverseProducerTask { } float phiM = sumVec.M(); - if (((phiM < ConfPhiSelection.ConfInvMassLowLimitPhi) || (phiM > ConfPhiSelection.ConfInvMassUpLimitPhi))) { + if (((phiM < ConfPhiSelection.ConfInvMassLowLimitPhi.value) || (phiM > ConfPhiSelection.ConfInvMassUpLimitPhi.value))) { continue; } diff --git a/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackPhi.cxx b/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackPhi.cxx index af7f0a39de9..b5b1aeb6296 100644 --- a/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackPhi.cxx +++ b/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackPhi.cxx @@ -70,14 +70,14 @@ struct femtoUniversePairTaskTrackPhi { // Efficiency struct : o2::framework::ConfigurableGroup { - Configurable ConfLocalEfficiencyProton{"ConfLocalEfficiencyProton", "", "Local path to proton efficiency TH2F file"}; - Configurable ConfLocalEfficiencyPhi{"ConfLocalEfficiencyPhi", "", "Local path to Phi efficiency TH2F file"}; - Configurable ConfEffProtonTimestamp{"ConfEffProtonTimestamp", 0, "(long int) Timestamp for hadron"}; - Configurable ConfEffPhiTimestamp{"ConfEffPhiTimestamp", 0, "(long int) Timestamp for phi"}; + Configurable ConfEfficiencyTrackPath{"ConfEfficiencyTrackPath", "", "Local path to proton efficiency TH2F file"}; + Configurable ConfEfficiencyPhiPath{"ConfEfficiencyPhiPath", "", "Local path to Phi efficiency TH2F file"}; + Configurable ConfEfficiencyTrackTimestamp{"ConfEfficiencyTrackTimestamp", 0, "(long int) Timestamp for hadron"}; + Configurable ConfEfficiencyPhiTimestamp{"ConfEfficiencyPhiTimestamp", 0, "(long int) Timestamp for phi"}; } ConfEff; struct : o2::framework::ConfigurableGroup { - Configurable ConfIsCPR{"ConfIsCPR", true, "Close Pair Rejection"}; + Configurable ConfCPRIsEnabled{"ConfCPRIsEnabled", 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"}; @@ -90,42 +90,44 @@ struct femtoUniversePairTaskTrackPhi { /// Table for both particles struct : o2::framework::ConfigurableGroup { - Configurable ConfNsigmaCombinedProton{"ConfNsigmaCombinedProton", 3.0, "TPC and TOF Proton Sigma (combined) for momentum > 0.5"}; - Configurable ConfNsigmaTPCProton{"ConfNsigmaTPCProton", 3.0, "TPC Proton Sigma for momentum < 0.5"}; - Configurable ConfNsigmaRejectKaon{"ConfNsigmaRejectKaon", 3.0, "Reject if particle could be a Kaon combined nsigma value."}; - Configurable ConfNsigmaRejectPion{"ConfNsigmaRejectPion", 3.0, "Reject if particle could be a Pion combined nsigma value."}; - Configurable ConfNsigmaRejectProton{"ConfNsigmaRejectProton", 3.0, "Reject if particle could be a Proton combined nsigma value."}; - Configurable ConfNsigmaCombinedPion{"ConfNsigmaCombinedPion", 3.0, "TPC and TOF Pion Sigma (combined) for momentum > 0.5"}; - Configurable ConfNsigmaTPCPion{"ConfNsigmaTPCPion", 3.0, "TPC Pion Sigma for momentum < 0.5"}; + Configurable ConfPIDProtonNsigmaCombined{"ConfPIDProtonNsigmaCombined", 3.0, "TPC and TOF Proton Sigma (combined) for momentum > 0.5"}; + Configurable ConfPIDProtonNsigmaTPC{"ConfPIDProtonNsigmaTPC", 3.0, "TPC Proton Sigma for momentum < 0.5"}; + Configurable ConfPIDKaonNsigmaReject{"ConfPIDKaonNsigmaReject", 3.0, "Reject if particle could be a Kaon combined nsigma value."}; + Configurable ConfPIDPionNsigmaReject{"ConfPIDPionNsigmaReject", 3.0, "Reject if particle could be a Pion combined nsigma value."}; + Configurable ConfPIDProtonNsigmaReject{"ConfPIDProtonNsigmaReject", 3.0, "Reject if particle could be a Proton combined nsigma value."}; + Configurable ConfPIDPionNsigmaCombined{"ConfPIDPionNsigmaCombined", 3.0, "TPC and TOF Pion Sigma (combined) for momentum > 0.5"}; + Configurable ConfPIDPionNsigmaTPC{"ConfPIDPionNsigmaTPC", 3.0, "TPC Pion Sigma for momentum < 0.5"}; Configurable> ConfCutTable{"ConfCutTable", {cutsTable[0], nPart, nCuts, partNames, cutNames}, "Particle selections"}; Configurable ConfNspecies{"ConfNspecies", 2, "Number of particle spieces with PID info"}; - Configurable ConfIsMC{"ConfIsMC", false, "Enable additional Histogramms in the case of a MonteCarlo Run"}; + Configurable ConfIsMC{"ConfIsMC", false, "Enable additional Histograms in the case of a MonteCarlo Run"}; Configurable> ConfTrkPIDnSigmaMax{"ConfTrkPIDnSigmaMax", std::vector{4.f, 3.f, 2.f}, "This configurable needs to be the same as the one used in the producer task"}; Configurable ConfUse3D{"ConfUse3D", false, "Enable three dimensional histogramms (to be used only for analysis with high statistics): k* vs mT vs multiplicity"}; - Configurable ConfPhiBins{"ConfPhiBins", 29, "Number of phi bins in deta dphi"}; - Configurable ConfEtaBins{"ConfEtaBins", 29, "Number of eta bins in deta dphi"}; + Configurable ConfBinsPhi{"ConfBinsPhi", 29, "Number of phi bins in deta dphi"}; + Configurable ConfBinsEta{"ConfBinsEta", 29, "Number of eta bins in deta dphi"}; } ConfBothTracks; /// Particle 1 --- IDENTIFIED TRACK struct : o2::framework::ConfigurableGroup { - Configurable ConfIsSame{"ConfIsSame", false, "Pairs of the same particle"}; - Configurable ConfPDGCodeTrack{"ConfPDGCodeTrack", 2212, "Particle 2 - PDG code"}; - Configurable ConfPIDTrack{"ConfPIDTrack", 2, "Particle 2 - Read from cutCulator"}; // we also need the possibility to specify whether the bit is true/false ->std>>vector> + Configurable ConfTrackIsSame{"ConfTrackIsSame", false, "Pairs of the same particle"}; + Configurable ConfTrackPDGCode{"ConfTrackPDGCode", 2212, "Particle 2 - PDG code"}; + Configurable ConfTrackPID{"ConfTrackPID", 2, "Particle 2 - Read from cutCulator"}; // we also need the possibility to specify whether the bit is true/false ->std>>vector> Configurable ConfTrackSign{"ConfTrackSign", 1, "Track sign"}; - Configurable ConfIsTrackIdentified{"ConfIsTrackIdentified", true, "Enable PID for the track"}; - Configurable ConfIsTrackRejected{"ConfIsTrackRejected", true, "Enable PID rejection for the track other species than the identified one."}; + Configurable ConfTrackIsIdentified{"ConfTrackIsIdentified", true, "Enable PID for the track"}; + Configurable ConfTrackIsRejected{"ConfTrackIsRejected", true, "Enable PID rejection for the track other species than the identified one."}; + Configurable ConfTrackPtLowLimit{"ConfTrackPtLowLimit", 0.5, "Lower limit of the Phi pT."}; + Configurable ConfTrackPtHighLimit{"ConfTrackPtHighLimit", 2.5, "Higher limit of the Phi pT."}; } ConfTrack; /// Particle 2 --- PHI struct : o2::framework::ConfigurableGroup { - Configurable ConfPDGCodePhi{"ConfPDGCodePhi", 333, "Phi meson - PDG code"}; - Configurable ConfPIDPhi{"ConfPIDPhi", 2, "Phi meson - Read from cutCulator"}; // we also need the possibility to specify whether the bit is true/false ->std>>vector>int>> + Configurable ConfPhiPDGCode{"ConfPhiPDGCode", 333, "Phi meson - PDG code"}; + Configurable ConfPhiPID{"ConfPhiPID", 2, "Phi meson - Read from cutCulator"}; // we also need the possibility to specify whether the bit is true/false ->std>>vector>int>> } ConfPhi; /// Partitions for particle 1 - Partition partsTrack = (aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kTrack)) && (aod::femtouniverseparticle::sign == ConfTrack.ConfTrackSign); - Partition> partsTrackMC = (aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kTrack)); + Partition partsTrack = (aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kTrack)) && (aod::femtouniverseparticle::sign == ConfTrack.ConfTrackSign.value) && (aod::femtouniverseparticle::pt > ConfTrack.ConfTrackPtLowLimit.value) && (aod::femtouniverseparticle::pt < ConfTrack.ConfTrackPtHighLimit.value); + Partition> partsTrackMC = (aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kTrack)) && (aod::femtouniverseparticle::sign == ConfTrack.ConfTrackSign.value) && (aod::femtouniverseparticle::pt > ConfTrack.ConfTrackPtLowLimit.value) && (aod::femtouniverseparticle::pt < ConfTrack.ConfTrackPtHighLimit.value); /// Partitions for particle 2 Partition partsPhi = (aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kPhi)); @@ -153,21 +155,21 @@ struct femtoUniversePairTaskTrackPhi { std::vector kNsigma; /// particle part - ConfigurableAxis ConfTempFitVarBins{"ConfDTempFitVarBins", {300, -0.15, 0.15}, "binning of the TempFitVar in the pT vs. TempFitVar plot"}; - ConfigurableAxis ConfTempFitVarInvMassBins{"ConfDTempFitVarInvMassBins", {6000, 0.9, 4.0}, "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 ConfBinsTempFitVar{"ConfDTempFitVarBins", {300, -0.15, 0.15}, "binning of the TempFitVar in the pT vs. TempFitVar plot"}; + ConfigurableAxis ConfBinsTempFitVarInvMass{"ConfDTempFitVarInvMassBins", {6000, 0.9, 4.0}, "binning of the TempFitVar in the pT vs. TempFitVar plot"}; + ConfigurableAxis ConfBinsTempFitVarpT{"ConfBinsTempFitVarpT", {20, 0.5, 4.05}, "pT binning of the pT vs. TempFitVar plot"}; /// Correlation part - ConfigurableAxis ConfMultBins{"ConfMultBins", {VARIABLE_WIDTH, 0.0f, 4.0f, 8.0f, 12.0f, 16.0f, 20.0f, 24.0f, 28.0f, 32.0f, 36.0f, 40.0f, 44.0f, 48.0f, 52.0f, 56.0f, 60.0f, 64.0f, 68.0f, 72.0f, 76.0f, 80.0f, 84.0f, 88.0f, 92.0f, 96.0f, 100.0f, 200.0f, 99999.f}, "Mixing bins - multiplicity"}; // \todo to be obtained from the hash task - ConfigurableAxis ConfVtxBins{"ConfVtxBins", {VARIABLE_WIDTH, -10.0f, -8.f, -6.f, -4.f, -2.f, 0.f, 2.f, 4.f, 6.f, 8.f, 10.f}, "Mixing bins - z-vertex"}; - ConfigurableAxis ConfmTBins3D{"ConfmTBins3D", {VARIABLE_WIDTH, 1.02f, 1.14f, 1.20f, 1.26f, 1.38f, 1.56f, 1.86f, 4.50f}, "mT Binning for the 3Dimensional plot: k* vs multiplicity vs mT (set <> to true in order to use)"}; - ConfigurableAxis ConfmultBins3D{"ConfmultBins3D", {VARIABLE_WIDTH, 0.0f, 20.0f, 30.0f, 40.0f, 99999.0f}, "multiplicity Binning for the 3Dimensional plot: k* vs multiplicity vs mT (set <> to true in order to use)"}; + ConfigurableAxis ConfBinsMult{"ConfBinsMult", {VARIABLE_WIDTH, 0.0f, 4.0f, 8.0f, 12.0f, 16.0f, 20.0f, 24.0f, 28.0f, 32.0f, 36.0f, 40.0f, 44.0f, 48.0f, 52.0f, 56.0f, 60.0f, 64.0f, 68.0f, 72.0f, 76.0f, 80.0f, 84.0f, 88.0f, 92.0f, 96.0f, 100.0f, 200.0f, 99999.f}, "Mixing bins - multiplicity"}; // \todo to be obtained from the hash task + ConfigurableAxis ConfBinsVtx{"ConfBinsVtx", {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 ConfBins3DmT{"ConfBins3DmT", {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 ConfBins3Dmult{"ConfBins3Dmult", {VARIABLE_WIDTH, 0.0f, 20.0f, 30.0f, 40.0f, 99999.0f}, "multiplicity Binning for the 3Dimensional plot: k* vs multiplicity vs mT (set <> to true in order to use)"}; - ColumnBinningPolicy colBinning{{ConfVtxBins, ConfMultBins}, true}; + ColumnBinningPolicy colBinning{{ConfBinsVtx, ConfBinsMult}, true}; - 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"}; + ConfigurableAxis ConfBinskstar{"ConfBinskstar", {1500, 0., 6.}, "binning kstar"}; + ConfigurableAxis ConfBinskT{"ConfBinskT", {150, 0., 9.}, "binning kT"}; + ConfigurableAxis ConfBinsmT{"ConfBinsmT", {225, 0., 7.5}, "binning mT"}; FemtoUniverseAngularContainer sameEventAngularCont; FemtoUniverseAngularContainer mixedEventAngularCont; @@ -191,13 +193,13 @@ struct femtoUniversePairTaskTrackPhi { bool IsProtonNSigma(float mom, float nsigmaTPCPr, float nsigmaTOFPr) // previous version from: https://github.com/alisw/AliPhysics/blob/master/PWGCF/FEMTOSCOPY/AliFemtoUser/AliFemtoMJTrackCut.cxx { if (mom < 0.5) { - if (TMath::Abs(nsigmaTPCPr) < ConfBothTracks.ConfNsigmaTPCProton) { + if (TMath::Abs(nsigmaTPCPr) < ConfBothTracks.ConfPIDProtonNsigmaTPC.value) { return true; } else { return false; } } else if (mom > 0.4) { - if (TMath::Hypot(nsigmaTOFPr, nsigmaTPCPr) < ConfBothTracks.ConfNsigmaCombinedProton) { + if (TMath::Hypot(nsigmaTOFPr, nsigmaTPCPr) < ConfBothTracks.ConfPIDProtonNsigmaCombined.value) { return true; } else { return false; @@ -212,9 +214,9 @@ struct femtoUniversePairTaskTrackPhi { return true; } if (mom > 0.5) { - if (TMath::Hypot(nsigmaTOFPi, nsigmaTPCPi) < ConfBothTracks.ConfNsigmaRejectPion) { + if (TMath::Hypot(nsigmaTOFPi, nsigmaTPCPi) < ConfBothTracks.ConfPIDPionNsigmaReject.value) { return true; - } else if (TMath::Hypot(nsigmaTOFK, nsigmaTPCK) < ConfBothTracks.ConfNsigmaRejectKaon) { + } else if (TMath::Hypot(nsigmaTOFK, nsigmaTPCK) < ConfBothTracks.ConfPIDKaonNsigmaReject.value) { return true; } else { return false; @@ -266,16 +268,16 @@ struct femtoUniversePairTaskTrackPhi { bool IsKaonRejected(float mom, float nsigmaTPCPr, float nsigmaTOFPr, float nsigmaTPCPi, float nsigmaTOFPi) { if (mom < 0.5) { - if (TMath::Abs(nsigmaTPCPi) < ConfBothTracks.ConfNsigmaRejectPion) { + if (TMath::Abs(nsigmaTPCPi) < ConfBothTracks.ConfPIDPionNsigmaReject.value) { return true; - } else if (TMath::Abs(nsigmaTPCPr) < ConfBothTracks.ConfNsigmaRejectProton) { + } else if (TMath::Abs(nsigmaTPCPr) < ConfBothTracks.ConfPIDProtonNsigmaReject.value) { return true; } } if (mom > 0.5) { - if (TMath::Hypot(nsigmaTOFPi, nsigmaTPCPi) < ConfBothTracks.ConfNsigmaRejectPion) { + if (TMath::Hypot(nsigmaTOFPi, nsigmaTPCPi) < ConfBothTracks.ConfPIDPionNsigmaReject.value) { return true; - } else if (TMath::Hypot(nsigmaTOFPr, nsigmaTPCPr) < ConfBothTracks.ConfNsigmaRejectProton) { + } else if (TMath::Hypot(nsigmaTOFPr, nsigmaTPCPr) < ConfBothTracks.ConfPIDProtonNsigmaReject.value) { return true; } else { return false; @@ -289,13 +291,13 @@ struct femtoUniversePairTaskTrackPhi { { if (true) { if (mom < 0.5) { - if (TMath::Abs(nsigmaTPCPi) < ConfBothTracks.ConfNsigmaTPCPion) { + if (TMath::Abs(nsigmaTPCPi) < ConfBothTracks.ConfPIDPionNsigmaTPC.value) { return true; } else { return false; } } else if (mom > 0.5) { - if (TMath::Hypot(nsigmaTOFPi, nsigmaTPCPi) < ConfBothTracks.ConfNsigmaCombinedPion) { + if (TMath::Hypot(nsigmaTOFPi, nsigmaTPCPi) < ConfBothTracks.ConfPIDPionNsigmaCombined.value) { return true; } else { return false; @@ -308,16 +310,16 @@ struct femtoUniversePairTaskTrackPhi { bool IsPionRejected(float mom, float nsigmaTPCPr, float nsigmaTOFPr, float nsigmaTPCK, float nsigmaTOFK) { if (mom < 0.5) { - if (TMath::Abs(nsigmaTPCK) < ConfBothTracks.ConfNsigmaRejectKaon) { + if (TMath::Abs(nsigmaTPCK) < ConfBothTracks.ConfPIDKaonNsigmaReject.value) { return true; - } else if (TMath::Abs(nsigmaTPCPr) < ConfBothTracks.ConfNsigmaRejectProton) { + } else if (TMath::Abs(nsigmaTPCPr) < ConfBothTracks.ConfPIDProtonNsigmaReject.value) { return true; } } if (mom > 0.5) { - if (TMath::Hypot(nsigmaTOFK, nsigmaTPCK) < ConfBothTracks.ConfNsigmaRejectKaon) { + if (TMath::Hypot(nsigmaTOFK, nsigmaTPCK) < ConfBothTracks.ConfPIDKaonNsigmaReject.value) { return true; - } else if (TMath::Hypot(nsigmaTOFPr, nsigmaTPCPr) < ConfBothTracks.ConfNsigmaRejectProton) { + } else if (TMath::Hypot(nsigmaTOFPr, nsigmaTPCPr) < ConfBothTracks.ConfPIDProtonNsigmaReject.value) { return true; } else { return false; @@ -329,7 +331,7 @@ struct femtoUniversePairTaskTrackPhi { bool IsParticleNSigmaAccepted(float mom, float nsigmaTPCPr, float nsigmaTOFPr, float nsigmaTPCPi, float nsigmaTOFPi, float nsigmaTPCK, float nsigmaTOFK) { - switch (ConfTrack.ConfPDGCodeTrack) { + switch (ConfTrack.ConfTrackPDGCode) { case 2212: // Proton case -2212: // anty Proton return IsProtonNSigma(mom, nsigmaTPCPr, nsigmaTOFPr); @@ -349,7 +351,7 @@ struct femtoUniversePairTaskTrackPhi { bool IsParticleNSigmaRejected(float mom, float nsigmaTPCPr, float nsigmaTOFPr, float nsigmaTPCPi, float nsigmaTOFPi, float nsigmaTPCK, float nsigmaTOFK) { - switch (ConfTrack.ConfPDGCodeTrack) { + switch (ConfTrack.ConfTrackPDGCode) { case 2212: // Proton case -2212: // anty Proton return IsProtonRejected(mom, nsigmaTPCPi, nsigmaTOFPi, nsigmaTPCK, nsigmaTOFK); @@ -412,22 +414,22 @@ struct femtoUniversePairTaskTrackPhi { registryMCreco.add("MCrecoPpos", "MC reco proton;#it{p}_{T} (GeV/c); #eta", {HistType::kTH2F, {{500, 0, 5}, {400, -1.0, 1.0}}}); registryMCreco.add("MCrecoPneg", "MC reco antiproton;#it{p}_{T} (GeV/c); #eta", {HistType::kTH2F, {{500, 0, 5}, {400, -1.0, 1.0}}}); - trackHistoPartPhi.init(&qaRegistry, ConfTempFitVarpTBins, ConfTempFitVarInvMassBins, ConfBothTracks.ConfIsMC, ConfPhi.ConfPDGCodePhi); - if (!ConfTrack.ConfIsSame) { - trackHistoPartTrack.init(&qaRegistry, ConfTempFitVarpTBins, ConfTempFitVarBins, ConfBothTracks.ConfIsMC, ConfTrack.ConfPDGCodeTrack); + trackHistoPartPhi.init(&qaRegistry, ConfBinsTempFitVarpT, ConfBinsTempFitVarInvMass, ConfBothTracks.ConfIsMC, ConfPhi.ConfPhiPDGCode); + if (!ConfTrack.ConfTrackIsSame) { + trackHistoPartTrack.init(&qaRegistry, ConfBinsTempFitVarpT, ConfBinsTempFitVar, ConfBothTracks.ConfIsMC, ConfTrack.ConfTrackPDGCode); } MixQaRegistry.add("MixingQA/hSECollisionBins", ";bin;Entries", kTH1F, {{120, -0.5, 119.5}}); MixQaRegistry.add("MixingQA/hMECollisionBins", ";bin;Entries", kTH1F, {{120, -0.5, 119.5}}); - sameEventAngularCont.init(&resultRegistry, ConfkstarBins, ConfMultBins, ConfkTBins, ConfmTBins, ConfmultBins3D, ConfmTBins3D, ConfBothTracks.ConfEtaBins, ConfBothTracks.ConfPhiBins, ConfBothTracks.ConfIsMC, ConfBothTracks.ConfUse3D); - mixedEventAngularCont.init(&resultRegistry, ConfkstarBins, ConfMultBins, ConfkTBins, ConfmTBins, ConfmultBins3D, ConfmTBins3D, ConfBothTracks.ConfEtaBins, ConfBothTracks.ConfPhiBins, ConfBothTracks.ConfIsMC, ConfBothTracks.ConfUse3D); + sameEventAngularCont.init(&resultRegistry, ConfBinskstar, ConfBinsMult, ConfBinskT, ConfBinsmT, ConfBins3Dmult, ConfBins3DmT, ConfBothTracks.ConfBinsEta, ConfBothTracks.ConfBinsPhi, ConfBothTracks.ConfIsMC, ConfBothTracks.ConfUse3D); + mixedEventAngularCont.init(&resultRegistry, ConfBinskstar, ConfBinsMult, ConfBinskT, ConfBinsmT, ConfBins3Dmult, ConfBins3DmT, ConfBothTracks.ConfBinsEta, ConfBothTracks.ConfBinsPhi, ConfBothTracks.ConfIsMC, ConfBothTracks.ConfUse3D); - sameEventAngularCont.setPDGCodes(ConfPhi.ConfPDGCodePhi, ConfTrack.ConfPDGCodeTrack); - mixedEventAngularCont.setPDGCodes(ConfPhi.ConfPDGCodePhi, ConfTrack.ConfPDGCodeTrack); + sameEventAngularCont.setPDGCodes(ConfPhi.ConfPhiPDGCode, ConfTrack.ConfTrackPDGCode); + mixedEventAngularCont.setPDGCodes(ConfPhi.ConfPhiPDGCode, ConfTrack.ConfTrackPDGCode); pairCleaner.init(&qaRegistry); - if (ConfCPR.ConfIsCPR.value) { + if (ConfCPR.ConfCPRIsEnabled.value) { pairCloseRejection.init(&resultRegistry, &qaRegistry, ConfCPR.ConfCPRdeltaPhiCutMin.value, ConfCPR.ConfCPRdeltaPhiCutMax.value, ConfCPR.ConfCPRdeltaEtaCutMin.value, ConfCPR.ConfCPRdeltaEtaCutMax.value, ConfCPR.ConfCPRChosenRadii.value, ConfCPR.ConfCPRPlotPerRadii.value, ConfCPR.ConfCPRInvMassCutMin.value, ConfCPR.ConfCPRInvMassCutMax.value); } @@ -439,21 +441,21 @@ struct femtoUniversePairTaskTrackPhi { long now = std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(); ccdb->setCreatedNotAfter(now); - if (!ConfEff.ConfLocalEfficiencyProton.value.empty()) { - protoneff = ccdb->getForTimeStamp(ConfEff.ConfLocalEfficiencyProton.value.c_str(), ConfEff.ConfEffProtonTimestamp.value); + if (!ConfEff.ConfEfficiencyTrackPath.value.empty()) { + protoneff = ccdb->getForTimeStamp(ConfEff.ConfEfficiencyTrackPath.value.c_str(), ConfEff.ConfEfficiencyTrackTimestamp.value); if (!protoneff || protoneff->IsZombie()) { - LOGF(fatal, "Could not load efficiency protoneff histogram from %s", ConfEff.ConfLocalEfficiencyProton.value.c_str()); + LOGF(fatal, "Could not load efficiency protoneff histogram from %s", ConfEff.ConfEfficiencyTrackPath.value.c_str()); } } - if (!ConfEff.ConfLocalEfficiencyPhi.value.empty()) { - phieff = ccdb->getForTimeStamp(ConfEff.ConfLocalEfficiencyPhi.value.c_str(), ConfEff.ConfEffPhiTimestamp.value); + if (!ConfEff.ConfEfficiencyPhiPath.value.empty()) { + phieff = ccdb->getForTimeStamp(ConfEff.ConfEfficiencyPhiPath.value.c_str(), ConfEff.ConfEfficiencyPhiTimestamp.value); if (!phieff || phieff->IsZombie()) { - LOGF(fatal, "Could not load efficiency phieff histogram from %s", ConfEff.ConfLocalEfficiencyPhi.value.c_str()); + LOGF(fatal, "Could not load efficiency phieff histogram from %s", ConfEff.ConfEfficiencyPhiPath.value.c_str()); } } - vPIDPhiCandidate = ConfPhi.ConfPIDPhi.value; - vPIDTrack = ConfTrack.ConfPIDTrack.value; + vPIDPhiCandidate = ConfPhi.ConfPhiPID.value; + vPIDTrack = ConfTrack.ConfTrackPID.value; kNsigma = ConfBothTracks.ConfTrkPIDnSigmaMax.value; } @@ -509,7 +511,7 @@ struct femtoUniversePairTaskTrackPhi { } } float tpcNSigmaPr, tofNSigmaPr, tpcNSigmaPi, tofNSigmaPi, tpcNSigmaKa, tofNSigmaKa; - if (!ConfTrack.ConfIsSame) { + if (!ConfTrack.ConfTrackIsSame) { for (auto& track : groupPartsTrack) { tpcNSigmaPi = trackCuts.getNsigmaTPC(track, o2::track::PID::Pion); tofNSigmaPi = trackCuts.getNsigmaTOF(track, o2::track::PID::Pion); @@ -518,13 +520,13 @@ struct femtoUniversePairTaskTrackPhi { tpcNSigmaPr = trackCuts.getNsigmaTPC(track, o2::track::PID::Proton); tofNSigmaPr = trackCuts.getNsigmaTOF(track, o2::track::PID::Proton); - if (ConfTrack.ConfIsTrackIdentified) { + if (ConfTrack.ConfTrackIsIdentified) { if (!IsParticleNSigmaAccepted(track.p(), tpcNSigmaPr, tofNSigmaPr, tpcNSigmaPi, tofNSigmaPi, tpcNSigmaKa, tofNSigmaKa)) { continue; } } - if (ConfTrack.ConfIsTrackRejected) { + if (ConfTrack.ConfTrackIsRejected) { if (IsParticleNSigmaRejected(track.p(), tpcNSigmaPr, tofNSigmaPr, tpcNSigmaPi, tofNSigmaPi, tpcNSigmaKa, tofNSigmaKa)) { continue; } @@ -542,20 +544,20 @@ struct femtoUniversePairTaskTrackPhi { } /// Now build the combinations for (auto& [track, phicandidate] : combinations(CombinationsFullIndexPolicy(groupPartsTrack, groupPartsPhi))) { - if (ConfTrack.ConfIsTrackIdentified) { + if (ConfTrack.ConfTrackIsIdentified) { if (!IsParticleNSigmaAccepted(track.p(), trackCuts.getNsigmaTPC(track, o2::track::PID::Proton), trackCuts.getNsigmaTOF(track, o2::track::PID::Proton), trackCuts.getNsigmaTPC(track, o2::track::PID::Pion), trackCuts.getNsigmaTOF(track, o2::track::PID::Pion), trackCuts.getNsigmaTPC(track, o2::track::PID::Kaon), trackCuts.getNsigmaTOF(track, o2::track::PID::Kaon))) { continue; } } - if (ConfTrack.ConfIsTrackRejected) { + if (ConfTrack.ConfTrackIsRejected) { if (IsParticleNSigmaRejected(track.p(), trackCuts.getNsigmaTPC(track, o2::track::PID::Proton), trackCuts.getNsigmaTOF(track, o2::track::PID::Proton), trackCuts.getNsigmaTPC(track, o2::track::PID::Pion), trackCuts.getNsigmaTOF(track, o2::track::PID::Pion), trackCuts.getNsigmaTPC(track, o2::track::PID::Kaon), trackCuts.getNsigmaTOF(track, o2::track::PID::Kaon))) { continue; } } // // Close Pair Rejection - if (ConfCPR.ConfIsCPR.value) { + if (ConfCPR.ConfCPRIsEnabled.value) { if (pairCloseRejection.isClosePair(track, phicandidate, parts, magFieldTesla, femtoUniverseContainer::EventType::same)) { continue; } @@ -655,19 +657,19 @@ struct femtoUniversePairTaskTrackPhi { { for (auto& [track, phicandidate] : combinations(CombinationsFullIndexPolicy(groupPartsTrack, groupPartsPhi))) { - if (ConfTrack.ConfIsTrackIdentified) { + if (ConfTrack.ConfTrackIsIdentified) { if (!IsParticleNSigmaAccepted(track.p(), trackCuts.getNsigmaTPC(track, o2::track::PID::Proton), trackCuts.getNsigmaTOF(track, o2::track::PID::Proton), trackCuts.getNsigmaTPC(track, o2::track::PID::Pion), trackCuts.getNsigmaTOF(track, o2::track::PID::Pion), trackCuts.getNsigmaTPC(track, o2::track::PID::Kaon), trackCuts.getNsigmaTOF(track, o2::track::PID::Kaon))) { continue; } } - if (ConfTrack.ConfIsTrackRejected) { + if (ConfTrack.ConfTrackIsRejected) { if (IsParticleNSigmaRejected(track.p(), trackCuts.getNsigmaTPC(track, o2::track::PID::Proton), trackCuts.getNsigmaTOF(track, o2::track::PID::Proton), trackCuts.getNsigmaTPC(track, o2::track::PID::Pion), trackCuts.getNsigmaTOF(track, o2::track::PID::Pion), trackCuts.getNsigmaTPC(track, o2::track::PID::Kaon), trackCuts.getNsigmaTOF(track, o2::track::PID::Kaon))) { continue; } } - if (ConfCPR.ConfIsCPR.value) { + if (ConfCPR.ConfCPRIsEnabled.value) { if (pairCloseRejection.isClosePair(track, phicandidate, parts, magFieldTesla, femtoUniverseContainer::EventType::mixed)) { continue; } diff --git a/PWGCF/Flow/Tasks/FlowTask.cxx b/PWGCF/Flow/Tasks/FlowTask.cxx index 2b9cd8e1be7..983c44abddb 100644 --- a/PWGCF/Flow/Tasks/FlowTask.cxx +++ b/PWGCF/Flow/Tasks/FlowTask.cxx @@ -47,14 +47,20 @@ using namespace o2::framework::expressions; struct FlowTask { + O2_DEFINE_CONFIGURABLE(cfgFilterFlag, int, 0, "0 for IsGlobalTrack, 1 for IsGlobalTrackSDD, 2 for IsGlobalTrackWoTPCCluster, 3 for IsGlobalTrackWoPtEta, 4 for IsGlobalTrackWoDCA, 5 for IsGlobalTrackWoDCATPCCluster") O2_DEFINE_CONFIGURABLE(cfgCutVertex, float, 10.0f, "Accepted z-vertex range") O2_DEFINE_CONFIGURABLE(cfgCutPtPOIMin, float, 0.2f, "Minimal pT for poi tracks") O2_DEFINE_CONFIGURABLE(cfgCutPtPOIMax, float, 10.0f, "Maximal pT for poi tracks") - O2_DEFINE_CONFIGURABLE(cfgCutPtMin, float, 0.2f, "Minimal pT for ref tracks") - O2_DEFINE_CONFIGURABLE(cfgCutPtMax, float, 3.0f, "Maximal pT for ref tracks") + O2_DEFINE_CONFIGURABLE(cfgCutPtRefMin, float, 0.2f, "Minimal pT for ref tracks") + O2_DEFINE_CONFIGURABLE(cfgCutPtRefMax, float, 3.0f, "Maximal pT for ref tracks") + O2_DEFINE_CONFIGURABLE(cfgCutPtMin, float, 0.2f, "Minimal pT for all tracks") + O2_DEFINE_CONFIGURABLE(cfgCutPtMax, float, 10.0f, "Maximal pT for all tracks") O2_DEFINE_CONFIGURABLE(cfgCutEta, float, 0.8f, "Eta range for tracks") - O2_DEFINE_CONFIGURABLE(cfgCutChi2prTPCcls, float, 2.5, "Chi2 per TPC clusters") + O2_DEFINE_CONFIGURABLE(cfgCutChi2prTPCcls, float, 2.5f, "max chi2 per TPC clusters") + O2_DEFINE_CONFIGURABLE(cfgCutChi2prITScls, float, 36.0f, "max chi2 per cluster ITS") O2_DEFINE_CONFIGURABLE(cfgCutTPCclu, float, 70.0f, "minimum TPC clusters") + O2_DEFINE_CONFIGURABLE(cfgCutDCAz, float, 2.0f, "max DCA to vertex z") + O2_DEFINE_CONFIGURABLE(cfgCutDCAxy, float, 3.675e-4f, "max DCA to vertex xy, default 0.0105 * 0.035 * pT^-1.1") O2_DEFINE_CONFIGURABLE(cfgUseAdditionalEventCut, bool, false, "Use additional event cut on mult correlations") O2_DEFINE_CONFIGURABLE(cfgUseAdditionalTrackCut, bool, false, "Use additional track cut on phi") O2_DEFINE_CONFIGURABLE(cfgGetInteractionRate, bool, false, "Get interaction rate from CCDB") @@ -68,6 +74,7 @@ struct FlowTask { O2_DEFINE_CONFIGURABLE(cfgMagnetField, std::string, "GLO/Config/GRPMagField", "CCDB path to Magnet field object") O2_DEFINE_CONFIGURABLE(cfgCutOccupancyHigh, int, 500, "High cut on TPC occupancy") O2_DEFINE_CONFIGURABLE(cfgCutOccupancyLow, int, 0, "Low cut on TPC occupancy") + O2_DEFINE_CONFIGURABLE(cfgUseSmallMemory, bool, false, "Use small memory mode") 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"}; @@ -87,7 +94,7 @@ struct FlowTask { ConfigurableAxis axisDCAxy{"axisDCAxy", {200, -1, 1}, "DCA_{xy} (cm)"}; Filter collisionFilter = nabs(aod::collision::posZ) < cfgCutVertex; - Filter trackFilter = (nabs(aod::track::eta) < cfgCutEta) && ((requireGlobalTrackInFilter()) || (aod::track::isGlobalTrackSDD == (uint8_t) true)) && (aod::track::tpcChi2NCl < cfgCutChi2prTPCcls); + Filter trackFilter = (nabs(aod::track::eta) < cfgCutEta) && (aod::track::pt > cfgCutPtMin) && (aod::track::pt < cfgCutPtMax) && (aod::track::tpcChi2NCl < cfgCutChi2prTPCcls) && (aod::track::itsChi2NCl < cfgCutChi2prITScls); // Corrections TH1D* mEfficiency = nullptr; @@ -158,20 +165,22 @@ struct FlowTask { registry.add("hVtxZ", "Vexter Z distribution", {HistType::kTH1D, {axisVertex}}); registry.add("hMult", "Multiplicity distribution", {HistType::kTH1D, {{3000, 0.5, 3000.5}}}); registry.add("hCent", "Centrality distribution", {HistType::kTH1D, {{90, 0, 90}}}); - registry.add("BeforeCut_globalTracks_centT0C", "before cut;Centrality T0C;mulplicity global tracks", {HistType::kTH2D, {axisCentForQA, axisNch}}); - registry.add("BeforeCut_PVTracks_centT0C", "before cut;Centrality T0C;mulplicity PV tracks", {HistType::kTH2D, {axisCentForQA, axisNchPV}}); - registry.add("BeforeCut_globalTracks_PVTracks", "before cut;mulplicity PV tracks;mulplicity global tracks", {HistType::kTH2D, {axisNchPV, axisNch}}); - registry.add("BeforeCut_globalTracks_multT0A", "before cut;mulplicity T0A;mulplicity global tracks", {HistType::kTH2D, {axisT0A, axisNch}}); - registry.add("BeforeCut_globalTracks_multV0A", "before cut;mulplicity V0A;mulplicity global tracks", {HistType::kTH2D, {axisT0A, axisNch}}); - registry.add("BeforeCut_multV0A_multT0A", "before cut;mulplicity T0A;mulplicity V0A", {HistType::kTH2D, {axisT0A, axisT0A}}); - registry.add("BeforeCut_multT0C_centT0C", "before cut;Centrality T0C;mulplicity T0C", {HistType::kTH2D, {axisCentForQA, axisT0C}}); - registry.add("globalTracks_centT0C", "after cut;Centrality T0C;mulplicity global tracks", {HistType::kTH2D, {axisCentForQA, axisNch}}); - registry.add("PVTracks_centT0C", "after cut;Centrality T0C;mulplicity PV tracks", {HistType::kTH2D, {axisCentForQA, axisNchPV}}); - registry.add("globalTracks_PVTracks", "after cut;mulplicity PV tracks;mulplicity global tracks", {HistType::kTH2D, {axisNchPV, axisNch}}); - registry.add("globalTracks_multT0A", "after cut;mulplicity T0A;mulplicity global tracks", {HistType::kTH2D, {axisT0A, axisNch}}); - registry.add("globalTracks_multV0A", "after cut;mulplicity V0A;mulplicity global tracks", {HistType::kTH2D, {axisT0A, axisNch}}); - registry.add("multV0A_multT0A", "after cut;mulplicity T0A;mulplicity V0A", {HistType::kTH2D, {axisT0A, axisT0A}}); - registry.add("multT0C_centT0C", "after cut;Centrality T0C;mulplicity T0C", {HistType::kTH2D, {axisCentForQA, axisT0C}}); + if (!cfgUseSmallMemory) { + registry.add("BeforeCut_globalTracks_centT0C", "before cut;Centrality T0C;mulplicity global tracks", {HistType::kTH2D, {axisCentForQA, axisNch}}); + registry.add("BeforeCut_PVTracks_centT0C", "before cut;Centrality T0C;mulplicity PV tracks", {HistType::kTH2D, {axisCentForQA, axisNchPV}}); + registry.add("BeforeCut_globalTracks_PVTracks", "before cut;mulplicity PV tracks;mulplicity global tracks", {HistType::kTH2D, {axisNchPV, axisNch}}); + registry.add("BeforeCut_globalTracks_multT0A", "before cut;mulplicity T0A;mulplicity global tracks", {HistType::kTH2D, {axisT0A, axisNch}}); + registry.add("BeforeCut_globalTracks_multV0A", "before cut;mulplicity V0A;mulplicity global tracks", {HistType::kTH2D, {axisT0A, axisNch}}); + registry.add("BeforeCut_multV0A_multT0A", "before cut;mulplicity T0A;mulplicity V0A", {HistType::kTH2D, {axisT0A, axisT0A}}); + registry.add("BeforeCut_multT0C_centT0C", "before cut;Centrality T0C;mulplicity T0C", {HistType::kTH2D, {axisCentForQA, axisT0C}}); + registry.add("globalTracks_centT0C", "after cut;Centrality T0C;mulplicity global tracks", {HistType::kTH2D, {axisCentForQA, axisNch}}); + registry.add("PVTracks_centT0C", "after cut;Centrality T0C;mulplicity PV tracks", {HistType::kTH2D, {axisCentForQA, axisNchPV}}); + registry.add("globalTracks_PVTracks", "after cut;mulplicity PV tracks;mulplicity global tracks", {HistType::kTH2D, {axisNchPV, axisNch}}); + registry.add("globalTracks_multT0A", "after cut;mulplicity T0A;mulplicity global tracks", {HistType::kTH2D, {axisT0A, axisNch}}); + registry.add("globalTracks_multV0A", "after cut;mulplicity V0A;mulplicity global tracks", {HistType::kTH2D, {axisT0A, axisNch}}); + registry.add("multV0A_multT0A", "after cut;mulplicity T0A;mulplicity V0A", {HistType::kTH2D, {axisT0A, axisT0A}}); + registry.add("multT0C_centT0C", "after cut;Centrality T0C;mulplicity T0C", {HistType::kTH2D, {axisCentForQA, axisT0C}}); + } // Track QA registry.add("hPhi", "#phi distribution", {HistType::kTH1D, {axisPhi}}); registry.add("hPhiWeighted", "corrected #phi distribution", {HistType::kTH1D, {axisPhi}}); @@ -181,30 +190,33 @@ struct FlowTask { registry.add("pt_phi_bef", "before cut;p_{T};#phi_{modn}", {HistType::kTH2D, {axisPt, axisPhiMod}}); registry.add("pt_phi_aft", "after cut;p_{T};#phi_{modn}", {HistType::kTH2D, {axisPt, axisPhiMod}}); registry.add("hChi2prTPCcls", "#chi^{2}/cluster for the TPC track segment", {HistType::kTH1D, {{100, 0., 5.}}}); + registry.add("hChi2prITScls", "#chi^{2}/cluster for the ITS track", {HistType::kTH1D, {{100, 0., 50.}}}); registry.add("hnTPCClu", "Number of found TPC clusters", {HistType::kTH1D, {{100, 40, 180}}}); registry.add("hnTPCCrossedRow", "Number of crossed TPC Rows", {HistType::kTH1D, {{100, 40, 180}}}); registry.add("hDCAz", "DCAz after cuts", {HistType::kTH1D, {{100, -3, 3}}}); registry.add("hDCAxy", "DCAxy after cuts; DCAxy (cm); Pt", {HistType::kTH2D, {{50, -1, 1}, {50, 0, 10}}}); registry.add("hTrackCorrection2d", "Correlation table for number of tracks table; uncorrected track; corrected track", {HistType::kTH2D, {axisNch, axisNch}}); - // additional Output histograms - registry.add("hMeanPt", "", {HistType::kTProfile, {axisIndependent}}); - registry.add("hMeanPtWithinGap08", "", {HistType::kTProfile, {axisIndependent}}); - registry.add("c22_gap08_Weff", "", {HistType::kTProfile, {axisIndependent}}); - registry.add("c22_gap08_trackMeanPt", "", {HistType::kTProfile, {axisIndependent}}); - registry.add("PtVariance_partA_WithinGap08", "", {HistType::kTProfile, {axisIndependent}}); - registry.add("PtVariance_partB_WithinGap08", "", {HistType::kTProfile, {axisIndependent}}); - - // initial array - BootstrapArray.resize(cfgNbootstrap); - for (int i = 0; i < cfgNbootstrap; i++) { - BootstrapArray[i].resize(kCount_ExtraProfile); - } - for (int i = 0; i < cfgNbootstrap; i++) { - BootstrapArray[i][kMeanPt_InGap08] = registry.add(Form("BootstrapContainer_%d/hMeanPtWithinGap08", i), "", {HistType::kTProfile, {axisIndependent}}); - BootstrapArray[i][kC22_Gap08_Weff] = registry.add(Form("BootstrapContainer_%d/c22_gap08_Weff", i), "", {HistType::kTProfile, {axisIndependent}}); - BootstrapArray[i][kC22_Gap08_MeanPt] = registry.add(Form("BootstrapContainer_%d/c22_gap08_trackMeanPt", i), "", {HistType::kTProfile, {axisIndependent}}); - BootstrapArray[i][kPtVarParA_InGap08] = registry.add(Form("BootstrapContainer_%d/PtVariance_partA_WithinGap08", i), "", {HistType::kTProfile, {axisIndependent}}); - BootstrapArray[i][kPtVarParB_InGap08] = registry.add(Form("BootstrapContainer_%d/PtVariance_partB_WithinGap08", i), "", {HistType::kTProfile, {axisIndependent}}); + if (!cfgUseSmallMemory) { + // additional Output histograms + registry.add("hMeanPt", "", {HistType::kTProfile, {axisIndependent}}); + registry.add("hMeanPtWithinGap08", "", {HistType::kTProfile, {axisIndependent}}); + registry.add("c22_gap08_Weff", "", {HistType::kTProfile, {axisIndependent}}); + registry.add("c22_gap08_trackMeanPt", "", {HistType::kTProfile, {axisIndependent}}); + registry.add("PtVariance_partA_WithinGap08", "", {HistType::kTProfile, {axisIndependent}}); + registry.add("PtVariance_partB_WithinGap08", "", {HistType::kTProfile, {axisIndependent}}); + + // initial array + BootstrapArray.resize(cfgNbootstrap); + for (int i = 0; i < cfgNbootstrap; i++) { + BootstrapArray[i].resize(kCount_ExtraProfile); + } + for (int i = 0; i < cfgNbootstrap; i++) { + BootstrapArray[i][kMeanPt_InGap08] = registry.add(Form("BootstrapContainer_%d/hMeanPtWithinGap08", i), "", {HistType::kTProfile, {axisIndependent}}); + BootstrapArray[i][kC22_Gap08_Weff] = registry.add(Form("BootstrapContainer_%d/c22_gap08_Weff", i), "", {HistType::kTProfile, {axisIndependent}}); + BootstrapArray[i][kC22_Gap08_MeanPt] = registry.add(Form("BootstrapContainer_%d/c22_gap08_trackMeanPt", i), "", {HistType::kTProfile, {axisIndependent}}); + BootstrapArray[i][kPtVarParA_InGap08] = registry.add(Form("BootstrapContainer_%d/PtVariance_partA_WithinGap08", i), "", {HistType::kTProfile, {axisIndependent}}); + BootstrapArray[i][kPtVarParB_InGap08] = registry.add(Form("BootstrapContainer_%d/PtVariance_partB_WithinGap08", i), "", {HistType::kTProfile, {axisIndependent}}); + } } o2::framework::AxisSpec axis = axisPt; @@ -231,14 +243,23 @@ struct FlowTask { oba->Add(new TNamed("Ch06Gap22", "Ch06Gap22")); oba->Add(new TNamed("Ch08Gap22", "Ch08Gap22")); oba->Add(new TNamed("Ch10Gap22", "Ch10Gap22")); + for (Int_t i = 0; i < fPtAxis->GetNbins(); i++) + oba->Add(new TNamed(Form("Ch10Gap22_pt_%i", i + 1), "Ch10Gap22_pTDiff")); + oba->Add(new TNamed("Ch12Gap22", "Ch12Gap22")); oba->Add(new TNamed("Ch04Gap32", "Ch04Gap32")); oba->Add(new TNamed("Ch06Gap32", "Ch06Gap32")); oba->Add(new TNamed("Ch08Gap32", "Ch08Gap32")); oba->Add(new TNamed("Ch10Gap32", "Ch10Gap32")); + for (Int_t i = 0; i < fPtAxis->GetNbins(); i++) + oba->Add(new TNamed(Form("Ch10Gap32_pt_%i", i + 1), "Ch10Gap32_pTDiff")); + oba->Add(new TNamed("Ch12Gap32", "Ch12Gap32")); oba->Add(new TNamed("Ch04Gap42", "Ch04Gap42")); oba->Add(new TNamed("Ch06Gap42", "Ch06Gap42")); oba->Add(new TNamed("Ch08Gap42", "Ch08Gap42")); oba->Add(new TNamed("Ch10Gap42", "Ch10Gap42")); + for (Int_t i = 0; i < fPtAxis->GetNbins(); i++) + oba->Add(new TNamed(Form("Ch10Gap42_pt_%i", i + 1), "Ch10Gap42_pTDiff")); + oba->Add(new TNamed("Ch12Gap42", "Ch12Gap42")); oba->Add(new TNamed("ChFull422", "ChFull422")); oba->Add(new TNamed("Ch04GapA422", "Ch04GapA422")); oba->Add(new TNamed("Ch04GapB422", "Ch04GapB422")); @@ -255,7 +276,7 @@ struct FlowTask { std::vector UserDefineGFWCorr = cfgUserDefineGFWCorr; std::vector UserDefineGFWName = cfgUserDefineGFWName; if (!UserDefineGFWCorr.empty() && !UserDefineGFWName.empty()) { - for (int i = 0; i < UserDefineGFWName.size(); i++) { + for (auto i = 0; i < UserDefineGFWName.size(); i++) { oba->Add(new TNamed(UserDefineGFWName.at(i).c_str(), UserDefineGFWName.at(i).c_str())); } } @@ -284,7 +305,9 @@ struct FlowTask { fGFW->AddRegion("refP", 0.4, 0.8, 1, 1); fGFW->AddRegion("refM", -0.4, 0.4, 1, 1); fGFW->AddRegion("poiN", -0.8, -0.4, 1 + fPtAxis->GetNbins(), 2); + fGFW->AddRegion("poiN10", -0.8, -0.5, 1 + fPtAxis->GetNbins(), 2); fGFW->AddRegion("olN", -0.8, -0.4, 1, 4); + fGFW->AddRegion("olN10", -0.8, -0.5, 1, 4); corrconfigs.push_back(fGFW->GetCorrelatorConfig("full {2 -2}", "ChFull22", kFALSE)); corrconfigs.push_back(fGFW->GetCorrelatorConfig("full {3 -3}", "ChFull32", kFALSE)); @@ -295,16 +318,22 @@ struct FlowTask { corrconfigs.push_back(fGFW->GetCorrelatorConfig("refN06 {2} refP06 {-2}", "Ch06Gap22", kFALSE)); corrconfigs.push_back(fGFW->GetCorrelatorConfig("refN08 {2} refP08 {-2}", "Ch08Gap22", kFALSE)); corrconfigs.push_back(fGFW->GetCorrelatorConfig("refN10 {2} refP10 {-2}", "Ch10Gap22", kFALSE)); + corrconfigs.push_back(fGFW->GetCorrelatorConfig("refN12 {2} refP12 {-2}", "Ch12Gap22", kFALSE)); corrconfigs.push_back(fGFW->GetCorrelatorConfig("refN04 {3} refP04 {-3}", "Ch04Gap32", kFALSE)); corrconfigs.push_back(fGFW->GetCorrelatorConfig("refN06 {3} refP06 {-3}", "Ch06Gap32", kFALSE)); corrconfigs.push_back(fGFW->GetCorrelatorConfig("refN08 {3} refP08 {-3}", "Ch08Gap32", kFALSE)); corrconfigs.push_back(fGFW->GetCorrelatorConfig("refN10 {3} refP10 {-3}", "Ch10Gap32", kFALSE)); + corrconfigs.push_back(fGFW->GetCorrelatorConfig("refN12 {3} refP12 {-3}", "Ch12Gap32", kFALSE)); corrconfigs.push_back(fGFW->GetCorrelatorConfig("refN04 {4} refP04 {-4}", "Ch04Gap42", kFALSE)); corrconfigs.push_back(fGFW->GetCorrelatorConfig("refN06 {4} refP06 {-4}", "Ch06Gap42", kFALSE)); corrconfigs.push_back(fGFW->GetCorrelatorConfig("refN08 {4} refP08 {-4}", "Ch08Gap42", kFALSE)); corrconfigs.push_back(fGFW->GetCorrelatorConfig("refN10 {4} refP10 {-4}", "Ch10Gap42", kFALSE)); + corrconfigs.push_back(fGFW->GetCorrelatorConfig("refN12 {4} refP12 {-4}", "Ch12Gap42", kFALSE)); corrconfigs.push_back(fGFW->GetCorrelatorConfig("refN {2} refP {-2}", "ChGap22", kFALSE)); corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiN refN | olN {2} refP {-2}", "ChGap22", kTRUE)); + corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiN10 refN10 | olN10 {2} refP10 {-2}", "Ch10Gap22", kTRUE)); + corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiN10 refN10 | olN10 {3} refP10 {-3}", "Ch10Gap32", kTRUE)); + corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiN10 refN10 | olN10 {4} refP10 {-4}", "Ch10Gap42", kTRUE)); corrconfigs.push_back(fGFW->GetCorrelatorConfig("full {4 -2 -2}", "ChFull422", kFALSE)); corrconfigs.push_back(fGFW->GetCorrelatorConfig("refN04 {-2 -2} refP04 {4}", "Ch04GapA422", kFALSE)); corrconfigs.push_back(fGFW->GetCorrelatorConfig("refN04 {4} refP04 {-2 -2}", "Ch04GapB422", kFALSE)); @@ -321,7 +350,7 @@ struct FlowTask { if (!UserDefineGFWCorr.empty() && !UserDefineGFWName.empty()) { LOGF(info, "User adding GFW CorrelatorConfig:"); // attentaion: here we follow the index of cfgUserDefineGFWCorr - for (int i = 0; i < UserDefineGFWCorr.size(); i++) { + for (auto i = 0; i < UserDefineGFWCorr.size(); i++) { if (i >= UserDefineGFWName.size()) { LOGF(fatal, "The names you provided are more than configurations. UserDefineGFWName.size(): %d > UserDefineGFWCorr.size(): %d", UserDefineGFWName.size(), UserDefineGFWCorr.size()); break; @@ -510,7 +539,7 @@ struct FlowTask { auto multNTracksPV = collision.multNTracksPV(); auto occupancy = collision.trackOccupancyInTimeRange(); - if (abs(vtxz) > cfgCutVertex) + if (fabs(vtxz) > cfgCutVertex) return 0; if (multNTracksPV < fMultPVCutLow->Eval(centrality)) return 0; @@ -524,7 +553,7 @@ struct FlowTask { return 0; // V0A T0A 5 sigma cut - if (abs(collision.multFV0A() - fT0AV0AMean->Eval(collision.multFT0A())) > 5 * fT0AV0ASigma->Eval(collision.multFT0A())) + if (fabs(collision.multFV0A() - fT0AV0AMean->Eval(collision.multFT0A())) > 5 * fT0AV0ASigma->Eval(collision.multFT0A())) return 0; return 1; @@ -545,7 +574,28 @@ struct FlowTask { } template - bool trackSelected(TTrack track, const int field) + bool trackSelected(TTrack track) + { + switch (cfgFilterFlag) { + case 0: + return track.isGlobalTrack(); + case 1: + return (track.isGlobalTrackSDD() == (uint8_t) true); + case 2: + return (track.isGlobalTrackWoTPCCluster() && track.tpcNClsFound() >= cfgCutTPCclu); + case 3: + return (track.isGlobalTrackWoPtEta() && (fabs(track.eta()) < cfgCutEta) && (track.pt() > cfgCutPtMin) && (track.pt() < cfgCutPtMax)); + case 4: + return (track.isGlobalTrackWoDCA() && fabs(track.dcaZ()) <= cfgCutDCAz && fabs(track.dcaXY()) <= cfgCutDCAxy * pow(track.pt(), -1.1)); + case 5: + return (track.isGlobalTrackWoDCATPCCluster() && fabs(track.dcaZ()) <= cfgCutDCAz && fabs(track.dcaXY()) <= cfgCutDCAxy * pow(track.pt(), -1.1) && track.tpcNClsFound() >= cfgCutTPCclu); + default: + return false; + } + } + + template + bool AdditionaltrackSelected(TTrack track, const int field) { double phimodn = track.phi(); if (field < 0) // for negative polarity field @@ -588,13 +638,15 @@ struct FlowTask { return; if (tracks.size() < 1) return; - registry.fill(HIST("BeforeCut_globalTracks_centT0C"), collision.centFT0C(), tracks.size()); - registry.fill(HIST("BeforeCut_PVTracks_centT0C"), collision.centFT0C(), collision.multNTracksPV()); - registry.fill(HIST("BeforeCut_globalTracks_PVTracks"), collision.multNTracksPV(), tracks.size()); - registry.fill(HIST("BeforeCut_globalTracks_multT0A"), collision.multFT0A(), tracks.size()); - registry.fill(HIST("BeforeCut_globalTracks_multV0A"), collision.multFV0A(), tracks.size()); - registry.fill(HIST("BeforeCut_multV0A_multT0A"), collision.multFT0A(), collision.multFV0A()); - registry.fill(HIST("BeforeCut_multT0C_centT0C"), collision.centFT0C(), collision.multFT0C()); + if (!cfgUseSmallMemory) { + registry.fill(HIST("BeforeCut_globalTracks_centT0C"), collision.centFT0C(), tracks.size()); + registry.fill(HIST("BeforeCut_PVTracks_centT0C"), collision.centFT0C(), collision.multNTracksPV()); + registry.fill(HIST("BeforeCut_globalTracks_PVTracks"), collision.multNTracksPV(), tracks.size()); + registry.fill(HIST("BeforeCut_globalTracks_multT0A"), collision.multFT0A(), tracks.size()); + registry.fill(HIST("BeforeCut_globalTracks_multV0A"), collision.multFV0A(), tracks.size()); + registry.fill(HIST("BeforeCut_multV0A_multT0A"), collision.multFT0A(), collision.multFV0A()); + registry.fill(HIST("BeforeCut_multT0C_centT0C"), collision.centFT0C(), collision.multFT0C()); + } registry.fill(HIST("hEventCount"), 1.5); // place holder for pile-up rejection registry.fill(HIST("hEventCount"), 2.5); @@ -621,13 +673,15 @@ struct FlowTask { registry.fill(HIST("hEventCount"), 4.5); // fill event QA - registry.fill(HIST("globalTracks_centT0C"), collision.centFT0C(), tracks.size()); - registry.fill(HIST("PVTracks_centT0C"), collision.centFT0C(), collision.multNTracksPV()); - registry.fill(HIST("globalTracks_PVTracks"), collision.multNTracksPV(), tracks.size()); - registry.fill(HIST("globalTracks_multT0A"), collision.multFT0A(), tracks.size()); - registry.fill(HIST("globalTracks_multV0A"), collision.multFV0A(), tracks.size()); - registry.fill(HIST("multV0A_multT0A"), collision.multFT0A(), collision.multFV0A()); - registry.fill(HIST("multT0C_centT0C"), collision.centFT0C(), collision.multFT0C()); + if (!cfgUseSmallMemory) { + registry.fill(HIST("globalTracks_centT0C"), collision.centFT0C(), tracks.size()); + registry.fill(HIST("PVTracks_centT0C"), collision.centFT0C(), collision.multNTracksPV()); + registry.fill(HIST("globalTracks_PVTracks"), collision.multNTracksPV(), tracks.size()); + registry.fill(HIST("globalTracks_multT0A"), collision.multFT0A(), tracks.size()); + registry.fill(HIST("globalTracks_multV0A"), collision.multFV0A(), tracks.size()); + registry.fill(HIST("multV0A_multT0A"), collision.multFT0A(), collision.multFV0A()); + registry.fill(HIST("multT0C_centT0C"), collision.centFT0C(), collision.multFT0C()); + } // track weights float weff = 1, wacc = 1; @@ -646,16 +700,16 @@ struct FlowTask { independent = static_cast(tracks.size()); for (auto& track : tracks) { - if (track.tpcNClsFound() < cfgCutTPCclu) + if (!trackSelected(track)) continue; - if (cfgUseAdditionalTrackCut && !trackSelected(track, Magnetfield)) + if (cfgUseAdditionalTrackCut && !AdditionaltrackSelected(track, Magnetfield)) continue; if (cfgOutputNUAWeights) fWeights->Fill(track.phi(), track.eta(), vtxz, track.pt(), cent, 0); if (!setCurrentParticleWeights(weff, wacc, track.phi(), track.eta(), track.pt(), vtxz)) continue; bool WithinPtPOI = (cfgCutPtPOIMin < track.pt()) && (track.pt() < cfgCutPtPOIMax); // within POI pT range - bool WithinPtRef = (cfgCutPtMin < track.pt()) && (track.pt() < cfgCutPtMax); // within RF pT range + bool WithinPtRef = (cfgCutPtRefMin < track.pt()) && (track.pt() < cfgCutPtRefMax); // within RF pT range bool WithinEtaGap08 = (track.eta() >= -0.4) && (track.eta() <= 0.4); registry.fill(HIST("hPt"), track.pt()); if (WithinPtRef) { @@ -664,6 +718,7 @@ struct FlowTask { registry.fill(HIST("hEta"), track.eta()); registry.fill(HIST("hPtRef"), track.pt()); registry.fill(HIST("hChi2prTPCcls"), track.tpcChi2NCl()); + registry.fill(HIST("hChi2prITScls"), track.itsChi2NCl()); registry.fill(HIST("hnTPCClu"), track.tpcNClsFound()); registry.fill(HIST("hnTPCCrossedRow"), track.tpcNClsCrossedRows()); registry.fill(HIST("hDCAz"), track.dcaZ()); @@ -688,40 +743,42 @@ struct FlowTask { } registry.fill(HIST("hTrackCorrection2d"), tracks.size(), NTracksCorrected); - double WeffEvent_diff_WithGap08 = weffEvent_WithinGap08 * weffEvent_WithinGap08 - weffEventSquare_WithinGap08; - // Filling TProfile - // MeanPt - if (weffEvent > 1e-6) - registry.fill(HIST("hMeanPt"), independent, ptSum / weffEvent, weffEvent); - if (weffEvent_WithinGap08 > 1e-6) - registry.fill(HIST("hMeanPtWithinGap08"), independent, ptSum_Gap08 / weffEvent_WithinGap08, weffEvent_WithinGap08); - // v22-Pt - // c22_gap8 * pt_withGap8 - if (weffEvent_WithinGap08 > 1e-6) - FillpTvnProfile(corrconfigs.at(7), ptSum_Gap08, weffEvent_WithinGap08, HIST("c22_gap08_Weff"), HIST("c22_gap08_trackMeanPt"), independent); - // PtVariance - if (WeffEvent_diff_WithGap08 > 1e-6) { - registry.fill(HIST("PtVariance_partA_WithinGap08"), independent, - (ptSum_Gap08 * ptSum_Gap08 - sum_ptSquare_wSquare_WithinGap08) / WeffEvent_diff_WithGap08, - WeffEvent_diff_WithGap08); - registry.fill(HIST("PtVariance_partB_WithinGap08"), independent, - (weffEvent_WithinGap08 * ptSum_Gap08 - sum_pt_wSquare_WithinGap08) / WeffEvent_diff_WithGap08, - WeffEvent_diff_WithGap08); - } - - // Filling Bootstrap Samples - int SampleIndex = static_cast(cfgNbootstrap * l_Random); - if (weffEvent_WithinGap08 > 1e-6) - BootstrapArray[SampleIndex][kMeanPt_InGap08]->Fill(independent, ptSum_Gap08 / weffEvent_WithinGap08, weffEvent_WithinGap08); - if (weffEvent_WithinGap08 > 1e-6) - FillpTvnProfile(corrconfigs.at(7), ptSum_Gap08, weffEvent_WithinGap08, BootstrapArray[SampleIndex][kC22_Gap08_Weff], BootstrapArray[SampleIndex][kC22_Gap08_MeanPt], independent); - if (WeffEvent_diff_WithGap08 > 1e-6) { - BootstrapArray[SampleIndex][kPtVarParA_InGap08]->Fill(independent, - (ptSum_Gap08 * ptSum_Gap08 - sum_ptSquare_wSquare_WithinGap08) / WeffEvent_diff_WithGap08, - WeffEvent_diff_WithGap08); - BootstrapArray[SampleIndex][kPtVarParB_InGap08]->Fill(independent, - (weffEvent_WithinGap08 * ptSum_Gap08 - sum_pt_wSquare_WithinGap08) / WeffEvent_diff_WithGap08, - WeffEvent_diff_WithGap08); + if (!cfgUseSmallMemory) { + double WeffEvent_diff_WithGap08 = weffEvent_WithinGap08 * weffEvent_WithinGap08 - weffEventSquare_WithinGap08; + // Filling TProfile + // MeanPt + if (weffEvent > 1e-6) + registry.fill(HIST("hMeanPt"), independent, ptSum / weffEvent, weffEvent); + if (weffEvent_WithinGap08 > 1e-6) + registry.fill(HIST("hMeanPtWithinGap08"), independent, ptSum_Gap08 / weffEvent_WithinGap08, weffEvent_WithinGap08); + // v22-Pt + // c22_gap8 * pt_withGap8 + if (weffEvent_WithinGap08 > 1e-6) + FillpTvnProfile(corrconfigs.at(7), ptSum_Gap08, weffEvent_WithinGap08, HIST("c22_gap08_Weff"), HIST("c22_gap08_trackMeanPt"), independent); + // PtVariance + if (WeffEvent_diff_WithGap08 > 1e-6) { + registry.fill(HIST("PtVariance_partA_WithinGap08"), independent, + (ptSum_Gap08 * ptSum_Gap08 - sum_ptSquare_wSquare_WithinGap08) / WeffEvent_diff_WithGap08, + WeffEvent_diff_WithGap08); + registry.fill(HIST("PtVariance_partB_WithinGap08"), independent, + (weffEvent_WithinGap08 * ptSum_Gap08 - sum_pt_wSquare_WithinGap08) / WeffEvent_diff_WithGap08, + WeffEvent_diff_WithGap08); + } + + // Filling Bootstrap Samples + int SampleIndex = static_cast(cfgNbootstrap * l_Random); + if (weffEvent_WithinGap08 > 1e-6) + BootstrapArray[SampleIndex][kMeanPt_InGap08]->Fill(independent, ptSum_Gap08 / weffEvent_WithinGap08, weffEvent_WithinGap08); + if (weffEvent_WithinGap08 > 1e-6) + FillpTvnProfile(corrconfigs.at(7), ptSum_Gap08, weffEvent_WithinGap08, BootstrapArray[SampleIndex][kC22_Gap08_Weff], BootstrapArray[SampleIndex][kC22_Gap08_MeanPt], independent); + if (WeffEvent_diff_WithGap08 > 1e-6) { + BootstrapArray[SampleIndex][kPtVarParA_InGap08]->Fill(independent, + (ptSum_Gap08 * ptSum_Gap08 - sum_ptSquare_wSquare_WithinGap08) / WeffEvent_diff_WithGap08, + WeffEvent_diff_WithGap08); + BootstrapArray[SampleIndex][kPtVarParB_InGap08]->Fill(independent, + (weffEvent_WithinGap08 * ptSum_Gap08 - sum_pt_wSquare_WithinGap08) / WeffEvent_diff_WithGap08, + WeffEvent_diff_WithGap08); + } } // Filling Flow Container diff --git a/PWGCF/Flow/Tasks/flowGFWOmegaXi.cxx b/PWGCF/Flow/Tasks/flowGFWOmegaXi.cxx index 9286f6d765e..e75736b7e94 100644 --- a/PWGCF/Flow/Tasks/flowGFWOmegaXi.cxx +++ b/PWGCF/Flow/Tasks/flowGFWOmegaXi.cxx @@ -40,6 +40,7 @@ #include #include #include +#include using namespace o2; using namespace o2::framework; @@ -88,6 +89,8 @@ struct FlowGFWOmegaXi { ConfigurableAxis cfgaxisVertex{"axisVertex", {20, -10, 10}, "vertex axis for histograms"}; ConfigurableAxis cfgaxisPhi{"axisPhi", {60, 0.0, constants::math::TwoPI}, "phi axis for histograms"}; ConfigurableAxis cfgaxisEta{"axisEta", {40, -1., 1.}, "eta axis for histograms"}; + ConfigurableAxis cfgaxisPtXi{"axisPtXi", {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{"axisPtV0", {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)"}; Configurable> cfgvecwacc{"vecwacc", std::vector{0.879543, 0.893808, 0.993375, 1.09663, 0.983883, 0.984094, 1.11362, 0.963896, 0.911212, 1.02934, 1.00295, 0.950711, 0.996856, 1.11934, 0.993665, 0.99087, 1.11915, 1.0198, 0.966849, 1.03237, 0.989367, 0.948312, 0.970883, 0.984305, 0.920335, 0.929722, 1.07467, 1.00862, 0.977185, 0.870868, 1.06552, 0.962393, 1.01025, 1.09959, 0.984226, 0.986361, 1.0931, 0.994377, 0.976051, 1.05249, 0.995538, 0.886452, 0.936763, 0.993613, 0.94491, 0.966559, 1.10829, 1.01998, 0.991503, 1.07918, 1.05655, 0.973784, 1.00914, 1.11678, 1.00092, 0.95232, 1.09814, 1.02322, 0.958543, 0.947231}, "wacc in phi bins"}; AxisSpec axisPt{{0.20, 0.25, 0.30, 0.35, 0.40, 0.45, 0.50, 0.55, 0.60, 0.65, 0.70, 0.75, 0.80, 0.85, 0.90, 0.95, 1.00, 1.10, 1.20, 1.30, 1.40, 1.50, 1.60, 1.70, 1.80, 1.90, 2.00, 2.20, 2.40, 2.60, 2.80, 3.00, 3.50, 4.00, 4.50, 5.00, 5.50, 6.00, 7.00, 8.00, 9.00, 10.0}, "pt(GeV)"}; @@ -96,6 +99,10 @@ struct FlowGFWOmegaXi { AxisSpec axisXiminusMass = {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)"}; + AxisSpec axisOmegaminusMassforflow = {cfgOmegaMassbins, 1.63f, 1.71f, "Inv. Mass (GeV)"}; + AxisSpec axisXiminusMassforflow = {cfgXiMassbins, 1.3f, 1.37f, "Inv. Mass (GeV)"}; + AxisSpec axisK0sMassforflow = {cfgK0sMassbins, 0.4f, 0.6f, "Inv. Mass (GeV)"}; + AxisSpec axisLambdaMassforflow = {cfgLambdaMassbins, 1.08f, 1.16f, "Inv. Mass (GeV)"}; Configurable cfgcheckDauTPC{"checkDauTPC", false, "check if daughter tracks have TPC match"}; Configurable cfgCasc_rapidity{"Casc_rapidity", 0.5, "rapidity"}; @@ -138,11 +145,20 @@ struct FlowGFWOmegaXi { using DaughterTracks = soa::Join; // Set the pt, mult and phi Axis; - o2::framework::AxisSpec axis = axisPt; - int nPtBins = axis.binEdges.size() - 1; - double* PtBins = &(axis.binEdges)[0]; + int nPtBins = axisPt.binEdges.size() - 1; + double* PtBins = &(axisPt.binEdges)[0]; TAxis* fPtAxis = new TAxis(nPtBins, PtBins); + o2::framework::AxisSpec axisXiPt = cfgaxisPtXi; + int nXiPtBins = axisXiPt.binEdges.size() - 1; + double* XiPtBins = &(axisXiPt.binEdges)[0]; + TAxis* fXiPtAxis = new TAxis(nXiPtBins, XiPtBins); + + o2::framework::AxisSpec axisV0Pt = cfgaxisPtV0; + int nV0PtBins = axisV0Pt.binEdges.size() - 1; + double* V0PtBins = &(axisV0Pt.binEdges)[0]; + TAxis* fV0PtAxis = new TAxis(nV0PtBins, V0PtBins); + o2::framework::AxisSpec axisMult = axisMultiplicity; int nMultBins = axisMult.binEdges.size() - 1; double* MultBins = &(axisMult.binEdges)[0]; @@ -176,40 +192,40 @@ struct FlowGFWOmegaXi { registry.add("hMult", "", {HistType::kTH1D, {{3000, 0.5, 3000.5}}}); registry.add("hCent", "", {HistType::kTH1D, {{90, 0, 90}}}); registry.add("hPt", "", {HistType::kTH1D, {axisPt}}); - registry.add("hEtaPhiREF", "", {HistType::kTH2D, {cfgaxisEta, cfgaxisPhi}}); - registry.add("hEtaPhiPOIXi", "", {HistType::kTH2D, {cfgaxisEta, cfgaxisPhi}}); - registry.add("hEtaPhiPOIOmega", "", {HistType::kTH2D, {cfgaxisEta, cfgaxisPhi}}); - registry.add("hEtaPhiPOIK0s", "", {HistType::kTH2D, {cfgaxisEta, cfgaxisPhi}}); - registry.add("hEtaPhiPOILambda", "", {HistType::kTH2D, {cfgaxisEta, cfgaxisPhi}}); + registry.add("hEtaPhiVtxzREF", "", {HistType::kTH3D, {cfgaxisEta, cfgaxisPhi, {20, -10, 10}}}); + registry.add("hEtaPhiVtxzPOIXi", "", {HistType::kTH3D, {cfgaxisEta, cfgaxisPhi, {20, -10, 10}}}); + registry.add("hEtaPhiVtxzPOIOmega", "", {HistType::kTH3D, {cfgaxisEta, cfgaxisPhi, {20, -10, 10}}}); + registry.add("hEtaPhiVtxzPOIK0s", "", {HistType::kTH3D, {cfgaxisEta, cfgaxisPhi, {20, -10, 10}}}); + registry.add("hEtaPhiVtxzPOILambda", "", {HistType::kTH3D, {cfgaxisEta, cfgaxisPhi, {20, -10, 10}}}); // cumulant of flow registry.add("c22", ";Centrality (%) ; C_{2}{2}", {HistType::kTProfile, {axisMultiplicity}}); registry.add("c24", ";Centrality (%) ; C_{2}{4}", {HistType::kTProfile, {axisMultiplicity}}); // pt-diff cumulant of flow - registry.add("Xic22dpt", ";pt ; C_{2}{2} ", {HistType::kTProfile3D, {axisPt, axisXiminusMass, axisMultiplicity}}); - registry.add("Omegac22dpt", ";pt ; C_{2}{2} ", {HistType::kTProfile3D, {axisPt, axisOmegaminusMass, axisMultiplicity}}); - registry.add("K0sc22dpt", ";pt ; C_{2}{2} ", {HistType::kTProfile3D, {axisPt, axisK0sMass, axisMultiplicity}}); - registry.add("Lambdac22dpt", ";pt ; C_{2}{2} ", {HistType::kTProfile3D, {axisPt, axisLambdaMass, axisMultiplicity}}); + registry.add("Xic22dpt", ";pt ; C_{2}{2} ", {HistType::kTProfile3D, {cfgaxisPtXi, axisXiminusMassforflow, axisMultiplicity}}); + registry.add("Omegac22dpt", ";pt ; C_{2}{2} ", {HistType::kTProfile3D, {cfgaxisPtXi, axisOmegaminusMassforflow, axisMultiplicity}}); + registry.add("K0sc22dpt", ";pt ; C_{2}{2} ", {HistType::kTProfile3D, {cfgaxisPtV0, axisK0sMassforflow, axisMultiplicity}}); + registry.add("Lambdac22dpt", ";pt ; C_{2}{2} ", {HistType::kTProfile3D, {cfgaxisPtV0, axisLambdaMassforflow, axisMultiplicity}}); // InvMass(GeV) of casc and v0 - registry.add("InvMassXiMinus_all", "", {HistType::kTHnSparseF, {axisPt, axisXiminusMass, cfgaxisEta, axisMultiplicity}}); - registry.add("InvMassOmegaMinus_all", "", {HistType::kTHnSparseF, {axisPt, axisOmegaminusMass, cfgaxisEta, axisMultiplicity}}); - registry.add("InvMassOmegaMinus", "", {HistType::kTHnSparseF, {axisPt, axisOmegaminusMass, cfgaxisEta, axisMultiplicity}}); - registry.add("InvMassXiMinus", "", {HistType::kTHnSparseF, {axisPt, axisXiminusMass, cfgaxisEta, axisMultiplicity}}); - registry.add("InvMassK0s_all", "", {HistType::kTHnSparseF, {axisPt, axisK0sMass, cfgaxisEta, axisMultiplicity}}); - registry.add("InvMassLambda_all", "", {HistType::kTHnSparseF, {axisPt, axisLambdaMass, cfgaxisEta, axisMultiplicity}}); - registry.add("InvMassK0s", "", {HistType::kTHnSparseF, {axisPt, axisK0sMass, cfgaxisEta, axisMultiplicity}}); - registry.add("InvMassLambda", "", {HistType::kTHnSparseF, {axisPt, axisLambdaMass, cfgaxisEta, axisMultiplicity}}); + registry.add("InvMassXiMinus_all", "", {HistType::kTHnSparseF, {cfgaxisPtXi, axisXiminusMass, cfgaxisEta, axisMultiplicity}}); + registry.add("InvMassOmegaMinus_all", "", {HistType::kTHnSparseF, {cfgaxisPtXi, axisOmegaminusMass, cfgaxisEta, axisMultiplicity}}); + registry.add("InvMassOmegaMinus", "", {HistType::kTHnSparseF, {cfgaxisPtXi, axisOmegaminusMass, cfgaxisEta, axisMultiplicity}}); + registry.add("InvMassXiMinus", "", {HistType::kTHnSparseF, {cfgaxisPtXi, axisXiminusMass, 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}}); fGFW->AddRegion("full", -0.8, 0.8, 1, 1); // ("name", etamin, etamax, ptbinnum, bitmask)eta region -0.8 to 0.8 // with (-0.5, 0.5) eta gap fGFW->AddRegion("refN10", -0.8, -0.5, 1, 1); fGFW->AddRegion("refP10", 0.5, 0.8, 1, 1); - int nXiptMassBins = nPtBins * nXiMassBins; + int nXiptMassBins = nXiPtBins * nXiMassBins; fGFW->AddRegion("poiXiP", 0.5, 0.8, nXiptMassBins, 2); - int nOmegaptMassBins = nPtBins * nOmegaMassBins; + int nOmegaptMassBins = nXiPtBins * nOmegaMassBins; fGFW->AddRegion("poiOmegaP", 0.5, 0.8, nOmegaptMassBins, 4); - int nK0sptMassBins = nPtBins * nK0sMassBins; + int nK0sptMassBins = nV0PtBins * nK0sMassBins; fGFW->AddRegion("poiK0sP", 0.5, 0.8, nK0sptMassBins, 8); - int nLambdaptMassBins = nPtBins * nLambdaMassBins; + int nLambdaptMassBins = nV0PtBins * nLambdaMassBins; fGFW->AddRegion("poiLambdaP", 0.5, 0.8, nLambdaptMassBins, 16); // pushback corrconfigs.push_back(fGFW->GetCorrelatorConfig("refP10 {2} refN10 {-2}", "ChFull220", kFALSE)); @@ -255,35 +271,45 @@ struct FlowGFWOmegaXi { } template - void FillProfilepT(const GFW::CorrConfig& corrconf, const ConstStr& tarName, const int& ptbin, const int& partical, const float& cent) + void FillProfilepT(const GFW::CorrConfig& corrconf, const ConstStr& tarName, const int& ptbin, const int& PDGCode, const float& cent) { int nMassBins = 0; + int nptbins = nPtBins; TAxis* fMass = nullptr; - if (partical == 3312) { + TAxis* fpt = nullptr; + if (PDGCode == kXiMinus) { nMassBins = nXiMassBins; + nptbins = nXiPtBins; + fpt = fXiPtAxis; fMass = fXiMass; - } else if (partical == 3334) { + } else if (PDGCode == kOmegaMinus) { nMassBins = nOmegaMassBins; + nptbins = nXiPtBins; + fpt = fXiPtAxis; fMass = fOmegaMass; - } else if (partical == 310) { + } else if (PDGCode == kK0Short) { nMassBins = nK0sMassBins; + nptbins = nV0PtBins; + fpt = fV0PtAxis; fMass = fK0sMass; - } else if (partical == 3122) { + } else if (PDGCode == kLambda0) { nMassBins = nLambdaMassBins; + nptbins = nV0PtBins; + fpt = fV0PtAxis; fMass = fLambdaMass; } else { - LOGF(error, "Error, please put in correct PDG particalID of K0s, Lambda, Xi or Omega"); + 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(); + 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; + val = fGFW->Calculate(corrconf, (ptbin - 1) + ((massbin - 1) * nptbins), kFALSE).real() / dnx; if (TMath::Abs(val) < 1) { - registry.fill(tarName, fPtAxis->GetBinCenter(ptbin), fMass->GetBinCenter(massbin), cent, val, dnx); + registry.fill(tarName, fpt->GetBinCenter(ptbin), fMass->GetBinCenter(massbin), cent, val, dnx); } } return; @@ -409,7 +435,7 @@ struct FlowGFWOmegaXi { wacc = 1 / vecwa[phibin]; registry.fill(HIST("hPhi"), track.phi()); registry.fill(HIST("hEta"), track.eta()); - registry.fill(HIST("hEtaPhiREF"), track.eta(), track.phi()); + registry.fill(HIST("hEtaPhiVtxzREF"), track.eta(), track.phi(), vtxz); registry.fill(HIST("hPt"), track.pt()); int ptbin = fPtAxis->FindBin(track.pt()) - 1; if ((track.pt() > cfgCutPtMin) && (track.pt() < cfgCutPtMax)) { @@ -421,13 +447,13 @@ struct FlowGFWOmegaXi { auto v0posdau = v0.posTrack_as(); auto v0negdau = v0.negTrack_as(); // check tpc - int partical = 0; + int PDGCode = 0; if (v0.qtarm() / TMath::Abs(v0.alpha()) > cfgv0_ArmPodocut && TMath::Abs(v0posdau.tpcNSigmaPi()) < cfgNSigmaCascPion && TMath::Abs(v0negdau.tpcNSigmaPi()) < cfgNSigmaCascPion) { registry.fill(HIST("InvMassK0s_all"), v0.pt(), v0.mK0Short(), v0.eta(), cent); - partical = 310; + PDGCode = kK0Short; } else if (v0.qtarm() / TMath::Abs(v0.alpha()) < cfgv0_ArmPodocut && TMath::Abs(v0posdau.tpcNSigmaPr()) < cfgNSigmaCascProton && TMath::Abs(v0negdau.tpcNSigmaPi()) < cfgNSigmaCascPion) { registry.fill(HIST("InvMassLambda_all"), v0.pt(), v0.mLambda(), v0.eta(), cent); - partical = 3122; + PDGCode = kLambda0; } // track quality check if (v0posdau.tpcNClsFound() < cfgtpcclusters) @@ -445,17 +471,17 @@ struct FlowGFWOmegaXi { continue; if (v0.dcaV0daughters() > cfgv0_dcav0dau) continue; - if (partical == 310) { + if (PDGCode == kK0Short) { if (TMath::Abs(v0.mK0Short() - 0.49761) < cfgv0_mk0swindow) { registry.fill(HIST("InvMassK0s"), v0.pt(), v0.mK0Short(), v0.eta(), cent); - registry.fill(HIST("hEtaPhiPOIK0s"), v0.eta(), v0.phi()); - fGFW->Fill(v0.eta(), fPtAxis->FindBin(v0.pt()) - 1 + ((fK0sMass->FindBin(v0.mK0Short()) - 1) * nPtBins), v0.phi(), wacc * weff, 8); + registry.fill(HIST("hEtaPhiVtxzPOIK0s"), v0.eta(), v0.phi(), vtxz); + fGFW->Fill(v0.eta(), fV0PtAxis->FindBin(v0.pt()) - 1 + ((fK0sMass->FindBin(v0.mK0Short()) - 1) * nV0PtBins), v0.phi(), wacc * weff, 8); } - } else if (partical == 3122) { + } else if (PDGCode == kLambda0) { if (TMath::Abs(v0.mLambda() - 1.115683) < cfgv0_mlambdawindow) { registry.fill(HIST("InvMassLambda"), v0.pt(), v0.mLambda(), v0.eta(), cent); - registry.fill(HIST("hEtaPhiPOILambda"), v0.eta(), v0.phi()); - fGFW->Fill(v0.eta(), fPtAxis->FindBin(v0.pt()) - 1 + ((fLambdaMass->FindBin(v0.mLambda()) - 1) * nPtBins), v0.phi(), wacc * weff, 16); + registry.fill(HIST("hEtaPhiVtxzPOILambda"), v0.eta(), v0.phi(), vtxz); + fGFW->Fill(v0.eta(), fV0PtAxis->FindBin(v0.pt()) - 1 + ((fLambdaMass->FindBin(v0.mLambda()) - 1) * nV0PtBins), v0.phi(), wacc * weff, 16); } } } @@ -468,13 +494,13 @@ struct FlowGFWOmegaXi { if (cfgcheckDauTPC && (!posdau.hasTPC() || !negdau.hasTPC() || !bachelor.hasTPC())) { continue; } - int partical = 0; + int PDGCode = 0; if (casc.sign() < 0 && TMath::Abs(casc.yOmega()) < cfgCasc_rapidity && TMath::Abs(bachelor.tpcNSigmaKa()) < cfgNSigmaCascKaon && TMath::Abs(posdau.tpcNSigmaPr()) < cfgNSigmaCascProton && TMath::Abs(negdau.tpcNSigmaPi()) < cfgNSigmaCascPion) { registry.fill(HIST("InvMassOmegaMinus_all"), casc.pt(), casc.mOmega(), casc.eta(), cent); - partical = 3334; + PDGCode = kOmegaMinus; } else if (casc.sign() < 0 && TMath::Abs(casc.yXi()) < cfgCasc_rapidity && TMath::Abs(bachelor.tpcNSigmaPi()) < cfgNSigmaCascPion && TMath::Abs(posdau.tpcNSigmaPr()) < cfgNSigmaCascProton && TMath::Abs(negdau.tpcNSigmaPi()) < cfgNSigmaCascPion) { registry.fill(HIST("InvMassXiMinus_all"), casc.pt(), casc.mXi(), casc.eta(), cent); - partical = 3312; + PDGCode = kXiMinus; } else { continue; } @@ -508,30 +534,32 @@ struct FlowGFWOmegaXi { continue; if (negdau.itsNCls() < cfgitsclusters) continue; - if (partical == 3334) { - registry.fill(HIST("hEtaPhiPOIOmega"), casc.eta(), casc.phi()); + if (PDGCode == kOmegaMinus) { + registry.fill(HIST("hEtaPhiVtxzPOIOmega"), casc.eta(), casc.phi(), vtxz); registry.fill(HIST("InvMassOmegaMinus"), casc.pt(), casc.mOmega(), casc.eta(), cent); if ((casc.pt() < cfgCutPtPOIMax) && (casc.pt() > cfgCutPtPOIMin) && (casc.mOmega() > 1.63) && (casc.mOmega() < 1.71)) { - fGFW->Fill(casc.eta(), fPtAxis->FindBin(casc.pt()) - 1 + ((fOmegaMass->FindBin(casc.mOmega()) - 1) * nPtBins), casc.phi(), wacc * weff, 4); + fGFW->Fill(casc.eta(), fXiPtAxis->FindBin(casc.pt()) - 1 + ((fOmegaMass->FindBin(casc.mOmega()) - 1) * nXiPtBins), casc.phi(), wacc * weff, 4); } } - if (partical == 3312) { - registry.fill(HIST("hEtaPhiPOIXi"), casc.eta(), casc.phi()); + if (PDGCode == kXiMinus) { + registry.fill(HIST("hEtaPhiVtxzPOIXi"), casc.eta(), casc.phi(), vtxz); registry.fill(HIST("InvMassXiMinus"), casc.pt(), casc.mXi(), casc.eta(), cent); if ((casc.pt() < cfgCutPtPOIMax) && (casc.pt() > cfgCutPtPOIMin) && (casc.mXi() > 1.30) && (casc.mXi() < 1.37)) { - fGFW->Fill(casc.eta(), fPtAxis->FindBin(casc.pt()) - 1 + ((fXiMass->FindBin(casc.mXi()) - 1) * nPtBins), casc.phi(), wacc * weff, 2); + fGFW->Fill(casc.eta(), fXiPtAxis->FindBin(casc.pt()) - 1 + ((fXiMass->FindBin(casc.mXi()) - 1) * nXiPtBins), casc.phi(), wacc * weff, 2); } } } // Filling cumulant with ROOT TProfile FillProfile(corrconfigs.at(0), HIST("c22"), cent); FillProfile(corrconfigs.at(1), HIST("c24"), cent); - for (int i = 1; i <= nPtBins; i++) // loop for all ptBins + for (int i = 1; i <= nV0PtBins; i++) // loop for all ptBins { - FillProfilepT(corrconfigs.at(2), HIST("Xic22dpt"), i, 3312, cent); - FillProfilepT(corrconfigs.at(3), HIST("Omegac22dpt"), i, 3334, cent); - FillProfilepT(corrconfigs.at(4), HIST("K0sc22dpt"), i, 310, cent); - FillProfilepT(corrconfigs.at(5), HIST("Lambdac22dpt"), i, 3122, cent); + FillProfilepT(corrconfigs.at(4), HIST("K0sc22dpt"), i, kK0Short, cent); + FillProfilepT(corrconfigs.at(5), HIST("Lambdac22dpt"), i, kLambda0, cent); + } + for (int i = 1; i <= nXiPtBins; i++) { + FillProfilepT(corrconfigs.at(2), HIST("Xic22dpt"), i, kXiMinus, cent); + FillProfilepT(corrconfigs.at(3), HIST("Omegac22dpt"), i, kOmegaMinus, cent); } } }; diff --git a/PWGCF/MultiparticleCorrelations/Core/MuPa-Configurables.h b/PWGCF/MultiparticleCorrelations/Core/MuPa-Configurables.h index 770ed87472f..4ebe0babbf8 100644 --- a/PWGCF/MultiparticleCorrelations/Core/MuPa-Configurables.h +++ b/PWGCF/MultiparticleCorrelations/Core/MuPa-Configurables.h @@ -38,7 +38,7 @@ struct : ConfigurableGroup { Configurable cfFillQAEventHistograms2D{"cfFillQAEventHistograms2D", false, "if false, all QA 2D event histograms are not filled. if true, only the ones for which fBookQAEventHistograms2D[...] is true, are filled"}; Configurable> cfBookQAEventHistograms2D{"cfBookQAEventHistograms2D", {"MultTPC_vs_NContributors-1", "Vertex_z_vs_MultTPC-1", "Vertex_z_vs_NContributors-1", "CentFT0M_vs_CentNTPV-1", "CentRun2V0M_vs_CentRun2SPDTracklets-1", "CentRun2V0M_vs_NContributors-1"}, "book (1) or do not book (0) this QA 2D event histogram"}; Configurable cfFillQAParticleHistograms2D{"cfFillQAParticleHistograms2D", false, "if false, all QA 2D particle histograms are not filled. if true, only the ones for which fBookQAParticleHistograms2D[...] is true, are filled"}; - Configurable> cfBookQAParticleHistograms2D{"cfBookQAParticleHistograms2D", {"dcaXY_vs_Pt-1"}, "book (1) or do not book (0) this QA 2D particle histogram"}; + Configurable> cfBookQAParticleHistograms2D{"cfBookQAParticleHistograms2D", {"Pt_vs_dcaXY-1"}, "book (1) or do not book (0) this QA 2D particle histogram"}; } cf_qa; // *) Event histograms: diff --git a/PWGCF/MultiparticleCorrelations/Core/MuPa-DataMembers.h b/PWGCF/MultiparticleCorrelations/Core/MuPa-DataMembers.h index 2d4d7536cc6..f7d7633bc46 100644 --- a/PWGCF/MultiparticleCorrelations/Core/MuPa-DataMembers.h +++ b/PWGCF/MultiparticleCorrelations/Core/MuPa-DataMembers.h @@ -69,35 +69,42 @@ struct EventByEventQuantities { } ebye; // "ebye" is a common label for objects in this struct // *) QA: -// Remark: I keep new histograms in this group, until I need them permanently in the analysis. Then, they are moved to EventHistograms or ParticleHistograms (yes, even if they are 2D). +// Remark 1: I keep new histograms in this group, until I need them permanently in the analysis. Then, they are moved to EventHistograms or ParticleHistograms (yes, even if they are 2D). +// Remark 2: All 2D histograms book as TH2F, due to "stmem error" in terminate (see .cxx for further details) struct QualityAssurance { - TList* fQAList = NULL; //! From documentation: Bypass this check if you analyse MC or continuous Run3 data. By now, it's validated only for \"Rec_Run2\", for other cases, simply switch off this event cut eTrigger. \033[0m", __FUNCTION__, __LINE__, ec.fsEventCuts[eTrigger].Data()); } + // *) This check is meant to prevent the case when I want to bailout for max number of events, but I do not fill event histograms + if (ec.fdEventCuts[eNumberOfEvents][eMax] < 1e6) { // TBI 20241011 Do I need to tune 1000000000 + // If I do not want to bail out when max number of events is reached, then in the configurable I have e.g. cfNumberOfEvents{"cfNumberOfEvents", {-1, 1000000000} + // So if the upper limit is set to some number < 1e6, I want to bail out for that number of events. + // TBI 20241011 this is a bit shaky, but nevermind now... + if (!eh.fBookEventHistograms[eNumberOfEvents]) { + LOGF(fatal, "\033[1;31m%s at line %d : Bailout for max number of events cannot be done, unless eh.fBookEventHistograms[eNumberOfEvents] is kTRUE.\033[0m", __FUNCTION__, __LINE__); + } + } if (tc.fProcess[eProcessRec_Run2]) { // TBI 20240517 for the time being, here I am enforcing that "kINT7" is mandatory for Run 2 and Run 1 converted real data @@ -1507,8 +1516,18 @@ void BookQAHistograms() LOGF(info, "\033[1;32m%s\033[0m", __FUNCTION__); } + // *) 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: + */ + 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__); + // a) Book the profile holding flags: - qa.fQAHistogramsPro = new TProfile("fQAHistogramsPro", "flags for QA histograms", 2, 0., 2.); // TBI 20240515 re-think how to organize the binning here + qa.fQAHistogramsPro = new TProfile("fQAHistogramsPro", "flags for QA histograms", 3, 0., 3.); qa.fQAHistogramsPro->SetStats(kFALSE); qa.fQAHistogramsPro->SetLineColor(eColor); qa.fQAHistogramsPro->SetFillColor(eFillColor); @@ -1516,6 +1535,8 @@ void BookQAHistograms() qa.fQAHistogramsPro->Fill(0.5, static_cast(qa.fCheckUnderflowAndOverflow)); qa.fQAHistogramsPro->GetXaxis()->SetBinLabel(2, "fFillQAEventHistograms2D"); qa.fQAHistogramsPro->Fill(1.5, static_cast(qa.fFillQAEventHistograms2D)); + qa.fQAHistogramsPro->GetXaxis()->SetBinLabel(3, "fFillQAParticleHistograms2D"); + qa.fQAHistogramsPro->Fill(2.5, static_cast(qa.fFillQAParticleHistograms2D)); // ... @@ -1539,31 +1560,31 @@ void BookQAHistograms() TString title_y_Event[eQAEventHistograms2D_N] = {""}; // *) "MultTPC_vs_NContributors": - nBins_x_Event[eMultTPC_vs_NContributors] = static_cast(eh.fEventHistogramsBins[eMultTPC][0]) / 10; // TBI 20240504 hardcoded number + nBins_x_Event[eMultTPC_vs_NContributors] = static_cast(eh.fEventHistogramsBins[eMultTPC][0]); // TBI 20240702 add support for rebinning min_x_Event[eMultTPC_vs_NContributors] = eh.fEventHistogramsBins[eMultTPC][1]; max_x_Event[eMultTPC_vs_NContributors] = eh.fEventHistogramsBins[eMultTPC][2]; title_x_Event[eMultTPC_vs_NContributors] = FancyFormatting(eh.fEventHistogramsName[eMultTPC].Data()); - nBins_y_Event[eMultTPC_vs_NContributors] = static_cast(eh.fEventHistogramsBins[eNContributors][0]) / 10; // TBI 20240504 hardcoded number + nBins_y_Event[eMultTPC_vs_NContributors] = static_cast(eh.fEventHistogramsBins[eNContributors][0]); // TBI 20240702 add support for rebinning min_y_Event[eMultTPC_vs_NContributors] = eh.fEventHistogramsBins[eNContributors][1]; max_y_Event[eMultTPC_vs_NContributors] = eh.fEventHistogramsBins[eNContributors][2]; title_y_Event[eMultTPC_vs_NContributors] = FancyFormatting(eh.fEventHistogramsName[eNContributors].Data()); // *) "Vertex_z_vs_MultTPC": - nBins_x_Event[eVertex_z_vs_MultTPC] = static_cast(eh.fEventHistogramsBins[eVertex_z][0]) / 10; // TBI 20240504 hardcoded number + nBins_x_Event[eVertex_z_vs_MultTPC] = static_cast(eh.fEventHistogramsBins[eVertex_z][0]); // TBI 20240702 add support for rebinning min_x_Event[eVertex_z_vs_MultTPC] = eh.fEventHistogramsBins[eVertex_z][1]; max_x_Event[eVertex_z_vs_MultTPC] = eh.fEventHistogramsBins[eVertex_z][2]; title_x_Event[eVertex_z_vs_MultTPC] = FancyFormatting(eh.fEventHistogramsName[eVertex_z].Data()); - nBins_y_Event[eVertex_z_vs_MultTPC] = static_cast(eh.fEventHistogramsBins[eMultTPC][0]) / 100; // TBI 20240504 hardcoded number + nBins_y_Event[eVertex_z_vs_MultTPC] = static_cast(eh.fEventHistogramsBins[eMultTPC][0]); // TBI 20240702 add support for rebinning min_y_Event[eVertex_z_vs_MultTPC] = eh.fEventHistogramsBins[eMultTPC][1]; max_y_Event[eVertex_z_vs_MultTPC] = eh.fEventHistogramsBins[eMultTPC][2]; title_y_Event[eVertex_z_vs_MultTPC] = FancyFormatting(eh.fEventHistogramsName[eMultTPC].Data()); // *) "Vertex_z_vs_NContributors": - nBins_x_Event[eVertex_z_vs_NContributors] = static_cast(eh.fEventHistogramsBins[eVertex_z][0]) / 10; // TBI 20240504 hardcoded number + nBins_x_Event[eVertex_z_vs_NContributors] = static_cast(eh.fEventHistogramsBins[eVertex_z][0]); // TBI 20240702 add support for rebinning min_x_Event[eVertex_z_vs_NContributors] = eh.fEventHistogramsBins[eVertex_z][1]; max_x_Event[eVertex_z_vs_NContributors] = eh.fEventHistogramsBins[eVertex_z][2]; title_x_Event[eVertex_z_vs_NContributors] = FancyFormatting(eh.fEventHistogramsName[eVertex_z].Data()); - nBins_y_Event[eVertex_z_vs_NContributors] = static_cast(eh.fEventHistogramsBins[eNContributors][0]) / 10; // TBI 20240504 hardcoded number + nBins_y_Event[eVertex_z_vs_NContributors] = static_cast(eh.fEventHistogramsBins[eNContributors][0]); // TBI 20240702 add support for rebinning min_y_Event[eVertex_z_vs_NContributors] = eh.fEventHistogramsBins[eNContributors][1]; max_y_Event[eVertex_z_vs_NContributors] = eh.fEventHistogramsBins[eNContributors][2]; title_y_Event[eVertex_z_vs_NContributors] = FancyFormatting(eh.fEventHistogramsName[eNContributors].Data()); @@ -1631,7 +1652,7 @@ void BookQAHistograms() for (Int_t ba = 0; ba < 2; ba++) // before/after cuts { - qa.fQAEventHistograms2D[t][rs][ba] = new TH2D( + qa.fQAEventHistograms2D[t][rs][ba] = new TH2F( Form("fQAEventHistograms2D[%s][%s][%s]", qa.fEventHistogramsName2D[t].Data(), srs[rs].Data(), sba[ba].Data()), Form("%s, %s, %s", "__RUN_NUMBER__", srs_long[rs].Data(), sba_long[ba].Data()), // __RUN_NUMBER__ is handled in DetermineAndPropagateRunNumber(T const& collision) nBins_x_Event[t], min_x_Event[t], max_x_Event[t], nBins_y_Event[t], min_y_Event[t], max_y_Event[t]); @@ -1659,15 +1680,15 @@ void BookQAHistograms() Double_t max_y_Particle[eQAParticleHistograms2D_N] = {0.}; TString title_y_Particle[eQAParticleHistograms2D_N] = {""}; - // *) "dcaXY_vs_Pt": - nBins_x_Particle[edcaXY_vs_Pt] = static_cast(ph.fParticleHistogramsBins[edcaXY][0]) / 10; // TBI 20240504 hardcoded number - min_x_Particle[edcaXY_vs_Pt] = ph.fParticleHistogramsBins[edcaXY][1]; - max_x_Particle[edcaXY_vs_Pt] = ph.fParticleHistogramsBins[edcaXY][2]; - title_x_Particle[edcaXY_vs_Pt] = FancyFormatting(ph.fParticleHistogramsName[edcaXY].Data()); - nBins_y_Particle[edcaXY_vs_Pt] = static_cast(ph.fParticleHistogramsBins[ePt][0]) / 10; // TBI 20240504 hardcoded number - min_y_Particle[edcaXY_vs_Pt] = ph.fParticleHistogramsBins[ePt][1]; - max_y_Particle[edcaXY_vs_Pt] = ph.fParticleHistogramsBins[ePt][2]; - title_y_Particle[edcaXY_vs_Pt] = FancyFormatting(ph.fParticleHistogramsName[ePt].Data()); + // *) "pt_vs_dcaXY": + nBins_x_Particle[ePt_vs_dcaXY] = static_cast(ph.fParticleHistogramsBins[ePt][0]); // TBI 20240702 add support for rebinning + min_x_Particle[ePt_vs_dcaXY] = ph.fParticleHistogramsBins[ePt][1]; + max_x_Particle[ePt_vs_dcaXY] = ph.fParticleHistogramsBins[ePt][2]; + title_x_Particle[ePt_vs_dcaXY] = FancyFormatting(ph.fParticleHistogramsName[ePt].Data()); + nBins_y_Particle[ePt_vs_dcaXY] = static_cast(ph.fParticleHistogramsBins[edcaXY][0]); // TBI 20240702 add support for rebinning + min_y_Particle[ePt_vs_dcaXY] = ph.fParticleHistogramsBins[edcaXY][1]; + max_y_Particle[ePt_vs_dcaXY] = ph.fParticleHistogramsBins[edcaXY][2]; + title_y_Particle[ePt_vs_dcaXY] = FancyFormatting(ph.fParticleHistogramsName[edcaXY].Data()); // ... @@ -1702,7 +1723,7 @@ void BookQAHistograms() for (Int_t ba = 0; ba < 2; ba++) // before/after cuts { - qa.fQAParticleHistograms2D[t][rs][ba] = new TH2D( + qa.fQAParticleHistograms2D[t][rs][ba] = new TH2F( Form("fQAParticleHistograms2D[%s][%s][%s]", qa.fParticleHistogramsName2D[t].Data(), srs[rs].Data(), sba[ba].Data()), Form("%s, %s, %s", "__RUN_NUMBER__", srs_long[rs].Data(), sba_long[ba].Data()), // __RUN_NUMBER__ is handled in DetermineAndPropagateRunNumber(T const& collision) nBins_x_Particle[t], min_x_Particle[t], max_x_Particle[t], nBins_y_Particle[t], min_y_Particle[t], max_y_Particle[t]); @@ -1734,10 +1755,12 @@ void BookEventHistograms() } // a) Book the profile holding flags: - eh.fEventHistogramsPro = new TProfile("fEventHistogramsPro", "flags for event histograms", 25, 0., 25.); + eh.fEventHistogramsPro = new TProfile("fEventHistogramsPro", "flags for event histograms", 1, 0., 1.); eh.fEventHistogramsPro->SetStats(kFALSE); eh.fEventHistogramsPro->SetLineColor(eColor); eh.fEventHistogramsPro->SetFillColor(eFillColor); + eh.fEventHistogramsPro->GetXaxis()->SetBinLabel(1, "fFillEventHistograms"); + eh.fEventHistogramsPro->Fill(0.5, static_cast(eh.fFillEventHistograms)); // ... eh.fEventHistogramsList->Add(eh.fEventHistogramsPro); @@ -1883,7 +1906,9 @@ void BookParticleHistograms() ph.fParticleHistogramsPro->SetStats(kFALSE); ph.fParticleHistogramsPro->SetLineColor(eColor); ph.fParticleHistogramsPro->SetFillColor(eFillColor); - // ... TBI 20240418 I shall fill something in this config profile... + ph.fParticleHistogramsPro->GetXaxis()->SetBinLabel(1, "fFillParticleHistograms"); + ph.fParticleHistogramsPro->Fill(0.5, static_cast(ph.fFillParticleHistograms)); + // ... ph.fParticleHistogramsList->Add(ph.fParticleHistogramsPro); // b) Book specific particle histograms 1D: @@ -3957,7 +3982,7 @@ Bool_t EventCut(Int_t rs, Int_t eventCut, eCutModus cutModus) template void FillEventHistograms(T1 const& collision, T2 const& tracks, eBeforeAfter ba) { - // Fill all event histograms for reconstructed or simulated data. + // Fill all event histograms for reconstructed or simulated data. QA event histograms are also filled here. // a) Fill reconstructed, and corresponding MC truth simulated (common to Run 3, Run 2 and Run 1); // b) Fill only simulated (common to Run 3, Run 2 and Run 1); @@ -3973,17 +3998,18 @@ void FillEventHistograms(T1 const& collision, T2 const& tracks, eBeforeAfter ba) // a) Fill reconstructed ... (common to Run 3, Run 2 and Run 1): if constexpr (rs == eRec || rs == eRecAndSim || rs == eRec_Run2 || rs == eRecAndSim_Run2 || rs == eRec_Run1 || rs == eRecAndSim_Run1) { - // 1D: - !eh.fEventHistograms[eNumberOfEvents][eRec][ba] ? true : eh.fEventHistograms[eNumberOfEvents][eRec][ba]->Fill(0.5); // basically, if histogram is not booked, do nothing. 'true' is a placeholder, for the time being - !eh.fEventHistograms[eVertex_x][eRec][ba] ? true : eh.fEventHistograms[eVertex_x][eRec][ba]->Fill(collision.posX()); - !eh.fEventHistograms[eVertex_y][eRec][ba] ? true : eh.fEventHistograms[eVertex_y][eRec][ba]->Fill(collision.posY()); - !eh.fEventHistograms[eVertex_z][eRec][ba] ? true : eh.fEventHistograms[eVertex_z][eRec][ba]->Fill(collision.posZ()); - !eh.fEventHistograms[eNContributors][eRec][ba] ? true : eh.fEventHistograms[eNContributors][eRec][ba]->Fill(collision.numContrib()); - !eh.fEventHistograms[eTotalMultiplicity][eRec][ba] ? true : eh.fEventHistograms[eTotalMultiplicity][eRec][ba]->Fill(tracks.size()); // TBI 20231106 check and validate further - !eh.fEventHistograms[eSelectedTracks][eRec][ba] ? true : eh.fEventHistograms[eSelectedTracks][eRec][ba]->Fill(ebye.fSelectedTracks); // TBI 20240108 this one makes sense only for eAfter - !eh.fEventHistograms[eMultTPC][eRec][ba] ? true : eh.fEventHistograms[eMultTPC][eRec][ba]->Fill(collision.multTPC()); - !eh.fEventHistograms[eMultNTracksPV][eRec][ba] ? true : eh.fEventHistograms[eMultNTracksPV][eRec][ba]->Fill(collision.multNTracksPV()); - !eh.fEventHistograms[eCentrality][eRec][ba] ? true : eh.fEventHistograms[eCentrality][eRec][ba]->Fill(ebye.fCentrality); + if (eh.fFillEventHistograms) { + !eh.fEventHistograms[eNumberOfEvents][eRec][ba] ? true : eh.fEventHistograms[eNumberOfEvents][eRec][ba]->Fill(0.5); // basically, if histogram is not booked, do nothing. 'true' is a placeholder, for the time being + !eh.fEventHistograms[eVertex_x][eRec][ba] ? true : eh.fEventHistograms[eVertex_x][eRec][ba]->Fill(collision.posX()); + !eh.fEventHistograms[eVertex_y][eRec][ba] ? true : eh.fEventHistograms[eVertex_y][eRec][ba]->Fill(collision.posY()); + !eh.fEventHistograms[eVertex_z][eRec][ba] ? true : eh.fEventHistograms[eVertex_z][eRec][ba]->Fill(collision.posZ()); + !eh.fEventHistograms[eNContributors][eRec][ba] ? true : eh.fEventHistograms[eNContributors][eRec][ba]->Fill(collision.numContrib()); + !eh.fEventHistograms[eTotalMultiplicity][eRec][ba] ? true : eh.fEventHistograms[eTotalMultiplicity][eRec][ba]->Fill(tracks.size()); // TBI 20231106 check and validate further + !eh.fEventHistograms[eSelectedTracks][eRec][ba] ? true : eh.fEventHistograms[eSelectedTracks][eRec][ba]->Fill(ebye.fSelectedTracks); // TBI 20240108 this one makes sense only for eAfter + !eh.fEventHistograms[eMultTPC][eRec][ba] ? true : eh.fEventHistograms[eMultTPC][eRec][ba]->Fill(collision.multTPC()); + !eh.fEventHistograms[eMultNTracksPV][eRec][ba] ? true : eh.fEventHistograms[eMultNTracksPV][eRec][ba]->Fill(collision.multNTracksPV()); + !eh.fEventHistograms[eCentrality][eRec][ba] ? true : eh.fEventHistograms[eCentrality][eRec][ba]->Fill(ebye.fCentrality); + } // QA: if (qa.fFillQAEventHistograms2D) { !qa.fQAEventHistograms2D[eMultTPC_vs_NContributors][eRec][ba] ? true : qa.fQAEventHistograms2D[eMultTPC_vs_NContributors][eRec][ba]->Fill(collision.multTPC(), collision.numContrib()); @@ -3998,15 +4024,17 @@ void FillEventHistograms(T1 const& collision, T2 const& tracks, eBeforeAfter ba) LOGF(warning, "No MC collision for this collision, skip..."); return; } - !eh.fEventHistograms[eNumberOfEvents][eSim][ba] ? true : eh.fEventHistograms[eNumberOfEvents][eSim][ba]->Fill(0.5); - !eh.fEventHistograms[eVertex_x][eSim][ba] ? true : eh.fEventHistograms[eVertex_x][eSim][ba]->Fill(collision.mcCollision().posX()); - !eh.fEventHistograms[eVertex_y][eSim][ba] ? true : eh.fEventHistograms[eVertex_y][eSim][ba]->Fill(collision.mcCollision().posY()); - !eh.fEventHistograms[eVertex_z][eSim][ba] ? true : eh.fEventHistograms[eVertex_z][eSim][ba]->Fill(collision.mcCollision().posZ()); - !eh.fEventHistograms[eImpactParameter][eSim][ba] ? true : eh.fEventHistograms[eImpactParameter][eSim][ba]->Fill(collision.mcCollision().impactParameter()); - // eh.fEventHistograms[eTotalMultiplicity][eSim][ba]->Fill(tracks.size()); // TBI 20231106 check how to get corresponding MC truth info, and validate further - // eh.fEventHistograms[eSelectedTracks][eSim][ba]->Fill(ebye.fSelectedTracks); // TBI 20240108 this one makes sense only for eAfter + re-think if I really need it here - // TBI 20240120 eMultFT0M, ..., eMultNTracksPV are not needed here - // eh.fEventHistograms[eCentrality][eSim][ba]->Fill(ebye.fCentrality); // TBI 20240120 this case is still not supported in DetermineCentrality() + if (eh.fFillEventHistograms) { + !eh.fEventHistograms[eNumberOfEvents][eSim][ba] ? true : eh.fEventHistograms[eNumberOfEvents][eSim][ba]->Fill(0.5); + !eh.fEventHistograms[eVertex_x][eSim][ba] ? true : eh.fEventHistograms[eVertex_x][eSim][ba]->Fill(collision.mcCollision().posX()); + !eh.fEventHistograms[eVertex_y][eSim][ba] ? true : eh.fEventHistograms[eVertex_y][eSim][ba]->Fill(collision.mcCollision().posY()); + !eh.fEventHistograms[eVertex_z][eSim][ba] ? true : eh.fEventHistograms[eVertex_z][eSim][ba]->Fill(collision.mcCollision().posZ()); + !eh.fEventHistograms[eImpactParameter][eSim][ba] ? true : eh.fEventHistograms[eImpactParameter][eSim][ba]->Fill(collision.mcCollision().impactParameter()); + // eh.fEventHistograms[eTotalMultiplicity][eSim][ba]->Fill(tracks.size()); // TBI 20231106 check how to get corresponding MC truth info, and validate further + // eh.fEventHistograms[eSelectedTracks][eSim][ba]->Fill(ebye.fSelectedTracks); // TBI 20240108 this one makes sense only for eAfter + re-think if I really need it here + // TBI 20240120 eMultFT0M, ..., eMultNTracksPV are not needed here + // eh.fEventHistograms[eCentrality][eSim][ba]->Fill(ebye.fCentrality); // TBI 20240120 this case is still not supported in DetermineCentrality() + } } // if constexpr (rs == eRecAndSim) { } // if constexpr (rs == eRec || rs == eRecAndSim) { @@ -4014,18 +4042,22 @@ void FillEventHistograms(T1 const& collision, T2 const& tracks, eBeforeAfter ba) // b) Fill only simulated (common to Run 3, Run 2 and Run 1): if constexpr (rs == eSim || rs == eSim_Run2 || rs == eSim_Run1) { - !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[eSelectedTracks][eSim][ba] ? true : eh.fEventHistograms[eSelectedTracks][eSim][ba]->Fill(ebye.fSelectedTracks); // TBI 20240108 this one makes sense only for eAfter - // eh.fEventHistograms[eCentrality][eSim][ba]->Fill(ebye.fCentrality); // TBI 20240120 this case is still not supported in DetermineCentrality() - // eh.fEventHistograms[eTotalMultiplicity][eSim][ba]->Fill(tracks.size()); // TBI 20231030 check further how to use the same thing for 'sim' - } // if constexpr (rs == eSim) { + if (eh.fFillEventHistograms) { + !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[eSelectedTracks][eSim][ba] ? true : eh.fEventHistograms[eSelectedTracks][eSim][ba]->Fill(ebye.fSelectedTracks); // TBI 20240108 this one makes sense only for eAfter + // eh.fEventHistograms[eCentrality][eSim][ba]->Fill(ebye.fCentrality); // TBI 20240120 this case is still not supported in DetermineCentrality() + // eh.fEventHistograms[eTotalMultiplicity][eSim][ba]->Fill(tracks.size()); // TBI 20231030 check further how to use the same thing for 'sim' + } + } // ----------------------------------------------------------------------------- // c) Fill reconstructed (Run 3 specific): if constexpr (rs == eRec || rs == eRecAndSim) { - !eh.fEventHistograms[eMultFT0M][eRec][ba] ? true : eh.fEventHistograms[eMultFT0M][eRec][ba]->Fill(collision.multFT0M()); - !eh.fEventHistograms[eMultFV0M][eRec][ba] ? true : eh.fEventHistograms[eMultFV0M][eRec][ba]->Fill(collision.multFV0M()); + if (eh.fFillEventHistograms) { + !eh.fEventHistograms[eMultFT0M][eRec][ba] ? true : eh.fEventHistograms[eMultFT0M][eRec][ba]->Fill(collision.multFT0M()); + !eh.fEventHistograms[eMultFV0M][eRec][ba] ? true : eh.fEventHistograms[eMultFV0M][eRec][ba]->Fill(collision.multFV0M()); + } // ... and corresponding MC truth simulated (Run 3 specific) // See https://github.com/AliceO2Group/O2Physics/blob/master/Tutorials/src/mcHistograms.cxx @@ -4049,7 +4081,9 @@ void FillEventHistograms(T1 const& collision, T2 const& tracks, eBeforeAfter ba) // e) Fill reconstructed (Run 1 and 2 specific): // In case there is some corner case between Run 1 and Run 2, simply branch further this one if constexpr (rs == eRec_Run2 || rs == eRecAndSim_Run2 || rs == eRec_Run1 || rs == eRecAndSim_Run1) { - !eh.fEventHistograms[eMultTracklets][eRec][ba] ? true : eh.fEventHistograms[eMultTracklets][eRec][ba]->Fill(collision.multTracklets()); + if (eh.fFillEventHistograms) { + !eh.fEventHistograms[eMultTracklets][eRec][ba] ? true : eh.fEventHistograms[eMultTracklets][eRec][ba]->Fill(collision.multTracklets()); + } // QA: if (qa.fFillQAEventHistograms2D) { !qa.fQAEventHistograms2D[eCentRun2V0M_vs_CentRun2SPDTracklets][eRec][ba] ? true : qa.fQAEventHistograms2D[eCentRun2V0M_vs_CentRun2SPDTracklets][eRec][ba]->Fill(qa.fCentrality[eCentRun2V0M], qa.fCentrality[eCentRun2SPDTracklets]); @@ -4081,9 +4115,11 @@ void FillEventHistograms(T1 const& collision, T2 const& tracks, eBeforeAfter ba) if constexpr (rs == eTest) { // TBI 20240223 for the time being, eTest fills only eRec histos: // A few example histograms, just to check if I access corresponding tables: - !eh.fEventHistograms[eVertex_z][eRec][ba] ? true : eh.fEventHistograms[eVertex_z][eRec][ba]->Fill(collision.posZ()); - !eh.fEventHistograms[eTotalMultiplicity][eRec][ba] ? true : eh.fEventHistograms[eTotalMultiplicity][eRec][ba]->Fill(tracks.size()); - !eh.fEventHistograms[eCentrality][eRec][ba] ? true : eh.fEventHistograms[eCentrality][eRec][ba]->Fill(ebye.fCentrality); + if (eh.fFillEventHistograms) { + !eh.fEventHistograms[eVertex_z][eRec][ba] ? true : eh.fEventHistograms[eVertex_z][eRec][ba]->Fill(collision.posZ()); + !eh.fEventHistograms[eTotalMultiplicity][eRec][ba] ? true : eh.fEventHistograms[eTotalMultiplicity][eRec][ba]->Fill(tracks.size()); + !eh.fEventHistograms[eCentrality][eRec][ba] ? true : eh.fEventHistograms[eCentrality][eRec][ba]->Fill(ebye.fCentrality); + } } // if constexpr (rs == eTest) { } // template void FillEventHistograms(...) @@ -5033,34 +5069,39 @@ void FillParticleHistograms(T const& track, eBeforeAfter ba, Int_t weight = 1) // But I have already tc.fProcess[eGenericRec] and tc.fProcess[eGenericRecSim], available, shall I simply re-use them? // 1D: - // From o2::aod::Tracks - !ph.fParticleHistograms[ePhi][eRec][ba] ? true : ph.fParticleHistograms[ePhi][eRec][ba]->Fill(track.phi(), weight); // 3 2 - !ph.fParticleHistograms[ePt][eRec][ba] ? true : ph.fParticleHistograms[ePt][eRec][ba]->Fill(track.pt(), weight); // 3 2 - !ph.fParticleHistograms[eEta][eRec][ba] ? true : ph.fParticleHistograms[eEta][eRec][ba]->Fill(track.eta(), weight); // 3 2 - !ph.fParticleHistograms[eCharge][eRec][ba] ? true : ph.fParticleHistograms[eCharge][eRec][ba]->Fill(track.sign(), weight); // 3 2 - - // From o2::aod::TracksExtra_001 - !ph.fParticleHistograms[etpcNClsFindable][eRec][ba] ? true : ph.fParticleHistograms[etpcNClsFindable][eRec][ba]->Fill(track.tpcNClsFindable(), weight); // 3 2 - !ph.fParticleHistograms[etpcNClsShared][eRec][ba] ? true : ph.fParticleHistograms[etpcNClsShared][eRec][ba]->Fill(track.tpcNClsShared(), weight); // 3 2 - !ph.fParticleHistograms[etpcNClsFound][eRec][ba] ? true : ph.fParticleHistograms[etpcNClsFound][eRec][ba]->Fill(track.tpcNClsFound(), weight); // 3 2 - !ph.fParticleHistograms[etpcNClsCrossedRows][eRec][ba] ? true : ph.fParticleHistograms[etpcNClsCrossedRows][eRec][ba]->Fill(track.tpcNClsCrossedRows(), weight); // 3 2 - !ph.fParticleHistograms[eitsNCls][eRec][ba] ? true : ph.fParticleHistograms[eitsNCls][eRec][ba]->Fill(track.itsNCls(), weight); // 3 2 - !ph.fParticleHistograms[eitsNClsInnerBarrel][eRec][ba] ? true : ph.fParticleHistograms[eitsNClsInnerBarrel][eRec][ba]->Fill(track.itsNClsInnerBarrel(), weight); // 3 2 - !ph.fParticleHistograms[etpcCrossedRowsOverFindableCls][eRec][ba] ? true : ph.fParticleHistograms[etpcCrossedRowsOverFindableCls][eRec][ba]->Fill(track.tpcCrossedRowsOverFindableCls(), weight); // 3 2 - !ph.fParticleHistograms[etpcFoundOverFindableCls][eRec][ba] ? true : ph.fParticleHistograms[etpcFoundOverFindableCls][eRec][ba]->Fill(track.tpcFoundOverFindableCls(), weight); // 3 2 - !ph.fParticleHistograms[etpcFractionSharedCls][eRec][ba] ? true : ph.fParticleHistograms[etpcFractionSharedCls][eRec][ba]->Fill(track.tpcFractionSharedCls(), weight); // 3 2 - - // From o2::aod::TracksDCA - // Remark: For this one, in Run 3 workflow I need helper task o2-analysis-track-propagation, while in Run 2 and 1 I need o2-analysis-trackextension . - !ph.fParticleHistograms[edcaXY][eRec][ba] ? true : ph.fParticleHistograms[edcaXY][eRec][ba]->Fill(track.dcaXY(), weight); // 3 2 - !ph.fParticleHistograms[edcaZ][eRec][ba] ? true : ph.fParticleHistograms[edcaZ][eRec][ba]->Fill(track.dcaZ(), weight); // 3 2 + if (ph.fFillParticleHistograms) { + // From o2::aod::Tracks + !ph.fParticleHistograms[ePhi][eRec][ba] ? true : ph.fParticleHistograms[ePhi][eRec][ba]->Fill(track.phi(), weight); // 3 2 + !ph.fParticleHistograms[ePt][eRec][ba] ? true : ph.fParticleHistograms[ePt][eRec][ba]->Fill(track.pt(), weight); // 3 2 + !ph.fParticleHistograms[eEta][eRec][ba] ? true : ph.fParticleHistograms[eEta][eRec][ba]->Fill(track.eta(), weight); // 3 2 + !ph.fParticleHistograms[eCharge][eRec][ba] ? true : ph.fParticleHistograms[eCharge][eRec][ba]->Fill(track.sign(), weight); // 3 2 + + // From o2::aod::TracksExtra_001 + !ph.fParticleHistograms[etpcNClsFindable][eRec][ba] ? true : ph.fParticleHistograms[etpcNClsFindable][eRec][ba]->Fill(track.tpcNClsFindable(), weight); // 3 2 + !ph.fParticleHistograms[etpcNClsShared][eRec][ba] ? true : ph.fParticleHistograms[etpcNClsShared][eRec][ba]->Fill(track.tpcNClsShared(), weight); // 3 2 + !ph.fParticleHistograms[etpcNClsFound][eRec][ba] ? true : ph.fParticleHistograms[etpcNClsFound][eRec][ba]->Fill(track.tpcNClsFound(), weight); // 3 2 + !ph.fParticleHistograms[etpcNClsCrossedRows][eRec][ba] ? true : ph.fParticleHistograms[etpcNClsCrossedRows][eRec][ba]->Fill(track.tpcNClsCrossedRows(), weight); // 3 2 + !ph.fParticleHistograms[eitsNCls][eRec][ba] ? true : ph.fParticleHistograms[eitsNCls][eRec][ba]->Fill(track.itsNCls(), weight); // 3 2 + !ph.fParticleHistograms[eitsNClsInnerBarrel][eRec][ba] ? true : ph.fParticleHistograms[eitsNClsInnerBarrel][eRec][ba]->Fill(track.itsNClsInnerBarrel(), weight); // 3 2 + !ph.fParticleHistograms[etpcCrossedRowsOverFindableCls][eRec][ba] ? true : ph.fParticleHistograms[etpcCrossedRowsOverFindableCls][eRec][ba]->Fill(track.tpcCrossedRowsOverFindableCls(), weight); // 3 2 + !ph.fParticleHistograms[etpcFoundOverFindableCls][eRec][ba] ? true : ph.fParticleHistograms[etpcFoundOverFindableCls][eRec][ba]->Fill(track.tpcFoundOverFindableCls(), weight); // 3 2 + !ph.fParticleHistograms[etpcFractionSharedCls][eRec][ba] ? true : ph.fParticleHistograms[etpcFractionSharedCls][eRec][ba]->Fill(track.tpcFractionSharedCls(), weight); // 3 2 + + // From o2::aod::TracksDCA + // Remark: For this one, in Run 3 workflow I need helper task o2-analysis-track-propagation, while in Run 2 and 1 I need o2-analysis-trackextension . + !ph.fParticleHistograms[edcaXY][eRec][ba] ? true : ph.fParticleHistograms[edcaXY][eRec][ba]->Fill(track.dcaXY(), weight); // 3 2 + !ph.fParticleHistograms[edcaZ][eRec][ba] ? true : ph.fParticleHistograms[edcaZ][eRec][ba]->Fill(track.dcaZ(), weight); // 3 2 + } // 2D: - !ph.fParticleHistograms2D[ePhiPt][eRec][ba] ? true : ph.fParticleHistograms2D[ePhiPt][eRec][ba]->Fill(track.phi(), track.pt(), weight); // 3 2 - !ph.fParticleHistograms2D[ePhiEta][eRec][ba] ? true : ph.fParticleHistograms2D[ePhiEta][eRec][ba]->Fill(track.phi(), track.eta(), weight); + if (ph.fFillParticleHistograms2D) { + !ph.fParticleHistograms2D[ePhiPt][eRec][ba] ? true : ph.fParticleHistograms2D[ePhiPt][eRec][ba]->Fill(track.phi(), track.pt(), weight); // 3 2 + !ph.fParticleHistograms2D[ePhiEta][eRec][ba] ? true : ph.fParticleHistograms2D[ePhiEta][eRec][ba]->Fill(track.phi(), track.eta(), weight); + } // if (ph.fFillParticleHistograms2D) { + // QA: if (qa.fFillQAParticleHistograms2D) { - !qa.fQAParticleHistograms2D[edcaXY_vs_Pt][eRec][ba] ? true : qa.fQAParticleHistograms2D[edcaXY_vs_Pt][eRec][ba]->Fill(track.dcaXY(), track.pt()); + !qa.fQAParticleHistograms2D[ePt_vs_dcaXY][eRec][ba] ? true : qa.fQAParticleHistograms2D[ePt_vs_dcaXY][eRec][ba]->Fill(track.pt(), track.dcaXY()); } // ... and corresponding MC truth simulated (common to Run 3, Run 2 and Run 1) @@ -5073,15 +5114,21 @@ void FillParticleHistograms(T const& track, eBeforeAfter ba, Int_t weight = 1) return; } auto mcparticle = track.mcParticle(); // corresponding MC truth simulated particle + // 1D: - !ph.fParticleHistograms[ePhi][eSim][ba] ? true : ph.fParticleHistograms[ePhi][eSim][ba]->Fill(mcparticle.phi(), weight); // 3 - !ph.fParticleHistograms[ePt][eSim][ba] ? true : ph.fParticleHistograms[ePt][eSim][ba]->Fill(mcparticle.pt(), weight); // 3 - !ph.fParticleHistograms[eEta][eSim][ba] ? true : ph.fParticleHistograms[eEta][eSim][ba]->Fill(mcparticle.eta(), weight); // 3 - // !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 + if (ph.fFillParticleHistograms) { + !ph.fParticleHistograms[ePhi][eSim][ba] ? true : ph.fParticleHistograms[ePhi][eSim][ba]->Fill(mcparticle.phi(), weight); // 3 + !ph.fParticleHistograms[ePt][eSim][ba] ? true : ph.fParticleHistograms[ePt][eSim][ba]->Fill(mcparticle.pt(), weight); // 3 + !ph.fParticleHistograms[eEta][eSim][ba] ? true : ph.fParticleHistograms[eEta][eSim][ba]->Fill(mcparticle.eta(), weight); // 3 + // !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 + } + // 2D: - !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) { + !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) { } // if constexpr (rs == eRecAndSim || rs == eRecAndSim_Run2 || rs == eRecAndSim_Run1) { } // if constexpr (rs == eRec || rs == eRecAndSim || rs == eRec_Run2 || rs == eRecAndSim_Run2 || rs == eRec_Run1 || rs == eRecAndSim_Run1) { @@ -5093,14 +5140,19 @@ void FillParticleHistograms(T const& track, eBeforeAfter ba, Int_t weight = 1) // Remark #2: In this branch, 'track' is always TracksSim = aod::McParticles, see https://aliceo2group.github.io/analysis-framework/docs/datamodel/ao2dTables.html#montecarlo if constexpr (rs == eSim || rs == eSim_Run2 || rs == eSim_Run1) { // 1D: - !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()) - !ph.fParticleHistograms[ePDG][eSim][ba] ? true : ph.fParticleHistograms[ePDG][eSim][ba]->Fill(track.pdgCode(), weight); + if (ph.fFillParticleHistograms) { + !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()) + !ph.fParticleHistograms[ePDG][eSim][ba] ? true : ph.fParticleHistograms[ePDG][eSim][ba]->Fill(track.pdgCode(), weight); + } // if(ph.fFillParticleHistograms) { + // 2D: - !ph.fParticleHistograms2D[ePhiPt][eSim][ba] ? true : ph.fParticleHistograms2D[ePhiPt][eSim][ba]->Fill(track.phi(), track.pt(), weight); - !ph.fParticleHistograms2D[ePhiEta][eSim][ba] ? true : ph.fParticleHistograms2D[ePhiEta][eSim][ba]->Fill(track.phi(), track.eta(), weight); + if (ph.fFillParticleHistograms2D) { + !ph.fParticleHistograms2D[ePhiPt][eSim][ba] ? true : ph.fParticleHistograms2D[ePhiPt][eSim][ba]->Fill(track.phi(), track.pt(), weight); + !ph.fParticleHistograms2D[ePhiEta][eSim][ba] ? true : ph.fParticleHistograms2D[ePhiEta][eSim][ba]->Fill(track.phi(), track.eta(), weight); + } // if(ph.fFillParticleHistograms2D) { } // if constexpr (rs == eSim || rs == eSim_Run2 || rs == eSim_Run1) { // ----------------------------------------------------------------------------- @@ -5181,12 +5233,16 @@ void FillParticleHistograms(T const& track, eBeforeAfter ba, Int_t weight = 1) // This branch corresponds to process with minimal subscription - I implement just a few example cuts, just for testing purposes. // Only eRec is support in Test for the time being. // 1D: - !ph.fParticleHistograms[ePhi][eRec][ba] ? true : ph.fParticleHistograms[ePhi][eRec][ba]->Fill(track.phi(), weight); - !ph.fParticleHistograms[ePt][eRec][ba] ? true : ph.fParticleHistograms[ePt][eRec][ba]->Fill(track.pt(), weight); - !ph.fParticleHistograms[eEta][eRec][ba] ? true : ph.fParticleHistograms[eEta][eRec][ba]->Fill(track.eta(), weight); + if (ph.fFillParticleHistograms) { + !ph.fParticleHistograms[ePhi][eRec][ba] ? true : ph.fParticleHistograms[ePhi][eRec][ba]->Fill(track.phi(), weight); + !ph.fParticleHistograms[ePt][eRec][ba] ? true : ph.fParticleHistograms[ePt][eRec][ba]->Fill(track.pt(), weight); + !ph.fParticleHistograms[eEta][eRec][ba] ? true : ph.fParticleHistograms[eEta][eRec][ba]->Fill(track.eta(), weight); + } // 2D: - !ph.fParticleHistograms2D[ePhiPt][eRec][ba] ? true : ph.fParticleHistograms2D[ePhiPt][eRec][ba]->Fill(track.phi(), track.pt(), weight); - !ph.fParticleHistograms2D[ePhiEta][eRec][ba] ? true : ph.fParticleHistograms2D[ePhiEta][eRec][ba]->Fill(track.phi(), track.eta(), weight); + if (ph.fFillParticleHistograms2D) { + !ph.fParticleHistograms2D[ePhiPt][eRec][ba] ? true : ph.fParticleHistograms2D[ePhiPt][eRec][ba]->Fill(track.phi(), track.pt(), weight); + !ph.fParticleHistograms2D[ePhiEta][eRec][ba] ? true : ph.fParticleHistograms2D[ePhiEta][eRec][ba]->Fill(track.phi(), track.eta(), weight); + } } // if constexpr (rs == eTest) { } // template void FillParticleHistograms(...) @@ -6494,12 +6550,16 @@ void SetWeightsHist(TH1D* const hist, eWeights whichWeight) pw.fWeightsHist[whichWeight]->GetYaxis()->SetTitle(sWeights[whichWeight].Data()); pw.fWeightsHist[whichWeight]->SetFillColor(eFillColor); pw.fWeightsHist[whichWeight]->SetLineColor(eColor); - pw.fWeightsList->Add(pw.fWeightsHist[whichWeight]); + if (!pw.fWeightsList) { + LOGF(fatal, "\033[1;31m%s at line %d: fWeightsList is NULL. That means that you have called SetWeightsHist(...) in init(), before this TList was booked.\033[0m", __FUNCTION__, __LINE__); + } + pw.fWeightsList->Add(pw.fWeightsHist[whichWeight]); // 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: pw.fUseWeights[whichWeight] = kTRUE; -} // void SetWeightsHist(TH1D* const hist, , eWeights whichWeight) +} // void SetWeightsHist(TH1D* const hist, eWeights whichWeight) //============================================================ @@ -8216,7 +8276,7 @@ void BanishmentLoopOverParticles(T const& tracks) lSelectedTracks++; // *) Banish particle histograms after particle cuts: - if (ph.fFillParticleHistograms || ph.fFillParticleHistograms2D) { + if (ph.fFillParticleHistograms || ph.fFillParticleHistograms2D || qa.fFillQAParticleHistograms2D) { FillParticleHistograms(track, eAfter, -1); // with negative weight -1, I effectively remove the previous fill for this track } @@ -8592,7 +8652,7 @@ void Steer(T1 const& collision, T2 const& tracks) DetermineCentrality(collision); // *) Fill event histograms before event cuts: - if (eh.fFillEventHistograms) { + if (eh.fFillEventHistograms || qa.fFillQAEventHistograms2D) { FillEventHistograms(collision, tracks, eBefore); } @@ -8634,7 +8694,7 @@ void Steer(T1 const& collision, T2 const& tracks) } // *) Fill event histograms after event AND particle cuts: // TBI 20240110 not sure still if this one is called here, or it has to be moved above - if (eh.fFillEventHistograms) { + if (eh.fFillEventHistograms || qa.fFillQAEventHistograms2D) { FillEventHistograms(collision, tracks, eAfter); } @@ -8728,7 +8788,7 @@ void MainLoopOverParticles(T const& tracks) } // *) Fill particle histograms before particle cuts: - if (ph.fFillParticleHistograms || ph.fFillParticleHistograms2D) { + if (ph.fFillParticleHistograms || ph.fFillParticleHistograms2D || qa.fFillQAParticleHistograms2D) { FillParticleHistograms(track, eBefore); } @@ -8743,7 +8803,7 @@ void MainLoopOverParticles(T const& tracks) } // *) Fill particle histograms after particle cuts: - if (ph.fFillParticleHistograms || ph.fFillParticleHistograms2D) { + if (ph.fFillParticleHistograms || ph.fFillParticleHistograms2D || qa.fFillQAParticleHistograms2D) { FillParticleHistograms(track, eAfter); } diff --git a/PWGCF/MultiparticleCorrelations/Tasks/ThreeParticleCorrelations.cxx b/PWGCF/MultiparticleCorrelations/Tasks/ThreeParticleCorrelations.cxx index 340e3ec112d..f16e72accd1 100644 --- a/PWGCF/MultiparticleCorrelations/Tasks/ThreeParticleCorrelations.cxx +++ b/PWGCF/MultiparticleCorrelations/Tasks/ThreeParticleCorrelations.cxx @@ -15,6 +15,7 @@ #include "Common/DataModel/PIDResponse.h" #include "PWGLF/DataModel/LFStrangenessTables.h" +#include "TPDGCode.h" #include "TLorentzVector.h" using namespace o2; @@ -26,11 +27,14 @@ struct ThreePartCorr { // Histogram registry HistogramRegistry MECorrRegistry{"MECorrRegistry", {}, OutputObjHandlingPolicy::AnalysisObject, false, true}; HistogramRegistry SECorrRegistry{"SECorrRegistry", {}, OutputObjHandlingPolicy::AnalysisObject, false, true}; + HistogramRegistry MCRegistry{"MCRegistry", {}, OutputObjHandlingPolicy::AnalysisObject, false, true}; HistogramRegistry QARegistry{"QARegistry", {}, OutputObjHandlingPolicy::AnalysisObject, false, true}; - // Collision filters + // Collision & Event filters Filter CollCent = aod::cent::centFT0C > 0.0f && aod::cent::centFT0C < 90.0f; Filter CollZvtx = nabs(aod::collision::posZ) < 7.0f; + Filter MCCollZvtx = nabs(aod::mccollision::posZ) < 7.0f; + Filter EvSelect = aod::evsel::sel8 == true; // V0 filters Filter V0Pt = aod::v0data::pt > 0.6f && aod::v0data::pt < 12.0f; @@ -39,15 +43,26 @@ struct ThreePartCorr { // Track filters Filter TrackPt = aod::track::pt > 0.2f && aod::track::pt < 3.0f; Filter TrackEta = nabs(aod::track::eta) < 0.8f; + Filter GlobalTracks = requireGlobalTrackInFilter(); - // Table aliases - using MyFilteredCollisions = soa::Filtered>; + // Particle filters + Filter ParticlePt = aod::mcparticle::pt > 0.2f && aod::mcparticle::pt < 3.0f; + Filter ParticleEta = nabs(aod::mcparticle::eta) < 0.8f; + + // Table aliases - Data + using MyFilteredCollisions = soa::Filtered>; using MyFilteredCollision = MyFilteredCollisions::iterator; using MyFilteredV0s = soa::Filtered; - using MyFilteredTracks = soa::Filtered>; + // Table aliases - MC + using MyFilteredMCGenCollision = soa::Filtered::iterator; + using MyFilteredMCParticles = soa::Filtered; + using MyFilteredMCRecCollision = soa::Filtered>::iterator; + using MyFilteredMCTracks = soa::Filtered>; + // Mixed-events binning policy SliceCache cache; ConfigurableAxis ConfCentBins{"ConfCentBins", {VARIABLE_WIDTH, 0.0f, 10.0f, 20.0f, 30.0f, 40.0f, 50.0f, 60.0f, 70.0f, 80.0f, 90.0f}, "ME Centrality binning"}; @@ -57,8 +72,11 @@ struct ThreePartCorr { BinningType CollBinning{{ConfCentBins, ConfZvtxBins}, true}; Pair pair{CollBinning, 5, -1, &cache}; + // Process configurables + Configurable ConfFilterSwitch{"ConfFilterSwitch", false, "Switch for the FakeV0Filter function"}; + // Particle masses - Double_t massLambda = 1.115683; + Double_t massLambda = o2::constants::physics::MassLambda0; Double_t DGaussSigma = 0.0021; // Correlation variables @@ -77,7 +95,8 @@ struct ThreePartCorr { const AxisSpec ZvtxAxis{ConfZvtxBins}; const AxisSpec PhiAxis{36, (-1. / 2) * M_PI, (3. / 2) * M_PI}; const AxisSpec EtaAxis{32, -1.52, 1.52}; - const AxisSpec PtAxis{120, 0, 12}; + const AxisSpec V0PtAxis{114, 0.6, 12}; + const AxisSpec TrackPtAxis{28, 0.2, 3}; const AxisSpec LambdaInvMassAxis{100, 1.08, 1.16}; QARegistry.add("hTrackPt", "hTrackPt", {HistType::kTH1D, {{100, 0, 4}}}); @@ -98,8 +117,21 @@ struct ThreePartCorr { QARegistry.add("hNSigmaKaon", "hNSigmaKaon", {HistType::kTH2D, {{201, -5.025, 5.025}, {201, -5.025, 5.025}}}); QARegistry.add("hNSigmaProton", "hNSigmaProton", {HistType::kTH2D, {{201, -5.025, 5.025}, {201, -5.025, 5.025}}}); - QARegistry.add("hInvMassLambda", "hInvMassLambda", {HistType::kTH3D, {{LambdaInvMassAxis}, {PtAxis}, {CentralityAxis}}}); - QARegistry.add("hInvMassAntiLambda", "hInvMassAntiLambda", {HistType::kTH3D, {{LambdaInvMassAxis}, {PtAxis}, {CentralityAxis}}}); + QARegistry.add("hInvMassLambda", "hInvMassLambda", {HistType::kTH3D, {{LambdaInvMassAxis}, {V0PtAxis}, {CentralityAxis}}}); + QARegistry.add("hInvMassAntiLambda", "hInvMassAntiLambda", {HistType::kTH3D, {{LambdaInvMassAxis}, {V0PtAxis}, {CentralityAxis}}}); + + MCRegistry.add("hGenPionP", "hGenPionP", {HistType::kTH1D, {TrackPtAxis}}); + MCRegistry.add("hGenPionN", "hGenPionN", {HistType::kTH1D, {TrackPtAxis}}); + MCRegistry.add("hGenKaonP", "hGenKaonP", {HistType::kTH1D, {TrackPtAxis}}); + MCRegistry.add("hGenKaonN", "hGenKaonN", {HistType::kTH1D, {TrackPtAxis}}); + MCRegistry.add("hGenProtonP", "hGenProtonP", {HistType::kTH1D, {TrackPtAxis}}); + MCRegistry.add("hGenProtonN", "hGenProtonN", {HistType::kTH1D, {TrackPtAxis}}); + MCRegistry.add("hRecPionP", "hRecPionP", {HistType::kTH1D, {TrackPtAxis}}); + MCRegistry.add("hRecPionN", "hRecPionN", {HistType::kTH1D, {TrackPtAxis}}); + MCRegistry.add("hRecKaonP", "hRecKaonP", {HistType::kTH1D, {TrackPtAxis}}); + MCRegistry.add("hRecKaonN", "hRecKaonN", {HistType::kTH1D, {TrackPtAxis}}); + MCRegistry.add("hRecProtonP", "hRecProtonP", {HistType::kTH1D, {TrackPtAxis}}); + MCRegistry.add("hRecProtonN", "hRecProtonN", {HistType::kTH1D, {TrackPtAxis}}); SECorrRegistry.add("hSameLambdaPion_SGNL", "Same-event #Lambda - #pi correlator (SGNL region)", {HistType::kTHnSparseD, {{PhiAxis}, {EtaAxis}, {CentralityAxis}, {ZvtxAxis}, {2, -2, 2}, {2, -2, 2}}}); SECorrRegistry.add("hSameLambdaPion_SB", "Same-event #Lambda - #pi correlator (SB region)", {HistType::kTHnSparseD, {{PhiAxis}, {EtaAxis}, {CentralityAxis}, {ZvtxAxis}, {2, -2, 2}, {2, -2, 2}}}); @@ -172,19 +204,19 @@ struct ThreePartCorr { DeltaEta = trigger.eta() - associate.eta(); if (CandMass >= massLambda - 4 * DGaussSigma && CandMass <= massLambda + 4 * DGaussSigma) { - if (A_PID[0] == 0) { // Pions + if (A_PID[0] == 0.0) { // Pions SECorrRegistry.fill(HIST("hSameLambdaPion_SGNL"), DeltaPhi, DeltaEta, collision.centFT0C(), collision.posZ(), T_Sign, associate.sign()); - } else if (A_PID[0] == 1) { // Kaons + } else if (A_PID[0] == 1.0) { // Kaons SECorrRegistry.fill(HIST("hSameLambdaKaon_SGNL"), DeltaPhi, DeltaEta, collision.centFT0C(), collision.posZ(), T_Sign, associate.sign()); - } else if (A_PID[0] == 2) { // Protons + } else if (A_PID[0] == 2.0) { // Protons SECorrRegistry.fill(HIST("hSameLambdaProton_SGNL"), DeltaPhi, DeltaEta, collision.centFT0C(), collision.posZ(), T_Sign, associate.sign()); } } else if (CandMass >= massLambda - 8 * DGaussSigma && CandMass <= massLambda + 8 * DGaussSigma) { - if (A_PID[0] == 0) { // Pions + if (A_PID[0] == 0.0) { // Pions SECorrRegistry.fill(HIST("hSameLambdaPion_SB"), DeltaPhi, DeltaEta, collision.centFT0C(), collision.posZ(), T_Sign, associate.sign()); - } else if (A_PID[0] == 1) { // Kaons + } else if (A_PID[0] == 1.0) { // Kaons SECorrRegistry.fill(HIST("hSameLambdaKaon_SB"), DeltaPhi, DeltaEta, collision.centFT0C(), collision.posZ(), T_Sign, associate.sign()); - } else if (A_PID[0] == 2) { // Protons + } else if (A_PID[0] == 2.0) { // Protons SECorrRegistry.fill(HIST("hSameLambdaProton_SB"), DeltaPhi, DeltaEta, collision.centFT0C(), collision.posZ(), T_Sign, associate.sign()); } } @@ -195,13 +227,10 @@ struct ThreePartCorr { } // End of the V0-Track Correlations } - PROCESS_SWITCH(ThreePartCorr, processSame, "Process same-event correlations", true); - void processMixed(MyFilteredCollisions const& collisions, MyFilteredV0s const& v0s, MyFilteredTracks const& tracks) + void processMixed(MyFilteredCollisions const&, MyFilteredV0s const&, MyFilteredTracks const&) { - LOGF(info, "Input data Collisions %d, V0s %d, Tracks %d ", collisions.size(), v0s.size(), tracks.size()); - // Start of the Mixed-events Correlations for (const auto& [coll_1, v0_1, coll_2, track_2] : pair) { for (const auto& [trigger, associate] : soa::combinations(soa::CombinationsFullIndexPolicy(v0_1, track_2))) { @@ -220,19 +249,19 @@ struct ThreePartCorr { DeltaEta = trigger.eta() - associate.eta(); if (CandMass >= massLambda - 4 * DGaussSigma && CandMass <= massLambda + 4 * DGaussSigma) { - if (A_PID[0] == 0) { // Pions + if (A_PID[0] == 0.0) { // Pions MECorrRegistry.fill(HIST("hMixLambdaPion_SGNL"), DeltaPhi, DeltaEta, coll_1.centFT0C(), coll_1.posZ(), T_Sign, associate.sign()); - } else if (A_PID[0] == 1) { // Kaons + } else if (A_PID[0] == 1.0) { // Kaons MECorrRegistry.fill(HIST("hMixLambdaKaon_SGNL"), DeltaPhi, DeltaEta, coll_1.centFT0C(), coll_1.posZ(), T_Sign, associate.sign()); - } else if (A_PID[0] == 2) { // Protons + } else if (A_PID[0] == 2.0) { // Protons MECorrRegistry.fill(HIST("hMixLambdaProton_SGNL"), DeltaPhi, DeltaEta, coll_1.centFT0C(), coll_1.posZ(), T_Sign, associate.sign()); } } else if (CandMass >= massLambda - 8 * DGaussSigma && CandMass <= massLambda + 8 * DGaussSigma) { - if (A_PID[0] == 0) { // Pions + if (A_PID[0] == 0.0) { // Pions MECorrRegistry.fill(HIST("hMixLambdaPion_SB"), DeltaPhi, DeltaEta, coll_1.centFT0C(), coll_1.posZ(), T_Sign, associate.sign()); - } else if (A_PID[0] == 1) { // Kaons + } else if (A_PID[0] == 1.0) { // Kaons MECorrRegistry.fill(HIST("hMixLambdaKaon_SB"), DeltaPhi, DeltaEta, coll_1.centFT0C(), coll_1.posZ(), T_Sign, associate.sign()); - } else if (A_PID[0] == 2) { // Protons + } else if (A_PID[0] == 2.0) { // Protons MECorrRegistry.fill(HIST("hMixLambdaProton_SB"), DeltaPhi, DeltaEta, coll_1.centFT0C(), coll_1.posZ(), T_Sign, associate.sign()); } } @@ -242,7 +271,70 @@ struct ThreePartCorr { } // End of the Mixed-events Correlations } + + void processMCGen(MyFilteredMCGenCollision const&, MyFilteredMCParticles const& particles) + { + + // Start of the Monte-Carlo generated QA + for (const auto& particle : particles) { + if (particle.isPhysicalPrimary()) { + + if (particle.pdgCode() == kPiPlus) { // Pos pions + MCRegistry.fill(HIST("hGenPionP"), particle.pt()); + } else if (particle.pdgCode() == kPiMinus) { // Neg pions + MCRegistry.fill(HIST("hGenPionN"), particle.pt()); + } else if (particle.pdgCode() == kKPlus) { // Pos kaons + MCRegistry.fill(HIST("hGenKaonP"), particle.pt()); + } else if (particle.pdgCode() == kKMinus) { // Neg kaons + MCRegistry.fill(HIST("hGenKaonN"), particle.pt()); + } else if (particle.pdgCode() == kProton) { // Pos protons + MCRegistry.fill(HIST("hGenProtonP"), particle.pt()); + } else if (particle.pdgCode() == kProtonBar) { // Neg protons + MCRegistry.fill(HIST("hGenProtonN"), particle.pt()); + } + } + } + // End of the Monte-Carlo generated QA + } + + void processMCRec(MyFilteredMCRecCollision const& collision, MyFilteredMCTracks const& tracks, aod::McCollisions const&, aod::McParticles const&) + { + + if (!collision.has_mcCollision()) { + return; + } + + // Start of the Monte-Carlo reconstructed QA + for (const auto& track : tracks) { + if (!track.has_mcParticle()) { + continue; + } + + auto particle = track.mcParticle(); + if (particle.isPhysicalPrimary()) { + + if (particle.pdgCode() == kPiPlus) { // Pos pions + MCRegistry.fill(HIST("hRecPionP"), track.pt()); + } else if (particle.pdgCode() == kPiMinus) { // Neg pions + MCRegistry.fill(HIST("hRecPionN"), track.pt()); + } else if (particle.pdgCode() == kKPlus) { // Pos kaons + MCRegistry.fill(HIST("hRecKaonP"), track.pt()); + } else if (particle.pdgCode() == kKMinus) { // Neg kaons + MCRegistry.fill(HIST("hRecKaonN"), track.pt()); + } else if (particle.pdgCode() == kProton) { // Pos protons + MCRegistry.fill(HIST("hRecProtonP"), track.pt()); + } else if (particle.pdgCode() == kProtonBar) { // Neg protons + MCRegistry.fill(HIST("hRecProtonN"), track.pt()); + } + } + } + // End of the Monte-Carlo reconstructed QA + } + + PROCESS_SWITCH(ThreePartCorr, processSame, "Process same-event correlations", true); PROCESS_SWITCH(ThreePartCorr, processMixed, "Process mixed-event correlations", true); + PROCESS_SWITCH(ThreePartCorr, processMCGen, "Process Monte-Carlo, generator level", false); + PROCESS_SWITCH(ThreePartCorr, processMCRec, "Process Monte-Carlo, reconstructed level", false); //================================================================================================================================================================================================================ @@ -345,29 +437,32 @@ struct ThreePartCorr { Bool_t FakeV0Filter(const V0Cand& V0, const TrackCand& Track) { - TLorentzVector Daughter, Associate; - if (TrackPID(Track)[0] == 1.0) { // Kaons - return kTRUE; - } else if (V0Sign(V0) == 1 && TrackPID(Track)[0] == 0 && Track.sign() == -1) { // Lambda - Pi_min - const auto& dTrack = V0.template posTrack_as(); - Daughter.SetPtEtaPhiM(dTrack.pt(), dTrack.eta(), dTrack.phi(), o2::constants::physics::MassProton); - Associate.SetPtEtaPhiM(Track.pt(), Track.eta(), Track.phi(), o2::constants::physics::MassPionCharged); - } else if (V0Sign(V0) == -1 && TrackPID(Track)[0] == 0 && Track.sign() == 1) { // Antilambda - Pi_plus - const auto& dTrack = V0.template negTrack_as(); - Daughter.SetPtEtaPhiM(dTrack.pt(), dTrack.eta(), dTrack.phi(), o2::constants::physics::MassProton); - Associate.SetPtEtaPhiM(Track.pt(), Track.eta(), Track.phi(), o2::constants::physics::MassPionCharged); - } else if (V0Sign(V0) == 1 && TrackPID(Track)[0] == 2 && Track.sign() == 1) { // Lambda - Proton - const auto& dTrack = V0.template negTrack_as(); - Daughter.SetPtEtaPhiM(dTrack.pt(), dTrack.eta(), dTrack.phi(), o2::constants::physics::MassPionCharged); - Associate.SetPtEtaPhiM(Track.pt(), Track.eta(), Track.phi(), o2::constants::physics::MassProton); - } else if (V0Sign(V0) == -1 && TrackPID(Track)[0] == 2 && Track.sign() == -1) { // Antilambda - Antiproton - const auto& dTrack = V0.template posTrack_as(); - Daughter.SetPtEtaPhiM(dTrack.pt(), dTrack.eta(), dTrack.phi(), o2::constants::physics::MassPionCharged); - Associate.SetPtEtaPhiM(Track.pt(), Track.eta(), Track.phi(), o2::constants::physics::MassProton); - } + if (ConfFilterSwitch) { + + TLorentzVector Daughter, Associate; + if (TrackPID(Track)[0] == 1.0) { // Kaons + return kTRUE; + } else if (V0Sign(V0) == 1 && TrackPID(Track)[0] == 0.0 && Track.sign() == -1) { // Lambda - Pi_min + const auto& dTrack = V0.template posTrack_as(); + Daughter.SetPtEtaPhiM(dTrack.pt(), dTrack.eta(), dTrack.phi(), o2::constants::physics::MassProton); + Associate.SetPtEtaPhiM(Track.pt(), Track.eta(), Track.phi(), o2::constants::physics::MassPionCharged); + } else if (V0Sign(V0) == -1 && TrackPID(Track)[0] == 0.0 && Track.sign() == 1) { // Antilambda - Pi_plus + const auto& dTrack = V0.template negTrack_as(); + Daughter.SetPtEtaPhiM(dTrack.pt(), dTrack.eta(), dTrack.phi(), o2::constants::physics::MassProton); + Associate.SetPtEtaPhiM(Track.pt(), Track.eta(), Track.phi(), o2::constants::physics::MassPionCharged); + } else if (V0Sign(V0) == 1 && TrackPID(Track)[0] == 2.0 && Track.sign() == 1) { // Lambda - Proton + const auto& dTrack = V0.template negTrack_as(); + Daughter.SetPtEtaPhiM(dTrack.pt(), dTrack.eta(), dTrack.phi(), o2::constants::physics::MassPionCharged); + Associate.SetPtEtaPhiM(Track.pt(), Track.eta(), Track.phi(), o2::constants::physics::MassProton); + } else if (V0Sign(V0) == -1 && TrackPID(Track)[0] == 2.0 && Track.sign() == -1) { // Antilambda - Antiproton + const auto& dTrack = V0.template posTrack_as(); + Daughter.SetPtEtaPhiM(dTrack.pt(), dTrack.eta(), dTrack.phi(), o2::constants::physics::MassPionCharged); + Associate.SetPtEtaPhiM(Track.pt(), Track.eta(), Track.phi(), o2::constants::physics::MassProton); + } - if ((Daughter + Associate).M() >= massLambda - 4 * DGaussSigma && (Daughter + Associate).M() <= massLambda + 4 * DGaussSigma) { - return kFALSE; + if ((Daughter + Associate).M() >= massLambda - 4 * DGaussSigma && (Daughter + Associate).M() <= massLambda + 4 * DGaussSigma) { + return kFALSE; + } } return kTRUE; diff --git a/PWGCF/Tasks/dptdptcorrelations.cxx b/PWGCF/Tasks/dptdptcorrelations.cxx index 066f70f5230..ad227a09e7d 100644 --- a/PWGCF/Tasks/dptdptcorrelations.cxx +++ b/PWGCF/Tasks/dptdptcorrelations.cxx @@ -66,6 +66,7 @@ bool processpairs = false; // process pairs analysis bool processmixedevents = false; // process mixed events bool ptorder = false; // consider pt ordering bool invmass = false; // produce the invariant mass histograms +bool corrana = false; // produce the correlation analysis histograms PairCuts fPairCuts; // pair suppression engine bool fUseConversionCuts = false; // suppress resonances and conversions @@ -104,7 +105,8 @@ struct DptDptCorrelationsTask { std::vector> fhSum2DptDpt_vsDEtaDPhi{nch, {nch, nullptr}}; //!) ({p_T}_2 - <{p_T}_2>) \f$ distribution vs \f$\Delta\eta,\;\Delta\phi\f$ for the different species combinations std::vector> fhSupN1N1_vsDEtaDPhi{nch, {nch, nullptr}}; //!> fhSupPt1Pt1_vsDEtaDPhi{nch, {nch, nullptr}}; //!> fhInvMass{nch, {nch, nullptr}}; //!> fhInvMassDEta{nch, {nch, nullptr}}; //!> fhInvMassDPhi{nch, {nch, nullptr}}; //! fhN1_vsC{nch, nullptr}; //! fhSum1Pt_vsC{nch, nullptr}; //! + float GetDEtaValue(TrackObject const& t1, TrackObject const& t2) + { + using namespace correlationstask; + using namespace o2::analysis::dptdptfilter; + + /* rule: ix are always zero based while bins are always one based */ + int etaix_1 = static_cast((t1.eta() - etalow) / etabinwidth); + int etaix_2 = static_cast((t2.eta() - etalow) / etabinwidth); + + int deltaeta_ix = etaix_1 - etaix_2 + etabins - 1; + + return deltaetalow + (deltaeta_ix + 0.5) * deltaetabinwidth; + } + + /// \brief Returns the delta phi value for the differential phi + /// \param t1 the intended track one + /// \param t2 the intended track two + /// \return the delta phi value within [-pi,pi] for delta phi + /// + /// WARNING: for performance reasons no checks are done about the consistency + /// of tracks' eta and phi within the corresponding ranges so, it is suppossed + /// the tracks have been accepted and they are within that ranges + /// IF THAT IS NOT THE CASE THE ROUTINE WILL PRODUCE NONSENSE RESULTS + template + float GetDPhiValue(TrackObject const& t1, TrackObject const& t2) + { + using namespace correlationstask; + using namespace o2::analysis::dptdptfilter; + + /* rule: ix are always zero based while bins are always one based */ + /* consider a potential phi origin shift */ + float phi = GetShiftedPhi(t1.phi()); + int phiix_1 = static_cast((phi - philow) / phibinwidth); + /* consider a potential phi origin shift */ + phi = GetShiftedPhi(t2.phi()); + int phiix_2 = static_cast((phi - philow) / phibinwidth); + + int deltaphi_ix = phiix_1 - phiix_2; + if (deltaphi_ix < 0) { + deltaphi_ix += phibins; + } + + float value = deltaphilow + (deltaphi_ix + 0.5) * deltaphibinwidth; + + return (value < (deltaphiup - constants::math::PI)) ? value : value - constants::math::TwoPI; + } + + /// \brief Returns the TH2 global bin for the differential histograms /// \param t1 the intended track one /// \param t2 the intended track two /// \return the globl TH2 bin for delta eta delta phi @@ -173,7 +232,7 @@ struct DptDptCorrelationsTask { /// the tracks have been accepted and they are within that ranges /// IF THAT IS NOT THE CASE THE ROUTINE WILL PRODUCE NONSENSE RESULTS template - int GetDEtaDPhiGlobalIndex(TrackObject const& t1, TrackObject const& t2) + int GetDEtaDPhiGlobalBin(TrackObject const& t1, TrackObject const& t2) { using namespace correlationstask; using namespace o2::analysis::dptdptfilter; @@ -351,7 +410,7 @@ struct DptDptCorrelationsTask { /// \param trks2 filtered table with the tracks associated to the second track in the pair /// \param cmul centrality - multiplicity for the collision being analyzed /// Be aware that in most of the cases traks1 and trks2 will have the same content (exception: mixed events) - template + template void processTrackPairs(TrackOneListObject const& trks1, TrackTwoListObject const& trks2, std::vector* corrs1, std::vector* corrs2, std::vector* ptavgs1, std::vector* ptavgs2, float cmul, int bfield) { using namespace correlationstask; @@ -365,6 +424,8 @@ struct DptDptCorrelationsTask { std::vector> sum2PtPtnw(nch, std::vector(nch, 0.0)); ///< accumulated sum of not weighted track 1 track 2 \f${p_T}_1 {p_T}_2\f$ for current collision std::vector> sum2DptDptnw(nch, std::vector(nch, 0.0)); ///< accumulated sum of not weighted number of track 1 tracks times not weighted track 2 \f$p_T\f$ for current collision int index1 = 0; + int globalbin = 0; + LOGF(debug, "Initializing globalbin to ", globalbin); for (auto& track1 : trks1) { double ptavg_1 = (*ptavgs1)[index1]; @@ -392,7 +453,9 @@ struct DptDptCorrelationsTask { double dptdptw = (corr1 * track1.pt() - ptavg_1) * (corr2 * track2.pt() - ptavg_2); /* get the global bin for filling the differential histograms */ - int globalbin = GetDEtaDPhiGlobalIndex(track1, track2); + if constexpr (docorrelations) { + globalbin = GetDEtaDPhiGlobalBin(track1, track2); + } float deltaeta = track1.eta() - track2.eta(); float deltaphi = track1.phi() - track2.phi(); while (deltaphi >= deltaphiup) { @@ -403,8 +466,10 @@ struct DptDptCorrelationsTask { } if ((fUseConversionCuts && fPairCuts.conversionCuts(track1, track2)) || (fUseTwoTrackCut && fPairCuts.twoTrackCut(track1, track2, bfield))) { /* suppress the pair */ - fhSupN1N1_vsDEtaDPhi[track1.trackacceptedid()][track2.trackacceptedid()]->AddBinContent(globalbin, corr); - fhSupPt1Pt1_vsDEtaDPhi[track1.trackacceptedid()][track2.trackacceptedid()]->AddBinContent(globalbin, track1.pt() * track2.pt() * corr); + if constexpr (docorrelations) { + fhSupN1N1_vsDEtaDPhi[track1.trackacceptedid()][track2.trackacceptedid()]->AddBinContent(globalbin, corr); + fhSupPt1Pt1_vsDEtaDPhi[track1.trackacceptedid()][track2.trackacceptedid()]->AddBinContent(globalbin, track1.pt() * track2.pt() * corr); + } n2sup[track1.trackacceptedid()][track2.trackacceptedid()] += corr; } else { /* count the pair */ @@ -415,18 +480,22 @@ struct DptDptCorrelationsTask { sum2PtPtnw[track1.trackacceptedid()][track2.trackacceptedid()] += track1.pt() * track2.pt(); sum2DptDptnw[track1.trackacceptedid()][track2.trackacceptedid()] += dptdptnw; - fhN2_vsDEtaDPhi[track1.trackacceptedid()][track2.trackacceptedid()]->AddBinContent(globalbin, corr); - fhN2cont_vsDEtaDPhi[track1.trackacceptedid()][track2.trackacceptedid()]->Fill(deltaeta, deltaphi, corr); - fhSum2DptDpt_vsDEtaDPhi[track1.trackacceptedid()][track2.trackacceptedid()]->AddBinContent(globalbin, dptdptw); - fhSum2PtPt_vsDEtaDPhi[track1.trackacceptedid()][track2.trackacceptedid()]->AddBinContent(globalbin, track1.pt() * track2.pt() * corr); + if constexpr (docorrelations) { + fhN2_vsDEtaDPhi[track1.trackacceptedid()][track2.trackacceptedid()]->AddBinContent(globalbin, corr); + fhN2cont_vsDEtaDPhi[track1.trackacceptedid()][track2.trackacceptedid()]->Fill(deltaeta, deltaphi, corr); + fhSum2DptDpt_vsDEtaDPhi[track1.trackacceptedid()][track2.trackacceptedid()]->AddBinContent(globalbin, dptdptw); + fhSum2PtPt_vsDEtaDPhi[track1.trackacceptedid()][track2.trackacceptedid()]->AddBinContent(globalbin, track1.pt() * track2.pt() * corr); + fhN2_vsPtPt[track1.trackacceptedid()][track2.trackacceptedid()]->Fill(track1.pt(), track2.pt(), corr); + } if constexpr (doinvmass) { - if ((track1.trackacceptedid() % 2) != (track2.trackacceptedid() % 2)) { - /* only opposite charge invariant mass*/ - fhInvMass[track1.trackacceptedid()][track2.trackacceptedid()]->Fill(std::sqrt(getInvMassSquared(track1, poimass[static_cast(track1.trackacceptedid() / 2)], track2, poimass[static_cast(track2.trackacceptedid() / 2)])) * 1000.0f); + if (!(track2.trackacceptedid() < track1.trackacceptedid())) { + /* only 12 combinations, 21 are exactly the same */ + double invariantMass = std::sqrt(getInvMassSquared(track1, poimass[static_cast(track1.trackacceptedid() / 2)], track2, poimass[static_cast(track2.trackacceptedid() / 2)])) * 1000.0f; + fhInvMassDEta[track1.trackacceptedid()][track2.trackacceptedid()]->Fill(GetDEtaValue(track1, track2), invariantMass); + fhInvMassDPhi[track1.trackacceptedid()][track2.trackacceptedid()]->Fill(GetDPhiValue(track1, track2), invariantMass); } } } - fhN2_vsPtPt[track1.trackacceptedid()][track2.trackacceptedid()]->Fill(track1.pt(), track2.pt(), corr); index2++; } index1++; @@ -440,11 +509,13 @@ struct DptDptCorrelationsTask { fhSum2PtPtnw_vsC[pid1][pid2]->Fill(cmul, sum2PtPtnw[pid1][pid2]); fhSum2DptDptnw_vsC[pid1][pid2]->Fill(cmul, sum2DptDptnw[pid1][pid2]); /* let's also update the number of entries in the differential histograms */ - fhN2_vsDEtaDPhi[pid1][pid2]->SetEntries(fhN2_vsDEtaDPhi[pid1][pid2]->GetEntries() + n2[pid1][pid2]); - fhSum2DptDpt_vsDEtaDPhi[pid1][pid2]->SetEntries(fhSum2DptDpt_vsDEtaDPhi[pid1][pid2]->GetEntries() + n2[pid1][pid2]); - fhSum2PtPt_vsDEtaDPhi[pid1][pid2]->SetEntries(fhSum2PtPt_vsDEtaDPhi[pid1][pid2]->GetEntries() + n2[pid1][pid2]); - fhSupN1N1_vsDEtaDPhi[pid1][pid2]->SetEntries(fhSupN1N1_vsDEtaDPhi[pid1][pid2]->GetEntries() + n2sup[pid1][pid2]); - fhSupPt1Pt1_vsDEtaDPhi[pid1][pid2]->SetEntries(fhSupPt1Pt1_vsDEtaDPhi[pid1][pid2]->GetEntries() + n2sup[pid1][pid2]); + if constexpr (docorrelations) { + fhN2_vsDEtaDPhi[pid1][pid2]->SetEntries(fhN2_vsDEtaDPhi[pid1][pid2]->GetEntries() + n2[pid1][pid2]); + fhSum2DptDpt_vsDEtaDPhi[pid1][pid2]->SetEntries(fhSum2DptDpt_vsDEtaDPhi[pid1][pid2]->GetEntries() + n2[pid1][pid2]); + fhSum2PtPt_vsDEtaDPhi[pid1][pid2]->SetEntries(fhSum2PtPt_vsDEtaDPhi[pid1][pid2]->GetEntries() + n2[pid1][pid2]); + fhSupN1N1_vsDEtaDPhi[pid1][pid2]->SetEntries(fhSupN1N1_vsDEtaDPhi[pid1][pid2]->GetEntries() + n2sup[pid1][pid2]); + fhSupPt1Pt1_vsDEtaDPhi[pid1][pid2]->SetEntries(fhSupPt1Pt1_vsDEtaDPhi[pid1][pid2]->GetEntries() + n2sup[pid1][pid2]); + } } } } @@ -485,22 +556,38 @@ struct DptDptCorrelationsTask { if constexpr (mixed) { if (ptorder) { /* no invariant mass analysis on a mixed event data collection */ - processTrackPairs(Tracks1, Tracks2, corrs1, corrs2, ptavgs1, ptavgs2, centmult, bfield); + processTrackPairs(Tracks1, Tracks2, corrs1, corrs2, ptavgs1, ptavgs2, centmult, bfield); } else { - processTrackPairs(Tracks1, Tracks2, corrs1, corrs2, ptavgs1, ptavgs2, centmult, bfield); + processTrackPairs(Tracks1, Tracks2, corrs1, corrs2, ptavgs1, ptavgs2, centmult, bfield); } } else { if (ptorder) { if (invmass) { - processTrackPairs(Tracks1, Tracks1, corrs1, corrs1, ptavgs1, ptavgs1, centmult, bfield); + if (corrana) { + processTrackPairs(Tracks1, Tracks1, corrs1, corrs1, ptavgs1, ptavgs1, centmult, bfield); + } else { + processTrackPairs(Tracks1, Tracks1, corrs1, corrs1, ptavgs1, ptavgs1, centmult, bfield); + } } else { - processTrackPairs(Tracks1, Tracks1, corrs1, corrs1, ptavgs1, ptavgs1, centmult, bfield); + if (corrana) { + processTrackPairs(Tracks1, Tracks1, corrs1, corrs1, ptavgs1, ptavgs1, centmult, bfield); + } else { + processTrackPairs(Tracks1, Tracks1, corrs1, corrs1, ptavgs1, ptavgs1, centmult, bfield); + } } } else { if (invmass) { - processTrackPairs(Tracks1, Tracks1, corrs1, corrs1, ptavgs1, ptavgs1, centmult, bfield); + if (corrana) { + processTrackPairs(Tracks1, Tracks1, corrs1, corrs1, ptavgs1, ptavgs1, centmult, bfield); + } else { + processTrackPairs(Tracks1, Tracks1, corrs1, corrs1, ptavgs1, ptavgs1, centmult, bfield); + } } else { - processTrackPairs(Tracks1, Tracks1, corrs1, corrs1, ptavgs1, ptavgs1, centmult, bfield); + if (corrana) { + processTrackPairs(Tracks1, Tracks1, corrs1, corrs1, ptavgs1, ptavgs1, centmult, bfield); + } else { + processTrackPairs(Tracks1, Tracks1, corrs1, corrs1, ptavgs1, ptavgs1, centmult, bfield); + } } } } @@ -516,12 +603,14 @@ struct DptDptCorrelationsTask { } } - template + template void init(TList* fOutputList) { using namespace correlationstask; using namespace o2::analysis::dptdptfilter; + LOGF(info, "Do invariant mass: %s; do correlation histograms: %s", doinvmass ? "yes" : "no", docorrelations ? "yes" : "no"); + /* create the histograms */ Bool_t oldstatus = TH1::AddDirectoryStatus(); TH1::AddDirectory(kFALSE); @@ -648,27 +737,34 @@ struct DptDptCorrelationsTask { bool defSumw2 = TH1::GetDefaultSumw2(); TH1::SetDefaultSumw2(false); const char* pname = trackPairsNames[i][j].c_str(); - fhN2_vsDEtaDPhi[i][j] = new TH2F(TString::Format("n2_12_vsDEtaDPhi_%s", pname), TString::Format("#LT n_{2} #GT (%s);#Delta#eta;#Delta#varphi;#LT n_{2} #GT", pname), - deltaetabins, deltaetalow, deltaetaup, deltaphibins, deltaphilow, deltaphiup); - fhN2cont_vsDEtaDPhi[i][j] = new TH2F(TString::Format("n2_12cont_vsDEtaDPhi_%s", pname), TString::Format("#LT n_{2} #GT (%s);#Delta#eta;#Delta#varphi;#LT n_{2} #GT", pname), - deltaetabins, deltaetalow, deltaetaup, deltaphibins, deltaphilow, deltaphiup); - fhSum2PtPt_vsDEtaDPhi[i][j] = new TH2F(TString::Format("sumPtPt_12_vsDEtaDPhi_%s", pname), TString::Format("#LT #Sigma p_{t,1}p_{t,2} #GT (%s);#Delta#eta;#Delta#varphi;#LT #Sigma p_{t,1}p_{t,2} #GT (GeV^{2})", pname), + if constexpr (docorrelations) { + fhN2_vsDEtaDPhi[i][j] = new TH2F(TString::Format("n2_12_vsDEtaDPhi_%s", pname), TString::Format("#LT n_{2} #GT (%s);#Delta#eta;#Delta#varphi;#LT n_{2} #GT", pname), + deltaetabins, deltaetalow, deltaetaup, deltaphibins, deltaphilow, deltaphiup); + fhN2cont_vsDEtaDPhi[i][j] = new TH2F(TString::Format("n2_12cont_vsDEtaDPhi_%s", pname), TString::Format("#LT n_{2} #GT (%s);#Delta#eta;#Delta#varphi;#LT n_{2} #GT", pname), deltaetabins, deltaetalow, deltaetaup, deltaphibins, deltaphilow, deltaphiup); - fhSum2DptDpt_vsDEtaDPhi[i][j] = new TH2F(TString::Format("sumDptDpt_12_vsDEtaDPhi_%s", pname), TString::Format("#LT #Sigma (p_{t,1} - #LT p_{t,1} #GT)(p_{t,2} - #LT p_{t,2} #GT) #GT (%s);#Delta#eta;#Delta#varphi;#LT #Sigma (p_{t,1} - #LT p_{t,1} #GT)(p_{t,2} - #LT p_{t,2} #GT) #GT (GeV^{2})", pname), + fhSum2PtPt_vsDEtaDPhi[i][j] = new TH2F(TString::Format("sumPtPt_12_vsDEtaDPhi_%s", pname), TString::Format("#LT #Sigma p_{t,1}p_{t,2} #GT (%s);#Delta#eta;#Delta#varphi;#LT #Sigma p_{t,1}p_{t,2} #GT (GeV^{2})", pname), deltaetabins, deltaetalow, deltaetaup, deltaphibins, deltaphilow, deltaphiup); - fhSupN1N1_vsDEtaDPhi[i][j] = new TH2F(TString::Format("suppn1n1_12_vsDEtaDPhi_%s", pname), TString::Format("Suppressed #LT n_{1} #GT#LT n_{1} #GT (%s);#Delta#eta;#Delta#varphi;#LT n_{1} #GT#LT n_{1} #GT", pname), - deltaetabins, deltaetalow, deltaetaup, deltaphibins, deltaphilow, deltaphiup); - fhSupPt1Pt1_vsDEtaDPhi[i][j] = new TH2F(TString::Format("suppPtPt_12_vsDEtaDPhi_%s", pname), TString::Format("Suppressed #LT p_{t,1} #GT#LT p_{t,2} #GT (%s);#Delta#eta;#Delta#varphi;#LT p_{t,1} #GT#LT p_{t,2} #GT (GeV^{2})", pname), + fhSum2DptDpt_vsDEtaDPhi[i][j] = new TH2F(TString::Format("sumDptDpt_12_vsDEtaDPhi_%s", pname), TString::Format("#LT #Sigma (p_{t,1} - #LT p_{t,1} #GT)(p_{t,2} - #LT p_{t,2} #GT) #GT (%s);#Delta#eta;#Delta#varphi;#LT #Sigma (p_{t,1} - #LT p_{t,1} #GT)(p_{t,2} - #LT p_{t,2} #GT) #GT (GeV^{2})", pname), + deltaetabins, deltaetalow, deltaetaup, deltaphibins, deltaphilow, deltaphiup); + fhSupN1N1_vsDEtaDPhi[i][j] = new TH2F(TString::Format("suppn1n1_12_vsDEtaDPhi_%s", pname), TString::Format("Suppressed #LT n_{1} #GT#LT n_{1} #GT (%s);#Delta#eta;#Delta#varphi;#LT n_{1} #GT#LT n_{1} #GT", pname), deltaetabins, deltaetalow, deltaetaup, deltaphibins, deltaphilow, deltaphiup); + fhSupPt1Pt1_vsDEtaDPhi[i][j] = new TH2F(TString::Format("suppPtPt_12_vsDEtaDPhi_%s", pname), TString::Format("Suppressed #LT p_{t,1} #GT#LT p_{t,2} #GT (%s);#Delta#eta;#Delta#varphi;#LT p_{t,1} #GT#LT p_{t,2} #GT (GeV^{2})", pname), + deltaetabins, deltaetalow, deltaetaup, deltaphibins, deltaphilow, deltaphiup); + fhN2_vsPtPt[i][j] = new TH2F(TString::Format("n2_12_vsPtVsPt_%s", pname), TString::Format("#LT n_{2} #GT (%s);p_{t,1} (GeV/c);p_{t,2} (GeV/c);#LT n_{2} #GT", pname), + ptbins, ptlow, ptup, ptbins, ptlow, ptup); + } if constexpr (doinvmass) { - fhInvMass[i][j] = new TH1D(TString::Format("n2_invMass_%s", pname), TString::Format("%s invariant mass;Mass (MeV/#it{c}^{2})", pname), 5000, 0, 5000); + if (!(j < i)) { + /* only 12 combinations, 21 are exactly the same */ + fhInvMassDEta[i][j] = new TH2D(TString::Format("n2_invMassDeta_%s", pname), TString::Format("%s invariant mass;#Delta#eta;Mass (MeV/#it{c}^{2})", pname), + deltaetabins, deltaetalow, deltaetaup, 5000, 0, 5000); + fhInvMassDPhi[i][j] = new TH2D(TString::Format("n2_invMassDphi_%s", pname), TString::Format("%s invariant mass;#Delta#varphi;Mass (MeV/#it{c}^{2})", pname), + deltaphibins, deltaphilow - constants::math::PI, deltaphiup - constants::math::PI, 5000, 0, 5000); + } } /* we return it back to previuos state */ TH1::SetDefaultSumw2(defSumw2); - fhN2_vsPtPt[i][j] = new TH2F(TString::Format("n2_12_vsPtVsPt_%s", pname), TString::Format("#LT n_{2} #GT (%s);p_{t,1} (GeV/c);p_{t,2} (GeV/c);#LT n_{2} #GT", pname), - ptbins, ptlow, ptup, ptbins, ptlow, ptup); - fhN2_vsC[i][j] = new TProfile(TString::Format("n2_12_vsM_%s", pname), TString::Format("#LT n_{2} #GT (%s) (weighted);Centrality/Multiplicity (%%);#LT n_{2} #GT", pname), 100, 0.0, 100.0); fhSum2PtPt_vsC[i][j] = new TProfile(TString::Format("sumPtPt_12_vsM_%s", pname), TString::Format("#LT #Sigma p_{t,1}p_{t,2} #GT (%s) (weighted);Centrality/Multiplicity (%%);#LT #Sigma p_{t,1}p_{t,2} #GT (GeV^{2})", pname), 100, 0.0, 100.0); fhSum2DptDpt_vsC[i][j] = new TProfile(TString::Format("sumDptDpt_12_vsM_%s", pname), TString::Format("#LT #Sigma (p_{t,1} - #LT p_{t,1} #GT)(p_{t,2} - #LT p_{t,2} #GT) #GT (%s) (weighted);Centrality/Multiplicity (%%);#LT #Sigma (p_{t,1} - #LT p_{t,1} #GT)(p_{t,2} - #LT p_{t,2} #GT) #GT (GeV^{2})", pname), 100, 0.0, 100.0); @@ -677,32 +773,45 @@ struct DptDptCorrelationsTask { fhSum2DptDptnw_vsC[i][j] = new TProfile(TString::Format("sumDptDptNw_12_vsM_%s", pname), TString::Format("#LT #Sigma (p_{t,1} - #LT p_{t,1} #GT)(p_{t,2} - #LT p_{t,2} #GT) #GT (%s);Centrality/Multiplicity (%%);#LT #Sigma (p_{t,1} - #LT p_{t,1} #GT)(p_{t,2} - #LT p_{t,2} #GT) #GT (GeV^{2})", pname), 100, 0.0, 100.0); /* the statistical uncertainties will be estimated by the subsamples method so let's get rid of the error tracking */ - fhN2_vsDEtaDPhi[i][j]->SetBit(TH1::kIsNotW); - fhN2_vsDEtaDPhi[i][j]->Sumw2(false); - fhN2cont_vsDEtaDPhi[i][j]->SetBit(TH1::kIsNotW); - fhN2cont_vsDEtaDPhi[i][j]->Sumw2(false); - fhSum2PtPt_vsDEtaDPhi[i][j]->SetBit(TH1::kIsNotW); - fhSum2PtPt_vsDEtaDPhi[i][j]->Sumw2(false); - fhSum2DptDpt_vsDEtaDPhi[i][j]->SetBit(TH1::kIsNotW); - fhSum2DptDpt_vsDEtaDPhi[i][j]->Sumw2(false); - fhSupN1N1_vsDEtaDPhi[i][j]->SetBit(TH1::kIsNotW); - fhSupN1N1_vsDEtaDPhi[i][j]->Sumw2(false); - fhSupPt1Pt1_vsDEtaDPhi[i][j]->SetBit(TH1::kIsNotW); - fhSupPt1Pt1_vsDEtaDPhi[i][j]->Sumw2(false); + if constexpr (docorrelations) { + fhN2_vsDEtaDPhi[i][j]->SetBit(TH1::kIsNotW); + fhN2_vsDEtaDPhi[i][j]->Sumw2(false); + fhN2cont_vsDEtaDPhi[i][j]->SetBit(TH1::kIsNotW); + fhN2cont_vsDEtaDPhi[i][j]->Sumw2(false); + fhSum2PtPt_vsDEtaDPhi[i][j]->SetBit(TH1::kIsNotW); + fhSum2PtPt_vsDEtaDPhi[i][j]->Sumw2(false); + fhSum2DptDpt_vsDEtaDPhi[i][j]->SetBit(TH1::kIsNotW); + fhSum2DptDpt_vsDEtaDPhi[i][j]->Sumw2(false); + fhSupN1N1_vsDEtaDPhi[i][j]->SetBit(TH1::kIsNotW); + fhSupN1N1_vsDEtaDPhi[i][j]->Sumw2(false); + fhSupPt1Pt1_vsDEtaDPhi[i][j]->SetBit(TH1::kIsNotW); + fhSupPt1Pt1_vsDEtaDPhi[i][j]->Sumw2(false); + } if constexpr (doinvmass) { - fhInvMass[i][j]->SetBit(TH1::kIsNotW); - fhInvMass[i][j]->Sumw2(false); + if (!(j < i)) { + /* only 12 combinations, 21 are exactly the same */ + fhInvMassDEta[i][j]->SetBit(TH1::kIsNotW); + fhInvMassDEta[i][j]->Sumw2(false); + fhInvMassDPhi[i][j]->SetBit(TH1::kIsNotW); + fhInvMassDPhi[i][j]->Sumw2(false); + } } - fOutputList->Add(fhN2_vsDEtaDPhi[i][j]); - fOutputList->Add(fhN2cont_vsDEtaDPhi[i][j]); - fOutputList->Add(fhSum2PtPt_vsDEtaDPhi[i][j]); - fOutputList->Add(fhSum2DptDpt_vsDEtaDPhi[i][j]); - fOutputList->Add(fhSupN1N1_vsDEtaDPhi[i][j]); - fOutputList->Add(fhSupPt1Pt1_vsDEtaDPhi[i][j]); - fOutputList->Add(fhN2_vsPtPt[i][j]); + if constexpr (docorrelations) { + fOutputList->Add(fhN2_vsDEtaDPhi[i][j]); + fOutputList->Add(fhN2cont_vsDEtaDPhi[i][j]); + fOutputList->Add(fhSum2PtPt_vsDEtaDPhi[i][j]); + fOutputList->Add(fhSum2DptDpt_vsDEtaDPhi[i][j]); + fOutputList->Add(fhSupN1N1_vsDEtaDPhi[i][j]); + fOutputList->Add(fhSupPt1Pt1_vsDEtaDPhi[i][j]); + fOutputList->Add(fhN2_vsPtPt[i][j]); + } if constexpr (doinvmass) { - fOutputList->Add(fhInvMass[i][j]); + if (!(j < i)) { + /* only 12 combinations, 21 are exactly the same */ + fOutputList->Add(fhInvMassDEta[i][j]); + fOutputList->Add(fhInvMassDPhi[i][j]); + } } fOutputList->Add(fhN2_vsC[i][j]); fOutputList->Add(fhSum2PtPt_vsC[i][j]); @@ -747,6 +856,7 @@ struct DptDptCorrelationsTask { Configurable cfgSmallDCE{"smalldce", true, "Use small data collecting engine for singles processing, true = yes. Default = true"}; Configurable cfgDoInvMass{"doinvmass", false, "Do the invariant mass analyis, true = yes. Default = false"}; + Configurable cfgDoCorrelations{"docorrelations", true, "Do the correlations analysis, true = yes. Default = true"}; Configurable cfgProcessPairs{"processpairs", false, "Process pairs: false = no, just singles, true = yes, process pairs"}; Configurable cfgProcessME{"processmixedevents", false, "Process mixed events: false = no, just same event, true = yes, also process mixed events"}; Configurable cfgPtOrder{"ptorder", false, "enforce pT_1 < pT_2. Defalut: false"}; @@ -791,6 +901,7 @@ struct DptDptCorrelationsTask { processmixedevents = cfgProcessME.value; ptorder = cfgPtOrder.value; invmass = cfgDoInvMass.value; + corrana = cfgDoCorrelations.value; /* self configure the CCDB access to the input file */ getTaskOptionValue(initContext, "dpt-dpt-filter", "input_ccdburl", cfgCCDBUrl, false); @@ -914,27 +1025,36 @@ struct DptDptCorrelationsTask { } for (int i = 0; i < ncmranges; ++i) { - auto initializeCEInstance = [&fGlobalOutputList](auto dce, auto name, bool im) { + auto initializeCEInstance = [&fGlobalOutputList](auto dce, auto name, bool im, bool corr) { /* crete the output list for the passed centrality/multiplicity range */ TList* fOutputList = new TList(); fOutputList->SetName(name); fOutputList->SetOwner(true); /* init the data collection instance */ if (im) { - dce->template init(fOutputList); + if (corr) { + dce->template init(fOutputList); + } else { + dce->template init(fOutputList); + } } else { - dce->template init(fOutputList); + if (corr) { + dce->template init(fOutputList); + } else { + dce->template init(fOutputList); + } } fGlobalOutputList->Add(fOutputList); }; auto builSmallDCEInstance = [&initializeCEInstance](auto rg, bool me = false) { + /* only for singles analysis, no sense of inv mass nor no correlations */ DataCollectingEngine* dce = new DataCollectingEngine(); - initializeCEInstance(dce, TString::Format("DptDptCorrelationsData%s-%s", me ? "ME" : "", rg), false); + initializeCEInstance(dce, TString::Format("DptDptCorrelationsData%s-%s", me ? "ME" : "", rg), false, false); return dce; }; - auto buildCEInstance = [&initializeCEInstance](auto rg, bool im, bool me = false) { + auto buildCEInstance = [&initializeCEInstance](auto rg, bool im, bool corr, bool me = false) { DataCollectingEngine* dce = new DataCollectingEngine(); - initializeCEInstance(dce, TString::Format("DptDptCorrelationsData%s-%s", me ? "ME" : "", rg), im); + initializeCEInstance(dce, TString::Format("DptDptCorrelationsData%s-%s", me ? "ME" : "", rg), im, corr); return dce; }; TString range = TString::Format("%d-%d", static_cast(fCentMultMin[i]), static_cast(fCentMultMax[i])); @@ -950,12 +1070,9 @@ struct DptDptCorrelationsTask { if (invmass) { if (!processpairs) { LOGF(fatal, "Invariant mass cannot be used in processing singles, please configure properly!!"); - } else { - dataCE[i] = buildCEInstance(range.Data(), true); } - } else { - dataCE[i] = buildCEInstance(range.Data(), false); } + dataCE[i] = buildCEInstance(range.Data(), invmass, corrana); } if (processmixedevents) { /* consistency check */ @@ -965,7 +1082,10 @@ struct DptDptCorrelationsTask { if (invmass) { LOGF(warning, "Invariant mass will not be used with Mixed events!!"); } - dataCEME[i] = buildCEInstance(range.Data(), false, true); + if (!corrana) { + LOGF(fatal, "Mixed events makes not sense to run it without correlations, please configure properly!!"); + } + dataCEME[i] = buildCEInstance(range.Data(), false, false, true); } } for (int i = 0; i < ncmranges; ++i) { diff --git a/PWGCF/TwoParticleCorrelations/TableProducer/identifiedBfFilter.cxx b/PWGCF/TwoParticleCorrelations/TableProducer/identifiedBfFilter.cxx index fffa1eca914..734b1b1185c 100644 --- a/PWGCF/TwoParticleCorrelations/TableProducer/identifiedBfFilter.cxx +++ b/PWGCF/TwoParticleCorrelations/TableProducer/identifiedBfFilter.cxx @@ -107,6 +107,9 @@ TH2F* fhdEdxIPTPCB = nullptr; TH2F* fhdEdxA[kIdBfNoOfSpecies + 1] = {nullptr}; TH2F* fhdEdxIPTPCA[kIdBfNoOfSpecies + 1] = {nullptr}; +TH1F* fhMassB = nullptr; +TH1F* fhMassA[kIdBfNoOfSpecies + 1] = {nullptr}; + TH2S* fhDoublePID = nullptr; TH1F* fhDCAxyB = nullptr; @@ -639,6 +642,8 @@ struct IdentifiedBfFilterTracks { Configurable minRejectSigma{"minrejectsigma", -1.0, "Minimum required sigma for PID double match rejection"}; Configurable maxRejectSigma{"maxrejectsigma", 1.0, "Maximum required sigma for PID double match rejection"}; + Configurable tofCut{"TOFCutoff", 0.8, "Momentum under which we don't use TOF PID data"}; + OutputObj fOutput{"IdentifiedBfFilterTracksInfo", OutputObjHandlingPolicy::AnalysisObject}; bool checkAmbiguousTracks = false; @@ -1218,13 +1223,11 @@ void fillNSigmaHistos(TrackObject const& track) float actualTPCNSigmaKa = track.tpcNSigmaKa(); float actualTPCNSigmaPr = track.tpcNSigmaPr(); - if (track.tpcInnerParam() > 0.3) { - if (loadfromccdb) { - actualTPCNSigmaEl = actualTPCNSigmaEl - fhNSigmaCorrection[kIdBfElectron]->GetBinContent(fhNSigmaCorrection[kIdBfElectron]->FindBin(track.tpcInnerParam())); - actualTPCNSigmaPi = actualTPCNSigmaPi - fhNSigmaCorrection[kIdBfPion]->GetBinContent(fhNSigmaCorrection[kIdBfPion]->FindBin(track.tpcInnerParam())); - actualTPCNSigmaKa = actualTPCNSigmaKa - fhNSigmaCorrection[kIdBfKaon]->GetBinContent(fhNSigmaCorrection[kIdBfKaon]->FindBin(track.tpcInnerParam())); - actualTPCNSigmaPr = actualTPCNSigmaPr - fhNSigmaCorrection[kIdBfProton]->GetBinContent(fhNSigmaCorrection[kIdBfProton]->FindBin(track.tpcInnerParam())); - } + if (loadfromccdb) { + actualTPCNSigmaEl = actualTPCNSigmaEl - fhNSigmaCorrection[kIdBfElectron]->GetBinContent(fhNSigmaCorrection[kIdBfElectron]->FindBin(track.tpcInnerParam())); + actualTPCNSigmaPi = actualTPCNSigmaPi - fhNSigmaCorrection[kIdBfPion]->GetBinContent(fhNSigmaCorrection[kIdBfPion]->FindBin(track.tpcInnerParam())); + actualTPCNSigmaKa = actualTPCNSigmaKa - fhNSigmaCorrection[kIdBfKaon]->GetBinContent(fhNSigmaCorrection[kIdBfKaon]->FindBin(track.tpcInnerParam())); + actualTPCNSigmaPr = actualTPCNSigmaPr - fhNSigmaCorrection[kIdBfProton]->GetBinContent(fhNSigmaCorrection[kIdBfProton]->FindBin(track.tpcInnerParam())); } fhNSigmaTPC[kIdBfElectron]->Fill(actualTPCNSigmaEl, track.tpcInnerParam()); @@ -1257,16 +1260,14 @@ inline MatchRecoGenSpecies IdentifiedBfFilterTracks::IdentifyTrack(TrackObject c float nsigmas[kIdBfNoOfSpecies]; - if (track.tpcInnerParam() > 0.3) { - if (loadfromccdb) { - actualTPCNSigmaEl = actualTPCNSigmaEl - fhNSigmaCorrection[kIdBfElectron]->GetBinContent(fhNSigmaCorrection[kIdBfElectron]->FindBin(track.tpcInnerParam())); - actualTPCNSigmaPi = actualTPCNSigmaPi - fhNSigmaCorrection[kIdBfPion]->GetBinContent(fhNSigmaCorrection[kIdBfPion]->FindBin(track.tpcInnerParam())); - actualTPCNSigmaKa = actualTPCNSigmaKa - fhNSigmaCorrection[kIdBfKaon]->GetBinContent(fhNSigmaCorrection[kIdBfKaon]->FindBin(track.tpcInnerParam())); - actualTPCNSigmaPr = actualTPCNSigmaPr - fhNSigmaCorrection[kIdBfProton]->GetBinContent(fhNSigmaCorrection[kIdBfProton]->FindBin(track.tpcInnerParam())); - } + if (loadfromccdb) { + actualTPCNSigmaEl = actualTPCNSigmaEl - fhNSigmaCorrection[kIdBfElectron]->GetBinContent(fhNSigmaCorrection[kIdBfElectron]->FindBin(track.tpcInnerParam())); + actualTPCNSigmaPi = actualTPCNSigmaPi - fhNSigmaCorrection[kIdBfPion]->GetBinContent(fhNSigmaCorrection[kIdBfPion]->FindBin(track.tpcInnerParam())); + actualTPCNSigmaKa = actualTPCNSigmaKa - fhNSigmaCorrection[kIdBfKaon]->GetBinContent(fhNSigmaCorrection[kIdBfKaon]->FindBin(track.tpcInnerParam())); + actualTPCNSigmaPr = actualTPCNSigmaPr - fhNSigmaCorrection[kIdBfProton]->GetBinContent(fhNSigmaCorrection[kIdBfProton]->FindBin(track.tpcInnerParam())); } - if (track.tpcInnerParam() < 0.8 && !reqTOF && !onlyTOF) { + if (track.tpcInnerParam() < tofCut && !reqTOF && !onlyTOF) { nsigmas[kIdBfElectron] = actualTPCNSigmaEl; nsigmas[kIdBfPion] = actualTPCNSigmaPi; diff --git a/PWGDQ/Core/CutsLibrary.cxx b/PWGDQ/Core/CutsLibrary.cxx index 5a52ad563b5..7b0c206235d 100644 --- a/PWGDQ/Core/CutsLibrary.cxx +++ b/PWGDQ/Core/CutsLibrary.cxx @@ -3465,6 +3465,26 @@ AnalysisCut* o2::aod::dqcuts::GetAnalysisCut(const char* cutName) return cutAorC; } + if (!nameStr.compare("eventUPCMode")) { + cut->AddCut(VarManager::kIsITSUPCMode, 0.5, 1.5); + return cut; + } + + if (!nameStr.compare("eventSingleGapACZDC_UPCMode")) { + AnalysisCompositeCut* cutA = new AnalysisCompositeCut("singleGapAZDC", "singleGapAZDC", kTRUE); + cutA->AddCut(GetAnalysisCut("eventSingleGapAZDC")); + cutA->AddCut(GetAnalysisCut("eventUPCMode")); + + AnalysisCompositeCut* cutC = new AnalysisCompositeCut("singleGapCZDC", "singleGapCZDC", kTRUE); + cutC->AddCut(GetAnalysisCut("eventSingleGapCZDC")); + cutC->AddCut(GetAnalysisCut("eventUPCMode")); + + AnalysisCompositeCut* cutAorC = new AnalysisCompositeCut("singleGapACZDC", "singleGapACZDC", kFALSE); + cutAorC->AddCut(cutA); + cutAorC->AddCut(cutC); + return cutAorC; + } + // Event cuts based on centrality if (!nameStr.compare("eventStandardNoINT7Cent090")) { cut->AddCut(VarManager::kVtxZ, -10.0, 10.0); diff --git a/PWGDQ/Core/HistogramsLibrary.cxx b/PWGDQ/Core/HistogramsLibrary.cxx index 9b9b6e79f9f..e55a529c7b4 100644 --- a/PWGDQ/Core/HistogramsLibrary.cxx +++ b/PWGDQ/Core/HistogramsLibrary.cxx @@ -301,6 +301,8 @@ void o2::aod::dqhistograms::DefineHistograms(HistogramManager* hm, const char* h hm->AddHistogram(histClass, "IsDoubleGap", "Is double gap", false, 2, -0.5, 1.5, VarManager::kIsDoubleGap); hm->AddHistogram(histClass, "IsSingleGapA", "Is single gap on side A", false, 2, -0.5, 1.5, VarManager::kIsSingleGapA); hm->AddHistogram(histClass, "IsSingleGapC", "Is single gap on side C", false, 2, -0.5, 1.5, VarManager::kIsSingleGapC); + hm->AddHistogram(histClass, "IsITSUPCMode", "UPC settings used", false, 2, -0.5, 1.5, VarManager::kIsITSUPCMode); + hm->AddHistogram(histClass, "IsITSUPCMode_IsSingleGap", "UPC settings used vs Is single gap", false, 2, -0.5, 1.5, VarManager::kIsITSUPCMode, 2, -0.5, 1.5, VarManager::kIsSingleGap); } if (subGroupStr.Contains("zdc")) { hm->AddHistogram(histClass, "energyCommonZNA_energyCommonZNC", "Common ZNA energy vs common ZNC energy", false, 1050, -10.0, 200.0, VarManager::kEnergyCommonZNA, 1050, -10.0, 200.0, VarManager::kEnergyCommonZNC); diff --git a/PWGDQ/Core/VarManager.cxx b/PWGDQ/Core/VarManager.cxx index 3026f9408a2..9efae351b8a 100644 --- a/PWGDQ/Core/VarManager.cxx +++ b/PWGDQ/Core/VarManager.cxx @@ -895,6 +895,10 @@ void VarManager::SetDefaultVarNames() fgVariableUnits[kIsSingleGapA] = ""; fgVariableNames[kIsSingleGapC] = "is single gap event side C"; fgVariableUnits[kIsSingleGapC] = ""; + fgVariableNames[kIsSingleGap] = "is single gap event"; + fgVariableUnits[kIsSingleGap] = ""; + fgVariableNames[kIsITSUPCMode] = "UPC settings used"; + fgVariableUnits[kIsITSUPCMode] = ""; fgVariableNames[kQuadMass] = "mass quadruplet"; fgVariableUnits[kQuadMass] = "GeV/c2"; fgVariableNames[kQuadPt] = "p_{T}"; diff --git a/PWGDQ/Core/VarManager.h b/PWGDQ/Core/VarManager.h index da04adbf3bf..d341bb1df36 100644 --- a/PWGDQ/Core/VarManager.h +++ b/PWGDQ/Core/VarManager.h @@ -334,6 +334,7 @@ class VarManager : public TObject kIsSingleGapA, // Rapidity gap on side A kIsSingleGapC, // Rapidity gap on side C kIsSingleGap, // Rapidity gap on either side + kIsITSUPCMode, // UPC mode used for event kTwoEvPosZ1, // vtx-z for collision 1 in two events correlations kTwoEvPosZ2, // vtx-z for collision 2 in two events correlations kTwoEvPosR1, // vtx-R for collision 1 in two events correlations @@ -718,7 +719,8 @@ class VarManager : public TObject enum EventFilters { kDoubleGap = 0, kSingleGapA, - kSingleGapC + kSingleGapC, + kITSUPCMode }; enum MuonExtrapolation { @@ -1465,6 +1467,9 @@ void VarManager::FillEvent(T const& event, float* values) values[kIsSingleGapC] = (event.tag_bit(56 + kSingleGapC) > 0); values[kIsSingleGap] = values[kIsSingleGapA] || values[kIsSingleGapC]; } + if (fgUsedVars[kIsITSUPCMode]) { + values[kIsITSUPCMode] = (event.tag_bit(56 + kITSUPCMode) > 0); + } values[kCollisionTime] = event.collisionTime(); values[kCollisionTimeRes] = event.collisionTimeRes(); } @@ -1667,6 +1672,7 @@ void VarManager::FillEvent(T const& event, float* values) values[kIsSingleGapA] = (event.eventFilter() & (uint64_t(1) << kSingleGapA)) > 0; values[kIsSingleGapC] = (event.eventFilter() & (uint64_t(1) << kSingleGapC)) > 0; values[kIsSingleGap] = values[kIsSingleGapA] || values[kIsSingleGapC]; + values[kIsITSUPCMode] = (event.eventFilter() & (uint64_t(1) << kITSUPCMode)) > 0; } if constexpr ((fillMap & ReducedZdc) > 0) { @@ -3827,6 +3833,8 @@ void VarManager::FillQVectorFromGFW(C const& /*collision*/, A const& compA11, A values[kM1111REF] = S41A - 6. * S12A * S21A + 8. * S13A * S11A + 3. * S22A - 6. * S14A; values[kCORR2REF] = (norm(compA21) - S12A) / values[kM11REF]; values[kCORR4REF] = (pow(norm(compA21), 2) + norm(compA42) - 2. * (compA42 * conj(compA21) * conj(compA21)).real() + 8. * (compA23 * conj(compA21)).real() - 4. * S12A * norm(compA21) - 6. * S14A - 2. * S22A) / values[kM1111REF]; + values[kCORR2REF] = std::isnan(values[kCORR2REF]) || std::isinf(values[kCORR2REF]) ? 0 : values[kCORR2REF]; + values[kCORR4REF] = std::isnan(values[kCORR4REF]) || std::isinf(values[kCORR4REF]) ? 0 : values[kCORR4REF]; // TODO: provide different computations for R // Compute the R factor using the 2 sub-events technique for second and third harmonic diff --git a/PWGDQ/DataModel/ReducedInfoTables.h b/PWGDQ/DataModel/ReducedInfoTables.h index ba3add306c7..0a25b71065e 100644 --- a/PWGDQ/DataModel/ReducedInfoTables.h +++ b/PWGDQ/DataModel/ReducedInfoTables.h @@ -574,6 +574,8 @@ 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 @@ -588,6 +590,8 @@ 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 @@ -765,8 +769,8 @@ DECLARE_SOA_TABLE(DielectronsAll, "AOD", "RTDIELECTRONALL", //! reducedpair::Pt, reducedpair::Eta, reducedpair::Phi, reducedpair::Sign, reducedpair::FilterMap, reducedpair::McDecision, - dilepton_track_index::Pt1, dilepton_track_index::Eta1, dilepton_track_index::Phi1, dilepton_track_index::TPCNClsCR1, dilepton_track_index::TPCNClsFound1, dilepton_track_index::TPCChi2NCl1, dilepton_track_index::DcaXY1, dilepton_track_index::DcaZ1, dilepton_track_index::TPCSignal1, dilepton_track_index::TPCNSigmaEl1, dilepton_track_index::TPCNSigmaPi1, dilepton_track_index::TPCNSigmaPr1, dilepton_track_index::TOFBeta1, dilepton_track_index::TOFNSigmaEl1, dilepton_track_index::TOFNSigmaPi1, dilepton_track_index::TOFNSigmaPr1, - dilepton_track_index::Pt2, dilepton_track_index::Eta2, dilepton_track_index::Phi2, dilepton_track_index::TPCNClsCR2, dilepton_track_index::TPCNClsFound2, dilepton_track_index::TPCChi2NCl2, dilepton_track_index::DcaXY2, dilepton_track_index::DcaZ2, dilepton_track_index::TPCSignal2, dilepton_track_index::TPCNSigmaEl2, dilepton_track_index::TPCNSigmaPi2, dilepton_track_index::TPCNSigmaPr2, dilepton_track_index::TOFBeta2, dilepton_track_index::TOFNSigmaEl2, dilepton_track_index::TOFNSigmaPi2, dilepton_track_index::TOFNSigmaPr2, + dilepton_track_index::Pt1, dilepton_track_index::Eta1, dilepton_track_index::Phi1, dilepton_track_index::ITSClusterMap1, dilepton_track_index::ITSChi2NCl1, dilepton_track_index::TPCNClsCR1, dilepton_track_index::TPCNClsFound1, dilepton_track_index::TPCChi2NCl1, dilepton_track_index::DcaXY1, dilepton_track_index::DcaZ1, dilepton_track_index::TPCSignal1, dilepton_track_index::TPCNSigmaEl1, dilepton_track_index::TPCNSigmaPi1, dilepton_track_index::TPCNSigmaPr1, dilepton_track_index::TOFBeta1, dilepton_track_index::TOFNSigmaEl1, dilepton_track_index::TOFNSigmaPi1, dilepton_track_index::TOFNSigmaPr1, + dilepton_track_index::Pt2, dilepton_track_index::Eta2, dilepton_track_index::Phi2, dilepton_track_index::ITSClusterMap2, dilepton_track_index::ITSChi2NCl2, dilepton_track_index::TPCNClsCR2, dilepton_track_index::TPCNClsFound2, dilepton_track_index::TPCChi2NCl2, dilepton_track_index::DcaXY2, dilepton_track_index::DcaZ2, dilepton_track_index::TPCSignal2, dilepton_track_index::TPCNSigmaEl2, dilepton_track_index::TPCNSigmaPi2, dilepton_track_index::TPCNSigmaPr2, dilepton_track_index::TOFBeta2, dilepton_track_index::TOFNSigmaEl2, dilepton_track_index::TOFNSigmaPi2, dilepton_track_index::TOFNSigmaPr2, dilepton_track_index::DCAxyzTrk0KF, dilepton_track_index::DCAxyzTrk1KF, reducedpair::DCAxyzBetweenTrksKF, dilepton_track_index::DCAxyTrk0KF, dilepton_track_index::DCAxyTrk1KF, reducedpair::DCAxyBetweenTrksKF, dilepton_track_index::DeviationTrk0KF, dilepton_track_index::DeviationTrk1KF, dilepton_track_index::DeviationxyTrk0KF, dilepton_track_index::DeviationxyTrk1KF, reducedpair::MassKFGeo, reducedpair::Chi2OverNDFKFGeo, reducedpair::DecayLengthKFGeo, reducedpair::DecayLengthOverErrKFGeo, reducedpair::DecayLengthXYKFGeo, reducedpair::DecayLengthXYOverErrKFGeo, reducedpair::PseudoproperDecayTimeKFGeo, reducedpair::PseudoproperDecayTimeErrKFGeo, reducedpair::CosPAKFGeo, reducedpair::PairDCAxyz, reducedpair::PairDCAxy, diff --git a/PWGDQ/Tasks/dqEfficiency.cxx b/PWGDQ/Tasks/dqEfficiency.cxx index 6a2cf8b9ecc..ee8cd2af5c1 100644 --- a/PWGDQ/Tasks/dqEfficiency.cxx +++ b/PWGDQ/Tasks/dqEfficiency.cxx @@ -813,8 +813,8 @@ struct AnalysisSameEventPairing { if constexpr ((TPairType == VarManager::kDecayToEE) && (TTrackFillMap & VarManager::ObjTypes::ReducedTrackBarrelPID) > 0) { if (fConfigFlatTables.value) { dielectronAllList(VarManager::fgValues[VarManager::kMass], VarManager::fgValues[VarManager::kPt], VarManager::fgValues[VarManager::kEta], VarManager::fgValues[VarManager::kPhi], t1.sign() + t2.sign(), dileptonFilterMap, dileptonMcDecision, - t1.pt(), t1.eta(), t1.phi(), t1.tpcNClsCrossedRows(), t1.tpcNClsFound(), t1.tpcChi2NCl(), t1.dcaXY(), t1.dcaZ(), t1.tpcSignal(), t1.tpcNSigmaEl(), t1.tpcNSigmaPi(), t1.tpcNSigmaPr(), t1.beta(), t1.tofNSigmaEl(), t1.tofNSigmaPi(), t1.tofNSigmaPr(), - t2.pt(), t2.eta(), t2.phi(), t2.tpcNClsCrossedRows(), t2.tpcNClsFound(), t2.tpcChi2NCl(), t2.dcaXY(), t2.dcaZ(), t2.tpcSignal(), t2.tpcNSigmaEl(), t2.tpcNSigmaPi(), t2.tpcNSigmaPr(), t2.beta(), t2.tofNSigmaEl(), t2.tofNSigmaPi(), t2.tofNSigmaPr(), + 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(), + t2.pt(), t2.eta(), t2.phi(), t2.itsClusterMap(), t2.itsChi2NCl(), t2.tpcNClsCrossedRows(), t2.tpcNClsFound(), t2.tpcChi2NCl(), t2.dcaXY(), t2.dcaZ(), t2.tpcSignal(), t2.tpcNSigmaEl(), t2.tpcNSigmaPi(), t2.tpcNSigmaPr(), t2.beta(), t2.tofNSigmaEl(), t2.tofNSigmaPi(), t2.tofNSigmaPr(), VarManager::fgValues[VarManager::kKFTrack0DCAxyz], VarManager::fgValues[VarManager::kKFTrack1DCAxyz], VarManager::fgValues[VarManager::kKFDCAxyzBetweenProngs], VarManager::fgValues[VarManager::kKFTrack0DCAxy], VarManager::fgValues[VarManager::kKFTrack1DCAxy], VarManager::fgValues[VarManager::kKFDCAxyBetweenProngs], VarManager::fgValues[VarManager::kKFTrack0DeviationFromPV], VarManager::fgValues[VarManager::kKFTrack1DeviationFromPV], VarManager::fgValues[VarManager::kKFTrack0DeviationxyFromPV], VarManager::fgValues[VarManager::kKFTrack1DeviationxyFromPV], VarManager::fgValues[VarManager::kKFMass], VarManager::fgValues[VarManager::kKFChi2OverNDFGeo], VarManager::fgValues[VarManager::kVertexingLxyz], VarManager::fgValues[VarManager::kVertexingLxyzOverErr], VarManager::fgValues[VarManager::kVertexingLxy], VarManager::fgValues[VarManager::kVertexingLxyOverErr], VarManager::fgValues[VarManager::kVertexingTauxy], VarManager::fgValues[VarManager::kVertexingTauxyErr], VarManager::fgValues[VarManager::kKFCosPA], VarManager::fgValues[VarManager::kKFJpsiDCAxyz], VarManager::fgValues[VarManager::kKFJpsiDCAxy], diff --git a/PWGDQ/Tasks/dqEfficiency_withAssoc.cxx b/PWGDQ/Tasks/dqEfficiency_withAssoc.cxx index 9f0b18c401b..03faa87837e 100644 --- a/PWGDQ/Tasks/dqEfficiency_withAssoc.cxx +++ b/PWGDQ/Tasks/dqEfficiency_withAssoc.cxx @@ -63,6 +63,8 @@ DECLARE_SOA_BITMAP_COLUMN(IsBarrelSelected, isBarrelSelected, 32); DECLARE_SOA_COLUMN(BarrelAmbiguityInBunch, barrelAmbiguityInBunch, int8_t); //! Barrel track in-bunch ambiguity DECLARE_SOA_COLUMN(BarrelAmbiguityOutOfBunch, barrelAmbiguityOutOfBunch, int8_t); //! Barrel track out of bunch ambiguity DECLARE_SOA_BITMAP_COLUMN(IsMuonSelected, isMuonSelected, 32); //! Muon track decisions (joinable to ReducedMuonsAssoc) +DECLARE_SOA_COLUMN(MuonAmbiguityInBunch, muonAmbiguityInBunch, int8_t); //! Muon track in-bunch ambiguity +DECLARE_SOA_COLUMN(MuonAmbiguityOutOfBunch, muonAmbiguityOutOfBunch, int8_t); //! Muon track out of bunch ambiguity DECLARE_SOA_BITMAP_COLUMN(IsBarrelSelectedPrefilter, isBarrelSelectedPrefilter, 32); //! Barrel prefilter decisions (joinable to ReducedTracksAssoc) // Bcandidate columns for ML analysis of B->Jpsi+K DECLARE_SOA_COLUMN(massBcandidate, MBcandidate, float); @@ -80,6 +82,7 @@ DECLARE_SOA_TABLE(EventCuts, "AOD", "DQANAEVCUTS", dqanalysisflags::IsEventSelec DECLARE_SOA_TABLE(BarrelTrackCuts, "AOD", "DQANATRKCUTS", dqanalysisflags::IsBarrelSelected); //! joinable to ReducedTracksAssoc DECLARE_SOA_TABLE(BarrelAmbiguities, "AOD", "DQBARRELAMB", dqanalysisflags::BarrelAmbiguityInBunch, dqanalysisflags::BarrelAmbiguityOutOfBunch); //! joinable to ReducedBarrelTracks DECLARE_SOA_TABLE(MuonTrackCuts, "AOD", "DQANAMUONCUTS", dqanalysisflags::IsMuonSelected); //! joinable to ReducedMuonsAssoc +DECLARE_SOA_TABLE(MuonAmbiguities, "AOD", "DQMUONAMB", dqanalysisflags::MuonAmbiguityInBunch, dqanalysisflags::MuonAmbiguityOutOfBunch); //! joinable to ReducedMuonTracks DECLARE_SOA_TABLE(Prefilter, "AOD", "DQPREFILTER", dqanalysisflags::IsBarrelSelectedPrefilter); //! joinable to ReducedTracksAssoc DECLARE_SOA_TABLE(BmesonCandidates, "AOD", "DQBMESONS", dqanalysisflags::massBcandidate, dqanalysisflags::pTBcandidate, dqanalysisflags::LxyBcandidate, dqanalysisflags::LxyzBcandidate, dqanalysisflags::LzBcandidate, dqanalysisflags::TauxyBcandidate, dqanalysisflags::TauzBcandidate, dqanalysisflags::CosPBcandidate, dqanalysisflags::Chi2Bcandidate); } // namespace o2::aod @@ -101,6 +104,7 @@ using MyDielectronCandidates = soa::Join; using MyMuonTracks = soa::Join; using MyMuonTracksWithCov = soa::Join; +using MyMuonTracksWithCovWithAmbiguities = soa::Join; // using MyMuonTracksSelectedWithColl = soa::Join; // bit maps used for the Fill functions of the VarManager @@ -620,6 +624,7 @@ struct AnalysisTrackSelection { // Here one should add all the track cuts needed through the workflow (e.g. cuts for same-event pairing, track for dilepton-track correlations) struct AnalysisMuonSelection { Produces muonSel; + Produces muonAmbiguities; OutputObj fOutputList{"output"}; Configurable fConfigCuts{"cfgMuonCuts", "muonQualityCuts", "Comma separated list of muon cuts"}; @@ -743,8 +748,6 @@ struct AnalysisMuonSelection { auto track = assoc.template reducedmuon_as(); VarManager::FillTrack(track); - // compute quantities which depend on the associated collision - VarManager::FillPropagateMuon(track, event); bool isCorrectAssoc = false; if (track.has_reducedMCTrack()) { @@ -769,6 +772,7 @@ struct AnalysisMuonSelection { } } // end loop over cuts muonSel(filterMap); + muonAmbiguities.reserve(muons.size()); // if no filter fulfilled, continue if (!filterMap) { @@ -853,6 +857,19 @@ struct AnalysisMuonSelection { VarManager::fgValues[VarManager::kMuonNAssocsOutOfBunch] = static_cast(evIndices.size()); fHistMan->FillHistClass("Muon_AmbiguityOutOfBunch", VarManager::fgValues); } // end loop over out-of-bunch ambiguous tracks + + // publish the ambiguity table + for (auto& track : muons) { + int8_t nInBunch = 0; + if (fNAssocsInBunch.find(track.globalIndex()) != fNAssocsInBunch.end()) { + nInBunch = fNAssocsInBunch[track.globalIndex()].size(); + } + int8_t nOutOfBunch = 0; + if (fNAssocsOutOfBunch.find(track.globalIndex()) != fNAssocsOutOfBunch.end()) { + nOutOfBunch = fNAssocsOutOfBunch[track.globalIndex()].size(); + } + muonAmbiguities(nInBunch, nOutOfBunch); + } } void processSkimmed(ReducedMuonsAssoc const& assocs, MyEventsSelected const& events, MyMuonTracks const& muons, ReducedMCEvents const& eventsMC, ReducedMCTracks const& tracksMC) @@ -1270,7 +1287,18 @@ struct AnalysisSameEventPairing { Form("PairsMuonSEPM_%s", objArray->At(icut)->GetName()), Form("PairsMuonSEPP_%s", objArray->At(icut)->GetName()), Form("PairsMuonSEMM_%s", objArray->At(icut)->GetName())}; - histNames += Form("%s;%s;%s;", names[0].Data(), names[1].Data(), names[2].Data()); + if (fConfigQA) { + // assign separate hist directories for ambiguous tracks + names.push_back(Form("PairsMuonSEPM_ambiguousInBunch_%s", objArray->At(icut)->GetName())); + names.push_back(Form("PairsMuonSEPP_ambiguousInBunch_%s", objArray->At(icut)->GetName())); + names.push_back(Form("PairsMuonSEMM_ambiguousInBunch_%s", objArray->At(icut)->GetName())); + names.push_back(Form("PairsMuonSEPM_ambiguousOutOfBunch_%s", objArray->At(icut)->GetName())); + names.push_back(Form("PairsMuonSEPP_ambiguousOutOfBunch_%s", objArray->At(icut)->GetName())); + names.push_back(Form("PairsMuonSEMM_ambiguousOutOfBunch_%s", objArray->At(icut)->GetName())); + } + for (auto& n : names) { + histNames += Form("%s;", n.Data()); + } fMuonHistNames[icut] = names; // if there are specified pair cuts, assign hist dirs for each muon cut - pair cut combination @@ -1292,11 +1320,23 @@ struct AnalysisSameEventPairing { if (!sigNamesStr.IsNull()) { for (auto& sig : fRecMCSignals) { names = { - Form("PairsMuonsSEPM_%s_%s", objArray->At(icut)->GetName(), sig.GetName()), - Form("PairsMuonsSEPMCorrectAssoc_%s_%s", objArray->At(icut)->GetName(), sig.GetName()), - Form("PairsMuonsSEPMIncorrectAssoc_%s_%s", objArray->At(icut)->GetName(), sig.GetName()), + Form("PairsMuonSEPM_%s_%s", objArray->At(icut)->GetName(), sig.GetName()), + Form("PairsMuonSEPP_%s_%s", objArray->At(icut)->GetName(), sig.GetName()), + Form("PairsMuonSEMM_%s_%s", objArray->At(icut)->GetName(), sig.GetName()), }; - histNames += Form("%s;%s;%s;", names[0].Data(), names[1].Data(), names[2].Data()); + if (fConfigQA) { + names.push_back(Form("PairsMuonSEPMCorrectAssoc_%s_%s", objArray->At(icut)->GetName(), sig.GetName())); + names.push_back(Form("PairsMuonSEPMIncorrectAssoc_%s_%s", objArray->At(icut)->GetName(), sig.GetName())); + names.push_back(Form("PairsMuonSEPM_ambiguousInBunch_%s_%s", objArray->At(icut)->GetName(), sig.GetName())); + names.push_back(Form("PairsMuonSEPM_ambiguousInBunchCorrectAssoc_%s_%s", objArray->At(icut)->GetName(), sig.GetName())); + names.push_back(Form("PairsMuonSEPM_ambiguousInBunchIncorrectAssoc_%s_%s", objArray->At(icut)->GetName(), sig.GetName())); + names.push_back(Form("PairsMuonSEPM_ambiguousOutOfBunch_%s_%s", objArray->At(icut)->GetName(), sig.GetName())); + names.push_back(Form("PairsMuonSEPM_ambiguousOutOfBunchCorrectAssoc_%s_%s", objArray->At(icut)->GetName(), sig.GetName())); + names.push_back(Form("PairsMuonSEPM_ambiguousOutOfBunchIncorrectAssoc_%s_%s", objArray->At(icut)->GetName(), sig.GetName())); + } + for (auto& n : names) { + histNames += Form("%s;", n.Data()); + } } // end loop over MC signals } fMuonHistNamesMCmatched[icut] = names; @@ -1512,8 +1552,25 @@ struct AnalysisSameEventPairing { } auto t1 = a1.template reducedmuon_as(); auto t2 = a2.template reducedmuon_as(); + if (t1.matchMCHTrackId() == t2.matchMCHTrackId()) + continue; + if (t1.matchMFTTrackId() == t2.matchMFTTrackId()) + continue; sign1 = t1.sign(); sign2 = t2.sign(); + // store the ambiguity number of the two dilepton legs in the last 4 digits of the two-track filter + if (t1.muonAmbiguityInBunch() > 1) { + twoTrackFilter |= (uint32_t(1) << 28); + } + if (t2.muonAmbiguityInBunch() > 1) { + twoTrackFilter |= (uint32_t(1) << 29); + } + if (t1.muonAmbiguityOutOfBunch() > 1) { + twoTrackFilter |= (uint32_t(1) << 30); + } + if (t2.muonAmbiguityOutOfBunch() > 1) { + twoTrackFilter |= (uint32_t(1) << 31); + } // run MC matching for this pair int isig = 0; @@ -1555,7 +1612,7 @@ struct AnalysisSameEventPairing { dimuonAllList(event.posX(), event.posY(), event.posZ(), event.numContrib(), -999., -999., -999., VarManager::fgValues[VarManager::kMass], - false, + mcDecision, VarManager::fgValues[VarManager::kPt], VarManager::fgValues[VarManager::kEta], VarManager::fgValues[VarManager::kPhi], t1.sign() + t2.sign(), VarManager::fgValues[VarManager::kVertexingChi2PCA], VarManager::fgValues[VarManager::kVertexingTauz], VarManager::fgValues[VarManager::kVertexingTauzErr], VarManager::fgValues[VarManager::kVertexingTauxy], VarManager::fgValues[VarManager::kVertexingTauxyErr], @@ -1571,7 +1628,7 @@ struct AnalysisSameEventPairing { -999., -999., -999., -999., -999., -999., -999., -999., -999., -999., -999., -999., - t1.isAmbiguous(), t2.isAmbiguous(), + (twoTrackFilter & (uint32_t(1) << 28)) || (twoTrackFilter & (uint32_t(1) << 30)), (twoTrackFilter & (uint32_t(1) << 29)) || (twoTrackFilter & (uint32_t(1) << 31)), -999.0, -999.0, -999.0, -999.0, -999.0, -999.0, -999.0, -999.0, -999.0, -999.0, -999.0, VarManager::fgValues[VarManager::kMultDimuons], @@ -1607,7 +1664,7 @@ struct AnalysisSameEventPairing { fHistMan->FillHistClass(histNamesMC[icut * fRecMCSignals.size() + isig][4].Data(), VarManager::fgValues); } if (isAmbiInBunch) { // ambiguous in bunch - fHistMan->FillHistClass(histNames[icut * fRecMCSignals.size() + isig][5].Data(), VarManager::fgValues); + fHistMan->FillHistClass(histNamesMC[icut * fRecMCSignals.size() + isig][5].Data(), VarManager::fgValues); if (isCorrectAssoc_leg1 && isCorrectAssoc_leg2) { fHistMan->FillHistClass(histNamesMC[icut * fRecMCSignals.size() + isig][6].Data(), VarManager::fgValues); } else { @@ -1615,7 +1672,7 @@ struct AnalysisSameEventPairing { } } if (isAmbiOutOfBunch) { // ambiguous out of bunch - fHistMan->FillHistClass(histNames[icut * fRecMCSignals.size() + isig][8].Data(), VarManager::fgValues); + fHistMan->FillHistClass(histNamesMC[icut * fRecMCSignals.size() + isig][8].Data(), VarManager::fgValues); if (isCorrectAssoc_leg1 && isCorrectAssoc_leg2) { fHistMan->FillHistClass(histNamesMC[icut * fRecMCSignals.size() + isig][9].Data(), VarManager::fgValues); } else { @@ -1624,6 +1681,14 @@ struct AnalysisSameEventPairing { } } } + if (fConfigQA) { + if (isAmbiInBunch) { + fHistMan->FillHistClass(histNames[icut][3].Data(), VarManager::fgValues); + } + if (isAmbiOutOfBunch) { + fHistMan->FillHistClass(histNames[icut][3 + 3].Data(), VarManager::fgValues); + } + } } } else { if (sign1 > 0) { // ++ pairs @@ -1731,7 +1796,7 @@ struct AnalysisSameEventPairing { void processAllSkimmed(MyEventsVtxCovSelected const& events, soa::Join const& barrelAssocs, MyBarrelTracksWithCovWithAmbiguities const& barrelTracks, - soa::Join const& muonAssocs, MyMuonTracksWithCov const& muons, + soa::Join const& muonAssocs, MyMuonTracksWithCovWithAmbiguities const& muons, ReducedMCEvents const& mcEvents, ReducedMCTracks const& mcTracks) { runSameEventPairing(events, trackAssocsPerCollision, barrelAssocs, barrelTracks, mcEvents, mcTracks); @@ -1760,7 +1825,7 @@ struct AnalysisSameEventPairing { } void processMuonOnlySkimmed(MyEventsVtxCovSelected const& events, - soa::Join const& muonAssocs, MyMuonTracksWithCov const& muons, ReducedMCEvents const& mcEvents, ReducedMCTracks const& mcTracks) + soa::Join const& muonAssocs, MyMuonTracksWithCovWithAmbiguities const& muons, ReducedMCEvents const& mcEvents, ReducedMCTracks const& mcTracks) { runSameEventPairing(events, muonAssocsPerCollision, muonAssocs, muons, mcEvents, mcTracks); if (fConfigRunMCGenPair) @@ -2193,7 +2258,7 @@ void DefineHistograms(HistogramManager* histMan, TString histClasses, const char } } } - if (classStr.Contains("Muon")) { + if (classStr.Contains("Muon") && !classStr.Contains("Pairs")) { if (!classStr.Contains("Ambiguity")) { dqhistograms::DefineHistograms(histMan, objArray->At(iclass)->GetName(), "track", histName); } else { diff --git a/PWGDQ/Tasks/filterPbPb.cxx b/PWGDQ/Tasks/filterPbPb.cxx index a562b34d4df..81dfa35a996 100644 --- a/PWGDQ/Tasks/filterPbPb.cxx +++ b/PWGDQ/Tasks/filterPbPb.cxx @@ -17,6 +17,7 @@ #include "PWGDQ/DataModel/ReducedInfoTables.h" #include "PWGDQ/Core/VarManager.h" #include "CommonConstants/LHCConstants.h" +#include "ReconstructionDataFormats/Vertex.h" using namespace std; @@ -58,7 +59,7 @@ struct DQFilterPbPbTask { fStats->GetXaxis()->SetBinLabel(1, "Events inspected"); fStats->GetXaxis()->SetBinLabel(2, "Events selected"); // setup the FilterOutcome histogram - fFilterOutcome.setObject(new TH1D("Filter outcome", "Filter outcome", 8, 0.5, 8.5)); + fFilterOutcome.setObject(new TH1D("Filter outcome", "Filter outcome", 9, 0.5, 9.5)); fFilterOutcome->GetXaxis()->SetBinLabel(1, "Events inspected"); fFilterOutcome->GetXaxis()->SetBinLabel(2, "Events selected"); fFilterOutcome->GetXaxis()->SetBinLabel(3, "!A && !C"); @@ -67,6 +68,7 @@ struct DQFilterPbPbTask { fFilterOutcome->GetXaxis()->SetBinLabel(6, "A && C"); fFilterOutcome->GetXaxis()->SetBinLabel(7, Form("numContrib not in [%d, %d]", fConfigMinNPVCs.value, fConfigMaxNPVCs.value)); fFilterOutcome->GetXaxis()->SetBinLabel(8, "BC not found"); + fFilterOutcome->GetXaxis()->SetBinLabel(9, "ITS UPC settings used"); TString eventTypesString = fConfigEventTypes.value; for (std::vector::size_type i = 0; i < eventTypeOptions.size(); i++) { @@ -265,6 +267,12 @@ struct DQFilterPbPbTask { bool isSelected = filter; fStats->Fill(-1.0, isSelected); + // Record whether UPC settings were used for this event + if (collision.flags() & dataformats::Vertex>::Flags::UPCMode) { + filter |= (uint64_t(1) << VarManager::kITSUPCMode); + fFilterOutcome->Fill(9, 1); + } + eventFilter(filter); } diff --git a/PWGDQ/Tasks/tableReader.cxx b/PWGDQ/Tasks/tableReader.cxx index 82dd3879192..c9dbbbe21af 100644 --- a/PWGDQ/Tasks/tableReader.cxx +++ b/PWGDQ/Tasks/tableReader.cxx @@ -1275,8 +1275,8 @@ struct AnalysisSameEventPairing { if constexpr ((TPairType == pairTypeEE) && (TTrackFillMap & VarManager::ObjTypes::ReducedTrackBarrelPID) > 0) { if (fConfigFlatTables.value) { dielectronAllList(VarManager::fgValues[VarManager::kMass], VarManager::fgValues[VarManager::kPt], VarManager::fgValues[VarManager::kEta], VarManager::fgValues[VarManager::kPhi], t1.sign() + t2.sign(), dileptonFilterMap, dileptonMcDecision, - t1.pt(), t1.eta(), t1.phi(), t1.tpcNClsCrossedRows(), t1.tpcNClsFound(), t1.tpcChi2NCl(), t1.dcaXY(), t1.dcaZ(), t1.tpcSignal(), t1.tpcNSigmaEl(), t1.tpcNSigmaPi(), t1.tpcNSigmaPr(), t1.beta(), t1.tofNSigmaEl(), t1.tofNSigmaPi(), t1.tofNSigmaPr(), - t2.pt(), t2.eta(), t2.phi(), t2.tpcNClsCrossedRows(), t2.tpcNClsFound(), t2.tpcChi2NCl(), t2.dcaXY(), t2.dcaZ(), t2.tpcSignal(), t2.tpcNSigmaEl(), t2.tpcNSigmaPi(), t2.tpcNSigmaPr(), t2.beta(), t2.tofNSigmaEl(), t2.tofNSigmaPi(), t2.tofNSigmaPr(), + 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(), + t2.pt(), t2.eta(), t2.phi(), t2.itsClusterMap(), t2.itsChi2NCl(), t2.tpcNClsCrossedRows(), t2.tpcNClsFound(), t2.tpcChi2NCl(), t2.dcaXY(), t2.dcaZ(), t2.tpcSignal(), t2.tpcNSigmaEl(), t2.tpcNSigmaPi(), t2.tpcNSigmaPr(), t2.beta(), t2.tofNSigmaEl(), t2.tofNSigmaPi(), t2.tofNSigmaPr(), VarManager::fgValues[VarManager::kKFTrack0DCAxyz], VarManager::fgValues[VarManager::kKFTrack1DCAxyz], VarManager::fgValues[VarManager::kKFDCAxyzBetweenProngs], VarManager::fgValues[VarManager::kKFTrack0DCAxy], VarManager::fgValues[VarManager::kKFTrack1DCAxy], VarManager::fgValues[VarManager::kKFDCAxyBetweenProngs], VarManager::fgValues[VarManager::kKFTrack0DeviationFromPV], VarManager::fgValues[VarManager::kKFTrack1DeviationFromPV], VarManager::fgValues[VarManager::kKFTrack0DeviationxyFromPV], VarManager::fgValues[VarManager::kKFTrack1DeviationxyFromPV], VarManager::fgValues[VarManager::kKFMass], VarManager::fgValues[VarManager::kKFChi2OverNDFGeo], VarManager::fgValues[VarManager::kVertexingLxyz], VarManager::fgValues[VarManager::kVertexingLxyzOverErr], VarManager::fgValues[VarManager::kVertexingLxy], VarManager::fgValues[VarManager::kVertexingLxyOverErr], VarManager::fgValues[VarManager::kVertexingTauxy], VarManager::fgValues[VarManager::kVertexingTauxyErr], VarManager::fgValues[VarManager::kKFCosPA], VarManager::fgValues[VarManager::kKFJpsiDCAxyz], VarManager::fgValues[VarManager::kKFJpsiDCAxy], diff --git a/PWGDQ/Tasks/tableReader_withAssoc.cxx b/PWGDQ/Tasks/tableReader_withAssoc.cxx index ac44ffd4657..ea7e384a409 100644 --- a/PWGDQ/Tasks/tableReader_withAssoc.cxx +++ b/PWGDQ/Tasks/tableReader_withAssoc.cxx @@ -677,8 +677,6 @@ struct AnalysisMuonSelection { auto track = assoc.template reducedmuon_as(); filterMap = 0; VarManager::FillTrack(track); - // compute quantities which depend on the associated collision - VarManager::FillPropagateMuon(track, event); if (fConfigQA) { fHistMan->FillHistClass("TrackMuon_BeforeCuts", VarManager::fgValues); } @@ -1355,8 +1353,8 @@ struct AnalysisSameEventPairing { if constexpr ((TTrackFillMap & VarManager::ObjTypes::ReducedTrackBarrelPID) > 0) { if (fConfigFlatTables.value) { dielectronAllList(VarManager::fgValues[VarManager::kMass], VarManager::fgValues[VarManager::kPt], VarManager::fgValues[VarManager::kEta], VarManager::fgValues[VarManager::kPhi], t1.sign() + t2.sign(), twoTrackFilter, dileptonMcDecision, - t1.pt(), t1.eta(), t1.phi(), t1.tpcNClsCrossedRows(), t1.tpcNClsFound(), t1.tpcChi2NCl(), t1.dcaXY(), t1.dcaZ(), t1.tpcSignal(), t1.tpcNSigmaEl(), t1.tpcNSigmaPi(), t1.tpcNSigmaPr(), t1.beta(), t1.tofNSigmaEl(), t1.tofNSigmaPi(), t1.tofNSigmaPr(), - t2.pt(), t2.eta(), t2.phi(), t2.tpcNClsCrossedRows(), t2.tpcNClsFound(), t2.tpcChi2NCl(), t2.dcaXY(), t2.dcaZ(), t2.tpcSignal(), t2.tpcNSigmaEl(), t2.tpcNSigmaPi(), t2.tpcNSigmaPr(), t2.beta(), t2.tofNSigmaEl(), t2.tofNSigmaPi(), t2.tofNSigmaPr(), + 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(), + t2.pt(), t2.eta(), t2.phi(), t2.itsClusterMap(), t2.itsChi2NCl(), t2.tpcNClsCrossedRows(), t2.tpcNClsFound(), t2.tpcChi2NCl(), t2.dcaXY(), t2.dcaZ(), t2.tpcSignal(), t2.tpcNSigmaEl(), t2.tpcNSigmaPi(), t2.tpcNSigmaPr(), t2.beta(), t2.tofNSigmaEl(), t2.tofNSigmaPi(), t2.tofNSigmaPr(), VarManager::fgValues[VarManager::kKFTrack0DCAxyz], VarManager::fgValues[VarManager::kKFTrack1DCAxyz], VarManager::fgValues[VarManager::kKFDCAxyzBetweenProngs], VarManager::fgValues[VarManager::kKFTrack0DCAxy], VarManager::fgValues[VarManager::kKFTrack1DCAxy], VarManager::fgValues[VarManager::kKFDCAxyBetweenProngs], VarManager::fgValues[VarManager::kKFTrack0DeviationFromPV], VarManager::fgValues[VarManager::kKFTrack1DeviationFromPV], VarManager::fgValues[VarManager::kKFTrack0DeviationxyFromPV], VarManager::fgValues[VarManager::kKFTrack1DeviationxyFromPV], VarManager::fgValues[VarManager::kKFMass], VarManager::fgValues[VarManager::kKFChi2OverNDFGeo], VarManager::fgValues[VarManager::kVertexingLxyz], VarManager::fgValues[VarManager::kVertexingLxyzOverErr], VarManager::fgValues[VarManager::kVertexingLxy], VarManager::fgValues[VarManager::kVertexingLxyOverErr], VarManager::fgValues[VarManager::kVertexingTauxy], VarManager::fgValues[VarManager::kVertexingTauxyErr], VarManager::fgValues[VarManager::kKFCosPA], VarManager::fgValues[VarManager::kKFJpsiDCAxyz], VarManager::fgValues[VarManager::kKFJpsiDCAxy], @@ -1375,9 +1373,9 @@ struct AnalysisSameEventPairing { auto t1 = a1.template reducedmuon_as(); auto t2 = a2.template reducedmuon_as(); - if (t1.matchMCHTrackId() == t2.matchMCHTrackId()) + if (t1.matchMCHTrackId() == t2.matchMCHTrackId() && t1.matchMCHTrackId() >= 0) continue; - if (t1.matchMFTTrackId() == t2.matchMFTTrackId()) + if (t1.matchMFTTrackId() == t2.matchMFTTrackId() && t1.matchMFTTrackId() >= 0) continue; sign1 = t1.sign(); sign2 = t2.sign(); diff --git a/PWGEM/Dilepton/Core/DielectronCut.cxx b/PWGEM/Dilepton/Core/DielectronCut.cxx index fb42e5ce9c8..f50efa586f7 100644 --- a/PWGEM/Dilepton/Core/DielectronCut.cxx +++ b/PWGEM/Dilepton/Core/DielectronCut.cxx @@ -101,6 +101,11 @@ void DielectronCut::SetMinNCrossedRowsOverFindableClustersTPC(float minNCrossedR mMinNCrossedRowsOverFindableClustersTPC = minNCrossedRowsOverFindableClustersTPC; LOG(info) << "Dielectron Cut, set min N crossed rows over findable clusters TPC: " << mMinNCrossedRowsOverFindableClustersTPC; } +void DielectronCut::SetMaxFracSharedClustersTPC(float max) +{ + mMaxFracSharedClustersTPC = max; + LOG(info) << "Dielectron Cut, set max fraction of shared clusters in TPC: " << mMaxFracSharedClustersTPC; +} void DielectronCut::SetChi2PerClusterTPC(float min, float max) { mMinChi2PerClusterTPC = min; diff --git a/PWGEM/Dilepton/Core/DielectronCut.h b/PWGEM/Dilepton/Core/DielectronCut.h index 8ccd67ee7db..51691d6e51f 100644 --- a/PWGEM/Dilepton/Core/DielectronCut.h +++ b/PWGEM/Dilepton/Core/DielectronCut.h @@ -56,6 +56,7 @@ class DielectronCut : public TNamed kTPCNCls, kTPCCrossedRows, kTPCCrossedRowsOverNCls, + kTPCFracSharedClusters, kTPCChi2NDF, kTPCNsigmaEl, kTPCNsigmaMu, @@ -203,6 +204,9 @@ class DielectronCut : public TNamed if (!IsSelectedTrack(track, DielectronCuts::kTPCCrossedRowsOverNCls)) { return false; } + if (!IsSelectedTrack(track, DielectronCuts::kTPCFracSharedClusters)) { + return false; + } if (!IsSelectedTrack(track, DielectronCuts::kTPCChi2NDF)) { return false; } @@ -337,6 +341,9 @@ class DielectronCut : public TNamed case DielectronCuts::kTPCCrossedRowsOverNCls: return track.tpcCrossedRowsOverFindableCls() >= mMinNCrossedRowsOverFindableClustersTPC; + case DielectronCuts::kTPCFracSharedClusters: + return track.tpcFractionSharedCls() <= mMaxFracSharedClustersTPC; + case DielectronCuts::kTPCChi2NDF: return mMinChi2PerClusterTPC < track.tpcChi2NCl() && track.tpcChi2NCl() < mMaxChi2PerClusterTPC; @@ -382,6 +389,7 @@ class DielectronCut : public TNamed 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); @@ -446,6 +454,7 @@ class DielectronCut : public TNamed int mMinNCrossedRowsTPC{0}; // min number of crossed rows in TPC float mMinChi2PerClusterTPC{-1e10f}, mMaxChi2PerClusterTPC{1e10f}; // max tpc fit chi2 per TPC cluster float mMinNCrossedRowsOverFindableClustersTPC{0.f}; // min ratio crossed rows / findable clusters + float mMaxFracSharedClustersTPC{999.f}; // max ratio shared clusters / clusters in TPC int mMinNClustersITS{0}, mMaxNClustersITS{7}; // range in number of ITS clusters float mMinChi2PerClusterITS{-1e10f}, mMaxChi2PerClusterITS{1e10f}; // max its fit chi2 per ITS cluster float mMaxPinMuonTPConly{0.2f}; // max pin cut for muon ID with TPConly diff --git a/PWGEM/Dilepton/Core/Dilepton.h b/PWGEM/Dilepton/Core/Dilepton.h index 9a228de9bcd..61ead12edcb 100644 --- a/PWGEM/Dilepton/Core/Dilepton.h +++ b/PWGEM/Dilepton/Core/Dilepton.h @@ -101,7 +101,7 @@ struct Dilepton { Configurable cfgAnalysisType{"cfgAnalysisType", static_cast(o2::aod::pwgem::dilepton::utils::pairutil::DileptonAnalysisType::kQC), "kQC:0, kUPC:1, kFlowV2:2, kFlowV3:3, kPolarization:4, kVM:5, kHFll:6"}; Configurable cfgEP2Estimator_for_Mix{"cfgEP2Estimator_for_Mix", 3, "FT0M:0, FT0A:1, FT0C:2, BTot:3, BPos:4, BNeg:5"}; Configurable cfgQvecEstimator{"cfgQvecEstimator", 0, "FT0M:0, FT0A:1, FT0C:2, BTot:3, BPos:4, BNeg:5"}; - Configurable cfgCentEstimator{"cfgCentEstimator", 2, "FT0M:0, FT0A:1, FT0C:2, NTPV:3"}; + Configurable cfgCentEstimator{"cfgCentEstimator", 2, "FT0M:0, FT0A:1, FT0C:2"}; Configurable cfgCentMin{"cfgCentMin", 0, "min. centrality"}; Configurable cfgCentMax{"cfgCentMax", 999.f, "max. centrality"}; Configurable cfgDoMix{"cfgDoMix", true, "flag for event mixing"}; @@ -168,12 +168,16 @@ struct Dilepton { 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_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_dcaxy{"cfg_max_dcaxy", 0.2, "max dca XY for single track in cm"}; + Configurable cfg_max_dcaz{"cfg_max_dcaz", 0.2, "max dca Z for single track in cm"}; Configurable cfg_require_itsib_any{"cfg_require_itsib_any", false, "flag to require ITS ib any hits"}; Configurable cfg_require_itsib_1st{"cfg_require_itsib_1st", true, "flag to require ITS ib 1st hit"}; + Configurable cfg_min_its_cluster_size{"cfg_min_its_cluster_size", 0.f, "min ITS cluster size"}; + Configurable cfg_max_its_cluster_size{"cfg_max_its_cluster_size", 16.f, "max ITS cluster size"}; + Configurable cfg_max_p_its_cluster_size{"cfg_max_p_its_cluster_size", 0.0, "max p to apply ITS cluster size cut"}; Configurable cfg_pid_scheme{"cfg_pid_scheme", static_cast(DielectronCut::PIDSchemes::kTPChadrejORTOFreq), "pid scheme [kTOFreq : 0, kTPChadrej : 1, kTPChadrejORTOFreq : 2, kTPConly : 3]"}; Configurable cfg_min_TPCNsigmaEl{"cfg_min_TPCNsigmaEl", -2.0, "min. TPC n sigma for electron inclusion"}; @@ -221,7 +225,7 @@ struct Dilepton { Configurable cfg_max_phi_track{"cfg_max_phi_track", 6.3, "max phi for single track"}; Configurable cfg_min_ncluster_mft{"cfg_min_ncluster_mft", 5, "min ncluster MFT"}; Configurable cfg_min_ncluster_mch{"cfg_min_ncluster_mch", 5, "min ncluster MCH"}; - Configurable cfg_max_chi2{"cfg_max_chi2", 1e+10, "max chi2/NclsTPC"}; + Configurable cfg_max_chi2{"cfg_max_chi2", 1e+10, "max chi2"}; Configurable cfg_max_matching_chi2_mftmch{"cfg_max_matching_chi2_mftmch", 1e+10, "max chi2 for MFT-MCH matching"}; Configurable cfg_max_matching_chi2_mchmid{"cfg_max_matching_chi2_mchmid", 1e+10, "max chi2 for MCH-MID matching"}; Configurable cfg_max_dcaxy{"cfg_max_dcaxy", 1e+10, "max dca XY for single track in cm"}; @@ -369,6 +373,7 @@ struct Dilepton { // fwdfitter.setTGeoMat(false); } + fRegistry.addClone("Event/before/hCollisionCounter", "Event/norm/hCollisionCounter"); fRegistry.add("Pair/mix/hDiffBC", "diff. global BC in mixed event;|BC_{current} - BC_{mixed}|", kTH1D, {{1001, -0.5, 1000.5}}, true); if (doprocessTriggerAnalysis) { fRegistry.add("Event/hNInspectedTVX", "N inspected TVX;run number;N_{TVX}", kTProfile, {{80000, 520000.5, 600000.5}}, true); @@ -619,10 +624,11 @@ struct Dilepton { 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, 16); + fDielectronCut.SetMeanClusterSizeITS(dielectroncuts.cfg_min_its_cluster_size, dielectroncuts.cfg_max_its_cluster_size, dielectroncuts.cfg_max_p_its_cluster_size); fDielectronCut.SetTrackMaxDcaXY(dielectroncuts.cfg_max_dcaxy); fDielectronCut.SetTrackMaxDcaZ(dielectroncuts.cfg_max_dcaz); fDielectronCut.RequireITSibAny(dielectroncuts.cfg_require_itsib_any); @@ -1052,7 +1058,7 @@ struct Dilepton { { for (auto& collision : collisions) { initCCDB(collision); - const float centralities[4] = {collision.centFT0M(), collision.centFT0A(), collision.centFT0C(), collision.centNTPV()}; + const float centralities[3] = {collision.centFT0M(), collision.centFT0A(), collision.centFT0C()}; float centrality = centralities[cfgCentEstimator]; if (centralities[cfgCentEstimator] < cfgCentMin || cfgCentMax < centralities[cfgCentEstimator]) { continue; @@ -1409,7 +1415,7 @@ struct Dilepton { for (auto& collision : collisions) { initCCDB(collision); - const float centralities[4] = {collision.centFT0M(), collision.centFT0A(), collision.centFT0C(), collision.centNTPV()}; + const float centralities[3] = {collision.centFT0M(), collision.centFT0A(), collision.centFT0C()}; if (centralities[cfgCentEstimator] < cfgCentMin || cfgCentMax < centralities[cfgCentEstimator]) { continue; } @@ -1543,6 +1549,51 @@ struct Dilepton { } PROCESS_SWITCH(Dilepton, processTriggerAnalysis, "run dilepton analysis on triggered data", false); + void processNorm(aod::EMEventNormInfos const& collisions) + { + for (auto& collision : collisions) { + fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 1.0); + if (collision.selection_bit(o2::aod::evsel::kIsTriggerTVX)) { + fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 2.0); + } + if (collision.selection_bit(o2::aod::evsel::kNoTimeFrameBorder)) { + fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 3.0); + } + if (collision.selection_bit(o2::aod::evsel::kNoITSROFrameBorder)) { + fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 4.0); + } + if (collision.selection_bit(o2::aod::evsel::kNoSameBunchPileup)) { + fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 5.0); + } + if (collision.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV)) { + fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 6.0); + } + if (collision.selection_bit(o2::aod::evsel::kIsVertexITSTPC)) { + fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 7.0); + } + if (collision.selection_bit(o2::aod::evsel::kIsVertexTRDmatched)) { + fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 8.0); + } + if (collision.selection_bit(o2::aod::evsel::kIsVertexTOFmatched)) { + fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 9.0); + } + if (collision.sel8()) { + fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 10.0); + } + if (abs(collision.posZ()) < 10.0) { + fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 11.0); + } + if (collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard)) { + fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 12.0); + } + if (!fEMEventCut.IsSelected(collision)) { + continue; + } + fRegistry.fill(HIST("Event/norm/hCollisionCounter"), o2::aod::pwgem::dilepton::utils::eventhistogram::nbin_ev); // accepted + } // end of collision loop + } + PROCESS_SWITCH(Dilepton, processNorm, "process normalization info", false); + void processDummy(MyCollisions const&) {} PROCESS_SWITCH(Dilepton, processDummy, "Dummy function", false); }; diff --git a/PWGEM/Dilepton/Core/DileptonMC.h b/PWGEM/Dilepton/Core/DileptonMC.h index 33571dceba7..e128115afb8 100644 --- a/PWGEM/Dilepton/Core/DileptonMC.h +++ b/PWGEM/Dilepton/Core/DileptonMC.h @@ -91,7 +91,7 @@ struct DileptonMC { Configurable d_bz_input{"d_bz_input", -999, "bz field in kG, -999 is automatic"}; Configurable cfgEventGeneratorType{"cfgEventGeneratorType", -1, "if positive, select event generator type. i.e. gap or signal"}; - Configurable cfgCentEstimator{"cfgCentEstimator", 2, "FT0M:0, FT0A:1, FT0C:2, NTPV:3"}; + Configurable cfgCentEstimator{"cfgCentEstimator", 2, "FT0M:0, FT0A:1, FT0C:2"}; Configurable cfgCentMin{"cfgCentMin", 0, "min. centrality"}; Configurable cfgCentMax{"cfgCentMax", 999.f, "max. centrality"}; Configurable cfgNtracksPV08Min{"cfgNtracksPV08Min", -1, "min. multNTracksPV"}; @@ -149,12 +149,16 @@ struct DileptonMC { 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_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_dcaxy{"cfg_max_dcaxy", 0.2, "max dca XY for single track in cm"}; + Configurable cfg_max_dcaz{"cfg_max_dcaz", 0.2, "max dca Z for single track in cm"}; Configurable cfg_require_itsib_any{"cfg_require_itsib_any", false, "flag to require ITS ib any hits"}; Configurable cfg_require_itsib_1st{"cfg_require_itsib_1st", true, "flag to require ITS ib 1st hit"}; + Configurable cfg_min_its_cluster_size{"cfg_min_its_cluster_size", 0.f, "min ITS cluster size"}; + Configurable cfg_max_its_cluster_size{"cfg_max_its_cluster_size", 16.f, "max ITS cluster size"}; + Configurable cfg_max_p_its_cluster_size{"cfg_max_p_its_cluster_size", 0.0, "max p to apply ITS cluster size cut"}; Configurable cfg_pid_scheme{"cfg_pid_scheme", static_cast(DielectronCut::PIDSchemes::kTPChadrejORTOFreq), "pid scheme [kTOFreq : 0, kTPChadrej : 1, kTPChadrejORTOFreq : 2, kTPConly : 3]"}; Configurable cfg_min_TPCNsigmaEl{"cfg_min_TPCNsigmaEl", -2.0, "min. TPC n sigma for electron inclusion"}; @@ -202,7 +206,7 @@ struct DileptonMC { Configurable cfg_max_phi_track{"cfg_max_phi_track", 6.3, "max phi for single track"}; Configurable cfg_min_ncluster_mft{"cfg_min_ncluster_mft", 5, "min ncluster MFT"}; Configurable cfg_min_ncluster_mch{"cfg_min_ncluster_mch", 5, "min ncluster MCH"}; - Configurable cfg_max_chi2{"cfg_max_chi2", 1e+10, "max chi2/NclsTPC"}; + Configurable cfg_max_chi2{"cfg_max_chi2", 1e+10, "max chi2"}; Configurable cfg_max_matching_chi2_mftmch{"cfg_max_matching_chi2_mftmch", 1e+10, "max chi2 for MFT-MCH matching"}; Configurable cfg_max_matching_chi2_mchmid{"cfg_max_matching_chi2_mchmid", 1e+10, "max chi2 for MCH-MID matching"}; Configurable cfg_max_dcaxy{"cfg_max_dcaxy", 1e+10, "max dca XY for single track in cm"}; @@ -401,6 +405,7 @@ struct DileptonMC { // fwdfitter.setUseAbsDCA(true); // fwdfitter.setTGeoMat(false); } + fRegistry.addClone("Event/before/hCollisionCounter", "Event/norm/hCollisionCounter"); } template @@ -503,10 +508,11 @@ struct DileptonMC { 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, 16); + fDielectronCut.SetMeanClusterSizeITS(dielectroncuts.cfg_min_its_cluster_size, dielectroncuts.cfg_max_its_cluster_size, dielectroncuts.cfg_max_p_its_cluster_size); fDielectronCut.SetTrackMaxDcaXY(dielectroncuts.cfg_max_dcaxy); fDielectronCut.SetTrackMaxDcaZ(dielectroncuts.cfg_max_dcaz); fDielectronCut.RequireITSibAny(dielectroncuts.cfg_require_itsib_any); @@ -911,7 +917,7 @@ struct DileptonMC { { for (auto& collision : collisions) { initCCDB(collision); - float centralities[4] = {collision.centFT0M(), collision.centFT0A(), collision.centFT0C(), collision.centNTPV()}; + float centralities[3] = {collision.centFT0M(), collision.centFT0A(), collision.centFT0C()}; if (centralities[cfgCentEstimator] < cfgCentMin || cfgCentMax < centralities[cfgCentEstimator]) { continue; } @@ -982,13 +988,22 @@ struct DileptonMC { // loop over mc stack and fill histograms for pure MC truth signals // all MC tracks which belong to the MC event corresponding to the current reconstructed event + std::vector used_mccollisionIds; // used mc collisionIds + used_mccollisionIds.reserve(collisions.size()); + for (auto& collision : collisions) { - float centralities[4] = {collision.centFT0M(), collision.centFT0A(), collision.centFT0C(), collision.centNTPV()}; + auto mccollision = collision.template emmcevent_as(); + if (std::find(used_mccollisionIds.begin(), used_mccollisionIds.end(), mccollision.globalIndex()) != used_mccollisionIds.end()) { + // LOGF(info, "same mc collision is repeated. continue;"); + continue; + } + used_mccollisionIds.emplace_back(mccollision.globalIndex()); + + float centralities[3] = {collision.centFT0M(), collision.centFT0A(), collision.centFT0C()}; if (centralities[cfgCentEstimator] < cfgCentMin || cfgCentMax < centralities[cfgCentEstimator]) { continue; } - auto mccollision = collision.template emmcevent_as(); if (cfgEventGeneratorType >= 0 && mccollision.getSubGeneratorId() != cfgEventGeneratorType) { continue; } @@ -1479,6 +1494,8 @@ struct DileptonMC { } } // end of true LS++ pair loop } // end of collision loop + used_mccollisionIds.clear(); + used_mccollisionIds.shrink_to_fit(); } template @@ -1521,7 +1538,7 @@ struct DileptonMC { for (auto& collision : collisions) { initCCDB(collision); - const float centralities[4] = {collision.centFT0M(), collision.centFT0A(), collision.centFT0C(), collision.centNTPV()}; + const float centralities[3] = {collision.centFT0M(), collision.centFT0A(), collision.centFT0C()}; if (centralities[cfgCentEstimator] < cfgCentMin || cfgCentMax < centralities[cfgCentEstimator]) { continue; } @@ -1682,7 +1699,7 @@ struct DileptonMC { { // for oemga, phi efficiency for (auto& collision : collisions) { - float centralities[4] = {collision.centFT0M(), collision.centFT0A(), collision.centFT0C(), collision.centNTPV()}; + float centralities[3] = {collision.centFT0M(), collision.centFT0A(), collision.centFT0C()}; if (centralities[cfgCentEstimator] < cfgCentMin || cfgCentMax < centralities[cfgCentEstimator]) { continue; } @@ -1728,6 +1745,51 @@ struct DileptonMC { } PROCESS_SWITCH(DileptonMC, processGen_VM, "process generated info for vector mesons", false); + void processNorm(aod::EMEventNormInfos const& collisions) + { + for (auto& collision : collisions) { + fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 1.0); + if (collision.selection_bit(o2::aod::evsel::kIsTriggerTVX)) { + fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 2.0); + } + if (collision.selection_bit(o2::aod::evsel::kNoTimeFrameBorder)) { + fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 3.0); + } + if (collision.selection_bit(o2::aod::evsel::kNoITSROFrameBorder)) { + fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 4.0); + } + if (collision.selection_bit(o2::aod::evsel::kNoSameBunchPileup)) { + fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 5.0); + } + if (collision.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV)) { + fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 6.0); + } + if (collision.selection_bit(o2::aod::evsel::kIsVertexITSTPC)) { + fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 7.0); + } + if (collision.selection_bit(o2::aod::evsel::kIsVertexTRDmatched)) { + fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 8.0); + } + if (collision.selection_bit(o2::aod::evsel::kIsVertexTOFmatched)) { + fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 9.0); + } + if (collision.sel8()) { + fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 10.0); + } + if (abs(collision.posZ()) < 10.0) { + fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 11.0); + } + if (collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard)) { + fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 12.0); + } + if (!fEMEventCut.IsSelected(collision)) { + continue; + } + fRegistry.fill(HIST("Event/norm/hCollisionCounter"), o2::aod::pwgem::dilepton::utils::eventhistogram::nbin_ev); // accepted + } // end of collision loop + } + PROCESS_SWITCH(DileptonMC, processNorm, "process normalization info", false); + void processDummy(MyCollisions const&) {} PROCESS_SWITCH(DileptonMC, processDummy, "Dummy function", false); }; diff --git a/PWGEM/Dilepton/Core/PhotonHBT.h b/PWGEM/Dilepton/Core/PhotonHBT.h index 8198a4fec30..401288f6efd 100644 --- a/PWGEM/Dilepton/Core/PhotonHBT.h +++ b/PWGEM/Dilepton/Core/PhotonHBT.h @@ -96,7 +96,7 @@ struct PhotonHBT { Configurable cfgDo3D{"cfgDo3D", false, "enable 3D analysis"}; Configurable cfgEP2Estimator_for_Mix{"cfgEP2Estimator_for_Mix", 3, "FT0M:0, FT0A:1, FT0C:2, BTot:3, BPos:4, BNeg:5"}; - Configurable cfgCentEstimator{"cfgCentEstimator", 2, "FT0M:0, FT0A:1, FT0C:2, NTPV:3"}; + Configurable cfgCentEstimator{"cfgCentEstimator", 2, "FT0M:0, FT0A:1, FT0C:2"}; Configurable cfgCentMin{"cfgCentMin", 0, "min. centrality"}; Configurable cfgCentMax{"cfgCentMax", 999, "max. centrality"}; // Configurable cfgSpherocityMin{"cfgSpherocityMin", -999.f, "min. spherocity"}; @@ -153,6 +153,7 @@ struct PhotonHBT { Configurable cfg_disable_itsonly_track{"cfg_disable_itsonly_track", false, "flag to disable ITSonly tracks"}; Configurable cfg_min_ncluster_tpc{"cfg_min_ncluster_tpc", 10, "min ncluster tpc"}; Configurable cfg_min_ncrossedrows{"cfg_min_ncrossedrows", 40, "min ncrossed rows"}; + Configurable cfg_max_frac_shared_clusters_tpc{"cfg_max_frac_shared_clusters_tpc", 999.f, "max fraction of shared clusters in TPC"}; Configurable cfg_max_chi2tpc{"cfg_max_chi2tpc", 4.0, "max chi2/NclsTPC"}; Configurable cfg_max_chi2its{"cfg_max_chi2its", 5.0, "max chi2/NclsITS"}; Configurable cfg_min_TPCNsigmaEl{"cfg_min_TPCNsigmaEl", -3.0, "min. TPC n sigma for electron"}; @@ -186,6 +187,7 @@ struct PhotonHBT { 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_dcaxy{"cfg_max_dcaxy", 1.0, "max dca XY for single track in cm"}; @@ -471,6 +473,7 @@ struct PhotonHBT { 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); @@ -534,6 +537,7 @@ struct PhotonHBT { 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); @@ -643,7 +647,7 @@ struct PhotonHBT { for (auto& collision : collisions) { initCCDB(collision); int ndiphoton = 0; - const float centralities[4] = {collision.centFT0M(), collision.centFT0A(), collision.centFT0C(), collision.centNTPV()}; + const float centralities[3] = {collision.centFT0M(), collision.centFT0A(), collision.centFT0C()}; if (centralities[cfgCentEstimator] < cfgCentMin || cfgCentMax < centralities[cfgCentEstimator]) { continue; } @@ -1228,7 +1232,7 @@ struct PhotonHBT { for (auto& collision : collisions) { initCCDB(collision); - const float centralities[4] = {collision.centFT0M(), collision.centFT0A(), collision.centFT0C(), collision.centNTPV()}; + const float centralities[3] = {collision.centFT0M(), collision.centFT0A(), collision.centFT0C()}; if (centralities[cfgCentEstimator] < cfgCentMin || cfgCentMax < centralities[cfgCentEstimator]) { continue; } diff --git a/PWGEM/Dilepton/Core/SingleTrackQC.h b/PWGEM/Dilepton/Core/SingleTrackQC.h index ed34bd4f6cb..47a357a0fb6 100644 --- a/PWGEM/Dilepton/Core/SingleTrackQC.h +++ b/PWGEM/Dilepton/Core/SingleTrackQC.h @@ -72,7 +72,7 @@ struct SingleTrackQC { // Configurables Configurable ccdburl{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; - Configurable cfgCentEstimator{"cfgCentEstimator", 2, "FT0M:0, FT0A:1, FT0C:2, NTPV:3"}; + Configurable cfgCentEstimator{"cfgCentEstimator", 2, "FT0M:0, FT0A:1, FT0C:2"}; Configurable cfgCentMin{"cfgCentMin", 0, "min. centrality"}; Configurable cfgCentMax{"cfgCentMax", 999.f, "max. centrality"}; Configurable cfg_swt_name{"cfg_swt_name", "fHighTrackMult", "desired software trigger name"}; // 1 trigger name per 1 task. fHighTrackMult, fHighFt0Mult @@ -111,12 +111,16 @@ struct SingleTrackQC { 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_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_dcaxy{"cfg_max_dcaxy", 0.2, "max dca XY for single track in cm"}; + Configurable cfg_max_dcaz{"cfg_max_dcaz", 0.2, "max dca Z for single track in cm"}; Configurable cfg_require_itsib_any{"cfg_require_itsib_any", false, "flag to require ITS ib any hits"}; Configurable cfg_require_itsib_1st{"cfg_require_itsib_1st", true, "flag to require ITS ib 1st hit"}; + Configurable cfg_min_its_cluster_size{"cfg_min_its_cluster_size", 0.f, "min ITS cluster size"}; + Configurable cfg_max_its_cluster_size{"cfg_max_its_cluster_size", 16.f, "max ITS cluster size"}; + Configurable cfg_max_p_its_cluster_size{"cfg_max_p_its_cluster_size", 0.0, "max p to apply ITS cluster size cut"}; Configurable cfg_pid_scheme{"cfg_pid_scheme", static_cast(DielectronCut::PIDSchemes::kTPChadrejORTOFreq), "pid scheme [kTOFreq : 0, kTPChadrej : 1, kTPChadrejORTOFreq : 2, kTPConly : 3]"}; Configurable cfg_min_TPCNsigmaEl{"cfg_min_TPCNsigmaEl", -2.0, "min. TPC n sigma for electron inclusion"}; @@ -159,7 +163,7 @@ struct SingleTrackQC { Configurable cfg_max_phi_track{"cfg_max_phi_track", 6.3, "max phi for single track"}; Configurable cfg_min_ncluster_mft{"cfg_min_ncluster_mft", 5, "min ncluster MFT"}; Configurable cfg_min_ncluster_mch{"cfg_min_ncluster_mch", 5, "min ncluster MCH"}; - Configurable cfg_max_chi2{"cfg_max_chi2", 1e+10, "max chi2/NclsTPC"}; + Configurable cfg_max_chi2{"cfg_max_chi2", 1e+10, "max chi2"}; Configurable cfg_max_matching_chi2_mftmch{"cfg_max_matching_chi2_mftmch", 1e+10, "max chi2 for MFT-MCH matching"}; Configurable cfg_max_matching_chi2_mchmid{"cfg_max_matching_chi2_mchmid", 1e+10, "max chi2 for MCH-MID matching"}; Configurable cfg_max_dcaxy{"cfg_max_dcaxy", 1e+10, "max dca XY for single track in cm"}; @@ -208,12 +212,13 @@ struct SingleTrackQC { fRegistry.add("Track/positive/hChi2TPC", "chi2/number of TPC clusters", kTH1F, {{100, 0, 10}}, false); fRegistry.add("Track/positive/hTPCNcr2Nf", "TPC Ncr/Nfindable", kTH1F, {{200, 0, 2}}, false); fRegistry.add("Track/positive/hTPCNcls2Nf", "TPC Ncls/Nfindable", kTH1F, {{200, 0, 2}}, false); + fRegistry.add("Track/positive/hTPCNclsShared", "TPC Ncls shared/Ncls;p_{T} (GeV/c);N_{cls}^{shared}/N_{cls} in TPC", kTH2F, {{1000, 0, 10}, {100, 0, 1}}, false); fRegistry.add("Track/positive/hNclsITS", "number of ITS clusters", kTH1F, {{8, -0.5, 7.5}}, false); fRegistry.add("Track/positive/hChi2ITS", "chi2/number of ITS clusters", kTH1F, {{100, 0, 10}}, false); fRegistry.add("Track/positive/hITSClusterMap", "ITS cluster map", kTH1F, {{128, -0.5, 127.5}}, false); fRegistry.add("Track/positive/hTPCdEdx", "TPC dE/dx;p_{in} (GeV/c);TPC dE/dx (a.u.)", kTH2F, {{1000, 0, 10}, {200, 0, 200}}, false); fRegistry.add("Track/positive/hTOFbeta", "TOF #beta;p_{pv} (GeV/c);#beta", kTH2F, {{1000, 0, 10}, {240, 0, 1.2}}, false); - fRegistry.add("Track/positive/hMeanClusterSizeITS", "mean cluster size ITS;p_{pv} (GeV/c); on ITS #times cos(#lambda);", kTH2F, {{1000, 0.f, 10.f}, {160, 0, 16}}, false); + fRegistry.add("Track/positive/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/hTPCNsigmaEl", "TPC n sigma el;p_{in} (GeV/c);n #sigma_{e}^{TPC}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); fRegistry.add("Track/positive/hTPCNsigmaMu", "TPC n sigma mu;p_{in} (GeV/c);n #sigma_{#mu}^{TPC}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); fRegistry.add("Track/positive/hTPCNsigmaPi", "TPC n sigma pi;p_{in} (GeV/c);n #sigma_{#pi}^{TPC}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); @@ -264,6 +269,7 @@ struct SingleTrackQC { addhistograms(); mRunNumber = 0; + fRegistry.addClone("Event/before/hCollisionCounter", "Event/norm/hCollisionCounter"); if (doprocessQC_TriggeredData) { fRegistry.add("Event/hNInspectedTVX", "N inspected TVX;run number;N_{TVX}", kTProfile, {{80000, 520000.5, 600000.5}}, true); } @@ -312,10 +318,11 @@ struct SingleTrackQC { 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, 16); + fDielectronCut.SetMeanClusterSizeITS(dielectroncuts.cfg_min_its_cluster_size, dielectroncuts.cfg_max_its_cluster_size, dielectroncuts.cfg_max_p_its_cluster_size); fDielectronCut.SetTrackMaxDcaXY(dielectroncuts.cfg_max_dcaxy); fDielectronCut.SetTrackMaxDcaZ(dielectroncuts.cfg_max_dcaz); fDielectronCut.RequireITSibAny(dielectroncuts.cfg_require_itsib_any); @@ -398,6 +405,7 @@ struct SingleTrackQC { fRegistry.fill(HIST("Track/positive/hNcrTPC"), track.tpcNClsCrossedRows()); fRegistry.fill(HIST("Track/positive/hTPCNcr2Nf"), track.tpcCrossedRowsOverFindableCls()); fRegistry.fill(HIST("Track/positive/hTPCNcls2Nf"), track.tpcFoundOverFindableCls()); + fRegistry.fill(HIST("Track/positive/hTPCNclsShared"), track.pt(), track.tpcFractionSharedCls()); fRegistry.fill(HIST("Track/positive/hChi2TPC"), track.tpcChi2NCl()); fRegistry.fill(HIST("Track/positive/hChi2ITS"), track.itsChi2NCl()); fRegistry.fill(HIST("Track/positive/hITSClusterMap"), track.itsClusterMap()); @@ -427,6 +435,7 @@ struct SingleTrackQC { fRegistry.fill(HIST("Track/negative/hNcrTPC"), track.tpcNClsCrossedRows()); fRegistry.fill(HIST("Track/negative/hTPCNcr2Nf"), track.tpcCrossedRowsOverFindableCls()); fRegistry.fill(HIST("Track/negative/hTPCNcls2Nf"), track.tpcFoundOverFindableCls()); + fRegistry.fill(HIST("Track/negative/hTPCNclsShared"), track.pt(), track.tpcFractionSharedCls()); fRegistry.fill(HIST("Track/negative/hChi2TPC"), track.tpcChi2NCl()); fRegistry.fill(HIST("Track/negative/hChi2ITS"), track.itsChi2NCl()); fRegistry.fill(HIST("Track/negative/hITSClusterMap"), track.itsClusterMap()); @@ -493,7 +502,7 @@ struct SingleTrackQC { { for (auto& collision : collisions) { initCCDB(collision); - float centralities[4] = {collision.centFT0M(), collision.centFT0A(), collision.centFT0C(), collision.centNTPV()}; + float centralities[3] = {collision.centFT0M(), collision.centFT0A(), collision.centFT0C()}; if (centralities[cfgCentEstimator] < cfgCentMin || cfgCentMax < centralities[cfgCentEstimator]) { continue; } @@ -545,7 +554,7 @@ struct SingleTrackQC { passed_trackIds.reserve(tracks.size()); for (auto& collision : collisions) { initCCDB(collision); - float centralities[4] = {collision.centFT0M(), collision.centFT0A(), collision.centFT0C(), collision.centNTPV()}; + float centralities[3] = {collision.centFT0M(), collision.centFT0A(), collision.centFT0C()}; if (centralities[cfgCentEstimator] < cfgCentMin || cfgCentMax < centralities[cfgCentEstimator]) { continue; } @@ -670,6 +679,51 @@ struct SingleTrackQC { } PROCESS_SWITCH(SingleTrackQC, processQC_TriggeredData, "run single track QC on triggered data", false); + void processNorm(aod::EMEventNormInfos const& collisions) + { + for (auto& collision : collisions) { + fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 1.0); + if (collision.selection_bit(o2::aod::evsel::kIsTriggerTVX)) { + fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 2.0); + } + if (collision.selection_bit(o2::aod::evsel::kNoTimeFrameBorder)) { + fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 3.0); + } + if (collision.selection_bit(o2::aod::evsel::kNoITSROFrameBorder)) { + fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 4.0); + } + if (collision.selection_bit(o2::aod::evsel::kNoSameBunchPileup)) { + fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 5.0); + } + if (collision.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV)) { + fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 6.0); + } + if (collision.selection_bit(o2::aod::evsel::kIsVertexITSTPC)) { + fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 7.0); + } + if (collision.selection_bit(o2::aod::evsel::kIsVertexTRDmatched)) { + fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 8.0); + } + if (collision.selection_bit(o2::aod::evsel::kIsVertexTOFmatched)) { + fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 9.0); + } + if (collision.sel8()) { + fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 10.0); + } + if (abs(collision.posZ()) < 10.0) { + fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 11.0); + } + if (collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard)) { + fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 12.0); + } + if (!fEMEventCut.IsSelected(collision)) { + continue; + } + fRegistry.fill(HIST("Event/norm/hCollisionCounter"), o2::aod::pwgem::dilepton::utils::eventhistogram::nbin_ev); // accepted + } // end of collision loop + } + PROCESS_SWITCH(SingleTrackQC, processNorm, "process normalization info", false); + void processDummy(MyCollisions const&) {} PROCESS_SWITCH(SingleTrackQC, processDummy, "Dummy function", false); }; diff --git a/PWGEM/Dilepton/Core/SingleTrackQCMC.h b/PWGEM/Dilepton/Core/SingleTrackQCMC.h index 0957e6e6d86..525383a9002 100644 --- a/PWGEM/Dilepton/Core/SingleTrackQCMC.h +++ b/PWGEM/Dilepton/Core/SingleTrackQCMC.h @@ -114,12 +114,16 @@ struct SingleTrackQCMC { 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_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_dcaxy{"cfg_max_dcaxy", 0.2, "max dca XY for single track in cm"}; + Configurable cfg_max_dcaz{"cfg_max_dcaz", 0.2, "max dca Z for single track in cm"}; Configurable cfg_require_itsib_any{"cfg_require_itsib_any", false, "flag to require ITS ib any hits"}; Configurable cfg_require_itsib_1st{"cfg_require_itsib_1st", true, "flag to require ITS ib 1st hit"}; + Configurable cfg_min_its_cluster_size{"cfg_min_its_cluster_size", 0.f, "min ITS cluster size"}; + Configurable cfg_max_its_cluster_size{"cfg_max_its_cluster_size", 16.f, "max ITS cluster size"}; + Configurable cfg_max_p_its_cluster_size{"cfg_max_p_its_cluster_size", 0.0, "max p to apply ITS cluster size cut"}; Configurable cfg_pid_scheme{"cfg_pid_scheme", static_cast(DielectronCut::PIDSchemes::kTPChadrejORTOFreq), "pid scheme [kTOFreq : 0, kTPChadrej : 1, kTPChadrejORTOFreq : 2, kTPConly : 3]"}; Configurable cfg_min_TPCNsigmaEl{"cfg_min_TPCNsigmaEl", -2.0, "min. TPC n sigma for electron inclusion"}; @@ -225,6 +229,7 @@ struct SingleTrackQCMC { fRegistry.add("Track/lf/positive/hChi2TPC", "chi2/number of TPC clusters", kTH1F, {{100, 0, 10}}, false); fRegistry.add("Track/lf/positive/hTPCNcr2Nf", "TPC Ncr/Nfindable", kTH1F, {{200, 0, 2}}, false); fRegistry.add("Track/lf/positive/hTPCNcls2Nf", "TPC Ncls/Nfindable", kTH1F, {{200, 0, 2}}, false); + fRegistry.add("Track/lf/positive/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/lf/positive/hNclsITS", "number of ITS clusters", kTH1F, {{8, -0.5, 7.5}}, false); fRegistry.add("Track/lf/positive/hChi2ITS", "chi2/number of ITS clusters", kTH1F, {{100, 0, 10}}, false); fRegistry.add("Track/lf/positive/hITSClusterMap", "ITS cluster map", kTH1F, {{128, -0.5, 127.5}}, false); @@ -245,7 +250,7 @@ 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/hTOFbeta", "TOF #beta;p_{pv} (GeV/c);#beta", kTH2F, {{1000, 0, 10}, {240, 0, 1.2}}, false); - fRegistry.add("Track/PID/positive/hMeanClusterSizeITS", "mean cluster size ITS;p_{pv} (GeV/c); on ITS #times cos(#lambda)", kTH2F, {{1000, 0.f, 10.f}, {160, 0, 16}}, false); + fRegistry.add("Track/PID/positive/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/hTPCNsigmaEl", "TPC n sigma el;p_{in} (GeV/c);n #sigma_{e}^{TPC}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); fRegistry.add("Track/PID/positive/hTPCNsigmaMu", "TPC n sigma mu;p_{in} (GeV/c);n #sigma_{#mu}^{TPC}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); fRegistry.add("Track/PID/positive/hTPCNsigmaPi", "TPC n sigma pi;p_{in} (GeV/c);n #sigma_{#pi}^{TPC}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); @@ -329,6 +334,7 @@ struct SingleTrackQCMC { pdg_lepton = 13; DefineDimuonCut(); } + fRegistry.addClone("Event/before/hCollisionCounter", "Event/norm/hCollisionCounter"); } void DefineEMEventCut() @@ -358,10 +364,11 @@ struct SingleTrackQCMC { 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, 16); + fDielectronCut.SetMeanClusterSizeITS(dielectroncuts.cfg_min_its_cluster_size, dielectroncuts.cfg_max_its_cluster_size, dielectroncuts.cfg_max_p_its_cluster_size); fDielectronCut.SetTrackMaxDcaXY(dielectroncuts.cfg_max_dcaxy); fDielectronCut.SetTrackMaxDcaZ(dielectroncuts.cfg_max_dcaz); fDielectronCut.RequireITSibAny(dielectroncuts.cfg_require_itsib_any); @@ -484,6 +491,7 @@ struct SingleTrackQCMC { fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("positive/hNcrTPC"), track.tpcNClsCrossedRows()); fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("positive/hTPCNcr2Nf"), track.tpcCrossedRowsOverFindableCls()); fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("positive/hTPCNcls2Nf"), track.tpcFoundOverFindableCls()); + fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("positive/hTPCNclsShared"), track.pt(), track.tpcFractionSharedCls()); fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("positive/hChi2TPC"), track.tpcChi2NCl()); fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("positive/hChi2ITS"), track.itsChi2NCl()); fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("positive/hITSClusterMap"), track.itsClusterMap()); @@ -518,6 +526,7 @@ struct SingleTrackQCMC { fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("negative/hNcrTPC"), track.tpcNClsCrossedRows()); fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("negative/hTPCNcr2Nf"), track.tpcCrossedRowsOverFindableCls()); fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("negative/hTPCNcls2Nf"), track.tpcFoundOverFindableCls()); + fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("negative/hTPCNclsShared"), track.pt(), track.tpcFractionSharedCls()); fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("negative/hChi2TPC"), track.tpcChi2NCl()); fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("negative/hChi2ITS"), track.itsChi2NCl()); fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("negative/hITSClusterMap"), track.itsClusterMap()); @@ -693,13 +702,22 @@ struct SingleTrackQCMC { // loop over mc stack and fill histograms for pure MC truth signals // all MC tracks which belong to the MC event corresponding to the current reconstructed event + std::vector used_mccollisionIds; // used mc collisionIds + used_mccollisionIds.reserve(collisions.size()); + for (auto& collision : collisions) { - float centralities[4] = {collision.centFT0M(), collision.centFT0A(), collision.centFT0C(), collision.centNTPV()}; + auto mccollision = collision.template emmcevent_as(); + if (std::find(used_mccollisionIds.begin(), used_mccollisionIds.end(), mccollision.globalIndex()) != used_mccollisionIds.end()) { + // LOGF(info, "same mc collision is repeated. continue;"); + continue; + } + used_mccollisionIds.emplace_back(mccollision.globalIndex()); + + float centralities[3] = {collision.centFT0M(), collision.centFT0A(), collision.centFT0C()}; if (centralities[cfgCentEstimator] < cfgCentMin || cfgCentMax < centralities[cfgCentEstimator]) { continue; } - auto mccollision = collision.template emmcevent_as(); // LOGF(info, "mccollision.getGeneratorId() = %d", mccollision.getGeneratorId()); // LOGF(info, "mccollision.getSubGeneratorId() = %d", mccollision.getSubGeneratorId()); // LOGF(info, "mccollision.getSourceId() = %d", mccollision.getSourceId()); @@ -783,6 +801,8 @@ struct SingleTrackQCMC { } } // end of collision loop + used_mccollisionIds.clear(); + used_mccollisionIds.shrink_to_fit(); } std::unordered_map map_weight; // map of track global index -> weight @@ -792,7 +812,7 @@ struct SingleTrackQCMC { std::vector passed_trackIds; passed_trackIds.reserve(tracks.size()); for (auto& collision : collisions) { - float centralities[4] = {collision.centFT0M(), collision.centFT0A(), collision.centFT0C(), collision.centNTPV()}; + float centralities[3] = {collision.centFT0M(), collision.centFT0A(), collision.centFT0C()}; if (centralities[cfgCentEstimator] < cfgCentMin || cfgCentMax < centralities[cfgCentEstimator]) { continue; } @@ -933,6 +953,51 @@ struct SingleTrackQCMC { } PROCESS_SWITCH(SingleTrackQCMC, processQCMC_Smeared, "run single track QC MC with smearing", false); + void processNorm(aod::EMEventNormInfos const& collisions) + { + for (auto& collision : collisions) { + fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 1.0); + if (collision.selection_bit(o2::aod::evsel::kIsTriggerTVX)) { + fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 2.0); + } + if (collision.selection_bit(o2::aod::evsel::kNoTimeFrameBorder)) { + fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 3.0); + } + if (collision.selection_bit(o2::aod::evsel::kNoITSROFrameBorder)) { + fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 4.0); + } + if (collision.selection_bit(o2::aod::evsel::kNoSameBunchPileup)) { + fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 5.0); + } + if (collision.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV)) { + fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 6.0); + } + if (collision.selection_bit(o2::aod::evsel::kIsVertexITSTPC)) { + fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 7.0); + } + if (collision.selection_bit(o2::aod::evsel::kIsVertexTRDmatched)) { + fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 8.0); + } + if (collision.selection_bit(o2::aod::evsel::kIsVertexTOFmatched)) { + fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 9.0); + } + if (collision.sel8()) { + fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 10.0); + } + if (abs(collision.posZ()) < 10.0) { + fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 11.0); + } + if (collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard)) { + fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 12.0); + } + if (!fEMEventCut.IsSelected(collision)) { + continue; + } + fRegistry.fill(HIST("Event/norm/hCollisionCounter"), o2::aod::pwgem::dilepton::utils::eventhistogram::nbin_ev); // accepted + } // end of collision loop + } + PROCESS_SWITCH(SingleTrackQCMC, processNorm, "process normalization info", false); + void processDummy(MyCollisions const&) {} PROCESS_SWITCH(SingleTrackQCMC, processDummy, "Dummy function", false); }; diff --git a/PWGEM/Dilepton/DataModel/dileptonTables.h b/PWGEM/Dilepton/DataModel/dileptonTables.h index c6b56495343..7a487529341 100644 --- a/PWGEM/Dilepton/DataModel/dileptonTables.h +++ b/PWGEM/Dilepton/DataModel/dileptonTables.h @@ -104,7 +104,12 @@ DECLARE_SOA_COLUMN(Q4yBTot, q4ybtot, float); //! DECLARE_SOA_COLUMN(SpherocityPtWeighted, spherocity_ptweighted, float); //! transverse spherocity DECLARE_SOA_COLUMN(SpherocityPtUnWeighted, spherocity_ptunweighted, float); //! transverse spherocity DECLARE_SOA_COLUMN(NtrackSpherocity, ntspherocity, int); -DECLARE_SOA_COLUMN(IsSelected, isSelected, bool); +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(PosZint16, posZint16, int16_t); //! this is only to reduce data size +DECLARE_SOA_COLUMN(NumTracksInTimeRange_int16, trackOccupancyInTimeRange_int16, 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; }); +DECLARE_SOA_DYNAMIC_COLUMN(NumTracksInTimeRange, trackOccupancyInTimeRange, [](int16_t trackOccupancyInTimeRange_int16) -> int { return (trackOccupancyInTimeRange_int16 < 0 ? -1 : static_cast(trackOccupancyInTimeRange_int16) * 100); }); DECLARE_SOA_DYNAMIC_COLUMN(Sel8, sel8, [](uint64_t selection_bit) -> bool { return (selection_bit & BIT(o2::aod::evsel::kIsTriggerTVX)) && (selection_bit & BIT(o2::aod::evsel::kNoTimeFrameBorder)) && (selection_bit & BIT(o2::aod::evsel::kNoITSROFrameBorder)); }); DECLARE_SOA_DYNAMIC_COLUMN(EP2FT0M, ep2ft0m, [](float q2x, float q2y) -> float { return std::atan2(q2y, q2x) / 2.0; }); @@ -141,13 +146,12 @@ DECLARE_SOA_TABLE(EMEventsBz, "AOD", "EMEVENTBZ", emevent::Bz); // joinable to E using EMEventBz = EMEventsBz::iterator; DECLARE_SOA_TABLE(EMEventsMult, "AOD", "EMEVENTMULT", //! event multiplicity table, joinable to EMEvents - mult::MultFT0A, mult::MultFT0C, - mult::MultTPC, mult::MultNTracksPV, mult::MultNTracksPVeta1, mult::MultNTracksPVetaHalf, + mult::MultFT0A, mult::MultFT0C, mult::MultNTracksPV, mult::MultNTracksPVeta1, mult::MultNTracksPVetaHalf, mult::IsInelGt0, mult::IsInelGt1, mult::MultFT0M); using EMEventMult = EMEventsMult::iterator; DECLARE_SOA_TABLE(EMEventsCent, "AOD", "EMEVENTCENT", //! event centrality table, joinable to EMEvents - cent::CentFT0M, cent::CentFT0A, cent::CentFT0C, cent::CentNTPV); + cent::CentFT0M, cent::CentFT0A, cent::CentFT0C); using EMEventCent = EMEventsCent::iterator; DECLARE_SOA_TABLE(EMEventsQvec, "AOD", "EMEVENTQVEC", //! event q vector table, joinable to EMEvents @@ -198,6 +202,14 @@ DECLARE_SOA_TABLE(EMEvSels, "AOD", "EMEVSEL", //! joinable to aod::Collisions emevent::IsSelected); using EMEvSel = EMEvSels::iterator; +DECLARE_SOA_TABLE(EMEoIs, "AOD", "EMEOI", //! joinable to aod::Collisions in createEMEventDilepton.cxx + emevent::IsEoI); +using EMEoI = EMEoIs::iterator; + +DECLARE_SOA_TABLE(EMEventNormInfos, "AOD", "EMEVENTNORMINFO", //! event information for normalization + o2::soa::Index<>, evsel::Alias, evsel::Selection, emevent::PosZint16, emevent::NumTracksInTimeRange_int16, emevent::PosZ, emevent::Sel8, emevent::NumTracksInTimeRange); +using EMEventNormInfo = EMEventNormInfos::iterator; + namespace emmcevent { DECLARE_SOA_COLUMN(McCollisionId, mcCollisionId, int); diff --git a/PWGEM/Dilepton/TableProducer/CMakeLists.txt b/PWGEM/Dilepton/TableProducer/CMakeLists.txt index c643adad8f1..a27e5b2674d 100644 --- a/PWGEM/Dilepton/TableProducer/CMakeLists.txt +++ b/PWGEM/Dilepton/TableProducer/CMakeLists.txt @@ -70,3 +70,8 @@ o2physics_add_dpl_workflow(event-selection PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(filter-eoi + SOURCES filterEoI.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + diff --git a/PWGEM/Dilepton/TableProducer/createEMEventDilepton.cxx b/PWGEM/Dilepton/TableProducer/createEMEventDilepton.cxx index 603c97138ff..670e1b5705c 100644 --- a/PWGEM/Dilepton/TableProducer/createEMEventDilepton.cxx +++ b/PWGEM/Dilepton/TableProducer/createEMEventDilepton.cxx @@ -37,16 +37,16 @@ using namespace o2::soa; using MyBCs = soa::Join; using MyQvectors = soa::Join; -using MyCollisions = soa::Join; -using MyCollisions_Cent = soa::Join; // centrality table has dependency on multiplicity table. +using MyCollisions = 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 = 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 = soa::Join; // centrality table has dependency on multiplicity table. using MyCollisionsMC_Cent_Qvec = soa::Join; struct CreateEMEventDilepton { @@ -56,6 +56,7 @@ struct CreateEMEventDilepton { Produces event_cent; Produces event_qvec; Produces emswtbit; + Produces event_norm_info; enum class EMEventType : int { kEvent = 0, @@ -143,11 +144,15 @@ struct CreateEMEventDilepton { continue; } } + registry.fill(HIST("hEventCounter"), 1); auto bc = collision.template foundBC_as(); initCCDB(bc); - if (!collision.isSelected()) { + int16_t occ_tmp = collision.trackOccupancyInTimeRange() < 0 ? -1 : static_cast(collision.trackOccupancyInTimeRange() / 100.f); + event_norm_info(collision.alias_raw(), collision.selection_raw(), static_cast(10.f * collision.posZ()), occ_tmp); + + if (!collision.isSelected() || !collision.isEoI()) { continue; } @@ -159,9 +164,7 @@ struct CreateEMEventDilepton { } } - // LOGF(info, "collision.multNTracksPV() = %d, collision.multFT0A() = %f, collision.multFT0C() = %f", collision.multNTracksPV(), collision.multFT0A(), collision.multFT0C()); - - registry.fill(HIST("hEventCounter"), 1); + registry.fill(HIST("hEventCounter"), 2); event(collision.globalIndex(), bc.runNumber(), bc.globalBC(), collision.alias_raw(), collision.selection_raw(), bc.timestamp(), collision.posX(), collision.posY(), collision.posZ(), @@ -169,20 +172,20 @@ struct CreateEMEventDilepton { // eventcov(collision.covXX(), collision.covXY(), collision.covXZ(), collision.covYY(), collision.covYZ(), collision.covZZ(), collision.chi2()); - event_mult(collision.multFT0A(), collision.multFT0C(), collision.multTPC(), collision.multNTracksPV(), collision.multNTracksPVeta1(), collision.multNTracksPVetaHalf()); + 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, 105.f); + 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(), collision.centNTPV()); + 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(), collision.centNTPV()); + 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; @@ -199,7 +202,7 @@ struct CreateEMEventDilepton { q2xft0m, q2yft0m, q2xft0a, q2yft0a, q2xft0c, q2yft0c, q2xbpos, q2ybpos, q2xbneg, q2ybneg, q2xbtot, q2ybtot, q3xft0m, q3yft0m, q3xft0a, q3yft0a, q3xft0c, q3yft0c, q3xbpos, q3ybpos, q3xbneg, q3ybneg, q3xbtot, q3ybtot); } else { - event_cent(105.f, 105.f, 105.f, 105.f); + event_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); diff --git a/PWGEM/Dilepton/TableProducer/filterDielectronEvent.cxx b/PWGEM/Dilepton/TableProducer/filterDielectronEvent.cxx index c68149598d0..57808f5bdc2 100644 --- a/PWGEM/Dilepton/TableProducer/filterDielectronEvent.cxx +++ b/PWGEM/Dilepton/TableProducer/filterDielectronEvent.cxx @@ -140,7 +140,7 @@ struct filterDielectronEvent { fRegistry.add("Track/hNclsITS", "number of ITS clusters", kTH1F, {{8, -0.5, 7.5}}, false); fRegistry.add("Track/hChi2ITS", "chi2/number of ITS clusters", kTH1F, {{100, 0, 10}}, false); fRegistry.add("Track/hITSClusterMap", "ITS cluster map", kTH1F, {{128, -0.5, 127.5}}, false); - fRegistry.add("Track/hMeanClusterSizeITS", "mean cluster size ITS;p_{pv} (GeV/c); on ITS #times cos(#lambda)", kTH2F, {{1000, 0, 10}, {160, 0, 16}}, false); + fRegistry.add("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, {{100, 0, 0.1}, {200, 0, 2}}, false); fRegistry.add("Pair/before/hMvsPhiV", "mee vs. phiv;#varphi_{V} (rad.);m_{ee} (GeV/c^{2})", kTH2F, {{90, 0, M_PI}, {100, 0, 0.1}}, false); fRegistry.addClone("Pair/before/", "Pair/after/"); @@ -1131,15 +1131,15 @@ struct createEMEvent2VP { using MyQvectors = soa::Join; using MyCollisions = soa::Join; - using MyCollisions_Cent = soa::Join; // centrality table has dependency on multiplicity table. + 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 = 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 = soa::Join; // centrality table has dependency on multiplicity table. using MyCollisionsMC_Cent_Qvec = soa::Join; Produces event; @@ -1218,20 +1218,20 @@ struct createEMEvent2VP { // eventcov(collision.covXX(), collision.covXY(), collision.covXZ(), collision.covYY(), collision.covYZ(), collision.covZZ(), collision.chi2()); - event_mult(collision.multFT0A(), collision.multFT0C(), collision.multTPC(), collision.multNTracksPV(), collision.multNTracksPVeta1(), collision.multNTracksPVetaHalf()); + 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, 105.f); + 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(), collision.centNTPV()); + 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(), collision.centNTPV()); + 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; @@ -1248,7 +1248,7 @@ struct createEMEvent2VP { q2xft0m, q2yft0m, q2xft0a, q2yft0a, q2xft0c, q2yft0c, q2xbpos, q2ybpos, q2xbneg, q2ybneg, q2xbtot, q2ybtot, q3xft0m, q3yft0m, q3xft0a, q3yft0a, q3xft0c, q3yft0c, q3xbpos, q3ybpos, q3xbneg, q3ybneg, q3xbtot, q3ybtot); } else { - event_cent(105.f, 105.f, 105.f, 105.f); + event_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); diff --git a/PWGEM/Dilepton/TableProducer/filterEoI.cxx b/PWGEM/Dilepton/TableProducer/filterEoI.cxx new file mode 100644 index 00000000000..ca7b524e19d --- /dev/null +++ b/PWGEM/Dilepton/TableProducer/filterEoI.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. +// +// ======================== +// +// 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" + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::soa; + +struct filterEoI { + enum SubSystem { + kElectron = 0x1, + kFwdMuon = 0x2, + }; + Produces emeoi; + + HistogramRegistry fRegistry{"output"}; + void init(o2::framework::InitContext&) + { + auto hEventCounter = fRegistry.add("hEventCounter", "hEventCounter", kTH1D, {{5, 0.5f, 5.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"); + } + + SliceCache cache; + Preslice perCollision_el = aod::emprimaryelectron::collisionId; + Preslice perCollision_mu = aod::emprimarymuon::collisionId; + + template + void selectEoI(TCollisions const& collisions, TElectrons const& electrons, TMuons const& muons) + { + for (auto& collision : collisions) { + bool does_electron_exist = false; + bool does_fwdmuon_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) { + 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) { + does_fwdmuon_exist = true; + fRegistry.fill(HIST("hEventCounter"), 3); + } + } + + if (does_electron_exist || does_fwdmuon_exist) { + fRegistry.fill(HIST("hEventCounter"), 4); + } + if (does_electron_exist && does_fwdmuon_exist) { + fRegistry.fill(HIST("hEventCounter"), 5); + } + + emeoi(does_electron_exist || does_fwdmuon_exist); + + } // end of collision loop + + } // end of selectEoI + + void process_Electron(aod::Collisions const& collisions, aod::EMPrimaryElectrons const& electrons) + { + const uint8_t sysflag = kElectron; + selectEoI(collisions, electrons, nullptr); + } + + void process_FwdMuon(aod::Collisions const& collisions, aod::EMPrimaryMuons const& muons) + { + const uint8_t sysflag = kFwdMuon; + selectEoI(collisions, nullptr, muons); + } + + 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); + } + + void processDummy(aod::Collisions const& collisions) + { + for (int i = 0; i < collisions.size(); i++) { + emeoi(true); + } + } + + 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_Electron_FwdMuon, "create filter bit for Electron, FwdMuon", false); + PROCESS_SWITCH(filterEoI, processDummy, "processDummy", true); +}; +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc, TaskName{"filter-eoi"})}; +} diff --git a/PWGEM/Dilepton/TableProducer/skimmerPrimaryElectron.cxx b/PWGEM/Dilepton/TableProducer/skimmerPrimaryElectron.cxx index bedcb5dc8d3..b075058edd5 100644 --- a/PWGEM/Dilepton/TableProducer/skimmerPrimaryElectron.cxx +++ b/PWGEM/Dilepton/TableProducer/skimmerPrimaryElectron.cxx @@ -65,6 +65,7 @@ struct skimmerPrimaryElectron { Configurable mincrossedrows{"mincrossedrows", 70, "min. crossed rows"}; Configurable min_tpc_cr_findable_ratio{"min_tpc_cr_findable_ratio", 0.8, "min. TPC Ncr/Nf ratio"}; Configurable max_mean_its_cluster_size{"max_mean_its_cluster_size", 16.f, "max. x cos(lambda)"}; // this is to suppress random combination. default 4 + 1 for skimming. + Configurable max_p_for_its_cluster_size{"max_p_for_its_cluster_size", 0.0, "its cluster size cut is applied below this p"}; 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"}; @@ -128,10 +129,11 @@ struct skimmerPrimaryElectron { 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/hTPCNclsShared", "TPC Ncls shared/Ncls;p_{T} (GeV/c);N_{cls}^{shared}/N_{cls} in TPC", kTH2F, {{1000, 0, 10}, {100, 0, 1}}, false); fRegistry.add("Track/hNclsITS", "number of ITS clusters", kTH1F, {{8, -0.5, 7.5}}, false); fRegistry.add("Track/hChi2ITS", "chi2/number of ITS clusters", kTH1F, {{100, 0, 10}}, false); fRegistry.add("Track/hITSClusterMap", "ITS cluster map", kTH1F, {{128, -0.5, 127.5}}, false); - fRegistry.add("Track/hMeanClusterSizeITS", "mean cluster size ITS; on ITS #times cos(#lambda)", kTH1F, {{32, 0, 16}}, 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); } } @@ -218,7 +220,7 @@ struct skimmerPrimaryElectron { } total_cluster_size += cluster_size_per_layer; } - if (static_cast(total_cluster_size) / static_cast(nl) * std::cos(std::atan(track.tgl())) > max_mean_its_cluster_size) { + if (static_cast(total_cluster_size) / static_cast(nl) * std::cos(std::atan(track.tgl())) > max_mean_its_cluster_size && track.p() < max_p_for_its_cluster_size) { return false; } @@ -356,7 +358,7 @@ struct skimmerPrimaryElectron { if (fillQAHistogram) { uint32_t itsClusterSizes = track.itsClusterSizes(); int total_cluster_size = 0, nl = 0; - for (unsigned int layer = 3; layer < 7; layer++) { + for (unsigned int layer = 0; layer < 7; layer++) { int cluster_size_per_layer = (itsClusterSizes >> (layer * 4)) & 0xf; if (cluster_size_per_layer > 0) { nl++; @@ -376,10 +378,11 @@ struct skimmerPrimaryElectron { 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"), static_cast(total_cluster_size) / static_cast(nl) * std::cos(std::atan(track.tgl()))); + 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()); diff --git a/PWGEM/Dilepton/TableProducer/skimmerSecondaryElectron.cxx b/PWGEM/Dilepton/TableProducer/skimmerSecondaryElectron.cxx index 09c695ef8b3..b0209e842aa 100644 --- a/PWGEM/Dilepton/TableProducer/skimmerSecondaryElectron.cxx +++ b/PWGEM/Dilepton/TableProducer/skimmerSecondaryElectron.cxx @@ -35,7 +35,7 @@ using namespace o2::framework; using namespace o2::framework::expressions; using namespace o2::constants::physics; -using MyCollisions = soa::Join; +using MyCollisions = soa::Join; using MyCollisionsMC = soa::Join; using MyTracks = soa::Join; using MyCollisions = soa::Join; -using MyCollisions_Cent = soa::Join; // centrality table has dependency on multiplicity table. +using MyCollisions_Cent = soa::Join; // centrality table has dependency on multiplicity table. using MyCollisionsMC = soa::Join; -using MyCollisionsMC_Cent = soa::Join; // centrality table has dependency on multiplicity table. +using MyCollisionsMC_Cent = soa::Join; // centrality table has dependency on multiplicity table. using MyTracks = soa::Join cfg_min_eta_track{"cfg_min_eta_track", -0.9, "min eta for single track"}; Configurable cfg_max_eta_track{"cfg_max_eta_track", +0.9, "max eta for single track"}; Configurable cfg_min_cr2findable_ratio_tpc{"cfg_min_cr2findable_ratio_tpc", 0.8, "min. TPC Ncr/Nf ratio"}; + Configurable cfg_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", 80, "min ncrossed rows"}; Configurable cfg_min_ncluster_tpc{"cfg_min_ncluster_tpc", 0, "min ncluster tpc"}; Configurable cfg_min_ncluster_its{"cfg_min_ncluster_its", 5, "min ncluster its"}; Configurable cfg_min_ncluster_itsib{"cfg_min_ncluster_itsib", 1, "min ncluster its"}; Configurable cfg_max_chi2tpc{"cfg_max_chi2tpc", 4.0, "max chi2/NclsTPC"}; Configurable cfg_max_chi2its{"cfg_max_chi2its", 5.0, "max chi2/NclsITS"}; - Configurable cfg_max_dcaxy{"cfg_max_dcaxy", 1.0, "max dca XY for single track in cm"}; - Configurable cfg_max_dcaz{"cfg_max_dcaz", 1.0, "max dca Z for single track in cm"}; + Configurable cfg_max_dcaxy{"cfg_max_dcaxy", 0.2, "max dca XY for single track in cm"}; + Configurable cfg_max_dcaz{"cfg_max_dcaz", 0.2, "max dca Z for single track in cm"}; } trackcuts; Service ccdb; @@ -495,6 +496,10 @@ struct eventQC { return false; } + if (track.tpcFractionSharedCls() > trackcuts.cfg_max_frac_shared_clusters_tpc) { + return false; + } + return true; } diff --git a/PWGEM/Dilepton/Tasks/lmeeHFCocktail.cxx b/PWGEM/Dilepton/Tasks/lmeeHFCocktail.cxx index f1b9148ab8e..69f556d778d 100644 --- a/PWGEM/Dilepton/Tasks/lmeeHFCocktail.cxx +++ b/PWGEM/Dilepton/Tasks/lmeeHFCocktail.cxx @@ -71,7 +71,7 @@ void doSingle(T& p, std::vector> hEta, std::vector cut_pt[i] && abs(eta[i]) < cut_eta[i]) { + if (pt[i] > cut_pt[i] && fabs(eta[i]) < cut_eta[i]) { hEta[i]->Fill(eta[i], weight[i]); hPt[i]->Fill(pt[i], weight[i]); hPtEta[i]->Fill(pt[i], eta[i], weight[i]); @@ -101,7 +101,7 @@ void doPair(T& p1, T& p2, std::vector> hMee, std::vector cut_pt[i] && pt2[i] > cut_pt[i] && abs(eta1[i]) < cut_eta[i] && abs(eta2[i]) < cut_eta[i]) { + if (pt1[i] > cut_pt[i] && pt2[i] > cut_pt[i] && fabs(eta1[i]) < cut_eta[i] && fabs(eta2[i]) < cut_eta[i]) { hMee[i]->Fill(mass[i], weight[i]); hMeePtee[i]->Fill(mass[i], pt[i], weight[i]); } diff --git a/PWGEM/Dilepton/Utils/EventHistograms.h b/PWGEM/Dilepton/Utils/EventHistograms.h index 410cf65120e..3223307c735 100644 --- a/PWGEM/Dilepton/Utils/EventHistograms.h +++ b/PWGEM/Dilepton/Utils/EventHistograms.h @@ -283,45 +283,46 @@ void fillEventInfo(HistogramRegistry* fRegistry, TCollision const& collision, co fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hPrfQ3FT0CQ3BNeg_CentFT0C"), collision.centFT0C(), RecoDecay::dotProd(q3ft0c, q3bneg)); fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hPrfQ3FT0CQ3BTot_CentFT0C"), collision.centFT0C(), RecoDecay::dotProd(q3ft0c, q3btot)); fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hPrfQ3FT0AQ3FT0C_CentFT0C"), collision.centFT0C(), RecoDecay::dotProd(q3ft0a, q3ft0c)); - } else if constexpr (nmod == 4) { // Q4 - std::array q4ft0m = {collision.q4xft0m(), collision.q4yft0m()}; - std::array q4ft0a = {collision.q4xft0a(), collision.q4yft0a()}; - std::array q4ft0c = {collision.q4xft0c(), collision.q4yft0c()}; - std::array q4bpos = {collision.q4xbpos(), collision.q4ybpos()}; - std::array q4bneg = {collision.q4xbneg(), collision.q4ybneg()}; - std::array q4btot = {collision.q4xbtot(), collision.q4ybtot()}; + } + // else if constexpr (nmod == 4) { // Q4 + // std::array q4ft0m = {collision.q4xft0m(), collision.q4yft0m()}; + // std::array q4ft0a = {collision.q4xft0a(), collision.q4yft0a()}; + // std::array q4ft0c = {collision.q4xft0c(), collision.q4yft0c()}; + // std::array q4bpos = {collision.q4xbpos(), collision.q4ybpos()}; + // std::array q4bneg = {collision.q4xbneg(), collision.q4ybneg()}; + // std::array q4btot = {collision.q4xbtot(), collision.q4ybtot()}; - fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hQ4xFT0M_CentFT0C"), collision.centFT0C(), collision.q4xft0m()); - fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hQ4yFT0M_CentFT0C"), collision.centFT0C(), collision.q4yft0m()); - fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hQ4xFT0A_CentFT0C"), collision.centFT0C(), collision.q4xft0a()); - fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hQ4yFT0A_CentFT0C"), collision.centFT0C(), collision.q4yft0a()); - fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hQ4xFT0C_CentFT0C"), collision.centFT0C(), collision.q4xft0c()); - fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hQ4yFT0C_CentFT0C"), collision.centFT0C(), collision.q4yft0c()); - fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hQ4xBPos_CentFT0C"), collision.centFT0C(), collision.q4xbpos()); - fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hQ4yBPos_CentFT0C"), collision.centFT0C(), collision.q4ybpos()); - fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hQ4xBNeg_CentFT0C"), collision.centFT0C(), collision.q4xbneg()); - fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hQ4yBNeg_CentFT0C"), collision.centFT0C(), collision.q4ybneg()); - fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hQ4xBTot_CentFT0C"), collision.centFT0C(), collision.q4xbtot()); - fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hQ4yBTot_CentFT0C"), collision.centFT0C(), collision.q4ybtot()); + // fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hQ4xFT0M_CentFT0C"), collision.centFT0C(), collision.q4xft0m()); + // fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hQ4yFT0M_CentFT0C"), collision.centFT0C(), collision.q4yft0m()); + // fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hQ4xFT0A_CentFT0C"), collision.centFT0C(), collision.q4xft0a()); + // fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hQ4yFT0A_CentFT0C"), collision.centFT0C(), collision.q4yft0a()); + // fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hQ4xFT0C_CentFT0C"), collision.centFT0C(), collision.q4xft0c()); + // fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hQ4yFT0C_CentFT0C"), collision.centFT0C(), collision.q4yft0c()); + // fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hQ4xBPos_CentFT0C"), collision.centFT0C(), collision.q4xbpos()); + // fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hQ4yBPos_CentFT0C"), collision.centFT0C(), collision.q4ybpos()); + // fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hQ4xBNeg_CentFT0C"), collision.centFT0C(), collision.q4xbneg()); + // fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hQ4yBNeg_CentFT0C"), collision.centFT0C(), collision.q4ybneg()); + // fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hQ4xBTot_CentFT0C"), collision.centFT0C(), collision.q4xbtot()); + // fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hQ4yBTot_CentFT0C"), collision.centFT0C(), collision.q4ybtot()); - fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hEP4FT0M_CentFT0C"), collision.centFT0C(), collision.ep4ft0m()); - fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hEP4FT0A_CentFT0C"), collision.centFT0C(), collision.ep4ft0a()); - fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hEP4FT0C_CentFT0C"), collision.centFT0C(), collision.ep4ft0c()); - fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hEP4BPos_CentFT0C"), collision.centFT0C(), collision.ep4bpos()); - fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hEP4BNeg_CentFT0C"), collision.centFT0C(), collision.ep4bneg()); - fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hEP4BTot_CentFT0C"), collision.centFT0C(), collision.ep4btot()); + // fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hEP4FT0M_CentFT0C"), collision.centFT0C(), collision.ep4ft0m()); + // fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hEP4FT0A_CentFT0C"), collision.centFT0C(), collision.ep4ft0a()); + // fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hEP4FT0C_CentFT0C"), collision.centFT0C(), collision.ep4ft0c()); + // fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hEP4BPos_CentFT0C"), collision.centFT0C(), collision.ep4bpos()); + // fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hEP4BNeg_CentFT0C"), collision.centFT0C(), collision.ep4bneg()); + // fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hEP4BTot_CentFT0C"), collision.centFT0C(), collision.ep4btot()); - fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hPrfQ4FT0MQ4BPos_CentFT0C"), collision.centFT0C(), RecoDecay::dotProd(q4ft0m, q4bpos)); - fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hPrfQ4FT0MQ4BNeg_CentFT0C"), collision.centFT0C(), RecoDecay::dotProd(q4ft0m, q4bneg)); - fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hPrfQ4BPosQ4BNeg_CentFT0C"), collision.centFT0C(), RecoDecay::dotProd(q4bpos, q4bneg)); - fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hPrfQ4FT0AQ4BPos_CentFT0C"), collision.centFT0C(), RecoDecay::dotProd(q4ft0a, q4bpos)); - fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hPrfQ4FT0AQ4BNeg_CentFT0C"), collision.centFT0C(), RecoDecay::dotProd(q4ft0a, q4bneg)); - fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hPrfQ4FT0AQ4BTot_CentFT0C"), collision.centFT0C(), RecoDecay::dotProd(q4ft0a, q4btot)); - fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hPrfQ4FT0CQ4BPos_CentFT0C"), collision.centFT0C(), RecoDecay::dotProd(q4ft0c, q4bpos)); - fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hPrfQ4FT0CQ4BNeg_CentFT0C"), collision.centFT0C(), RecoDecay::dotProd(q4ft0c, q4bneg)); - fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hPrfQ4FT0CQ4BTot_CentFT0C"), collision.centFT0C(), RecoDecay::dotProd(q4ft0c, q4btot)); - fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hPrfQ4FT0AQ4FT0C_CentFT0C"), collision.centFT0C(), RecoDecay::dotProd(q4ft0a, q4ft0c)); - } + // fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hPrfQ4FT0MQ4BPos_CentFT0C"), collision.centFT0C(), RecoDecay::dotProd(q4ft0m, q4bpos)); + // fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hPrfQ4FT0MQ4BNeg_CentFT0C"), collision.centFT0C(), RecoDecay::dotProd(q4ft0m, q4bneg)); + // fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hPrfQ4BPosQ4BNeg_CentFT0C"), collision.centFT0C(), RecoDecay::dotProd(q4bpos, q4bneg)); + // fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hPrfQ4FT0AQ4BPos_CentFT0C"), collision.centFT0C(), RecoDecay::dotProd(q4ft0a, q4bpos)); + // fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hPrfQ4FT0AQ4BNeg_CentFT0C"), collision.centFT0C(), RecoDecay::dotProd(q4ft0a, q4bneg)); + // fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hPrfQ4FT0AQ4BTot_CentFT0C"), collision.centFT0C(), RecoDecay::dotProd(q4ft0a, q4btot)); + // fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hPrfQ4FT0CQ4BPos_CentFT0C"), collision.centFT0C(), RecoDecay::dotProd(q4ft0c, q4bpos)); + // fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hPrfQ4FT0CQ4BNeg_CentFT0C"), collision.centFT0C(), RecoDecay::dotProd(q4ft0c, q4bneg)); + // fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hPrfQ4FT0CQ4BTot_CentFT0C"), collision.centFT0C(), RecoDecay::dotProd(q4ft0c, q4btot)); + // fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hPrfQ4FT0AQ4FT0C_CentFT0C"), collision.centFT0C(), RecoDecay::dotProd(q4ft0a, q4ft0c)); + // } } } // namespace o2::aod::pwgem::dilepton::utils::eventhistogram diff --git a/PWGEM/PhotonMeson/Core/Pi0EtaToGammaGamma.h b/PWGEM/PhotonMeson/Core/Pi0EtaToGammaGamma.h index 395e338e655..00475bd4885 100644 --- a/PWGEM/PhotonMeson/Core/Pi0EtaToGammaGamma.h +++ b/PWGEM/PhotonMeson/Core/Pi0EtaToGammaGamma.h @@ -424,8 +424,8 @@ struct Pi0EtaToGammaGamma { fEMCCut.SetM02Range(emccuts.EMC_minM02, emccuts.EMC_maxM02); fEMCCut.SetTimeRange(emccuts.EMC_minTime, emccuts.EMC_maxTime); - fEMCCut.SetTrackMatchingEta([&a, &b, &c](float pT) { return a + pow(pT + b, c); }); - fEMCCut.SetTrackMatchingPhi([&d, &e, &f](float pT) { return d + pow(pT + e, f); }); + fEMCCut.SetTrackMatchingEta([a, b, c](float pT) { return a + pow(pT + b, c); }); + fEMCCut.SetTrackMatchingPhi([d, e, f](float pT) { return d + pow(pT + e, f); }); fEMCCut.SetMinEoverP(emccuts.EMC_Eoverp); fEMCCut.SetUseExoticCut(emccuts.EMC_UseExoticCut); diff --git a/PWGEM/PhotonMeson/Core/Pi0EtaToGammaGammaMC.h b/PWGEM/PhotonMeson/Core/Pi0EtaToGammaGammaMC.h index f1001c2d20c..0dda29e4d24 100644 --- a/PWGEM/PhotonMeson/Core/Pi0EtaToGammaGammaMC.h +++ b/PWGEM/PhotonMeson/Core/Pi0EtaToGammaGammaMC.h @@ -391,8 +391,8 @@ struct Pi0EtaToGammaGammaMC { fEMCCut.SetM02Range(emccuts.EMC_minM02, emccuts.EMC_maxM02); fEMCCut.SetTimeRange(emccuts.EMC_minTime, emccuts.EMC_maxTime); - fEMCCut.SetTrackMatchingEta([&a, &b, &c](float pT) { return a + pow(pT + b, c); }); - fEMCCut.SetTrackMatchingPhi([&d, &e, &f](float pT) { return d + pow(pT + e, f); }); + fEMCCut.SetTrackMatchingEta([a, b, c](float pT) { return a + pow(pT + b, c); }); + fEMCCut.SetTrackMatchingPhi([d, e, f](float pT) { return d + pow(pT + e, f); }); fEMCCut.SetMinEoverP(emccuts.EMC_Eoverp); fEMCCut.SetUseExoticCut(emccuts.EMC_UseExoticCut); diff --git a/PWGEM/PhotonMeson/Core/V0PhotonCut.cxx b/PWGEM/PhotonMeson/Core/V0PhotonCut.cxx index bceee717d76..9c369df9514 100644 --- a/PWGEM/PhotonMeson/Core/V0PhotonCut.cxx +++ b/PWGEM/PhotonMeson/Core/V0PhotonCut.cxx @@ -18,8 +18,6 @@ ClassImp(V0PhotonCut); -const char* V0PhotonCut::mCutNames[static_cast(V0PhotonCut::V0PhotonCuts::kNCuts)] = {"Mee", "V0PtRange", "V0EtaRange", "AP", " PsiPair", "PhivPair", "Rxy", "CosPA", "PCA", "RZLine", "OnWwireIB", "OnWwireOB", "TrackPtRange", "TrackEtaRange", "TPCNCls", "TPCCrossedRows", "TPCCrossedRowsOverNCls", "TPCChi2NDF", "TPCNsigmaEl", "TPCNsigmaPi", "DCAxy", "DCAz", "ITSNCls", "ITSChi2NDF", "IsWithinBeamPipe", "RequireITSTPC", "RequireITSonly", "RequireTPConly", "RequireTPCTRD", "RequireTPCTOF", "RequireTPCTRDTOF"}; - const std::pair> V0PhotonCut::its_ib_Requirement = {0, {0, 1, 2}}; // no hit on 3 ITS ib layers. const std::pair> V0PhotonCut::its_ob_Requirement = {4, {3, 4, 5, 6}}; // all hits on 4 ITS ob layers. const std::pair> V0PhotonCut::its_ob_Requirement_ITSTPC = {2, {3, 4, 5, 6}}; // at least 2 hits on 4 ITS ob layers. @@ -140,6 +138,11 @@ void V0PhotonCut::SetMinNCrossedRowsOverFindableClustersTPC(float minNCrossedRow mMinNCrossedRowsOverFindableClustersTPC = minNCrossedRowsOverFindableClustersTPC; LOG(info) << "V0 Photon Cut, set min N crossed rows over findable clusters TPC: " << mMinNCrossedRowsOverFindableClustersTPC; } +void V0PhotonCut::SetMaxFracSharedClustersTPC(float max) +{ + mMaxFracSharedClustersTPC = max; + LOG(info) << "V0 Photon Cut, set max fraction of shared clusters in TPC: " << mMaxFracSharedClustersTPC; +} void V0PhotonCut::SetChi2PerClusterTPC(float min, float max) { mMinChi2PerClusterTPC = min; @@ -229,38 +232,3 @@ void V0PhotonCut::SetDisableITSonly(bool flag) mDisableITSonly = flag; LOG(info) << "V0 Photon Cut, disable ITS only track: " << mDisableITSonly; } - -void V0PhotonCut::print() const -{ - LOG(info) << "V0 Photon Cut:"; - for (int i = 0; i < static_cast(V0PhotonCuts::kNCuts); i++) { - switch (static_cast(i)) { - case V0PhotonCuts::kTrackPtRange: - LOG(info) << mCutNames[i] << " in [" << mMinTrackPt << ", " << mMaxTrackPt << "]"; - break; - case V0PhotonCuts::kTrackEtaRange: - LOG(info) << mCutNames[i] << " in [" << mMinTrackEta << ", " << mMaxTrackEta << "]"; - break; - case V0PhotonCuts::kTPCNCls: - LOG(info) << mCutNames[i] << " > " << mMinNClustersTPC; - break; - case V0PhotonCuts::kTPCCrossedRows: - LOG(info) << mCutNames[i] << " > " << mMinNCrossedRowsTPC; - break; - case V0PhotonCuts::kTPCCrossedRowsOverNCls: - LOG(info) << mCutNames[i] << " > " << mMinNCrossedRowsOverFindableClustersTPC; - break; - case V0PhotonCuts::kTPCChi2NDF: - LOG(info) << mCutNames[i] << " < " << mMaxChi2PerClusterTPC; - break; - case V0PhotonCuts::kDCAxy: - LOG(info) << mCutNames[i] << " < " << mMaxDcaXY; - break; - case V0PhotonCuts::kDCAz: - LOG(info) << mCutNames[i] << " < " << mMaxDcaZ; - break; - default: - LOG(fatal) << "Cut unknown!"; - } - } -} diff --git a/PWGEM/PhotonMeson/Core/V0PhotonCut.h b/PWGEM/PhotonMeson/Core/V0PhotonCut.h index 55e9718e156..2acd533d14f 100644 --- a/PWGEM/PhotonMeson/Core/V0PhotonCut.h +++ b/PWGEM/PhotonMeson/Core/V0PhotonCut.h @@ -54,6 +54,7 @@ class V0PhotonCut : public TNamed kTPCNCls, kTPCCrossedRows, kTPCCrossedRowsOverNCls, + kTPCFracSharedClusters, kTPCChi2NDF, kTPCNsigmaEl, kTPCNsigmaPi, @@ -72,8 +73,6 @@ class V0PhotonCut : public TNamed kNCuts }; - static const char* mCutNames[static_cast(V0PhotonCuts::kNCuts)]; - template bool IsSelected(TV0 const& v0) const { @@ -226,6 +225,9 @@ class V0PhotonCut : public TNamed if (!IsSelectedTrack(track, V0PhotonCuts::kTPCCrossedRowsOverNCls)) { return false; } + if (!IsSelectedTrack(track, V0PhotonCuts::kTPCFracSharedClusters)) { + return false; + } if (!IsSelectedTrack(track, V0PhotonCuts::kTPCChi2NDF)) { return false; } @@ -238,31 +240,6 @@ class V0PhotonCut : public TNamed return true; } - template - uint32_t IsSelectedMask(T const& track) const - { - uint32_t flag = 0; - - auto setFlag = [&](const V0PhotonCuts& cut) { - if (IsSelectedTrack(track, cut)) { - flag |= 1UL << static_cast(cut); - } - }; - - setFlag(V0PhotonCuts::kV0PtRange); - setFlag(V0PhotonCuts::kV0EtaRange); - setFlag(V0PhotonCuts::kTrackPtRange); - setFlag(V0PhotonCuts::kTrackEtaRange); - setFlag(V0PhotonCuts::kTPCNCls); - setFlag(V0PhotonCuts::kTPCCrossedRows); - setFlag(V0PhotonCuts::kTPCCrossedRowsOverNCls); - setFlag(V0PhotonCuts::kTPCChi2NDF); - setFlag(V0PhotonCuts::kDCAxy); - setFlag(V0PhotonCuts::kDCAz); - - return flag; - } - template bool IsSelectedV0(T const& v0, const V0PhotonCuts& cut) const { @@ -374,6 +351,9 @@ class V0PhotonCut : public TNamed case V0PhotonCuts::kTPCCrossedRowsOverNCls: return track.tpcCrossedRowsOverFindableCls() >= mMinNCrossedRowsOverFindableClustersTPC; + case V0PhotonCuts::kTPCFracSharedClusters: + return track.tpcFractionSharedCls() <= mMaxFracSharedClustersTPC; + case V0PhotonCuts::kTPCChi2NDF: return mMinChi2PerClusterTPC < track.tpcChi2NCl() && track.tpcChi2NCl() < mMaxChi2PerClusterTPC; @@ -468,6 +448,7 @@ class V0PhotonCut : public TNamed 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); @@ -488,9 +469,6 @@ class V0PhotonCut : public TNamed void SetRequireTPCTRDTOF(bool flag); void SetDisableITSonly(bool flag); - /// @brief Print the track selection - void print() const; - private: static const std::pair> its_ib_Requirement; static const std::pair> its_ob_Requirement; @@ -524,6 +502,7 @@ class V0PhotonCut : public TNamed int mMinNCrossedRowsTPC{0}; // min number of crossed rows in TPC float mMinChi2PerClusterTPC{-1e10f}, mMaxChi2PerClusterTPC{1e10f}; // max tpc fit chi2 per TPC cluster float mMinNCrossedRowsOverFindableClustersTPC{0.f}; // min ratio crossed rows / findable clusters + float mMaxFracSharedClustersTPC{999.f}; // max ratio shared clusters / clusters in TPC int mMinNClustersITS{0}, mMaxNClustersITS{7}; // range in number of ITS clusters float mMinChi2PerClusterITS{-1e10f}, mMaxChi2PerClusterITS{1e10f}; // max its fit chi2 per ITS cluster float mMinMeanClusterSizeITS{-1e10f}, mMaxMeanClusterSizeITS{1e10f}; // max x cos(Lmabda) diff --git a/PWGEM/PhotonMeson/TableProducer/createEMEventPhoton.cxx b/PWGEM/PhotonMeson/TableProducer/createEMEventPhoton.cxx index 9e331503783..f6398d11929 100644 --- a/PWGEM/PhotonMeson/TableProducer/createEMEventPhoton.cxx +++ b/PWGEM/PhotonMeson/TableProducer/createEMEventPhoton.cxx @@ -36,11 +36,11 @@ 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 = soa::Join; // centrality table has dependency on multiplicity table. using MyCollisions_Cent_Qvec = soa::Join; using MyCollisionsMC = soa::Join; -using MyCollisionsMC_Cent = soa::Join; // centrality table has dependency on multiplicity table. +using MyCollisionsMC_Cent = soa::Join; // centrality table has dependency on multiplicity table. using MyCollisionsMC_Cent_Qvec = soa::Join; struct CreateEMEvent { @@ -158,7 +158,7 @@ struct CreateEMEvent { eventcov(collision.covXX(), collision.covXY(), collision.covXZ(), collision.covYY(), collision.covYZ(), collision.covZZ(), collision.chi2()); - event_mult(collision.multFT0A(), collision.multFT0C(), collision.multTPC(), collision.multNTracksPV(), collision.multNTracksPVeta1(), collision.multNTracksPVetaHalf()); + event_mult(collision.multFT0A(), collision.multFT0C(), collision.multNTracksPV(), collision.multNTracksPVeta1(), collision.multNTracksPVetaHalf()); if constexpr (eventype != EMEventType::kEvent_JJ) { event_weights(1.f); @@ -168,15 +168,15 @@ struct CreateEMEvent { float q3xft0m = 999.f, q3yft0m = 999.f, q3xft0a = 999.f, q3yft0a = 999.f, q3xft0c = 999.f, q3yft0c = 999.f, q3xbpos = 999.f, q3ybpos = 999.f, q3xbneg = 999.f, q3ybneg = 999.f, q3xbtot = 999.f, q3ybtot = 999.f; if constexpr (eventype == EMEventType::kEvent) { - event_cent(105.f, 105.f, 105.f, 105.f); + event_cent(105.f, 105.f, 105.f); event_qvec(q2xft0m, q2yft0m, q2xft0a, q2yft0a, q2xft0c, q2yft0c, q2xbpos, q2ybpos, q2xbneg, q2ybneg, q2xbtot, q2ybtot, q3xft0m, q3yft0m, q3xft0a, q3yft0a, q3xft0c, q3yft0c, q3xbpos, q3ybpos, q3xbneg, q3ybneg, q3xbtot, q3ybtot); } else if constexpr (eventype == EMEventType::kEvent_Cent) { - event_cent(collision.centFT0M(), collision.centFT0A(), collision.centFT0C(), collision.centNTPV()); + event_cent(collision.centFT0M(), collision.centFT0A(), collision.centFT0C()); event_qvec(q2xft0m, q2yft0m, q2xft0a, q2yft0a, q2xft0c, q2yft0c, q2xbpos, q2ybpos, q2xbneg, q2ybneg, q2xbtot, q2ybtot, q3xft0m, q3yft0m, q3xft0a, q3yft0a, q3xft0c, q3yft0c, q3xbpos, q3ybpos, q3xbneg, q3ybneg, q3xbtot, q3ybtot); } else if constexpr (eventype == EMEventType::kEvent_Cent_Qvec) { - event_cent(collision.centFT0M(), collision.centFT0A(), collision.centFT0C(), collision.centNTPV()); + event_cent(collision.centFT0M(), collision.centFT0A(), collision.centFT0C()); 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]; @@ -190,7 +190,7 @@ struct CreateEMEvent { event_qvec(q2xft0m, q2yft0m, q2xft0a, q2yft0a, q2xft0c, q2yft0c, q2xbpos, q2ybpos, q2xbneg, q2ybneg, q2xbtot, q2ybtot, q3xft0m, q3yft0m, q3xft0a, q3yft0a, q3xft0c, q3yft0c, q3xbpos, q3ybpos, q3xbneg, q3ybneg, q3xbtot, q3ybtot); } else { - event_cent(105.f, 105.f, 105.f, 105.f); + event_cent(105.f, 105.f, 105.f); event_qvec(q2xft0m, q2yft0m, q2xft0a, q2yft0a, q2xft0c, q2yft0c, q2xbpos, q2ybpos, q2xbneg, q2ybneg, q2xbtot, q2ybtot, q3xft0m, q3yft0m, q3xft0a, q3yft0a, q3xft0c, q3yft0c, q3xbpos, q3ybpos, q3xbneg, q3ybneg, q3xbtot, q3ybtot); } @@ -198,7 +198,7 @@ struct CreateEMEvent { map_ncolls_per_bc.clear(); } // end of skimEvent - void fillEventWeights(MyCollisionsMC const& collisions, aod::McCollisions const&, MyBCs const& bcs) + void fillEventWeights(MyCollisionsMC const& collisions, aod::McCollisions const&, MyBCs const&) { for (auto& collision : collisions) { if (!collision.has_mcCollision()) { diff --git a/PWGEM/PhotonMeson/TableProducer/skimmerGammaCalo.cxx b/PWGEM/PhotonMeson/TableProducer/skimmerGammaCalo.cxx index 68e6d26ddfb..5990d1b1c74 100644 --- a/PWGEM/PhotonMeson/TableProducer/skimmerGammaCalo.cxx +++ b/PWGEM/PhotonMeson/TableProducer/skimmerGammaCalo.cxx @@ -152,8 +152,6 @@ struct skimmerGammaCalo { return; } for (const auto& emccluster : emcclusters) { - historeg.fill(HIST("hCaloClusterEIn"), emccluster.energy()); - historeg.fill(HIST("hCaloClusterFilter"), 0); // Energy cut if (emccluster.energy() < minE) { diff --git a/PWGEM/PhotonMeson/Tasks/SinglePhoton.cxx b/PWGEM/PhotonMeson/Tasks/SinglePhoton.cxx index ddf61e9765e..9c82fa7b09a 100644 --- a/PWGEM/PhotonMeson/Tasks/SinglePhoton.cxx +++ b/PWGEM/PhotonMeson/Tasks/SinglePhoton.cxx @@ -228,10 +228,10 @@ struct SinglePhoton { custom_cut->SetM02Range(EMC_minM02, EMC_maxM02); custom_cut->SetTimeRange(EMC_minTime, EMC_maxTime); - custom_cut->SetTrackMatchingEta([&a, &b, &c](float pT) { + custom_cut->SetTrackMatchingEta([a, b, c](float pT) { return a + pow(pT + b, c); }); - custom_cut->SetTrackMatchingPhi([&d, &e, &f](float pT) { + custom_cut->SetTrackMatchingPhi([d, e, f](float pT) { return d + pow(pT + e, f); }); @@ -331,8 +331,8 @@ struct SinglePhoton { reinterpret_cast(list_photon_det_cut->FindObject("hY"))->Fill(photon.eta()); reinterpret_cast(list_photon_det_cut->FindObject("hPhi"))->Fill(photon.phi()); } // 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. diff --git a/PWGEM/PhotonMeson/Tasks/TaggingPi0.cxx b/PWGEM/PhotonMeson/Tasks/TaggingPi0.cxx index f12cf270290..4d00ddb1a21 100644 --- a/PWGEM/PhotonMeson/Tasks/TaggingPi0.cxx +++ b/PWGEM/PhotonMeson/Tasks/TaggingPi0.cxx @@ -313,10 +313,10 @@ struct TaggingPi0 { custom_cut->SetM02Range(EMC_minM02, EMC_maxM02); custom_cut->SetTimeRange(EMC_minTime, EMC_maxTime); - custom_cut->SetTrackMatchingEta([&a, &b, &c](float pT) { + custom_cut->SetTrackMatchingEta([a, b, c](float pT) { return a + pow(pT + b, c); }); - custom_cut->SetTrackMatchingPhi([&d, &e, &f](float pT) { + custom_cut->SetTrackMatchingPhi([d, e, f](float pT) { return d + pow(pT + e, f); }); diff --git a/PWGEM/PhotonMeson/Tasks/TaggingPi0MC.cxx b/PWGEM/PhotonMeson/Tasks/TaggingPi0MC.cxx index 3cf8a46a2b0..335e8195d8b 100644 --- a/PWGEM/PhotonMeson/Tasks/TaggingPi0MC.cxx +++ b/PWGEM/PhotonMeson/Tasks/TaggingPi0MC.cxx @@ -330,10 +330,10 @@ struct TaggingPi0MC { custom_cut->SetM02Range(EMC_minM02, EMC_maxM02); custom_cut->SetTimeRange(EMC_minTime, EMC_maxTime); - custom_cut->SetTrackMatchingEta([&a, &b, &c](float pT) { + custom_cut->SetTrackMatchingEta([a, b, c](float pT) { return a + pow(pT + b, c); }); - custom_cut->SetTrackMatchingPhi([&d, &e, &f](float pT) { + custom_cut->SetTrackMatchingPhi([d, e, f](float pT) { return d + pow(pT + e, f); }); diff --git a/PWGEM/PhotonMeson/Tasks/emcalQC.cxx b/PWGEM/PhotonMeson/Tasks/emcalQC.cxx index ded5abf9c70..0669017704c 100644 --- a/PWGEM/PhotonMeson/Tasks/emcalQC.cxx +++ b/PWGEM/PhotonMeson/Tasks/emcalQC.cxx @@ -119,8 +119,8 @@ struct emcalQC { fEMCCut.SetM02Range(emccuts.EMC_minM02, emccuts.EMC_maxM02); fEMCCut.SetTimeRange(emccuts.EMC_minTime, emccuts.EMC_maxTime); - fEMCCut.SetTrackMatchingEta([&a, &b, &c](float pT) { return a + pow(pT + b, c); }); - fEMCCut.SetTrackMatchingPhi([&d, &e, &f](float pT) { return d + pow(pT + e, f); }); + fEMCCut.SetTrackMatchingEta([a, b, c](float pT) { return a + pow(pT + b, c); }); + fEMCCut.SetTrackMatchingPhi([d, e, f](float pT) { return d + pow(pT + e, f); }); fEMCCut.SetMinEoverP(emccuts.EMC_Eoverp); fEMCCut.SetUseExoticCut(emccuts.EMC_UseExoticCut); diff --git a/PWGEM/PhotonMeson/Tasks/pcmQC.cxx b/PWGEM/PhotonMeson/Tasks/pcmQC.cxx index 64d106ff78e..f5ab18bc572 100644 --- a/PWGEM/PhotonMeson/Tasks/pcmQC.cxx +++ b/PWGEM/PhotonMeson/Tasks/pcmQC.cxx @@ -78,6 +78,7 @@ struct PCMQC { 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_min_TPCNsigmaEl{"cfg_min_TPCNsigmaEl", -3.0, "min. TPC n sigma for electron"}; @@ -203,6 +204,7 @@ struct PCMQC { 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); diff --git a/PWGEM/PhotonMeson/Tasks/pcmQCMC.cxx b/PWGEM/PhotonMeson/Tasks/pcmQCMC.cxx index 656c0a7442c..c0a6bfa5943 100644 --- a/PWGEM/PhotonMeson/Tasks/pcmQCMC.cxx +++ b/PWGEM/PhotonMeson/Tasks/pcmQCMC.cxx @@ -49,7 +49,7 @@ using MyMCV0Leg = MyMCV0Legs::iterator; struct PCMQCMC { - Configurable cfgCentEstimator{"cfgCentEstimator", 2, "FT0M:0, FT0A:1, FT0C:2, NTPV:3"}; + Configurable cfgCentEstimator{"cfgCentEstimator", 2, "FT0M:0, FT0A:1, FT0C:2"}; Configurable cfgCentMin{"cfgCentMin", 0, "min. centrality"}; Configurable cfgCentMax{"cfgCentMax", 999.f, "max. centrality"}; @@ -92,6 +92,7 @@ struct PCMQCMC { 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_min_TPCNsigmaEl{"cfg_min_TPCNsigmaEl", -3.0, "min. TPC n sigma for electron"}; @@ -260,6 +261,7 @@ struct PCMQCMC { 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); @@ -410,7 +412,7 @@ struct PCMQCMC { void processQCMC(FilteredMyCollisions const& collisions, MyV0Photons const& v0photons, MyMCV0Legs const&, aod::EMMCParticles const& mcparticles, aod::EMMCEvents const&) { for (auto& collision : collisions) { - const float centralities[4] = {collision.centFT0M(), collision.centFT0A(), collision.centFT0C(), collision.centNTPV()}; + const float centralities[3] = {collision.centFT0M(), collision.centFT0A(), collision.centFT0C()}; if (centralities[cfgCentEstimator] < cfgCentMin || cfgCentMax < centralities[cfgCentEstimator]) { continue; } @@ -500,7 +502,7 @@ struct PCMQCMC { // all MC tracks which belong to the MC event corresponding to the current reconstructed event for (auto& collision : collisions) { - const float centralities[4] = {collision.centFT0M(), collision.centFT0A(), collision.centFT0C(), collision.centNTPV()}; + const float centralities[3] = {collision.centFT0M(), collision.centFT0A(), collision.centFT0C()}; if (centralities[cfgCentEstimator] < cfgCentMin || cfgCentMax < centralities[cfgCentEstimator]) { continue; } diff --git a/PWGHF/Core/HfMlResponseB0ToDPi.h b/PWGHF/Core/HfMlResponseB0ToDPi.h index 08853a21eac..18584ae5258 100644 --- a/PWGHF/Core/HfMlResponseB0ToDPi.h +++ b/PWGHF/Core/HfMlResponseB0ToDPi.h @@ -21,6 +21,7 @@ #include #include "PWGHF/Core/HfMlResponse.h" +#include "PWGHF/D2H/Utils/utilsRedDataFormat.h" // Fill the map of available input features // the key is the feature's name (std::string) @@ -58,31 +59,6 @@ break; \ } -namespace o2::pid_tpc_tof_utils -{ -template -float getTpcTofNSigmaPi1(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.tpcNSigmaPi(); - float tofNSigma = prong1.tofNSigmaPi(); - return sqrt(.5f * tpcNSigma * tpcNSigma + .5f * tofNSigma * tofNSigma); - } - if (hasTpc) { - return abs(prong1.tpcNSigmaPi()); - } - if (hasTof) { - return abs(prong1.tofNSigmaPi()); - } - return defaultNSigma; -} -} // namespace o2::pid_tpc_tof_utils - namespace o2::analysis { diff --git a/PWGHF/Core/HfMlResponseBplusToD0Pi.h b/PWGHF/Core/HfMlResponseBplusToD0Pi.h index 8d47d4ade89..8a3b3875dae 100644 --- a/PWGHF/Core/HfMlResponseBplusToD0Pi.h +++ b/PWGHF/Core/HfMlResponseBplusToD0Pi.h @@ -21,6 +21,7 @@ #include #include "PWGHF/Core/HfMlResponse.h" +#include "PWGHF/D2H/Utils/utilsRedDataFormat.h" // Fill the map of available input features // the key is the feature's name (std::string) @@ -58,31 +59,6 @@ break; \ } -namespace o2::pid_tpc_tof_utils -{ -template -float getTpcTofNSigmaPi1(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.tpcNSigmaPi(); - float tofNSigma = prong1.tofNSigmaPi(); - return sqrt(.5f * tpcNSigma * tpcNSigma + .5f * tofNSigma * tofNSigma); - } - if (hasTpc) { - return abs(prong1.tpcNSigmaPi()); - } - if (hasTof) { - return abs(prong1.tofNSigmaPi()); - } - return defaultNSigma; -} -} // namespace o2::pid_tpc_tof_utils - namespace o2::analysis { diff --git a/PWGHF/Core/HfMlResponseBsToDsPi.h b/PWGHF/Core/HfMlResponseBsToDsPi.h new file mode 100644 index 00000000000..821463e0ec8 --- /dev/null +++ b/PWGHF/Core/HfMlResponseBsToDsPi.h @@ -0,0 +1,191 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does 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 HfMlResponsBsToDsPi.h +/// \brief Class to compute the ML response for Bs → Ds∓ π± analysis selections +/// \author Fabio Catalano , CERN + +#ifndef PWGHF_CORE_HFMLRESPONSEBSTODSPI_H_ +#define PWGHF_CORE_HFMLRESPONSEBSTODSPI_H_ + +#include +#include +#include + +#include "PWGHF/Core/HfMlResponse.h" +#include "PWGHF/D2H/Utils/utilsRedDataFormat.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 +#define FILL_MAP_BS(FEATURE) \ + { \ + #FEATURE, static_cast(InputFeaturesBsToDsPi::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(InputFeaturesBsToDsPi::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(InputFeaturesBsToDsPi::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(InputFeaturesBsToDsPi::GETTER): { \ + inputFeatures.emplace_back(candidate.GETTER()); \ + break; \ + } + +namespace o2::analysis +{ + +enum class InputFeaturesBsToDsPi : uint8_t { + ptProng0 = 0, + ptProng1, + impactParameter0, + impactParameter1, + impactParameterProduct, + chi2PCA, + decayLength, + decayLengthXY, + decayLengthNormalised, + decayLengthXYNormalised, + cpa, + cpaXY, + maxNormalisedDeltaIP, + prong0MlScoreBkg, + prong0MlScorePrompt, + prong0MlScoreNonprompt, + tpcNSigmaPi1, + tofNSigmaPi1, + tpcTofNSigmaPi1 +}; + +template +class HfMlResponseBsToDsPi : public HfMlResponse +{ + public: + /// Default constructor + HfMlResponseBsToDsPi() = default; + /// Default destructor + virtual ~HfMlResponseBsToDsPi() = 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) + { + std::vector inputFeatures; + + for (const auto& idx : MlResponse::mCachedIndices) { + if constexpr (withDmesMl) { + 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(impactParameterProduct); + 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(prong0MlScoreBkg); + CHECK_AND_FILL_VEC_BS(prong0MlScorePrompt); + CHECK_AND_FILL_VEC_BS(prong0MlScoreNonprompt); + // Pion PID variables + CHECK_AND_FILL_VEC_BS_FULL(prong1, tpcNSigmaPi1, tpcNSigmaPi); + CHECK_AND_FILL_VEC_BS_FULL(prong1, tofNSigmaPi1, tofNSigmaPi); + CHECK_AND_FILL_VEC_BS_FUNC(prong1, tpcTofNSigmaPi1, o2::pid_tpc_tof_utils::getTpcTofNSigmaPi1); + } + } else { + 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(impactParameterProduct); + 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); + // Pion PID variables + CHECK_AND_FILL_VEC_BS_FULL(prong1, tpcNSigmaPi1, tpcNSigmaPi); + CHECK_AND_FILL_VEC_BS_FULL(prong1, tofNSigmaPi1, tofNSigmaPi); + CHECK_AND_FILL_VEC_BS_FUNC(prong1, tpcTofNSigmaPi1, o2::pid_tpc_tof_utils::getTpcTofNSigmaPi1); + } + } + } + + 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(impactParameterProduct), + 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(prong0MlScoreBkg), + FILL_MAP_BS(prong0MlScorePrompt), + FILL_MAP_BS(prong0MlScoreNonprompt), + // Pion PID variables + FILL_MAP_BS(tpcNSigmaPi1), + FILL_MAP_BS(tofNSigmaPi1), + FILL_MAP_BS(tpcTofNSigmaPi1)}; + } +}; + +} // 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_HFMLRESPONSEBSTODSPI_H_ diff --git a/PWGHF/Core/HfMlResponseDsToKKPi.h b/PWGHF/Core/HfMlResponseDsToKKPi.h index 62e93882ddf..1b27d52adde 100644 --- a/PWGHF/Core/HfMlResponseDsToKKPi.h +++ b/PWGHF/Core/HfMlResponseDsToKKPi.h @@ -68,6 +68,19 @@ break; \ } +// Variation of CHECK_AND_FILL_VEC_DS_HFHELPER(OBJECT, FEATURE, GETTER) +// where OBJECT1 and OBJECT2 are the objects from which we call the GETTER method, and the variable +// is filled depending on whether it is a DsToKKPi or a DsToPiKK +#define CHECK_AND_FILL_VEC_DS_OBJECT_SIGNED(OBJECT1, OBJECT2, FEATURE, GETTER) \ + case static_cast(InputFeaturesDsToKKPi::FEATURE): { \ + if (caseDsToKKPi) { \ + inputFeatures.emplace_back(OBJECT1.GETTER()); \ + } else { \ + inputFeatures.emplace_back(OBJECT2.GETTER()); \ + } \ + break; \ + } + namespace o2::analysis { enum class InputFeaturesDsToKKPi : uint8_t { @@ -95,12 +108,24 @@ enum class InputFeaturesDsToKKPi : uint8_t { nSigTpcKa0, nSigTpcKa1, nSigTpcKa2, + nSigTofPi0, + nSigTofPi1, + nSigTofPi2, + nSigTofKa0, + nSigTofKa1, + nSigTofKa2, nSigTpcTofPi0, nSigTpcTofPi1, nSigTpcTofPi2, nSigTpcTofKa0, nSigTpcTofKa1, nSigTpcTofKa2, + nSigTpcKaExpKa0, + nSigTpcPiExpPi2, + nSigTofKaExpKa0, + nSigTofPiExpPi2, + nSigTpcTofKaExpKa0, + nSigTpcTofPiExpPi2, absCos3PiK, deltaMassPhi }; @@ -156,6 +181,17 @@ class HfMlResponseDsToKKPi : public HfMlResponse CHECK_AND_FILL_VEC_DS_FULL(prong0, nSigTpcKa0, tpcNSigmaKa); CHECK_AND_FILL_VEC_DS_FULL(prong1, nSigTpcKa1, tpcNSigmaKa); CHECK_AND_FILL_VEC_DS_FULL(prong2, nSigTpcKa2, tpcNSigmaKa); + CHECK_AND_FILL_VEC_DS_FULL(prong0, nSigTofPi0, tofNSigmaPi); + CHECK_AND_FILL_VEC_DS_FULL(prong1, nSigTofPi1, tofNSigmaPi); + CHECK_AND_FILL_VEC_DS_FULL(prong2, nSigTofPi2, tofNSigmaPi); + CHECK_AND_FILL_VEC_DS_FULL(prong0, nSigTofKa0, tofNSigmaKa); + CHECK_AND_FILL_VEC_DS_FULL(prong1, nSigTofKa1, tofNSigmaKa); + CHECK_AND_FILL_VEC_DS_FULL(prong2, nSigTofKa2, tofNSigmaKa); + CHECK_AND_FILL_VEC_DS_OBJECT_SIGNED(prong0, prong2, nSigTpcKaExpKa0, tpcNSigmaKa); + CHECK_AND_FILL_VEC_DS_OBJECT_SIGNED(prong2, prong0, nSigTpcPiExpPi2, tpcNSigmaPi); + CHECK_AND_FILL_VEC_DS_OBJECT_SIGNED(prong0, prong2, nSigTofKaExpKa0, tofNSigmaKa); + CHECK_AND_FILL_VEC_DS_OBJECT_SIGNED(prong2, prong0, nSigTofPiExpPi2, tofNSigmaPi); + // Combined PID variables CHECK_AND_FILL_VEC_DS_FULL(prong0, nSigTpcTofPi0, tpcTofNSigmaPi); CHECK_AND_FILL_VEC_DS_FULL(prong1, nSigTpcTofPi1, tpcTofNSigmaPi); @@ -163,6 +199,8 @@ class HfMlResponseDsToKKPi : public HfMlResponse CHECK_AND_FILL_VEC_DS_FULL(prong0, nSigTpcTofKa0, tpcTofNSigmaKa); CHECK_AND_FILL_VEC_DS_FULL(prong1, nSigTpcTofKa1, tpcTofNSigmaKa); CHECK_AND_FILL_VEC_DS_FULL(prong2, nSigTpcTofKa2, tpcTofNSigmaKa); + CHECK_AND_FILL_VEC_DS_OBJECT_SIGNED(prong0, prong2, nSigTpcTofKaExpKa0, tpcTofNSigmaKa); + CHECK_AND_FILL_VEC_DS_OBJECT_SIGNED(prong2, prong0, nSigTpcTofPiExpPi2, tpcTofNSigmaPi); // Ds specific variables CHECK_AND_FILL_VEC_DS_HFHELPER_SIGNED(candidate, absCos3PiK, absCos3PiKDsToKKPi, absCos3PiKDsToPiKK); @@ -193,6 +231,9 @@ class HfMlResponseDsToKKPi : public HfMlResponse FILL_MAP_DS(impactParameterXY0), FILL_MAP_DS(impactParameterXY1), FILL_MAP_DS(impactParameterXY2), + FILL_MAP_DS(impactParameterZ0), + FILL_MAP_DS(impactParameterZ1), + FILL_MAP_DS(impactParameterZ2), // TPC PID variables FILL_MAP_DS(nSigTpcPi0), FILL_MAP_DS(nSigTpcPi1), @@ -200,6 +241,16 @@ class HfMlResponseDsToKKPi : public HfMlResponse FILL_MAP_DS(nSigTpcKa0), FILL_MAP_DS(nSigTpcKa1), FILL_MAP_DS(nSigTpcKa2), + FILL_MAP_DS(nSigTofPi0), + FILL_MAP_DS(nSigTofPi1), + FILL_MAP_DS(nSigTofPi2), + FILL_MAP_DS(nSigTofKa0), + FILL_MAP_DS(nSigTofKa1), + FILL_MAP_DS(nSigTofKa2), + FILL_MAP_DS(nSigTpcKaExpKa0), + FILL_MAP_DS(nSigTpcPiExpPi2), + FILL_MAP_DS(nSigTofKaExpKa0), + FILL_MAP_DS(nSigTofPiExpPi2), // Combined PID variables FILL_MAP_DS(nSigTpcTofPi0), FILL_MAP_DS(nSigTpcTofPi1), @@ -207,6 +258,8 @@ class HfMlResponseDsToKKPi : public HfMlResponse FILL_MAP_DS(nSigTpcTofKa0), FILL_MAP_DS(nSigTpcTofKa1), FILL_MAP_DS(nSigTpcTofKa2), + FILL_MAP_DS(nSigTpcTofKaExpKa0), + FILL_MAP_DS(nSigTpcTofPiExpPi2), // Ds specific variables FILL_MAP_DS(absCos3PiK), @@ -221,5 +274,6 @@ class HfMlResponseDsToKKPi : public HfMlResponse #undef CHECK_AND_FILL_VEC_DS #undef CHECK_AND_FILL_VEC_DS_HFHELPER #undef CHECK_AND_FILL_VEC_DS_HFHELPER_SIGNED +#undef CHECK_AND_FILL_VEC_D0_OBJECT_HFHELPER_SIGNED #endif // PWGHF_CORE_HFMLRESPONSEDSTOKKPI_H_ diff --git a/PWGHF/Core/HfMlResponseLcToPKPi.h b/PWGHF/Core/HfMlResponseLcToPKPi.h index e011567c4d6..ea4767b85c6 100644 --- a/PWGHF/Core/HfMlResponseLcToPKPi.h +++ b/PWGHF/Core/HfMlResponseLcToPKPi.h @@ -54,6 +54,19 @@ break; \ } +// Variation of CHECK_AND_FILL_VEC_LCTOPKPI_OBJECT_SIGNED(OBJECT1, OBJECT2, FEATURE, GETTER) +// where OBJECT1 and OBJECT2 are the objects from which we call the GETTER method, and the variable +// is filled depending on whether it is a LcToPKPi or a LcToPiKP +#define CHECK_AND_FILL_VEC_LCTOPKPI_OBJECT_SIGNED(OBJECT1, OBJECT2, FEATURE, GETTER) \ + case static_cast(InputFeaturesLcToPKPi::FEATURE): { \ + if (caseLcToPKPi) { \ + inputFeatures.emplace_back(OBJECT1.GETTER()); \ + } else { \ + inputFeatures.emplace_back(OBJECT2.GETTER()); \ + } \ + break; \ + } + namespace o2::analysis { enum class InputFeaturesLcToPKPi : uint8_t { @@ -98,7 +111,13 @@ enum class InputFeaturesLcToPKPi : uint8_t { tpcTofNSigmaKa2, tpcTofNSigmaPr0, tpcTofNSigmaPr1, - tpcTofNSigmaPr2 + tpcTofNSigmaPr2, + tpcNSigmaPrExpPr0, + tpcNSigmaPiExpPi2, + tofNSigmaPrExpPr0, + tofNSigmaPiExpPi2, + tpcTofNSigmaPrExpPr0, + tpcTofNSigmaPiExpPi2 }; template @@ -118,7 +137,7 @@ class HfMlResponseLcToPKPi : public HfMlResponse /// \return inputFeatures vector template std::vector getInputFeatures(T1 const& candidate, - T2 const& prong0, T2 const& prong1, T2 const& prong2) + T2 const& prong0, T2 const& prong1, T2 const& prong2, bool const& caseLcToPKPi) { std::vector inputFeatures; @@ -149,6 +168,8 @@ class HfMlResponseLcToPKPi : public HfMlResponse CHECK_AND_FILL_VEC_LCTOPKPI_FULL(prong2, tpcNSigmaP2, tpcNSigmaPr); CHECK_AND_FILL_VEC_LCTOPKPI_FULL(prong2, tpcNSigmaKa2, tpcNSigmaKa); CHECK_AND_FILL_VEC_LCTOPKPI_FULL(prong2, tpcNSigmaPi2, tpcNSigmaPi); + CHECK_AND_FILL_VEC_LCTOPKPI_OBJECT_SIGNED(prong0, prong2, tpcNSigmaPrExpPr0, tpcNSigmaPr); + CHECK_AND_FILL_VEC_LCTOPKPI_OBJECT_SIGNED(prong2, prong0, tpcNSigmaPiExpPi2, tpcNSigmaPi); // TOF PID variables CHECK_AND_FILL_VEC_LCTOPKPI_FULL(prong0, tofNSigmaP0, tofNSigmaPr); CHECK_AND_FILL_VEC_LCTOPKPI_FULL(prong0, tofNSigmaKa0, tofNSigmaKa); @@ -159,6 +180,8 @@ class HfMlResponseLcToPKPi : public HfMlResponse CHECK_AND_FILL_VEC_LCTOPKPI_FULL(prong2, tofNSigmaP2, tofNSigmaPr); CHECK_AND_FILL_VEC_LCTOPKPI_FULL(prong2, tofNSigmaKa2, tofNSigmaKa); CHECK_AND_FILL_VEC_LCTOPKPI_FULL(prong2, tofNSigmaPi2, tofNSigmaPi); + CHECK_AND_FILL_VEC_LCTOPKPI_OBJECT_SIGNED(prong0, prong2, tofNSigmaPrExpPr0, tofNSigmaPr); + CHECK_AND_FILL_VEC_LCTOPKPI_OBJECT_SIGNED(prong2, prong0, tofNSigmaPiExpPi2, tofNSigmaPi); // Combined PID variables CHECK_AND_FILL_VEC_LCTOPKPI_FULL(prong0, tpcTofNSigmaPi0, tpcTofNSigmaPi); CHECK_AND_FILL_VEC_LCTOPKPI_FULL(prong1, tpcTofNSigmaPi1, tpcTofNSigmaPi); @@ -169,6 +192,8 @@ class HfMlResponseLcToPKPi : public HfMlResponse CHECK_AND_FILL_VEC_LCTOPKPI_FULL(prong0, tpcTofNSigmaPr0, tpcTofNSigmaPr); CHECK_AND_FILL_VEC_LCTOPKPI_FULL(prong1, tpcTofNSigmaPr1, tpcTofNSigmaPr); CHECK_AND_FILL_VEC_LCTOPKPI_FULL(prong2, tpcTofNSigmaPr2, tpcTofNSigmaPr); + CHECK_AND_FILL_VEC_LCTOPKPI_OBJECT_SIGNED(prong0, prong2, tpcTofNSigmaPrExpPr0, tpcTofNSigmaPr); + CHECK_AND_FILL_VEC_LCTOPKPI_OBJECT_SIGNED(prong2, prong0, tpcTofNSigmaPiExpPi2, tpcTofNSigmaPi); } } @@ -205,6 +230,8 @@ class HfMlResponseLcToPKPi : public HfMlResponse FILL_MAP_LCTOPKPI(tpcNSigmaP2), FILL_MAP_LCTOPKPI(tpcNSigmaKa2), FILL_MAP_LCTOPKPI(tpcNSigmaPi2), + FILL_MAP_LCTOPKPI(tpcNSigmaPrExpPr0), + FILL_MAP_LCTOPKPI(tpcNSigmaPiExpPi2), // TOF PID variables FILL_MAP_LCTOPKPI(tofNSigmaP0), FILL_MAP_LCTOPKPI(tofNSigmaKa0), @@ -215,6 +242,8 @@ class HfMlResponseLcToPKPi : public HfMlResponse FILL_MAP_LCTOPKPI(tofNSigmaP2), FILL_MAP_LCTOPKPI(tofNSigmaKa2), FILL_MAP_LCTOPKPI(tofNSigmaPi2), + FILL_MAP_LCTOPKPI(tofNSigmaPrExpPr0), + FILL_MAP_LCTOPKPI(tofNSigmaPiExpPi2), // Combined PID variables FILL_MAP_LCTOPKPI(tpcTofNSigmaPi0), FILL_MAP_LCTOPKPI(tpcTofNSigmaPi1), @@ -224,7 +253,9 @@ class HfMlResponseLcToPKPi : public HfMlResponse FILL_MAP_LCTOPKPI(tpcTofNSigmaKa2), FILL_MAP_LCTOPKPI(tpcTofNSigmaPr0), FILL_MAP_LCTOPKPI(tpcTofNSigmaPr1), - FILL_MAP_LCTOPKPI(tpcTofNSigmaPr2)}; + FILL_MAP_LCTOPKPI(tpcTofNSigmaPr2), + FILL_MAP_LCTOPKPI(tpcTofNSigmaPrExpPr0), + FILL_MAP_LCTOPKPI(tpcTofNSigmaPiExpPi2)}; } }; @@ -234,5 +265,6 @@ class HfMlResponseLcToPKPi : public HfMlResponse #undef CHECK_AND_FILL_VEC_LCTOPKPI_FULL #undef CHECK_AND_FILL_VEC_LCTOPKPI #undef CHECK_AND_FILL_VEC_LCTOPKPI_HFHELPER +#undef CHECK_AND_FILL_VEC_LCTOPKPI_OBJECT_SIGNED #endif // PWGHF_CORE_HFMLRESPONSELCTOPKPI_H_ diff --git a/PWGHF/Core/HfMlResponseXicToPKPi.h b/PWGHF/Core/HfMlResponseXicToPKPi.h index 398357a66d6..94542745772 100644 --- a/PWGHF/Core/HfMlResponseXicToPKPi.h +++ b/PWGHF/Core/HfMlResponseXicToPKPi.h @@ -48,6 +48,19 @@ break; \ } +// Variation of CHECK_AND_FILL_VEC_XIC_OBJECT_SIGNED(OBJECT1, OBJECT2, FEATURE, GETTER) +// where OBJECT1 and OBJECT2 are the objects from which we call the GETTER method, and the variable +// is filled depending on whether it is a XicToPKPi or a XicToPiKP +#define CHECK_AND_FILL_VEC_XIC_OBJECT_SIGNED(OBJECT1, OBJECT2, FEATURE, GETTER) \ + case static_cast(InputFeaturesXicToPKPi::FEATURE): { \ + if (caseXicToPKPi) { \ + inputFeatures.emplace_back(OBJECT1.GETTER()); \ + } else { \ + inputFeatures.emplace_back(OBJECT2.GETTER()); \ + } \ + break; \ + } + namespace o2::analysis { enum class InputFeaturesXicToPKPi : uint8_t { @@ -92,8 +105,13 @@ enum class InputFeaturesXicToPKPi : uint8_t { tpcTofNSigmaKa2, tpcTofNSigmaPr0, tpcTofNSigmaPr1, - tpcTofNSigmaPr2 - + tpcTofNSigmaPr2, + tpcNSigmaPrExpPr0, + tpcNSigmaPiExpPi2, + tofNSigmaPrExpPr0, + tofNSigmaPiExpPi2, + tpcTofNSigmaPrExpPr0, + tpcTofNSigmaPiExpPi2 }; template @@ -113,7 +131,7 @@ class HfMlResponseXicToPKPi : public HfMlResponse /// \return inputFeatures vector template std::vector getInputFeatures(T1 const& candidate, - T2 const& prong0, T2 const& prong1, T2 const& prong2) + T2 const& prong0, T2 const& prong1, T2 const& prong2, bool const& caseXicToPKPi) { std::vector inputFeatures; @@ -144,6 +162,8 @@ class HfMlResponseXicToPKPi : public HfMlResponse CHECK_AND_FILL_VEC_XIC_FULL(prong2, tpcNSigmaP2, tpcNSigmaPr); CHECK_AND_FILL_VEC_XIC_FULL(prong2, tpcNSigmaKa2, tpcNSigmaKa); CHECK_AND_FILL_VEC_XIC_FULL(prong2, tpcNSigmaPi2, tpcNSigmaPi); + CHECK_AND_FILL_VEC_XIC_OBJECT_SIGNED(prong0, prong2, tpcNSigmaPrExpPr0, tpcNSigmaPr); + CHECK_AND_FILL_VEC_XIC_OBJECT_SIGNED(prong2, prong0, tpcNSigmaPiExpPi2, tpcNSigmaPi); // TOF PID variables CHECK_AND_FILL_VEC_XIC_FULL(prong0, tofNSigmaP0, tofNSigmaPr); CHECK_AND_FILL_VEC_XIC_FULL(prong0, tofNSigmaKa0, tofNSigmaKa); @@ -154,6 +174,8 @@ class HfMlResponseXicToPKPi : public HfMlResponse CHECK_AND_FILL_VEC_XIC_FULL(prong2, tofNSigmaP2, tofNSigmaPr); CHECK_AND_FILL_VEC_XIC_FULL(prong2, tofNSigmaKa2, tofNSigmaKa); CHECK_AND_FILL_VEC_XIC_FULL(prong2, tofNSigmaPi2, tofNSigmaPi); + CHECK_AND_FILL_VEC_XIC_OBJECT_SIGNED(prong0, prong2, tofNSigmaPrExpPr0, tofNSigmaPr); + CHECK_AND_FILL_VEC_XIC_OBJECT_SIGNED(prong2, prong0, tofNSigmaPiExpPi2, tofNSigmaPi); // Combined PID variables CHECK_AND_FILL_VEC_XIC_FULL(prong0, tpcTofNSigmaPi0, tpcTofNSigmaPi); CHECK_AND_FILL_VEC_XIC_FULL(prong1, tpcTofNSigmaPi1, tpcTofNSigmaPi); @@ -164,6 +186,8 @@ class HfMlResponseXicToPKPi : public HfMlResponse CHECK_AND_FILL_VEC_XIC_FULL(prong0, tpcTofNSigmaPr0, tpcTofNSigmaPr); CHECK_AND_FILL_VEC_XIC_FULL(prong1, tpcTofNSigmaPr1, tpcTofNSigmaPr); CHECK_AND_FILL_VEC_XIC_FULL(prong2, tpcTofNSigmaPr2, tpcTofNSigmaPr); + CHECK_AND_FILL_VEC_XIC_OBJECT_SIGNED(prong0, prong2, tpcTofNSigmaPrExpPr0, tpcTofNSigmaPr); + CHECK_AND_FILL_VEC_XIC_OBJECT_SIGNED(prong2, prong0, tpcTofNSigmaPiExpPi2, tpcTofNSigmaPi); } } @@ -200,6 +224,8 @@ class HfMlResponseXicToPKPi : public HfMlResponse FILL_MAP_XIC(tpcNSigmaP2), FILL_MAP_XIC(tpcNSigmaKa2), FILL_MAP_XIC(tpcNSigmaPi2), + FILL_MAP_XIC(tpcNSigmaPrExpPr0), + FILL_MAP_XIC(tpcNSigmaPiExpPi2), // TOF PID variables FILL_MAP_XIC(tofNSigmaP0), FILL_MAP_XIC(tofNSigmaKa0), @@ -210,6 +236,8 @@ class HfMlResponseXicToPKPi : public HfMlResponse FILL_MAP_XIC(tofNSigmaP2), FILL_MAP_XIC(tofNSigmaKa2), FILL_MAP_XIC(tofNSigmaPi2), + FILL_MAP_XIC(tofNSigmaPrExpPr0), + FILL_MAP_XIC(tofNSigmaPiExpPi2), // Combined PID variables FILL_MAP_XIC(tpcTofNSigmaPi0), FILL_MAP_XIC(tpcTofNSigmaPi1), @@ -219,7 +247,9 @@ class HfMlResponseXicToPKPi : public HfMlResponse FILL_MAP_XIC(tpcTofNSigmaKa2), FILL_MAP_XIC(tpcTofNSigmaPr0), FILL_MAP_XIC(tpcTofNSigmaPr1), - FILL_MAP_XIC(tpcTofNSigmaPr2)}; + FILL_MAP_XIC(tpcTofNSigmaPr2), + FILL_MAP_XIC(tpcTofNSigmaPrExpPr0), + FILL_MAP_XIC(tpcTofNSigmaPiExpPi2)}; } }; @@ -228,5 +258,6 @@ class HfMlResponseXicToPKPi : public HfMlResponse #undef FILL_MAP_XIC #undef CHECK_AND_FILL_VEC_XIC_FULL #undef CHECK_AND_FILL_VEC_XIC +#undef CHECK_AND_FILL_VEC_XIC_OBJECT_SIGNED #endif // PWGHF_CORE_HFMLRESPONSEXICTOPKPI_H_ diff --git a/PWGHF/Core/SelectorCuts.h b/PWGHF/Core/SelectorCuts.h index 0f364875ec3..014547d927d 100644 --- a/PWGHF/Core/SelectorCuts.h +++ b/PWGHF/Core/SelectorCuts.h @@ -903,25 +903,50 @@ static const std::vector labelsCutVar = {"m", "CPA", "Chi2PCA", "d0 namespace hf_cuts_bs_to_ds_pi { -static constexpr int nBinsPt = 2; +static constexpr int nBinsPt = 10; static constexpr int nCutVars = 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 binsPt[nBinsPt + 1] = { 0, 1.0, - 2.0}; + 2.0, + 3.0, + 4.0, + 5.0, + 8.0, + 10.0, + 12.0, + 16.0, + 24.0}; auto vecBinsPt = std::vector{binsPt, binsPt + nBinsPt + 1}; // default values for the cuts // DeltaM CPA chi2PCA d0Ds d0Pi pTDs pTPi BsDecayLength BsDecayLengthXY IPProd constexpr double cuts[nBinsPt][nCutVars] = {{1., 0.8, 1., 0.01, 0.01, 1.0, 0.15, 0.05, 0.05, 0.}, /* 0 < pt < 1 */ - {1., 0.8, 1., 0.01, 0.01, 1.0, 0.15, 0.05, 0.05, 0.}}; /* 1 < pt < 2 */ + {1., 0.8, 1., 0.01, 0.01, 1.0, 0.15, 0.05, 0.05, 0.}, /* 1 < pt < 2 */ + {1., 0.8, 1., 0.01, 0.01, 1.0, 0.15, 0.05, 0.05, 0.}, /* 2 < pt < 3 */ + {1., 0.8, 1., 0.01, 0.01, 1.0, 0.15, 0.05, 0.05, 0.}, /* 3 < pt < 4 */ + {1., 0.8, 1., 0.01, 0.01, 1.0, 0.15, 0.05, 0.05, 0.}, /* 4 < pt < 5 */ + {1., 0.8, 1., 0.01, 0.01, 1.0, 0.15, 0.05, 0.05, 0.}, /* 5 < pt < 6 */ + {1., 0.8, 1., 0.01, 0.01, 1.0, 0.15, 0.05, 0.05, 0.}, /* 8 < pt < 10 */ + {1., 0.8, 1., 0.01, 0.01, 1.0, 0.15, 0.05, 0.05, 0.}, /* 10 < pt < 12 */ + {1., 0.8, 1., 0.01, 0.01, 1.0, 0.15, 0.05, 0.05, 0.}, /* 12 < pt < 16 */ + {1., 0.8, 1., 0.01, 0.01, 1.0, 0.15, 0.05, 0.05, 0.}}; /* 16 < pt < 24 */ + // row labels static const std::vector labelsPt = { "pT bin 0", - "pT bin 1"}; + "pT bin 1", + "pT bin 2", + "pT bin 3", + "pT bin 4", + "pT bin 5", + "pT bin 6", + "pT bin 7", + "pT bin 8", + "pT bin 9"}; // column labels static const std::vector labelsCutVar = {"m", "CPA", "Chi2PCA", "d0 Ds", "d0 Pi", "pT Ds", "pT Pi", "Bs decLen", "Bs decLenXY", "Imp. Par. Product"}; diff --git a/PWGHF/D2H/DataModel/ReducedDataModel.h b/PWGHF/D2H/DataModel/ReducedDataModel.h index 02cdc1be0b3..fc84b17a70f 100644 --- a/PWGHF/D2H/DataModel/ReducedDataModel.h +++ b/PWGHF/D2H/DataModel/ReducedDataModel.h @@ -16,6 +16,7 @@ /// /// \author Alexandre Bigot , IPHC Strasbourg /// \author Antonio Palasciano , Università degli Studi di Bari & INFN, Bari +/// \author Fabio Catalano , CERN #ifndef PWGHF_D2H_DATAMODEL_REDUCEDDATAMODEL_H_ #define PWGHF_D2H_DATAMODEL_REDUCEDDATAMODEL_H_ @@ -164,9 +165,8 @@ using HfRedTracks = HfRedTracksExt; namespace hf_charm_cand_reduced { -DECLARE_SOA_COLUMN(InvMass, invMass, float); //! Invariant mass of 2prong candidate in GeV/c2 -DECLARE_SOA_COLUMN(InvMassD0, invMassD0, float); //! Invariant mass of 2prong candidate in GeV/c2 -DECLARE_SOA_COLUMN(InvMassD0Bar, invMassD0Bar, float); //! Invariant mass of 2prong candidate in GeV/c2 +DECLARE_SOA_COLUMN(InvMassHypo0, invMassHypo0, float); //! Invariant mass of candidate in GeV/c2 (mass hypothesis 0) +DECLARE_SOA_COLUMN(InvMassHypo1, invMassHypo1, float); //! Invariant mass of candidate in GeV/c2 (mass hypothesis 1) DECLARE_SOA_COLUMN(MlScoreBkgMassHypo0, mlScoreBkgMassHypo0, float); //! ML score for background class (mass hypothesis 0) DECLARE_SOA_COLUMN(MlScorePromptMassHypo0, mlScorePromptMassHypo0, float); //! ML score for prompt class (mass hypothesis 0) DECLARE_SOA_COLUMN(MlScoreNonpromptMassHypo0, mlScoreNonpromptMassHypo0, float); //! ML score for non-prompt class (mass hypothesis 0) @@ -183,7 +183,7 @@ DECLARE_SOA_TABLE(HfRed2Prongs, "AOD", "HFRED2PRONG", //! Table with 2prong cand hf_track_index_reduced::HfRedCollisionId, HFTRACKPAR_COLUMNS, hf_cand::XSecondaryVertex, hf_cand::YSecondaryVertex, hf_cand::ZSecondaryVertex, - hf_charm_cand_reduced::InvMassD0, hf_charm_cand_reduced::InvMassD0Bar, + hf_charm_cand_reduced::InvMassHypo0, hf_charm_cand_reduced::InvMassHypo1, aod::track::Px, aod::track::Py, aod::track::Pz, @@ -210,7 +210,7 @@ DECLARE_SOA_TABLE(HfRed3Prongs, "AOD", "HFRED3PRONG", //! Table with 3prong cand hf_track_index_reduced::HfRedCollisionId, HFTRACKPAR_COLUMNS, hf_cand::XSecondaryVertex, hf_cand::YSecondaryVertex, hf_cand::ZSecondaryVertex, - hf_charm_cand_reduced::InvMass, + hf_charm_cand_reduced::InvMassHypo0, hf_charm_cand_reduced::InvMassHypo1, aod::track::Px, aod::track::Py, aod::track::Pz, @@ -221,11 +221,22 @@ DECLARE_SOA_TABLE(HfRed3ProngsCov, "AOD", "HFRED3PRONGSCOV", //! Table with 3pro HFTRACKPARCOV_COLUMNS, o2::soa::Marker<2>); -DECLARE_SOA_TABLE(HfRed3ProngsMl, "AOD", "HFRED3PRONGML", //! Table with 3prong candidate ML scores +DECLARE_SOA_TABLE(HfRed3ProngsMl_000, "AOD", "HFRED3PRONGML", //! Table with 3prong candidate ML scores hf_charm_cand_reduced::MlScoreBkgMassHypo0, hf_charm_cand_reduced::MlScorePromptMassHypo0, hf_charm_cand_reduced::MlScoreNonpromptMassHypo0); +DECLARE_SOA_TABLE_VERSIONED(HfRed3ProngsMl_001, "AOD", "HFRED3PRONGML", 1, //! Table with 3prong candidate ML scores (format for 2 mass hypotheses needed for Ds and Lc) + hf_charm_cand_reduced::MlScoreBkgMassHypo0, + hf_charm_cand_reduced::MlScorePromptMassHypo0, + hf_charm_cand_reduced::MlScoreNonpromptMassHypo0, + hf_charm_cand_reduced::MlScoreBkgMassHypo1, + hf_charm_cand_reduced::MlScorePromptMassHypo1, + hf_charm_cand_reduced::MlScoreNonpromptMassHypo1, + o2::soa::Marker<1>); + +using HfRed3ProngsMl = HfRed3ProngsMl_001; + // Beauty candidates prongs namespace hf_cand_b0_reduced { @@ -259,7 +270,7 @@ 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(HfRedBplusD0Mls, "AOD", "HFREDBPLUSD0ML", //! Table with ML scores for the D+ daughter +DECLARE_SOA_TABLE(HfRedBplusD0Mls, "AOD", "HFREDBPLUSD0ML", //! Table with ML scores for the D0 daughter hf_cand_bplus_reduced::Prong0MlScoreBkg, hf_cand_bplus_reduced::Prong0MlScorePrompt, hf_cand_bplus_reduced::Prong0MlScoreNonprompt, @@ -267,6 +278,26 @@ DECLARE_SOA_TABLE(HfRedBplusD0Mls, "AOD", "HFREDBPLUSD0ML", //! Table with ML sc using HfRedCandBplus = 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 +} // 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(HfRedBsDsMls, "AOD", "HFREDBSDSML", //! Table with ML scores for the Ds daughter + hf_cand_bs_reduced::Prong0MlScoreBkg, + hf_cand_bs_reduced::Prong0MlScorePrompt, + hf_cand_bs_reduced::Prong0MlScoreNonprompt, + o2::soa::Marker<1>); + +using HfRedCandBs = soa::Join; + namespace hf_b0_mc { // MC Rec @@ -428,30 +459,90 @@ DECLARE_SOA_TABLE(HfCandBpConfigs, "AOD", "HFCANDBPCONFIG", //! Table with confi hf_cand_bplus_config::MySelectionFlagD0bar, hf_cand_bplus_config::MyInvMassWindowD0Pi); -// Charm resonances analysis -namespace hf_reso_cand_reduced +namespace hf_bs_mc { -DECLARE_SOA_COLUMN(InvMass, invMass, float); //! Invariant mass in GeV/c2 -DECLARE_SOA_COLUMN(InvMassProng0, invMassProng0, float); //! Invariant Mass of D daughter in GeV/c -DECLARE_SOA_COLUMN(InvMassProng1, invMassProng1, float); //! Invariant Mass of V0 daughter in GeV/c -DECLARE_SOA_COLUMN(MlScoreBkgProng0, mlScoreBkgProng0, float); //! Bkg ML score of the D daughter -DECLARE_SOA_COLUMN(MlScorePromptProng0, mlScorePromptProng0, float); //! Prompt ML score of the D daughter -DECLARE_SOA_COLUMN(MlScoreNonpromptProng0, mlScoreNonpromptProng0, float); //! Nonprompt ML score of the D daughter +// MC Rec +DECLARE_SOA_COLUMN(PtMother, ptMother, float); //! Transverse momentum of the mother in GeV/c +// MC Gen +DECLARE_SOA_COLUMN(PtTrack, ptTrack, float); //! Transverse momentum of the track in GeV/c +DECLARE_SOA_COLUMN(YTrack, yTrack, float); //! Rapidity of the track +DECLARE_SOA_COLUMN(EtaTrack, etaTrack, float); //! Pseudorapidity of the track +DECLARE_SOA_COLUMN(PtProng0, ptProng0, float); //! Transverse momentum of the track's prong0 in GeV/c +DECLARE_SOA_COLUMN(YProng0, yProng0, float); //! Rapidity of the track's prong0 +DECLARE_SOA_COLUMN(EtaProng0, etaProng0, float); //! Pseudorapidity of the track's prong0 +DECLARE_SOA_COLUMN(PtProng1, ptProng1, float); //! Transverse momentum of the track's prong1 in GeV/c +DECLARE_SOA_COLUMN(YProng1, yProng1, float); //! Rapidity of the track's prong1 +DECLARE_SOA_COLUMN(EtaProng1, etaProng1, float); //! Pseudorapidity of the track's prong1 -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 +DECLARE_SOA_COLUMN(PdgCodeBeautyMother, pdgCodeBeautyMother, int); //! Pdg code of beauty mother +DECLARE_SOA_COLUMN(PdgCodeCharmMother, pdgCodeCharmMother, int); //! Pdg code of charm mother +DECLARE_SOA_COLUMN(PdgCodeProng0, pdgCodeProng0, int); //! Pdg code of prong0 +DECLARE_SOA_COLUMN(PdgCodeProng1, pdgCodeProng1, int); //! Pdg code of prong1 +DECLARE_SOA_COLUMN(PdgCodeProng2, pdgCodeProng2, int); //! Pdg code of prong2 +DECLARE_SOA_COLUMN(PdgCodeProng3, pdgCodeProng3, int); //! Pdg code of prong3 +} // namespace hf_bs_mc + +// table with results of reconstruction level MC matching +DECLARE_SOA_TABLE(HfMcRecRedDsPis, "AOD", "HFMCRECREDDSPI", //! Table with reconstructed MC information on DsPi(<-Bs) pairs for reduced workflow + hf_cand_bs_reduced::Prong0Id, + hf_cand_bs_reduced::Prong1Id, + hf_cand_bs::FlagMcMatchRec, + hf_cand_bs::FlagWrongCollision, + hf_cand_bs::DebugMcRec, + hf_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 + hf_bs_mc::PdgCodeBeautyMother, + hf_bs_mc::PdgCodeCharmMother, + hf_bs_mc::PdgCodeProng0, + hf_bs_mc::PdgCodeProng1, + hf_bs_mc::PdgCodeProng2, + hf_bs_mc::PdgCodeProng3, + o2::soa::Marker<1>); +// 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::FlagWrongCollision, + hf_cand_bs::DebugMcRec, + hf_bs_mc::PtMother); + +DECLARE_SOA_TABLE(HfMcCheckBss, "AOD", "HFMCCHECKBS", //! Table with reconstructed MC information on Bs candidates for MC checks in reduced workflow + hf_bs_mc::PdgCodeBeautyMother, + hf_bs_mc::PdgCodeCharmMother, + hf_bs_mc::PdgCodeProng0, + hf_bs_mc::PdgCodeProng1, + hf_bs_mc::PdgCodeProng2, + hf_bs_mc::PdgCodeProng3, + o2::soa::Marker<2>); + +DECLARE_SOA_TABLE(HfMcGenRedBss, "AOD", "HFMCGENREDBS", //! Generation-level MC information on Bs candidates for reduced workflow + hf_cand_bs::FlagMcMatchGen, + hf_bs_mc::PtTrack, + hf_bs_mc::YTrack, + hf_bs_mc::EtaTrack, + hf_bs_mc::PtProng0, + hf_bs_mc::YProng0, + hf_bs_mc::EtaProng0, + hf_bs_mc::PtProng1, + hf_bs_mc::YProng1, + hf_bs_mc::EtaProng1); + +// 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 +} // 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); + +// 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 @@ -583,10 +674,41 @@ DECLARE_SOA_TABLE(HfRed3PrNoTrks, "AOD", "HFRED3PRNOTRK", //! Table with 3 prong hf_reso_3_prong::InvMassAntiDstar, hf_reso_3_prong::Pt); +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(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(FlagMcMatchGen, flagMcMatchGen, int8_t); // flag for decay channel classification generator level +DECLARE_SOA_COLUMN(DebugMcRec, debugMcRec, int8_t); // debug flag for mis-association reconstruction level + +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 + DECLARE_SOA_TABLE(HfCandCharmReso, "AOD", "HFCANDCHARMRESO", //! Table with Resonance candidate information for resonances reduced workflow o2::soa::Index<>, // Indices hf_track_index_reduced::HfRedCollisionId, + hf_reso_cand_reduced::Prong0Id, + hf_reso_cand_reduced::Prong1Id, // Static hf_cand::PxProng0, hf_cand::PyProng0, hf_cand::PzProng0, hf_cand::PxProng1, hf_cand::PyProng1, hf_cand::PzProng1, @@ -611,6 +733,38 @@ DECLARE_SOA_TABLE(HfCharmResoMLs, "AOD", "HFCHARMRESOML", //! Table with ML scor hf_reso_cand_reduced::MlScorePromptProng0, hf_reso_cand_reduced::MlScoreNonpromptProng0, o2::soa::Marker<1>); + +// 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, + hf_reso_cand_reduced::FlagMcMatchRec, + hf_reso_cand_reduced::DebugMcRec, + hf_b0_mc::PtMother, + o2::soa::Marker<1>); + +DECLARE_SOA_TABLE(HfMcGenRedResos, "AOD", "HFMCGENREDRESO", //! Generation-level MC information on B0 candidates for reduced workflow + hf_cand_b0::FlagMcMatchGen, + hf_b0_mc::PtTrack, + hf_b0_mc::YTrack, + hf_b0_mc::EtaTrack, + hf_b0_mc::PtProng0, + hf_b0_mc::YProng0, + hf_b0_mc::EtaProng0, + hf_b0_mc::PtProng1, + hf_b0_mc::YProng1, + hf_b0_mc::EtaProng1, + 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); } // namespace aod namespace soa diff --git a/PWGHF/D2H/TableProducer/CMakeLists.txt b/PWGHF/D2H/TableProducer/CMakeLists.txt index 3579b44cc6e..92eeda51051 100644 --- a/PWGHF/D2H/TableProducer/CMakeLists.txt +++ b/PWGHF/D2H/TableProducer/CMakeLists.txt @@ -21,6 +21,11 @@ o2physics_add_dpl_workflow(candidate-creator-bplus-reduced PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2::DCAFitter COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(candidate-creator-bs-reduced + SOURCES candidateCreatorBsReduced.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2::DCAFitter + COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(candidate-creator-charm-reso-reduced SOURCES candidateCreatorCharmResoReduced.cxx PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore @@ -38,6 +43,11 @@ o2physics_add_dpl_workflow(candidate-selector-bplus-to-d0-pi-reduced PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2Physics::MLCore COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(candidate-selector-bs-to-ds-pi-reduced + SOURCES candidateSelectorBsToDsPiReduced.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2Physics::MLCore + COMPONENT_NAME Analysis) + # Data creators o2physics_add_dpl_workflow(data-creator-charm-had-pi-reduced @@ -50,3 +60,9 @@ o2physics_add_dpl_workflow(data-creator-charm-reso-reduced PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2Physics::EventFilteringUtils COMPONENT_NAME Analysis) +# Converters + +o2physics_add_dpl_workflow(converter-reduced-3-prongs-ml + SOURCES converterReduced3ProngsMl.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore + COMPONENT_NAME Analysis) \ No newline at end of file diff --git a/PWGHF/D2H/TableProducer/candidateCreatorBsReduced.cxx b/PWGHF/D2H/TableProducer/candidateCreatorBsReduced.cxx new file mode 100644 index 00000000000..f75b5608ca1 --- /dev/null +++ b/PWGHF/D2H/TableProducer/candidateCreatorBsReduced.cxx @@ -0,0 +1,331 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// \file candidateCreatorBsReduced.cxx +/// \brief Reconstruction of Bs candidates +/// +/// \author Fabio Catalano , CERN + +#include "CommonConstants/PhysicsConstants.h" +#include "DCAFitter/DCAFitterN.h" +#include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" +#include "ReconstructionDataFormats/DCA.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" + +using namespace o2; +using namespace o2::aod; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::hf_trkcandsel; + +/// Reconstruction of Bs candidates +struct HfCandidateCreatorBsReduced { + Produces rowCandidateBase; // table defined in CandidateReconstructionTables.h + Produces rowCandidateProngs; // table defined in ReducedDataModel.h + Produces rowCandidateDmesMlScores; // 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 B0 is smaller than this"}; + Configurable minRelChi2Change{"minRelChi2Change", 0.9, "stop iterations is chi2/chi2old > this"}; + // selection + Configurable invMassWindowDPiTolerance{"invMassWindowDPiTolerance", 0.01, "invariant-mass window tolerance for DsPi pair preselections (GeV/c2)"}; + + float myInvMassWindowDPi{1.}; // variable that will store the value of invMassWindowCharmHadPi (defined in dataCreatorCharmHadPiReduced.cxx) + float massPi{o2::constants::physics::MassPiPlus}; + float massD{o2::constants::physics::MassDS}; + float massB{o2::constants::physics::MassBS}; + float bz{0.}; + + o2::vertexing::DCAFitterN<2> df2; // fitter for B vertex (2-prong vertex fitter) + + using HfRedCollisionsWithExtras = soa::Join; + + Preslice> candsDPerCollision = hf_track_index_reduced::hfRedCollisionId; + Preslice> candsDWithMlPerCollision = hf_track_index_reduced::hfRedCollisionId; + Preslice> tracksPionPerCollision = hf_track_index_reduced::hfRedCollisionId; + + std::shared_ptr hCandidates; + HistogramRegistry registry{"registry"}; + + void init(InitContext const&) + { + std::array doprocess{doprocessData, doprocessDataWithDmesMl}; + if ((std::accumulate(doprocess.begin(), doprocess.end(), 0)) != 1) { + LOGP(fatal, "Only one process function for data should be enabled at a time."); + } + + // Initialize fitter + df2.setPropagateToPCA(propagateToPCA); + df2.setMaxR(maxR); + df2.setMaxDZIni(maxDZIni); + df2.setMinParamChange(minParamChange); + df2.setMinRelChi2Change(minRelChi2Change); + df2.setUseAbsDCA(useAbsDCA); + df2.setWeightedFinalPCA(useWeightedFinalPCA); + + // histograms + registry.add("hMassBsToDsPi", "2-prong candidates;inv. mass (B^{0}_{s} #rightarrow D_{s}^{#minus}#pi^{#plus} #rightarrow #K^{#minus}K^{#plus}#pi^{#minus}#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 + hCandidates = registry.add("hCandidates", "candidates counter", {HistType::kTH1D, {axisCands}}); + setLabelHistoCands(hCandidates); + } + + /// Main function to perform Bs candidate creation + /// \param withDmesMl is the flag to use the table with ML scores for the Ds- daughter (only possible if present in the derived data) + /// \param collision the collision + /// \param candsDThisColl Bs candidates in this collision + /// \param tracksPionThisCollision pion tracks in this collision + /// \param invMass2DPiMin minimum Bs invariant-mass + /// \param invMass2DPiMax maximum Bs invariant-mass + template + void runCandidateCreation(Coll const& collision, + Cands const& candsDThisColl, + Pions const& tracksPionThisCollision, + const float& invMass2DPiMin, + const float& invMass2DPiMax) + { + auto primaryVertex = getPrimaryVertex(collision); + auto covMatrixPV = primaryVertex.getCov(); + + // Set the magnetic field from ccdb + bz = collision.bz(); + df2.setBz(bz); + + for (const auto& candD : candsDThisColl) { + auto trackParCovD = getTrackParCov(candD); + std::array pVecD = candD.pVector(); + + for (const auto& trackPion : tracksPionThisCollision) { + // this track is among daughters + if (trackPion.trackId() == candD.prong0Id() || trackPion.trackId() == candD.prong1Id() || trackPion.trackId() == candD.prong2Id()) { + continue; + } + + auto trackParCovPi = getTrackParCov(trackPion); + std::array pVecPion = trackPion.pVector(); + + // compute invariant mass square and apply selection + auto invMass2DPi = RecoDecay::m2(std::array{pVecD, pVecPion}, std::array{massD, massPi}); + if ((invMass2DPi < invMass2DPiMin) || (invMass2DPi > invMass2DPiMax)) { + continue; + } + // --------------------------------- + // reconstruct the 2-prong Bs vertex + hCandidates->Fill(SVFitting::BeforeFit); + try { + if (df2.process(trackParCovD, trackParCovPi) == 0) { + continue; + } + } catch (const std::runtime_error& error) { + LOG(info) << "Run time error found: " << error.what() << ". DCAFitterN cannot work, skipping the candidate."; + hCandidates->Fill(SVFitting::Fail); + continue; + } + hCandidates->Fill(SVFitting::FitOk); // DsPi passed Bs reconstruction + + // calculate relevant properties + const auto& secondaryVertexB = df2.getPCACandidate(); + auto chi2PCA = df2.getChi2AtPCACandidate(); + auto covMatrixPCA = df2.calcPCACovMatrixFlat(); + registry.fill(HIST("hCovSVXX"), covMatrixPCA[0]); + registry.fill(HIST("hCovPVXX"), covMatrixPV[0]); + + // propagate Ds and Pi to the Bs vertex + df2.propagateTracksToVertex(); + // track.getPxPyPzGlo(pVec) modifies pVec of track + df2.getTrack(0).getPxPyPzGlo(pVecD); // momentum of Ds at the Bs vertex + df2.getTrack(1).getPxPyPzGlo(pVecPion); // momentum of Pi at the Bs vertex + + registry.fill(HIST("hMassBsToDsPi"), std::sqrt(invMass2DPi)); + + // compute impact parameters of Ds and Pi + o2::dataformats::DCA dcaD; + o2::dataformats::DCA dcaPion; + trackParCovD.propagateToDCA(primaryVertex, bz, &dcaD); + trackParCovPi.propagateToDCA(primaryVertex, bz, &dcaPion); + + // get uncertainty of the decay length + float phi, theta; + // getPointDirection modifies phi and theta + getPointDirection(std::array{collision.posX(), collision.posY(), collision.posZ()}, secondaryVertexB, phi, theta); + auto errorDecayLength = std::sqrt(getRotatedCovMatrixXX(covMatrixPV, phi, theta) + getRotatedCovMatrixXX(covMatrixPCA, phi, theta)); + auto errorDecayLengthXY = std::sqrt(getRotatedCovMatrixXX(covMatrixPV, phi, 0.) + getRotatedCovMatrixXX(covMatrixPCA, phi, 0.)); + + // fill the candidate table for the Bs here: + rowCandidateBase(collision.globalIndex(), + collision.posX(), collision.posY(), collision.posZ(), + secondaryVertexB[0], secondaryVertexB[1], secondaryVertexB[2], + errorDecayLength, errorDecayLengthXY, + chi2PCA, + pVecD[0], pVecD[1], pVecD[2], + pVecPion[0], pVecPion[1], pVecPion[2], + dcaD.getY(), dcaPion.getY(), + std::sqrt(dcaD.getSigmaY2()), std::sqrt(dcaPion.getSigmaY2())); + + rowCandidateProngs(candD.globalIndex(), trackPion.globalIndex()); + + if constexpr (withDmesMl) { + if (candD.invMassHypo0() > 0) { + rowCandidateDmesMlScores(candD.mlScoreBkgMassHypo0(), candD.mlScorePromptMassHypo0(), candD.mlScoreNonpromptMassHypo0()); + } else { + rowCandidateDmesMlScores(candD.mlScoreBkgMassHypo1(), candD.mlScorePromptMassHypo1(), candD.mlScoreNonpromptMassHypo1()); + } + // TODO: here we are assuming that only one of the two hypotheses is filled, to be checked + } + } // pi loop + } // D loop + } + + void processData(HfRedCollisionsWithExtras const& collisions, + soa::Join const& candsD, + soa::Join const& tracksPion, + aod::HfOrigColCounts const& collisionsCounter, + aod::HfCandBsConfigs const& configs) + { + // DsPi invariant-mass window cut + for (const auto& config : configs) { + myInvMassWindowDPi = config.myInvMassWindowDPi(); + } + // invMassWindowDPiTolerance is used to apply a slightly tighter cut than in DsPi pair preselection + // to avoid accepting DsPi pairs that were not formed in DsPi pair creator + float invMass2DPiMin = (massB - myInvMassWindowDPi + invMassWindowDPiTolerance) * (massB - myInvMassWindowDPi + invMassWindowDPiTolerance); + float invMass2DPiMax = (massB + myInvMassWindowDPi - invMassWindowDPiTolerance) * (massB + myInvMassWindowDPi - invMassWindowDPiTolerance); + + for (const auto& collisionCounter : collisionsCounter) { + registry.fill(HIST("hEvents"), 1, collisionCounter.originalCollisionCount()); + } + + static int ncol = 0; + for (const auto& collision : collisions) { + auto thisCollId = collision.globalIndex(); + auto candsDThisColl = candsD.sliceBy(candsDPerCollision, thisCollId); + auto tracksPionThisCollision = tracksPion.sliceBy(tracksPionPerCollision, thisCollId); + runCandidateCreation(collision, candsDThisColl, tracksPionThisCollision, invMass2DPiMin, invMass2DPiMax); + if (ncol % 10000 == 0) { + LOGP(debug, "collisions parsed {}", ncol); + } + ncol++; + } + } // processData + + PROCESS_SWITCH(HfCandidateCreatorBsReduced, processData, "Process data without any ML score", true); + + void processDataWithDmesMl(HfRedCollisionsWithExtras const& collisions, + soa::Join const& candsD, + soa::Join const& tracksPion, + aod::HfOrigColCounts const& collisionsCounter, + aod::HfCandBsConfigs const& configs) + { + // DPi invariant-mass window cut + for (const auto& config : configs) { + myInvMassWindowDPi = config.myInvMassWindowDPi(); + } + // invMassWindowDPiTolerance is used to apply a slightly tighter cut than in DsPi pair preselection + // to avoid accepting DPi pairs that were not formed in DsPi pair creator + float invMass2DPiMin = (massB - myInvMassWindowDPi + invMassWindowDPiTolerance) * (massB - myInvMassWindowDPi + invMassWindowDPiTolerance); + float invMass2DPiMax = (massB + myInvMassWindowDPi - invMassWindowDPiTolerance) * (massB + myInvMassWindowDPi - invMassWindowDPiTolerance); + + for (const auto& collisionCounter : collisionsCounter) { + registry.fill(HIST("hEvents"), 1, collisionCounter.originalCollisionCount()); + } + + static int ncol = 0; + for (const auto& collision : collisions) { + auto thisCollId = collision.globalIndex(); + auto candsDThisColl = candsD.sliceBy(candsDPerCollision, thisCollId); + auto tracksPionThisCollision = tracksPion.sliceBy(tracksPionPerCollision, thisCollId); + runCandidateCreation(collision, candsDThisColl, tracksPionThisCollision, invMass2DPiMin, invMass2DPiMax); + if (ncol % 10000 == 0) { + LOGP(debug, "collisions parsed {}", ncol); + } + ncol++; + } + } // processDataWithDmesMl + + PROCESS_SWITCH(HfCandidateCreatorBsReduced, processDataWithDmesMl, "Process data with ML scores of D mesons", false); +}; // struct + +/// Extends the table base with expression columns and performs MC matching. +struct HfCandidateCreatorBsReducedExpressions { + Spawns rowCandidateBs; + Spawns rowTracksExt; + Produces rowBsMcRec; + Produces rowBsMcCheck; + + /// Fill candidate information at MC reconstruction level + /// \param checkDecayTypeMc + /// \param rowsDPiMcRec MC reco information on DsPi pairs + /// \param candsB prong global indices of Bs candidates + template + void fillBsMcRec(McRec const& rowsDPiMcRec, HfRedBsProngs const& candsB) + { + for (const auto& candB : candsB) { + bool filledMcInfo{false}; + for (const auto& rowDPiMcRec : rowsDPiMcRec) { + if ((rowDPiMcRec.prong0Id() != candB.prong0Id()) || (rowDPiMcRec.prong1Id() != candB.prong1Id())) { + continue; + } + rowBsMcRec(rowDPiMcRec.flagMcMatchRec(), rowDPiMcRec.flagWrongCollision(), rowDPiMcRec.debugMcRec(), rowDPiMcRec.ptMother()); + filledMcInfo = true; + if constexpr (checkDecayTypeMc) { + rowBsMcCheck(rowDPiMcRec.pdgCodeBeautyMother(), + rowDPiMcRec.pdgCodeCharmMother(), + rowDPiMcRec.pdgCodeProng0(), + rowDPiMcRec.pdgCodeProng1(), + rowDPiMcRec.pdgCodeProng2(), + rowDPiMcRec.pdgCodeProng3()); + } + 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); + if constexpr (checkDecayTypeMc) { + rowBsMcCheck(-1, -1, -1, -1, -1, -1); + } + } + } + } + + void processMc(HfMcRecRedDsPis const& rowsDPiMcRec, HfRedBsProngs const& candsB) + { + fillBsMcRec(rowsDPiMcRec, candsB); + } + PROCESS_SWITCH(HfCandidateCreatorBsReducedExpressions, processMc, "Process MC", false); + + void processMcWithDecayTypeCheck(soa::Join const& rowsDPiMcRec, HfRedBsProngs const& candsB) + { + fillBsMcRec(rowsDPiMcRec, candsB); + } + PROCESS_SWITCH(HfCandidateCreatorBsReducedExpressions, processMcWithDecayTypeCheck, "Process MC with decay type checks", false); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc), + adaptAnalysisTask(cfgc)}; +} diff --git a/PWGHF/D2H/TableProducer/candidateCreatorCharmResoReduced.cxx b/PWGHF/D2H/TableProducer/candidateCreatorCharmResoReduced.cxx index c3f3af5086b..935153adb83 100644 --- a/PWGHF/D2H/TableProducer/candidateCreatorCharmResoReduced.cxx +++ b/PWGHF/D2H/TableProducer/candidateCreatorCharmResoReduced.cxx @@ -38,13 +38,15 @@ enum Selections : uint8_t { NoSel = 0, DSel, V0Sel, + TrackSel, NSelSteps }; enum DecayChannel : uint8_t { Ds1ToDstarK0s = 0, Ds2StarToDplusK0s, XcToDplusLambda, - LambdaDminus + LambdaDminus, + DstarTrack }; enum V0Type : uint8_t { K0s = 0, @@ -67,6 +69,7 @@ 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; @@ -89,11 +92,13 @@ struct HfCandidateCreatorCharmResoReduced { Partition candidatesLambda = aod::hf_reso_v0::v0Type == (uint8_t)2 || aod::hf_reso_v0::v0Type == (uint8_t)4; Preslice candsV0PerCollision = aod::hf_track_index_reduced::hfRedCollisionId; + Preslice candsTrackPerCollision = aod::hf_track_index_reduced::hfRedCollisionId; Preslice candsDPerCollision = hf_track_index_reduced::hfRedCollisionId; // Useful constants double massK0{0.}; double massLambda{0.}; + double massProton{0.}; double massDplus{0.}; double massDstar{0.}; double massD0{0.}; @@ -103,7 +108,7 @@ struct HfCandidateCreatorCharmResoReduced { void init(InitContext const&) { // check that only one process function is enabled - std::array doprocess{doprocessDs2StarToDplusK0s, doprocessDs2StarToDplusK0sWithMl, doprocessDs1ToDstarK0s, doprocessDs1ToDstarK0sWithMl, doprocessXcToDplusLambda, doprocessXcToDplusLambdaWithMl, doprocessLambdaDminus, doprocessLambdaDminusWithMl}; + std::array doprocess{doprocessDs2StarToDplusK0s, doprocessDs2StarToDplusK0sWithMl, doprocessDs1ToDstarK0s, doprocessDs1ToDstarK0sWithMl, 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!"); } @@ -113,12 +118,15 @@ struct HfCandidateCreatorCharmResoReduced { registry.add("hMassDs2Star", "Ds^{*}2 candidates; m_Ds^{*}2 (GeV/#it{c}^{2}) ;entries", {HistType::kTH2F, {{100, 2.4, 2.7}, {(std::vector)binsPt, "#it{p}_{T} (GeV/#it{c})"}}}); registry.add("hMassXcRes", "XcRes candidates; m_XcRes (GeV/#it{c}^{2}) ;entries", {HistType::kTH2F, {{100, 2.9, 3.3}, {(std::vector)binsPt, "#it{p}_{T} (GeV/#it{c})"}}}); registry.add("hMassLambdaDminus", "LambdaDminus candidates; m_LambdaDminus (GeV/#it{c}^{2}) ;entries", {HistType::kTH2F, {{100, 2.9, 3.3}, {(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 (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) { @@ -128,6 +136,7 @@ struct HfCandidateCreatorCharmResoReduced { // mass constants massK0 = o2::constants::physics::MassK0Short; massLambda = o2::constants::physics::MassLambda; + massProton = o2::constants::physics::MassProton; massDplus = o2::constants::physics::MassDPlus; massDstar = o2::constants::physics::MassDStar; massD0 = o2::constants::physics::MassD0; @@ -147,7 +156,7 @@ struct HfCandidateCreatorCharmResoReduced { // slection on D candidate mass if (channel == DecayChannel::Ds2StarToDplusK0s || channel == DecayChannel::XcToDplusLambda || channel == DecayChannel::LambdaDminus) { invMassD = candD.invMassDplus(); - } else if (channel == DecayChannel::Ds1ToDstarK0s) { + } else if (channel == DecayChannel::Ds1ToDstarK0s || channel == DecayChannel::DstarTrack) { if (candD.dType() > 0) invMassD = candD.invMassDstar(); else @@ -169,7 +178,7 @@ struct HfCandidateCreatorCharmResoReduced { return true; } - /// Basic selection of V0 candidates + /// 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 @@ -215,10 +224,10 @@ struct HfCandidateCreatorCharmResoReduced { return true; } - template + template void runCandidateCreation(Coll const& collision, DRedTable const& candsD, - V0RedTable const& candsV0) + V0TrRedTable const& candsV0Tr) { // loop on D candidates for (const auto& candD : candsD) { @@ -241,70 +250,93 @@ struct HfCandidateCreatorCharmResoReduced { invMassD = candD.invMassAntiDstar(); std::array pVecD = {candD.px(), candD.py(), candD.pz()}; std::array dDaughtersIds = {candD.prong0Id(), candD.prong1Id(), candD.prong2Id()}; - ; - // loop on V0 candidates + + // loop on V0 or track candidates bool alreadyCounted{false}; - for (const auto& candV0 : candsV0) { + for (const auto& candV0Tr : candsV0Tr) { if (rejectDV0PairsWithCommonDaughter) { const std::array dDaughtersIDs = {candD.prong0Id(), candD.prong1Id(), candD.prong2Id()}; - if (std::find(dDaughtersIDs.begin(), dDaughtersIDs.end(), candV0.prong0Id()) != dDaughtersIDs.end() || std::find(dDaughtersIDs.begin(), dDaughtersIDs.end(), candV0.prong1Id()) != dDaughtersIDs.end()) { + if constexpr (channel == DecayChannel::DstarTrack) { + if (std::find(dDaughtersIDs.begin(), dDaughtersIDs.end(), candV0Tr.globalIndex()) != dDaughtersIDs.end()) { + continue; + } + } else { + if (std::find(dDaughtersIDs.begin(), dDaughtersIDs.end(), candV0Tr.prong0Id()) != dDaughtersIDs.end() || std::find(dDaughtersIDs.begin(), dDaughtersIDs.end(), candV0Tr.prong1Id()) != dDaughtersIDs.end()) { + continue; + } + } + } + if constexpr (channel != DecayChannel::DstarTrack) { + if (!isV0Selected(candV0Tr, candD)) { continue; } + if (activateQA && !alreadyCounted) { + registry.fill(HIST("hSelections"), 1 + Selections::V0Sel); + alreadyCounted = true; + } } - if (!isV0Selected(candV0, candD)) { - continue; - } - if (activateQA && !alreadyCounted) { - registry.fill(HIST("hSelections"), 1 + Selections::V0Sel); - alreadyCounted = true; - } float invMassReso{0.}; float invMassV0{0.}; - std::array pVecV0 = {candV0.px(), candV0.py(), candV0.pz()}; - float ptReso = RecoDecay::pt(RecoDecay::sumOfVec(pVecV0, pVecD)); - switch (channel) { - case DecayChannel::Ds1ToDstarK0s: - invMassV0 = candV0.invMassK0s(); - invMassReso = RecoDecay::m(std::array{pVecD, pVecV0}, std::array{massDstar, massK0}); - registry.fill(HIST("hMassDs1"), invMassReso, ptReso); - break; - case DecayChannel::Ds2StarToDplusK0s: - invMassV0 = candV0.invMassK0s(); - invMassReso = RecoDecay::m(std::array{pVecD, pVecV0}, std::array{massDplus, massK0}); - registry.fill(HIST("hMassDs2Star"), invMassReso, ptReso); - break; - case DecayChannel::XcToDplusLambda: - if (candD.dType() > 0) { - invMassV0 = candV0.invMassLambda(); - } else { - invMassV0 = candV0.invMassAntiLambda(); - } - invMassReso = RecoDecay::m(std::array{pVecD, pVecV0}, std::array{massDplus, massLambda}); - registry.fill(HIST("hMassXcRes"), invMassReso, ptReso); - break; - case DecayChannel::LambdaDminus: - if (candD.dType() < 0) { - invMassV0 = candV0.invMassLambda(); - } else { - invMassV0 = candV0.invMassAntiLambda(); - } - invMassReso = RecoDecay::m(std::array{pVecD, pVecV0}, std::array{massDplus, massLambda}); - registry.fill(HIST("hMassLambdaDminus"), invMassReso, ptReso); - break; - default: - break; + std::array pVecV0Tr = {candV0Tr.px(), candV0Tr.py(), candV0Tr.pz()}; + float ptReso = RecoDecay::pt(RecoDecay::sumOfVec(pVecV0Tr, pVecD)); + + if constexpr (channel == DecayChannel::DstarTrack) { + invMassReso = RecoDecay::m(std::array{pVecD, pVecV0Tr}, std::array{massDstar, massProton}); + registry.fill(HIST("hMassDstarTrack"), invMassReso, ptReso); + } else { + switch (channel) { + case DecayChannel::Ds1ToDstarK0s: + invMassV0 = candV0Tr.invMassK0s(); + invMassReso = RecoDecay::m(std::array{pVecD, pVecV0Tr}, std::array{massDstar, massK0}); + registry.fill(HIST("hMassDs1"), invMassReso, ptReso); + break; + case DecayChannel::Ds2StarToDplusK0s: + invMassV0 = candV0Tr.invMassK0s(); + invMassReso = RecoDecay::m(std::array{pVecD, pVecV0Tr}, std::array{massDplus, massK0}); + 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{pVecD, pVecV0Tr}, std::array{massDplus, massLambda}); + 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{pVecD, pVecV0Tr}, std::array{massDplus, massLambda}); + registry.fill(HIST("hMassLambdaDminus"), invMassReso, ptReso); + break; + default: + break; + } } // Filling Output table - rowCandidateReso(collision.globalIndex(), - pVecD[0], pVecD[1], pVecD[2], - pVecV0[0], pVecV0[1], pVecV0[2], - invMassReso, - invMassD, - invMassV0, - candV0.cpa(), - candV0.dca(), - candV0.v0Radius()); + if constexpr (channel == DecayChannel::DstarTrack) { + rowCandidateResoTrack(pVecD[0], pVecD[1], pVecD[2], + candV0Tr.px(), candV0Tr.py(), candV0Tr.pz(), + invMassReso, + invMassD); + } else { + rowCandidateReso(collision.globalIndex(), + candD.globalIndex(), + candV0Tr.globalIndex(), + pVecD[0], pVecD[1], pVecD[2], + pVecV0Tr[0], pVecV0Tr[1], pVecV0Tr[2], + invMassReso, + invMassD, + invMassV0, + candV0Tr.cpa(), + candV0Tr.dca(), + candV0Tr.v0Radius()); + } if constexpr (fillMl) { mlScores(candD.mlScoreBkgMassHypo0(), candD.mlScorePromptMassHypo0(), candD.mlScoreNonpromptMassHypo0()); } @@ -415,6 +447,32 @@ struct HfCandidateCreatorCharmResoReduced { } } PROCESS_SWITCH(HfCandidateCreatorCharmResoReduced, processLambdaDminusWithMl, "Process LambdaDminus candidates with Ml info", false); + void processDstarTrack(aod::HfRedCollisions const& collisions, + aod::HfRed3PrNoTrks const& candsD, + soa::Join const& candidatesTrack) + { + 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); + } + } + PROCESS_SWITCH(HfCandidateCreatorCharmResoReduced, processDstarTrack, "Process DStar candidates without Ml info", false); + + void processDstarTrackWithMl(aod::HfRedCollisions const& collisions, + soa::Join const& candsD, + soa::Join const& candidatesTrack) + // aod::HfRedTracks const&) + { + 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); + } + } + PROCESS_SWITCH(HfCandidateCreatorCharmResoReduced, processDstarTrackWithMl, "Process DStar candidates with Ml info", false); }; // struct diff --git a/PWGHF/D2H/TableProducer/candidateSelectorB0ToDPiReduced.cxx b/PWGHF/D2H/TableProducer/candidateSelectorB0ToDPiReduced.cxx index 5bf352517e4..02db4418680 100644 --- a/PWGHF/D2H/TableProducer/candidateSelectorB0ToDPiReduced.cxx +++ b/PWGHF/D2H/TableProducer/candidateSelectorB0ToDPiReduced.cxx @@ -114,6 +114,7 @@ struct HfCandidateSelectorB0ToDPiReduced { labels[1 + SelectionStep::RecoSkims] = "Skims selection"; labels[1 + SelectionStep::RecoTopol] = "Skims & Topological selections"; labels[1 + SelectionStep::RecoPID] = "Skims & Topological & PID selections"; + labels[1 + aod::SelectionStep::RecoMl] = "ML selection"; static const AxisSpec axisSelections = {kNBinsSelections, 0.5, kNBinsSelections + 0.5, ""}; registry.add("hSelections", "Selections;;#it{p}_{T} (GeV/#it{c})", {HistType::kTH2F, {axisSelections, {(std::vector)binsPt, "#it{p}_{T} (GeV/#it{c})"}}}); for (int iBin = 0; iBin < kNBinsSelections; ++iBin) { diff --git a/PWGHF/D2H/TableProducer/candidateSelectorBplusToD0PiReduced.cxx b/PWGHF/D2H/TableProducer/candidateSelectorBplusToD0PiReduced.cxx index b10dfe22752..5a45f7c3fab 100644 --- a/PWGHF/D2H/TableProducer/candidateSelectorBplusToD0PiReduced.cxx +++ b/PWGHF/D2H/TableProducer/candidateSelectorBplusToD0PiReduced.cxx @@ -114,6 +114,7 @@ struct HfCandidateSelectorBplusToD0PiReduced { labels[1 + SelectionStep::RecoSkims] = "Skims selection"; labels[1 + SelectionStep::RecoTopol] = "Skims & Topological selections"; labels[1 + SelectionStep::RecoPID] = "Skims & Topological & PID selections"; + labels[1 + aod::SelectionStep::RecoMl] = "ML selection"; static const AxisSpec axisSelections = {kNBinsSelections, 0.5, kNBinsSelections + 0.5, ""}; registry.add("hSelections", "Selections;;#it{p}_{T} (GeV/#it{c})", {HistType::kTH2F, {axisSelections, {(std::vector)binsPt, "#it{p}_{T} (GeV/#it{c})"}}}); for (int iBin = 0; iBin < kNBinsSelections; ++iBin) { diff --git a/PWGHF/D2H/TableProducer/candidateSelectorBsToDsPiReduced.cxx b/PWGHF/D2H/TableProducer/candidateSelectorBsToDsPiReduced.cxx new file mode 100644 index 00000000000..2c26a329243 --- /dev/null +++ b/PWGHF/D2H/TableProducer/candidateSelectorBsToDsPiReduced.cxx @@ -0,0 +1,242 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does 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 candidateSelectorBsToDsPiReduced.cxx +/// \brief Bs → Ds- Ï€+ candidate selector +/// +/// \author Fabio Catalano , CERN + +#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" + +using namespace o2; +using namespace o2::aod; +using namespace o2::framework; +using namespace o2::analysis; + +struct HfCandidateSelectorBsToDsPiReduced { + Produces hfSelBsToDsPiCandidate; // table defined in CandidateSelectionTables.h + Produces hfMlBsToDsPiCandidate; // table defined in CandidateSelectionTables.h + + Configurable ptCandMin{"ptCandMin", 0., "Lower bound of candidate pT"}; + Configurable ptCandMax{"ptCandMax", 50., "Upper bound of candidate pT"}; + // Enable PID + Configurable pionPidMethod{"pionPidMethod", 1, "PID selection method for the bachelor pion (0: none, 1: TPC or TOF, 2: 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"}; + // topological cuts + Configurable> binsPt{"binsPt", std::vector{hf_cuts_bs_to_ds_pi::vecBinsPt}, "pT bin limits"}; + Configurable> cuts{"cuts", {hf_cuts_bs_to_ds_pi::cuts[0], hf_cuts_bs_to_ds_pi::nBinsPt, hf_cuts_bs_to_ds_pi::nCutVars, hf_cuts_bs_to_ds_pi::labelsPt, hf_cuts_bs_to_ds_pi::labelsCutVar}, "Bs candidate selection per pT bin"}; + // D-meson ML cuts + Configurable> binsPtDmesMl{"binsPtDmesMl", std::vector{hf_cuts_ml::vecBinsPt}, "D-meson pT bin limits for ML cuts"}; + Configurable> cutsDmesMl{"cutsDmesMl", {hf_cuts_ml::cuts[0], hf_cuts_ml::nBinsPt, hf_cuts_ml::nCutScores, hf_cuts_ml::labelsPt, hf_cuts_ml::labelsDmesCutScore}, "D-meson ML cuts per pT bin"}; + // QA switch + Configurable activateQA{"activateQA", false, "Flag to enable QA histogram"}; + // B0 ML inference + Configurable applyBsMl{"applyBsMl", false, "Flag to apply ML selections"}; + 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", (int8_t)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_BsToDsPi.onnx"}, "ONNX file names for each pT bin (if not from CCDB full path)"}; + Configurable timestampCCDB{"timestampCCDB", -1, "timestamp of the ONNX file for ML model used to query in CCDB"}; + Configurable loadModelsFromCCDB{"loadModelsFromCCDB", false, "Flag to enable or disable the loading of models from CCDB"}; + + o2::analysis::HfMlResponseBsToDsPi hfMlResponse; + std::vector outputMl = {}; + o2::ccdb::CcdbApi ccdbApi; + + TrackSelectorPi selectorPion; + HfHelper hfHelper; + + using TracksPion = soa::Join; + + HistogramRegistry registry{"registry"}; + + void init(InitContext const&) + { + std::array doprocess{doprocessSelection, doprocessSelectionWithDmesMl}; + if ((std::accumulate(doprocess.begin(), doprocess.end(), 0)) != 1) { + LOGP(fatal, "Only one process function for data should be enabled at a time."); + } + + if (pionPidMethod < 0 || pionPidMethod > 2) { + LOGP(fatal, "Invalid PID option in configurable, please set 0 (no PID), 1 (TPC or TOF), or 2 (TPC and TOF)"); + } + + if (pionPidMethod) { + selectorPion.setRangePtTpc(ptPidTpcMin, ptPidTpcMax); + selectorPion.setRangeNSigmaTpc(-nSigmaTpcMax, nSigmaTpcMax); + selectorPion.setRangeNSigmaTpcCondTof(-nSigmaTpcCombinedMax, nSigmaTpcCombinedMax); + selectorPion.setRangePtTof(ptPidTofMin, ptPidTofMax); + selectorPion.setRangeNSigmaTof(-nSigmaTofMax, nSigmaTofMax); + selectorPion.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 + aod::SelectionStep::RecoMl] = "ML selection"; + static const AxisSpec axisSelections = {kNBinsSelections, 0.5, kNBinsSelections + 0.5, ""}; + registry.add("hSelections", "Selections;;#it{p}_{T} (GeV/#it{c})", {HistType::kTH2F, {axisSelections, {(std::vector)binsPt, "#it{p}_{T} (GeV/#it{c})"}}}); + for (int iBin = 0; iBin < kNBinsSelections; ++iBin) { + registry.get(HIST("hSelections"))->GetXaxis()->SetBinLabel(iBin + 1, labels[iBin].data()); + } + } + + if (applyBsMl) { + 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(); + } + } + + /// Main function to perform Bs candidate selection + /// \param withDmesMl is the flag to use the table with ML scores for the Ds- daughter (only possible if present in the derived data) + /// \param hfCandsBs Bs candidates + /// \param pionTracks pion tracks + /// \param configs config inherited from the charm-hadron data creator + template + void runSelection(Cands const& hfCandsBs, + TracksPion const&, + HfCandBsConfigs const& configs) + { + for (const auto& hfCandBs : hfCandsBs) { + int statusBsToDsPi = 0; + outputMl.clear(); + auto ptCandBs = hfCandBs.pt(); + + SETBIT(statusBsToDsPi, SelectionStep::RecoSkims); // RecoSkims = 0 --> statusBsToDsPi = 1 + if (activateQA) { + registry.fill(HIST("hSelections"), 2 + SelectionStep::RecoSkims, ptCandBs); + } + + // topological cuts + if (!hfHelper.selectionBsToDsPiTopol(hfCandBs, cuts, binsPt)) { + hfSelBsToDsPiCandidate(statusBsToDsPi); + if (applyBsMl) { + hfMlBsToDsPiCandidate(outputMl); + } + continue; + } + + if constexpr (withDmesMl) { // we include it in the topological selections + if (!hfHelper.selectionDmesMlScoresForB(hfCandBs, cutsDmesMl, binsPtDmesMl)) { + hfSelBsToDsPiCandidate(statusBsToDsPi); + if (applyBsMl) { + hfMlBsToDsPiCandidate(outputMl); + } + continue; + } + } + + SETBIT(statusBsToDsPi, SelectionStep::RecoTopol); // RecoTopol = 1 --> statusBsToDsPi = 3 + if (activateQA) { + registry.fill(HIST("hSelections"), 2 + SelectionStep::RecoTopol, ptCandBs); + } + + // track-level PID selection + auto trackPi = hfCandBs.template prong1_as(); + if (pionPidMethod) { + int pidTrackPi{TrackSelectorPID::Status::NotApplicable}; + if (pionPidMethod == 1) { + pidTrackPi = selectorPion.statusTpcOrTof(trackPi); + } else { + pidTrackPi = selectorPion.statusTpcAndTof(trackPi); + } + if (!hfHelper.selectionBsToDsPiPid(pidTrackPi, acceptPIDNotApplicable.value)) { + hfSelBsToDsPiCandidate(statusBsToDsPi); + if (applyBsMl) { + hfMlBsToDsPiCandidate(outputMl); + } + continue; + } + SETBIT(statusBsToDsPi, SelectionStep::RecoPID); // RecoPID = 2 --> statusBsToDsPi = 7 + if (activateQA) { + registry.fill(HIST("hSelections"), 2 + SelectionStep::RecoPID, ptCandBs); + } + } + + if (applyBsMl) { + // Bs ML selections + std::vector inputFeatures = hfMlResponse.getInputFeatures(hfCandBs, trackPi); + bool isSelectedMl = hfMlResponse.isSelectedMl(inputFeatures, ptCandBs, outputMl); + hfMlBsToDsPiCandidate(outputMl); + + if (!isSelectedMl) { + hfSelBsToDsPiCandidate(statusBsToDsPi); + continue; + } + SETBIT(statusBsToDsPi, SelectionStep::RecoMl); // RecoML = 3 --> statusBsToDsPi = 15 if pionPidMethod, 11 otherwise + if (activateQA) { + registry.fill(HIST("hSelections"), 2 + SelectionStep::RecoMl, ptCandBs); + } + } + + hfSelBsToDsPiCandidate(statusBsToDsPi); + } + } + + void processSelection(HfRedCandBs const& hfCandsBs, + TracksPion const& pionTracks, + HfCandBsConfigs const& configs) + { + runSelection(hfCandsBs, pionTracks, configs); + } // processSelection + + PROCESS_SWITCH(HfCandidateSelectorBsToDsPiReduced, processSelection, "Process selection without ML scores of D mesons", true); + + void processSelectionWithDmesMl(soa::Join const& hfCandsBs, + TracksPion const& pionTracks, + HfCandBsConfigs const& configs) + { + runSelection(hfCandsBs, pionTracks, configs); + } // processSelectionWithDmesMl + + PROCESS_SWITCH(HfCandidateSelectorBsToDsPiReduced, processSelectionWithDmesMl, "Process selection with ML scores of D mesons", false); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc)}; +} diff --git a/PWGHF/D2H/TableProducer/converterReduced3ProngsMl.cxx b/PWGHF/D2H/TableProducer/converterReduced3ProngsMl.cxx new file mode 100644 index 00000000000..ea9450eca08 --- /dev/null +++ b/PWGHF/D2H/TableProducer/converterReduced3ProngsMl.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. + +/// \file converterReduced3ProngsMl.cxx +/// \brief Task for conversion of HfRed3ProngsMl to version 001 +/// +/// \author Fabrizio Grosa , CERN + +#include "Framework/runDataProcessing.h" +#include "Framework/AnalysisTask.h" +#include "Framework/AnalysisDataModel.h" + +#include "PWGHF/D2H/DataModel/ReducedDataModel.h" + +using namespace o2; +using namespace o2::framework; + +// Swaps covariance matrix elements if the data is known to be bogus (collision_000 is bogus) +struct HfConverterReduced3ProngsMl { + Produces ml3Prongs; + + void process(aod::HfRed3ProngsMl_000::iterator const& mlScoreTable) + { + ml3Prongs(mlScoreTable.mlScoreBkgMassHypo0(), mlScoreTable.mlScorePromptMassHypo0(), mlScoreTable.mlScoreNonpromptMassHypo0(), -1.f, -1.f, -1.f); + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc), + }; +} diff --git a/PWGHF/D2H/TableProducer/dataCreatorCharmHadPiReduced.cxx b/PWGHF/D2H/TableProducer/dataCreatorCharmHadPiReduced.cxx index 71299af44d9..2058ac86611 100644 --- a/PWGHF/D2H/TableProducer/dataCreatorCharmHadPiReduced.cxx +++ b/PWGHF/D2H/TableProducer/dataCreatorCharmHadPiReduced.cxx @@ -15,6 +15,7 @@ /// \author Alexandre Bigot , IPHC Strasbourg /// \author Antonio Palasciano , Università degli Studi di Bari /// \author Fabrizio Grosa , CERN +/// \author Fabio Catalano , CERN #include @@ -55,6 +56,7 @@ enum Event : uint8_t { enum DecayChannel : uint8_t { B0ToDminusPi = 0, BplusToD0barPi, + BsToDsminusPi }; enum WrongCollisionType : uint8_t { @@ -92,6 +94,11 @@ struct HfDataCreatorCharmHadPiReduced { Produces rowHfD0PiMcCheckReduced; Produces rowHfBpMcGenReduced; + Produces rowCandidateConfigBs; + Produces rowHfDsPiMcRecReduced; + Produces rowHfDsPiMcCheckReduced; + Produces rowHfBsMcGenReduced; + // vertexing // Configurable bz{"bz", 5., "magnetic field"}; Configurable propagateToPCA{"propagateToPCA", true, "create tracks version propagated to PCA"}; @@ -108,6 +115,7 @@ struct HfDataCreatorCharmHadPiReduced { 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"}; Configurable invMassWindowCharmHadPi{"invMassWindowCharmHadPi", 0.3, "invariant-mass window for CharmHad-Pi pair preselections (GeV/c2)"}; 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"}; @@ -148,27 +156,37 @@ struct HfDataCreatorCharmHadPiReduced { using CandsDplusFiltered = soa::Filtered>; using CandsDplusFilteredWithMl = soa::Filtered>; + using CandsDsFiltered = soa::Filtered>; + using CandsDsFilteredWithMl = soa::Filtered>; using CandsD0Filtered = soa::Filtered>; using CandsD0FilteredWithMl = soa::Filtered>; using CollisionsWMcLabels = soa::Join; Filter filterSelectDplusCandidates = (aod::hf_sel_candidate_dplus::isSelDplusToPiKPi >= selectionFlagDplus); + Filter filterSelectDsCandidates = (aod::hf_sel_candidate_ds::isSelDsToKKPi >= selectionFlagDs || aod::hf_sel_candidate_ds::isSelDsToPiKK >= selectionFlagDs); Filter filterSelectDzeroCandidates = (aod::hf_sel_candidate_d0::isSelD0 >= selectionFlagD0 || aod::hf_sel_candidate_d0::isSelD0bar >= selectionFlagD0bar); 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 trackIndicesPerCollision = aod::track_association::collisionId; PresliceUnsorted colPerMcCollision = aod::mccollisionlabel::mcCollisionId; - std::shared_ptr hCandidatesD0, hCandidatesDPlus; + std::shared_ptr hCandidatesD0, hCandidatesDPlus, hCandidatesDs; 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&) { - std::array doProcess = {doprocessDplusPiData, doprocessDplusPiDataWithMl, doprocessDplusPiMc, doprocessDplusPiMcWithMl, doprocessD0PiData, doprocessD0PiDataWithMl, doprocessD0PiMc, doprocessD0PiMcWithMl}; + std::array doProcess = {doprocessDplusPiData, doprocessDplusPiDataWithMl, doprocessDplusPiMc, doprocessDplusPiMcWithMl, + doprocessDsPiData, doprocessDsPiDataWithMl, doprocessDsPiMc, doprocessDsPiMcWithMl, + doprocessD0PiData, doprocessD0PiDataWithMl, doprocessD0PiMc, doprocessD0PiMcWithMl}; 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!"); } @@ -178,6 +196,9 @@ struct HfDataCreatorCharmHadPiReduced { if (doprocessDplusPiData || doprocessDplusPiDataWithMl || doprocessDplusPiMc || doprocessDplusPiMcWithMl) { massC = MassDMinus; massB = MassB0; + } else if (doprocessDsPiData || doprocessDsPiDataWithMl || doprocessDsPiMc || doprocessDsPiMcWithMl) { + massC = MassDS; + massB = MassBS; } else if (doprocessD0PiData || doprocessD0PiDataWithMl || doprocessD0PiMc || doprocessD0PiMcWithMl) { massC = MassD0; massB = MassBPlus; @@ -186,7 +207,8 @@ struct HfDataCreatorCharmHadPiReduced { invMass2ChHadPiMax = (massB + invMassWindowCharmHadPi) * (massB + invMassWindowCharmHadPi); // Initialize fitter - if (doprocessDplusPiData || doprocessDplusPiDataWithMl || doprocessDplusPiMc || doprocessDplusPiMcWithMl) { + if (doprocessDplusPiData || doprocessDplusPiDataWithMl || doprocessDplusPiMc || doprocessDplusPiMcWithMl || + doprocessDsPiData || doprocessDsPiDataWithMl || doprocessDsPiMc || doprocessDsPiMcWithMl) { df3.setPropagateToPCA(propagateToPCA); df3.setMaxR(maxR); df3.setMaxDZIni(maxDZIni); @@ -224,36 +246,35 @@ struct HfDataCreatorCharmHadPiReduced { registry.get(HIST("hEvents"))->GetXaxis()->SetBinLabel(iBin + 1, labels[iBin].data()); } - std::string charmHadInvMassTitle = ""; - std::string charmHadTitle0 = ""; - std::string charmHadTitle1 = ""; - std::string histMassTitle0 = ""; - std::string histMassTitle1 = ""; + std::string charmHadTitle = ""; + std::string histMassTitle = ""; if (doprocessDplusPiData || doprocessDplusPiDataWithMl || doprocessDplusPiMc || doprocessDplusPiMcWithMl) { - charmHadTitle0 = "D^{#plus}"; - histMassTitle0 = "Dplus"; - charmHadInvMassTitle = "#it{M}(K#pi#pi)"; + charmHadTitle = "D^{#plus}"; + histMassTitle = "Dplus"; + registry.add("hMassDplus", "D^{#plus} candidates; #it{M}(K#pi#pi) (GeV/#it{c}^{2});entries", {HistType::kTH1F, {{500, 0., 5.}}}); + } else if (doprocessDsPiData || doprocessDsPiDataWithMl || 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::kTH1F, {{500, 0., 5.}}}); + registry.add("hMassDsToPiKK", "D_{s}^{#plus} to piKK candidates; #it{M}(KK#pi) (GeV/#it{c}^{2});entries", {HistType::kTH1F, {{500, 0., 5.}}}); } else if (doprocessD0PiData || doprocessD0PiDataWithMl || doprocessD0PiMc || doprocessD0PiMcWithMl) { - charmHadTitle0 = "D^{0}"; - charmHadTitle1 = "#overline{D}^{0}"; - histMassTitle0 = "D0"; - histMassTitle1 = "D0bar"; - charmHadInvMassTitle = "#it{M}(K#pi)"; + charmHadTitle = "D^{0}"; + histMassTitle = "D0"; + registry.add("hMassD0", "D^{0} candidates; #it{M}(K#pi) (GeV/#it{c}^{2});entries", {HistType::kTH1F, {{500, 0., 5.}}}); + registry.add("hMassD0bar", "#overline{D}^{0} candidates; #it{M}(K#pi) (GeV/#it{c}^{2});entries", {HistType::kTH1F, {{500, 0., 5.}}}); } - registry.add(Form("hMass%s", histMassTitle0.data()), Form("%s candidates; %s (GeV/#it{c}^{2});entries", charmHadTitle0.data(), charmHadInvMassTitle.data()), {HistType::kTH1F, {{500, 0., 5.}}}); - if (doprocessD0PiData || doprocessD0PiDataWithMl || doprocessD0PiMc || doprocessD0PiMcWithMl) { - registry.add(Form("hMass%s", histMassTitle1.data()), Form("%s candidates; %s (GeV/#it{c}^{2});entries", charmHadTitle1.data(), charmHadInvMassTitle.data()), {HistType::kTH1F, {{500, 0., 5.}}}); - } - registry.add(Form("hPt%s", histMassTitle0.data()), Form("%s candidates candidates;%s candidate #it{p}_{T} (GeV/#it{c});entries", charmHadTitle0.data(), charmHadTitle0.data()), {HistType::kTH1F, {{100, 0., 10.}}}); + 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::kTH1F, {{100, 0., 10.}}}); registry.add("hPtPion", "#pi^{#plus} candidates;#pi^{#plus} candidate #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {{100, 0., 10.}}}); - registry.add(Form("hCpa%s", histMassTitle0.data()), Form("%s candidates;%s cosine of pointing angle;entries", charmHadTitle0.data(), charmHadTitle0.data()), {HistType::kTH1F, {{110, -1.1, 1.1}}}); + registry.add(Form("hCpa%s", histMassTitle.data()), Form("%s candidates;%s cosine of pointing angle;entries", charmHadTitle.data(), charmHadTitle.data()), {HistType::kTH1F, {{110, -1.1, 1.1}}}); /// candidate monitoring - hCandidatesD0 = registry.add("hCandidatesD0", "D candidate counter", {HistType::kTH1D, {axisCands}}); - hCandidatesDPlus = registry.add("hCandidatesDPlus", "B candidate counter", {HistType::kTH1D, {axisCands}}); + hCandidatesD0 = registry.add("hCandidatesD0", "D0 candidate counter", {HistType::kTH1D, {axisCands}}); + hCandidatesDPlus = registry.add("hCandidatesDPlus", "Dplus candidate counter", {HistType::kTH1D, {axisCands}}); + hCandidatesDs = registry.add("hCandidatesDs", "Ds candidate counter", {HistType::kTH1D, {axisCands}}); setLabelHistoCands(hCandidatesD0); setLabelHistoCands(hCandidatesDPlus); + setLabelHistoCands(hCandidatesDs); } /// Pion selection (D Pi <-- B0) @@ -472,11 +493,131 @@ struct HfDataCreatorCharmHadPiReduced { rowHfDPiMcCheckReduced(pdgCodeBeautyMother, pdgCodeCharmMother, pdgCodeProng0, pdgCodeProng1, pdgCodeProng2, pdgCodeProng3); } 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); + if (indexRec > -1) { + // Ds- → K- K+ Ï€- + indexRec = RecoDecay::getMatchedMCRec(particlesMc, std::array{vecDaughtersB[0], vecDaughtersB[1], vecDaughtersB[2]}, -Pdg::kDS, std::array{-kKPlus, +kKPlus, -kPiPlus}, true, &sign, 2); + if (indexRec > -1) { + std::vector arrDaughDsIndex; + std::array arrPDGDaughDs; + RecoDecay::getDaughters(particlesMc.rawIteratorAt(indexRec), &arrDaughDsIndex, std::array{0}, 1); + if (arrDaughDsIndex.size() == 2) { + for (auto iProng = 0u; iProng < arrDaughDsIndex.size(); ++iProng) { + auto daughI = particlesMc.rawIteratorAt(arrDaughDsIndex[iProng]); + arrPDGDaughDs[iProng] = std::abs(daughI.pdgCode()); + } + // Ds- → Phi Ï€- → K- K+ Ï€- and Ds- → K0* K- → K- K+ Ï€- + 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); + } else if ((arrPDGDaughDs[0] == arrPDGResonantDKstarK[0] && arrPDGDaughDs[1] == arrPDGResonantDKstarK[1]) || (arrPDGDaughDs[0] == arrPDGResonantDKstarK[1] && arrPDGDaughDs[1] == arrPDGResonantDKstarK[0])) { + flag = sign * BIT(hf_cand_bs::DecayTypeMc::BsToDsPiToK0starKPiToKKPiPi); + } + } + } else { + debug = 1; + LOGF(debug, "Bs 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::kBS, true); + if (indexMother >= 0) { + auto particleMother = particlesMc.rawIteratorAt(indexMother); + motherPt = particleMother.pt(); + checkWrongCollision(particleMother, collision, indexCollisionMaxNumContrib, flagWrongCollision); + } + } + + // additional checks for correlated backgrounds + if (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); + if (indexRec > -1) { + // Ds- → K- K+ Ï€- + indexRec = RecoDecay::getMatchedMCRec(particlesMc, std::array{vecDaughtersB[0], vecDaughtersB[1], vecDaughtersB[2]}, -Pdg::kDS, std::array{-kKPlus, +kKPlus, -kPiPlus}, true, &sign, 2); + if (indexRec > -1) { + std::vector arrDaughDsIndex; + std::array arrPDGDaughDs; + RecoDecay::getDaughters(particlesMc.rawIteratorAt(indexRec), &arrDaughDsIndex, std::array{0}, 1); + if (arrDaughDsIndex.size() == 2) { + for (auto iProng = 0u; iProng < arrDaughDsIndex.size(); ++iProng) { + auto daughI = particlesMc.rawIteratorAt(arrDaughDsIndex[iProng]); + arrPDGDaughDs[iProng] = std::abs(daughI.pdgCode()); + } + // Ds- → Phi Ï€- → K- K+ Ï€- and Ds- → K0* K- → K- K+ Ï€- + 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); + } else if ((arrPDGDaughDs[0] == arrPDGResonantDKstarK[0] && arrPDGDaughDs[1] == arrPDGResonantDKstarK[1]) || (arrPDGDaughDs[0] == arrPDGResonantDKstarK[1] && arrPDGDaughDs[1] == arrPDGResonantDKstarK[0])) { + flag = sign * BIT(hf_cand_bs::DecayTypeMc::B0ToDsPiToK0starKPiToKKPiPi); + } + } + } + } + } + // 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) { + auto particleProng0 = vecDaughtersB[0].mcParticle(); + auto particleProng1 = vecDaughtersB[1].mcParticle(); + auto particleProng2 = vecDaughtersB[2].mcParticle(); + auto particleProng3 = vecDaughtersB[3].mcParticle(); + // b-hadron hypothesis + std::array bHadronMotherHypos = {Pdg::kB0, Pdg::kBS, Pdg::kLambdaB0}; + // c-hadron hypothesis + std::array cHadronMotherHypos = {Pdg::kDPlus, Pdg::kDS, Pdg::kDStar, Pdg::kDSStar, Pdg::kLambdaCPlus}; + + for (const auto& bHadronMotherHypo : bHadronMotherHypos) { + int index0Mother = RecoDecay::getMother(particlesMc, particleProng0, bHadronMotherHypo, true); + int index1Mother = RecoDecay::getMother(particlesMc, particleProng1, bHadronMotherHypo, true); + int index2Mother = RecoDecay::getMother(particlesMc, particleProng2, bHadronMotherHypo, true); + int index3Mother = RecoDecay::getMother(particlesMc, 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); + pdgCodeBeautyMother = particlesMc.rawIteratorAt(index0Mother).pdgCode(); + pdgCodeCharmMother = 0; + pdgCodeProng0 = particleProng0.pdgCode(); + pdgCodeProng1 = particleProng1.pdgCode(); + pdgCodeProng2 = particleProng2.pdgCode(); + pdgCodeProng3 = particleProng3.pdgCode(); + // look for common c-hadron mother among prongs 0, 1 and 2 + for (const auto& cHadronMotherHypo : cHadronMotherHypos) { + int8_t depthMax = 2; + if (cHadronMotherHypo == Pdg::kDStar || cHadronMotherHypo == Pdg::kDSStar) { // to include D* -> D Ï€0/γ, D* -> D0 Ï€, and Ds* -> Ds Ï€0/γ + depthMax += 1; + } + int index0CharmMother = RecoDecay::getMother(particlesMc, particleProng0, cHadronMotherHypo, true, &sign, depthMax); + int index1CharmMother = RecoDecay::getMother(particlesMc, particleProng1, cHadronMotherHypo, true, &sign, depthMax); + int index2CharmMother = RecoDecay::getMother(particlesMc, particleProng2, cHadronMotherHypo, true, &sign, depthMax); + if (index0CharmMother > -1 && index1CharmMother > -1 && index2CharmMother > -1) { + if (index0CharmMother == index1CharmMother && index1CharmMother == index2CharmMother) { + // pdgCodeCharmMother = + // Pdg::kDPlus (if D+ is the mother and does not come from D*+) + // Pdg::kDPlus + Pdg::kDStar (if D+ is the mother and D*+ -> D+ Ï€0/γ) + // Pdg::kDStar (if D*+ is the mother and D*+ -> D0 Ï€+) + // Pdg::kDS (if Ds is the mother and does not come from Ds*) + // Pdg::kDS + Pdg::kDSStar (if Ds is the mother and Ds* -> Ds Ï€0/γ) + // Pdg::kLambdaCPlus (if Λc+ is the mother) + pdgCodeCharmMother += std::abs(particlesMc.rawIteratorAt(index0CharmMother).pdgCode()); + } + } + } + break; + } + } + } + } + rowHfDsPiMcCheckReduced(pdgCodeBeautyMother, pdgCodeCharmMother, pdgCodeProng0, pdgCodeProng1, pdgCodeProng2, pdgCodeProng3); + } + 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); if (indexRec > -1) { - // Printf("Checking D0bar → K+ Ï€-"); + // D0(bar) → K+ Ï€-; indexRec = RecoDecay::getMatchedMCRec(particlesMc, std::array{vecDaughtersB[0], vecDaughtersB[1]}, Pdg::kD0, std::array{+kPiPlus, -kKPlus}, true, &sign, 1); if (indexRec > -1) { flag = sign * BIT(hf_cand_bplus::DecayType::BplusToD0Pi); @@ -492,8 +633,6 @@ struct HfDataCreatorCharmHadPiReduced { checkWrongCollision(particleMother, collision, indexCollisionMaxNumContrib, flagWrongCollision); } } - rowHfD0PiMcRecReduced(indexHfCandCharm, selectedTracksPion[vecDaughtersB.back().globalIndex()], flag, flagWrongCollision, debug, motherPt); - // additional checks for correlated backgrounds if (checkDecayTypeMc) { // Partly reconstructed decays, i.e. the 3 prongs have a common b-hadron ancestor @@ -526,6 +665,7 @@ struct HfDataCreatorCharmHadPiReduced { } rowHfD0PiMcCheckReduced(pdgCodeBeautyMother, pdgCodeProng0, pdgCodeProng1, pdgCodeProng2); } + rowHfD0PiMcRecReduced(indexHfCandCharm, selectedTracksPion[vecDaughtersB.back().globalIndex()], flag, flagWrongCollision, debug, motherPt); } } @@ -574,6 +714,18 @@ struct HfDataCreatorCharmHadPiReduced { 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; + if (candC.isSelDsToKKPi() >= selectionFlagDs) { + invMassC0 = hfHelper.invMassDsToKKPi(candC); + registry.fill(HIST("hMassDsToKKPi"), invMassC0); + } + if (candC.isSelDsToPiKK() >= selectionFlagDs) { + invMassC1 = hfHelper.invMassDsToPiKK(candC); + registry.fill(HIST("hMassDsToPiKK"), invMassC1); + } + registry.fill(HIST("hPtDs"), candC.pt()); + registry.fill(HIST("hCpaDs"), candC.cpa()); } else if constexpr (decChannel == DecayChannel::BplusToD0barPi) { indexHfCandCharm = hfCand2Prong.lastIndex() + 1; if (candC.isSelD0() >= selectionFlagD0) { @@ -612,7 +764,7 @@ struct HfDataCreatorCharmHadPiReduced { } // third track, if it's a 3-prong - if constexpr (decChannel == DecayChannel::B0ToDminusPi) { + if constexpr (decChannel == DecayChannel::B0ToDminusPi || decChannel == DecayChannel::BsToDsminusPi) { charmHadDauTracks.push_back(candC.template prong2_as()); trackParCov2 = getTrackParCov(charmHadDauTracks[2]); pVec2 = charmHadDauTracks[2].pVector(); @@ -627,19 +779,32 @@ struct HfDataCreatorCharmHadPiReduced { // reconstruct charm candidate secondary vertex o2::track::TrackParCov trackParCovCharmHad{}; std::array pVecCharm{}; - if constexpr (decChannel == DecayChannel::B0ToDminusPi) { // D∓ → π∓ K± π∓ + if constexpr (decChannel == DecayChannel::B0ToDminusPi || decChannel == DecayChannel::BsToDsminusPi) { // D∓ → π∓ K± π∓ and Ds∓ → K∓ K± π∓ + + if constexpr (decChannel == DecayChannel::B0ToDminusPi) { + hCandidatesDPlus->Fill(SVFitting::BeforeFit); + } else { + hCandidatesDs->Fill(SVFitting::BeforeFit); + } - hCandidatesDPlus->Fill(SVFitting::BeforeFit); try { if (df3.process(trackParCov0, trackParCov1, trackParCov2) == 0) { continue; } } catch (const std::runtime_error& error) { LOG(info) << "Run time error found: " << error.what() << ". DCAFitterN cannot work, skipping the candidate."; - hCandidatesDPlus->Fill(SVFitting::Fail); + if constexpr (decChannel == DecayChannel::B0ToDminusPi) { + hCandidatesDPlus->Fill(SVFitting::Fail); + } else { + hCandidatesDs->Fill(SVFitting::Fail); + } continue; } - hCandidatesDPlus->Fill(SVFitting::FitOk); + if constexpr (decChannel == DecayChannel::B0ToDminusPi) { + hCandidatesDPlus->Fill(SVFitting::FitOk); + } else { + hCandidatesDs->Fill(SVFitting::FitOk); + } auto secondaryVertexCharm = df3.getPCACandidate(); trackParCov0.propagateTo(secondaryVertexCharm[0], bz); @@ -688,7 +853,7 @@ struct HfDataCreatorCharmHadPiReduced { } // reject pi D with same sign as D - if constexpr (decChannel == DecayChannel::B0ToDminusPi) { // D∓ → π∓ K± π∓ + if constexpr (decChannel == DecayChannel::B0ToDminusPi || decChannel == DecayChannel::BsToDsminusPi) { // D∓ → π∓ K± π∓ and Ds∓ → K∓ K± π∓ if (trackPion.sign() * charmHadDauTracks[0].sign() > 0) { continue; } @@ -742,13 +907,13 @@ struct HfDataCreatorCharmHadPiReduced { fillHfCandCharm = true; } // pion loop if (fillHfCandCharm) { // fill candCplus table only once per D candidate - if constexpr (decChannel == DecayChannel::B0ToDminusPi) { // D∓ → π∓ K± π∓ + if constexpr (decChannel == DecayChannel::B0ToDminusPi || decChannel == DecayChannel::BsToDsminusPi) { // D∓ → π∓ K± π∓ and Ds∓ → K∓ 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); + candC.xSecondaryVertex(), candC.ySecondaryVertex(), candC.zSecondaryVertex(), invMassC0, invMassC1); hfCand3ProngCov(trackParCovCharmHad.getSigmaY2(), trackParCovCharmHad.getSigmaZY(), trackParCovCharmHad.getSigmaZ2(), trackParCovCharmHad.getSigmaSnpY(), trackParCovCharmHad.getSigmaSnpZ(), trackParCovCharmHad.getSigmaSnp2(), trackParCovCharmHad.getSigmaTglY(), trackParCovCharmHad.getSigmaTglZ(), @@ -756,7 +921,18 @@ struct HfDataCreatorCharmHadPiReduced { trackParCovCharmHad.getSigma1PtY(), trackParCovCharmHad.getSigma1PtZ(), trackParCovCharmHad.getSigma1PtSnp(), trackParCovCharmHad.getSigma1PtTgl(), trackParCovCharmHad.getSigma1Pt2()); if constexpr (withMl) { - hfCand3ProngMl(candC.mlProbDplusToPiKPi()[0], candC.mlProbDplusToPiKPi()[1], candC.mlProbDplusToPiKPi()[2]); + if constexpr (decChannel == DecayChannel::B0ToDminusPi) { + hfCand3ProngMl(candC.mlProbDplusToPiKPi()[0], candC.mlProbDplusToPiKPi()[1], candC.mlProbDplusToPiKPi()[2], -1., -1., -1.); + } else { + std::array mlScores = {-1.f, -1.f, -1.f, -1.f, -1.f, -1.f}; + if (candC.mlProbDsToKKPi().size() == 3) { + std::copy(candC.mlProbDsToKKPi().begin(), candC.mlProbDsToKKPi().end(), mlScores.begin()); + } + if (candC.mlProbDsToPiKK().size() == 3) { + std::copy(candC.mlProbDsToPiKK().begin(), candC.mlProbDsToPiKK().end(), mlScores.begin() + 3); + } + 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(), @@ -772,15 +948,14 @@ struct HfDataCreatorCharmHadPiReduced { trackParCovCharmHad.getSigma1PtY(), trackParCovCharmHad.getSigma1PtZ(), trackParCovCharmHad.getSigma1PtSnp(), trackParCovCharmHad.getSigma1PtTgl(), trackParCovCharmHad.getSigma1Pt2()); if constexpr (withMl) { - std::array bdtScores = {-1.f, -1.f, -1.f, -1.f, -1.f, -1.f}; + std::array mlScores = {-1.f, -1.f, -1.f, -1.f, -1.f, -1.f}; if (candC.mlProbD0().size() == 3) { - std::copy(candC.mlProbD0().begin(), candC.mlProbD0().end(), bdtScores.begin()); + std::copy(candC.mlProbD0().begin(), candC.mlProbD0().end(), mlScores.begin()); } if (candC.mlProbD0bar().size() == 3) { - std::copy(candC.mlProbD0bar().begin(), candC.mlProbD0bar().end(), bdtScores.begin() + 3); + std::copy(candC.mlProbD0bar().begin(), candC.mlProbD0bar().end(), mlScores.begin() + 3); } - - hfCand2ProngMl(bdtScores[0], bdtScores[1], bdtScores[2], bdtScores[3], bdtScores[4], bdtScores[5]); + hfCand2ProngMl(mlScores[0], mlScores[1], mlScores[2], mlScores[3], mlScores[4], mlScores[5]); } } fillHfReducedCollision = true; @@ -841,6 +1016,81 @@ struct HfDataCreatorCharmHadPiReduced { rowHfB0McGenReduced(flag, ptParticle, yParticle, etaParticle, ptProngs[0], yProngs[0], etaProngs[0], ptProngs[1], yProngs[1], etaProngs[1]); + } else if constexpr (decayChannel == DecayChannel::BsToDsminusPi) { + // Bs → Ds- Ï€+ + if (RecoDecay::isMatchedMCGen(particlesMc, particle, Pdg::kBS, std::array{-static_cast(Pdg::kDS), +kPiPlus}, true)) { + // Match Ds- -> Ï€- K+ Ï€- + auto candCMC = particlesMc.rawIteratorAt(particle.daughtersIds().front()); + if (RecoDecay::isMatchedMCGen(particlesMc, candCMC, -static_cast(Pdg::kDS), std::array{-kKPlus, +kKPlus, -kPiPlus}, true, &sign, 2)) { + std::vector arrDaughDsIndex; + std::array arrPDGDaughDs; + RecoDecay::getDaughters(candCMC, &arrDaughDsIndex, std::array{0}, 1); + if (arrDaughDsIndex.size() == 2) { + for (auto jProng = 0u; jProng < arrDaughDsIndex.size(); ++jProng) { + auto daughJ = particlesMc.rawIteratorAt(arrDaughDsIndex[jProng]); + arrPDGDaughDs[jProng] = std::abs(daughJ.pdgCode()); + } + // Ds- → Phi Ï€- → K- K+ Ï€- and Ds- → K0* K- → K- K+ Ï€- + 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); + } else if ((arrPDGDaughDs[0] == arrPDGResonantDKstarK[0] && arrPDGDaughDs[1] == arrPDGResonantDKstarK[1]) || (arrPDGDaughDs[0] == arrPDGResonantDKstarK[1] && arrPDGDaughDs[1] == arrPDGResonantDKstarK[0])) { + flag = sign * BIT(hf_cand_bs::DecayTypeMc::BsToDsPiToK0starKPiToKKPiPi); + } + } + } + } + + // additional checks for correlated backgrounds + if (checkDecayTypeMc) { + // B0 → Ds- Ï€+ + if (!flag) { + if (RecoDecay::isMatchedMCGen(particlesMc, particle, Pdg::kB0, std::array{-static_cast(Pdg::kDS), +kPiPlus}, true)) { + // Match Ds- -> Ï€- K+ Ï€- + auto candCMC = particlesMc.rawIteratorAt(particle.daughtersIds().front()); + if (RecoDecay::isMatchedMCGen(particlesMc, candCMC, -static_cast(Pdg::kDS), std::array{-kKPlus, +kKPlus, -kPiPlus}, true, &sign, 2)) { + std::vector arrDaughDsIndex; + std::array arrPDGDaughDs; + RecoDecay::getDaughters(candCMC, &arrDaughDsIndex, std::array{0}, 1); + if (arrDaughDsIndex.size() == 2) { + for (auto jProng = 0u; jProng < arrDaughDsIndex.size(); ++jProng) { + auto daughJ = particlesMc.rawIteratorAt(arrDaughDsIndex[jProng]); + arrPDGDaughDs[jProng] = std::abs(daughJ.pdgCode()); + } + // Ds- → Phi Ï€- → K- K+ Ï€- and Ds- → K0* K- → K- K+ Ï€- + 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); + } else if ((arrPDGDaughDs[0] == arrPDGResonantDKstarK[0] && arrPDGDaughDs[1] == arrPDGResonantDKstarK[1]) || (arrPDGDaughDs[0] == arrPDGResonantDKstarK[1] && arrPDGDaughDs[1] == arrPDGResonantDKstarK[0])) { + flag = sign * BIT(hf_cand_bs::DecayTypeMc::B0ToDsPiToK0starKPiToKKPiPi); + } + } + } + } + } + } + + // save information for Bs task + if (!TESTBIT(std::abs(flag), hf_cand_bs::DecayTypeMc::BsToDsPiToPhiPiPiToKKPiPi) && !TESTBIT(std::abs(flag), hf_cand_bs::DecayTypeMc::BsToDsPiToK0starKPiToKKPiPi) && + !TESTBIT(std::abs(flag), hf_cand_bs::DecayTypeMc::B0ToDsPiToPhiPiPiToKKPiPi) && !TESTBIT(std::abs(flag), hf_cand_bs::DecayTypeMc::B0ToDsPiToK0starKPiToKKPiPi)) { + 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++; + } + rowHfBsMcGenReduced(flag, ptParticle, yParticle, etaParticle, + ptProngs[0], yProngs[0], etaProngs[0], + ptProngs[1], yProngs[1], etaProngs[1]); } else if constexpr (decayChannel == DecayChannel::BplusToD0barPi) { // B+ → D0bar Ï€+ if (RecoDecay::isMatchedMCGen(particlesMc, particle, Pdg::kBPlus, std::array{-static_cast(Pdg::kD0), +kPiPlus}, true)) { @@ -941,6 +1191,66 @@ struct HfDataCreatorCharmHadPiReduced { } PROCESS_SWITCH(HfDataCreatorCharmHadPiReduced, processDplusPiDataWithMl, "Process DplusPi without MC info and with ML info", false); + void processDsPiData(soa::Join const& collisions, + CandsDsFiltered const& candsC, + aod::TrackAssoc const& trackIndices, + TracksPidWithSel const& tracks, + aod::BCsWithTimestamps const& bcs) + { + // store configurables needed for Bs workflow + if (!isHfCandBhadConfigFilled) { + rowCandidateConfigBs(selectionFlagDs.value, 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(candsDplusPerCollision, thisCollId); + auto trackIdsThisCollision = trackIndices.sliceBy(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); + } + PROCESS_SWITCH(HfDataCreatorCharmHadPiReduced, processDsPiData, "Process DsPi without MC info and without ML info", true); + + void processDsPiDataWithMl(soa::Join const& collisions, + CandsDsFilteredWithMl const& candsC, + aod::TrackAssoc const& trackIndices, + TracksPidWithSel const& tracks, + aod::BCsWithTimestamps const& bcs) + { + // store configurables needed for Bs workflow + if (!isHfCandBhadConfigFilled) { + rowCandidateConfigBs(selectionFlagDs.value, 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(candsDplusPerCollisionWithMl, thisCollId); + auto trackIdsThisCollision = trackIndices.sliceBy(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); + } + PROCESS_SWITCH(HfDataCreatorCharmHadPiReduced, processDsPiDataWithMl, "Process DsPi without MC info and with ML info", false); + void processD0PiData(soa::Join const& collisions, CandsD0Filtered const& candsC, aod::TrackAssoc const& trackIndices, @@ -1074,6 +1384,76 @@ struct HfDataCreatorCharmHadPiReduced { } PROCESS_SWITCH(HfDataCreatorCharmHadPiReduced, processDplusPiMcWithMl, "Process DplusPi with MC info and with ML info", false); + void processDsPiMc(CollisionsWMcLabels const& collisions, + CandsDsFiltered const& candsC, + aod::TrackAssoc const& trackIndices, + TracksPidWithSelAndMc const& tracks, + aod::McParticles const& particlesMc, + aod::BCsWithTimestamps const& bcs, + McCollisions const&) + { + // store configurables needed for Bs workflow + if (!isHfCandBhadConfigFilled) { + rowCandidateConfigBs(selectionFlagDs.value, 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(candsDplusPerCollision, thisCollId); + auto trackIdsThisCollision = trackIndices.sliceBy(trackIndicesPerCollision, thisCollId); + auto collsSameMcCollision = collisions.sliceBy(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); + } + PROCESS_SWITCH(HfDataCreatorCharmHadPiReduced, processDsPiMc, "Process DsPi with MC info and without ML info", false); + + void processDsPiMcWithMl(CollisionsWMcLabels const& collisions, + CandsDsFilteredWithMl const& candsC, + aod::TrackAssoc const& trackIndices, + TracksPidWithSelAndMc const& tracks, + aod::McParticles const& particlesMc, + aod::BCsWithTimestamps const& bcs, + McCollisions const&) + { + // store configurables needed for Bs workflow + if (!isHfCandBhadConfigFilled) { + rowCandidateConfigBs(selectionFlagDs.value, 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(candsDplusPerCollisionWithMl, thisCollId); + auto trackIdsThisCollision = trackIndices.sliceBy(trackIndicesPerCollision, thisCollId); + auto collsSameMcCollision = collisions.sliceBy(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); + } + PROCESS_SWITCH(HfDataCreatorCharmHadPiReduced, processDsPiMcWithMl, "Process DsPi with MC info and with ML info", false); + void processD0PiMc(CollisionsWMcLabels const& collisions, CandsD0Filtered const& candsC, aod::TrackAssoc const& trackIndices, diff --git a/PWGHF/D2H/TableProducer/dataCreatorCharmResoReduced.cxx b/PWGHF/D2H/TableProducer/dataCreatorCharmResoReduced.cxx index 39f647b6b94..5e57bbd8598 100644 --- a/PWGHF/D2H/TableProducer/dataCreatorCharmResoReduced.cxx +++ b/PWGHF/D2H/TableProducer/dataCreatorCharmResoReduced.cxx @@ -73,10 +73,17 @@ enum DType : uint8_t { Dstar }; +enum DecayTypeMc : uint8_t { + Ds1ToDStarK0ToD0PiK0s = 0, + Ds2StarToDplusK0s, + Ds1ToDStarK0ToDPlusPi0K0s, + Ds1ToDStarK0ToDPlusGammaK0s +}; + /// Creation of D-V0 pairs struct HfDataCreatorCharmResoReduced { - // Produces AOD tables to store track information + // Produces AOD tables to store collision information Produces hfReducedCollision; // Defined in PWGHF/D2H/DataModel/ReducedDataModel.h Produces hfCollisionCounter; // Defined in PWGHF/D2H/DataModel/ReducedDataModel.h // tracks, V0 and D candidates reduced tables @@ -85,6 +92,9 @@ struct HfDataCreatorCharmResoReduced { Produces hfCandD; // Defined in PWGHF/D2H/DataModel/ReducedDataModel.h // ML optional Tables Produces hfCandDMl; // Defined in PWGHF/D2H/DataModel/ReducedDataModel.h + // MC Tables + Produces rowHfDV0McRecReduced; + Produces rowHfResoMcGenReduced; // CCDB configuration o2::ccdb::CcdbApi ccdbApi; @@ -92,6 +102,7 @@ struct HfDataCreatorCharmResoReduced { Configurable url{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; Configurable ccdbPathGrpMag{"ccdbPathGrpMag", "GLO/Config/GRPMagField", "CCDB path of the GRPMagField object (Run 3)"}; Configurable propagateV0toPV{"propagateV0toPV", false, "Enable or disable V0 propagation to V0"}; + o2::framework::Configurable rejectBackground{"rejectBackground", true, "Reject particles from background events"}; int runNumber{0}; // needed to detect if the run changed and trigger update of calibrations etc. // selection D @@ -141,8 +152,9 @@ struct HfDataCreatorCharmResoReduced { o2::hf_evsel::HfEventSelection hfEvSel; o2::vertexing::DCAFitterN<2> fitter; double bz{0.}; + Service pdg; - bool isHfCandResoConfigFilled = false; + // bool isHfCandResoConfigFilled = false; // Helper struct to pass V0 informations struct { @@ -168,6 +180,7 @@ struct HfDataCreatorCharmResoReduced { using CandDstarFilteredWithMl = soa::Filtered>; using TracksWithPID = soa::Join; using TracksIUWithPID = soa::Join; + using TracksIUWithPIDAndMC = soa::Join; Filter filterSelectDplus = (aod::hf_sel_candidate_dplus::isSelDplusToPiKPi >= cfgDmesCuts.selectionFlagDplus); Filter filterSelectedCandDstar = (aod::hf_sel_candidate_dstar::isSelDstarToD0Pi == cfgDmesCuts.selectionFlagDstarToD0Pi); @@ -218,6 +231,14 @@ struct HfDataCreatorCharmResoReduced { registry.add("hMassDstarProton", "D^{*}-proton candidates;m_{D^{*}p} - m_{D^{*}} (GeV/#it{c}^{2});entries", {HistType::kTH1F, {{500, 0.9, 1.4}}}); registry.add("hDType", "D selection flag", {HistType::kTH1F, {{5, -2.5, 2.5}}}); + registry.add("hMCRecCounter", "Number of Reconstructed MC Matched candidates per channel", {HistType::kTH1F, {{11, -5.5, 5.5}}}); + registry.add("hMCRecDebug", "Debug of MC Reco", {HistType::kTH1F, {{5, -0.5, 4.5}}}); + + registry.add("hMCGenCounter", "Number of Generated particles; Decay Channel Flag; pT [GeV/c]", {HistType::kTH2F, {{11, -5.5, 5.5}, {100, 0, 50}}}); + registry.add("hMCSignCounter", "Sign of Generated particles", {HistType::kTH1F, {{3, -1.5, 1.5}}}); + registry.add("hMCOriginCounter", "Origin of Generated particles", {HistType::kTH1F, {{3, -0.5, 2.5}}}); + registry.add("hMCOriginCounterWrongDecay", "Origin of Generated particles in Wrong decay", {HistType::kTH1F, {{3, -0.5, 2.5}}}); + // Configure CCDB access ccdb->setURL(url.value); ccdb->setCaching(true); @@ -460,11 +481,113 @@ struct HfDataCreatorCharmResoReduced { return true; } - template + /// 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) + { + + // 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}; + float motherPt{-1.f}; + bool fillHisto{false}; + + if constexpr (decChannel == DecayChannel::DstarV0) { + // Ds1 → D* K0 → (D0 Ï€+) K0s → ((K-Ï€+) Ï€+)(Ï€+Ï€-) + auto indexRec = 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 (indexRec > -1) { + // D* → Ï€- K+ Ï€- + indexRec = RecoDecay::getMatchedMCRec(particlesMc, std::array{vecDaughtersReso[0], vecDaughtersReso[1], vecDaughtersReso[2]}, Pdg::kDStar, std::array{-kKPlus, +kPiPlus, +kPiPlus}, true, &signDStar, 2); + auto indexRecD0 = RecoDecay::getMatchedMCRec(particlesMc, std::array{vecDaughtersReso[0], vecDaughtersReso[1]}, Pdg::kD0, std::array{+kPiPlus, -kKPlus}, true, &signD0, 1); + auto indexRecK0 = RecoDecay::getMatchedMCRec(particlesMc, std::array{vecDaughtersReso[3], vecDaughtersReso[4]}, kK0, std::array{+kPiPlus, -kPiPlus}, true, &signV0, 2); + if (indexRec > -1 && indexRecD0 > -1 && indexRecK0 > -1) { + flag = sign * BIT(DecayTypeMc::Ds1ToDStarK0ToD0PiK0s); + } else { + if (indexRec <= -1) { + debug = 1; + LOGF(debug, "DS1 decays in the expected final state but Dstar does not!"); + } + if (indexRec > -1 && indexRecD0 <= -1) { + debug = 2; + LOGF(debug, "DS1 and Dstar decays in the expected final state but D0 does not!"); + } + if (indexRec > -1 && indexRecK0 <= -1) { + debug = 3; + LOGF(debug, "DS1 and Dstar decays in the expected final state but K0 does not!"); + } + } + auto indexMother = RecoDecay::getMother(particlesMc, vecDaughtersReso.back().template mcParticle_as(), Pdg::kDS1, true); + if (indexMother >= 0) { + auto particleMother = particlesMc.rawIteratorAt(indexMother); + motherPt = particleMother.pt(); + } + fillHisto = true; + } + } else if constexpr (decChannel == DecayChannel::DplusV0) { + // Ds2Star → D+ K0 → (Ï€+K-Ï€+) K0s → (Ï€+K-Ï€+)(Ï€+Ï€-) + auto indexRec = 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); + if (indexRec > -1) { + // D+ → Ï€+ K- Ï€+ + indexRec = RecoDecay::getMatchedMCRec(particlesMc, std::array{vecDaughtersReso[0], vecDaughtersReso[1], vecDaughtersReso[2]}, Pdg::kDPlus, std::array{+kPiPlus, -kKPlus, +kPiPlus}, true, &signDPlus, 2); + auto indexRecK0 = RecoDecay::getMatchedMCRec(particlesMc, std::array{vecDaughtersReso[3], vecDaughtersReso[4]}, kK0, std::array{+kPiPlus, -kPiPlus}, true, &signV0, 2); + if (indexRec > -1 && indexRecK0 > -1) { + flag = sign * BIT(DecayTypeMc::Ds2StarToDplusK0s); + } else { + if (indexRec <= -1) { + debug = 1; + LOGF(debug, "DS2Star decays in the expected final state but DPlus does not!"); + } + if (indexRec > -1 && indexRecK0 <= -1) { + debug = 3; + LOGF(debug, "DS2Star and DPlus decays in the expected final state but K0 does not!"); + } + } + auto indexMother = RecoDecay::getMother(particlesMc, vecDaughtersReso.back().template mcParticle_as(), Pdg::kDS2Star, true); + if (indexMother >= 0) { + auto particleMother = particlesMc.rawIteratorAt(indexMother); + motherPt = particleMother.pt(); + } + fillHisto = true; + } else { // Verify partly reconstructed decay Ds1 -> D* K0s -> D+ Ï€0 K0s + indexRec = 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 (indexRec > -1) { + auto indexRecDstar = RecoDecay::getMatchedMCRec(particlesMc, std::array{vecDaughtersReso[0], vecDaughtersReso[1], vecDaughtersReso[2]}, Pdg::kDStar, std::array{-kKPlus, +kPiPlus, +kPiPlus}, true, &signDStar, 2); + auto indexRecK0 = RecoDecay::getMatchedMCRec(particlesMc, std::array{vecDaughtersReso[3], vecDaughtersReso[4]}, kK0, std::array{+kPiPlus, -kPiPlus}, true, &signV0, 2); + if (indexRecDstar > -1 && indexRecK0 > -1) { + auto indexRecDplus = RecoDecay::getMatchedMCRec(particlesMc, std::array{vecDaughtersReso[0], vecDaughtersReso[1], vecDaughtersReso[2]}, Pdg::kDPlus, std::array{+kPiPlus, -kKPlus, +kPiPlus}, true, &sign, 2); + if (indexRecDplus > -1) { + flag = sign * BIT(DecayTypeMc::Ds1ToDStarK0ToDPlusPi0K0s); + fillHisto = true; + } + } + } + } + } + if (fillHisto) { + registry.fill(HIST("hMCRecCounter"), flag); + registry.fill(HIST("hMCRecDebug"), debug); + } + rowHfDV0McRecReduced(indexHfCandCharm, indexCandV0, flag, debug, motherPt); + } + + template void runDataCreation(Coll const& collision, CCands const& candsD, BBach const& bachelors, Tr const&, + PParticles const& particlesMc, aod::BCsWithTimestamps const&) { // helpers for ReducedTables filling @@ -493,6 +616,7 @@ struct HfDataCreatorCharmResoReduced { std::array prongIdsD; int8_t dtype; std::array bdtScores; + std::vector charmHadDauTracks{}; if constexpr (DecayChannel == DecayChannel::DstarV0 || DecayChannel == DecayChannel::DstarTrack) { if (candD.signSoftPi() > 0) { invMassD = candD.invMassDstar(); @@ -509,7 +633,9 @@ struct HfDataCreatorCharmResoReduced { prongIdsD[1] = candD.prong1Id(); prongIdsD[2] = candD.prongPiId(); pVecProng2 = candD.pVecSoftPi(); - + charmHadDauTracks.push_back(candD.template prong0_as()); + charmHadDauTracks.push_back(candD.template prong1_as()); + charmHadDauTracks.push_back(candD.template prongPi_as()); dtype = candD.signSoftPi() * DType::Dstar; if constexpr (withMl) { std::copy(candD.mlProbDstarToD0Pi().begin(), candD.mlProbDstarToD0Pi().end(), bdtScores.begin()); @@ -527,10 +653,12 @@ struct HfDataCreatorCharmResoReduced { prongIdsD[2] = candD.prong2Id(); pVecProng2 = candD.pVectorProng2(); dtype = static_cast(prong0.sign() * DType::Dplus); + charmHadDauTracks.push_back(candD.template prong0_as()); + charmHadDauTracks.push_back(candD.template prong1_as()); + charmHadDauTracks.push_back(candD.template prong2_as()); if constexpr (withMl) { - std::copy(candD.mlProbDplusToPiKPi().begin(), candD.mlProbDplusToPiKPi().end(), bdtScores.begin()); + registry.fill(HIST("hMassVsPtDplusAll"), candD.pt(), invMassD); } - registry.fill(HIST("hMassVsPtDplusAll"), candD.pt(), invMassD); } // else if if constexpr (DecayChannel == DecayChannel::DplusV0 || DecayChannel == DecayChannel::DstarV0) { @@ -604,6 +732,18 @@ struct HfDataCreatorCharmResoReduced { selectedV0s[v0.globalIndex()] = hfCandV0.lastIndex(); } fillHfCandD = true; + // Optional filling of MC Rec table + if constexpr (doMc) { + std::vector charmResoDauTracks{}; + for (const auto& track : charmHadDauTracks) { + charmResoDauTracks.push_back(track); + } + charmResoDauTracks.push_back(trackPos); + charmResoDauTracks.push_back(trackNeg); + int indexHfCandCharm = hfCandD.lastIndex() + 1; + int indexHfCandV0 = hfCandV0.lastIndex(); + fillMcRecoInfo(particlesMc, charmResoDauTracks, indexHfCandCharm, indexHfCandV0); + } } // V0 loop } else if constexpr (DecayChannel == DecayChannel::DstarTrack) { for (const auto& trackIndex : bachelors) { @@ -650,7 +790,7 @@ struct HfDataCreatorCharmResoReduced { pVecProng2[0], pVecProng2[1], pVecProng2[2], dtype); if constexpr (withMl) { - hfCandDMl(bdtScores[0], bdtScores[1], bdtScores[2]); + hfCandDMl(bdtScores[0], bdtScores[1], bdtScores[2], -1., -1., -1.); } fillHfReducedCollision = true; if constexpr (DecayChannel == DecayChannel::DstarV0 || DecayChannel == DecayChannel::DstarTrack) { @@ -673,6 +813,127 @@ struct HfDataCreatorCharmResoReduced { hfReducedCollision(collision.posX(), collision.posY(), collision.posZ(), collision.numContrib(), hfRejMap, bz); } // run data creation + template + void runMcGen(aod::McParticles const& particlesMc) + { + // 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("hMCOriginCounter"), origin); + 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* -> D0 Ï€+ -> K-Ï€+Ï€+ + if (RecoDecay::isMatchedMCGen(particlesMc, candDStarMC, Pdg::kDStar, std::array{-kKPlus, +kPiPlus, +kPiPlus}, true, &signDStar, 2)) { + flag = signDStar * BIT(DecayTypeMc::Ds1ToDStarK0ToD0PiK0s); + } + } + } else { + if (std::abs(particle.pdgCode()) == Pdg::kDS1) { + origin = RecoDecay::getCharmHadronOrigin(particlesMc, particle, false, &idxBhadMothers); + registry.fill(HIST("hMCOriginCounterWrongDecay"), origin); + } + } + // save information for task + if (!TESTBIT(std::abs(flag), DecayTypeMc::Ds1ToDStarK0ToD0PiK0s)) { + 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, 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("hMCOriginCounter"), 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 * BIT(DecayTypeMc::Ds2StarToDplusK0s); + } + } + } 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+ γ + if (RecoDecay::isMatchedMCGen(particlesMc, candDStarMC, Pdg::kDStar, std::array{static_cast(Pdg::kDPlus), static_cast(kGamma)}, true, &signDPlus, 1)) { + flag = sign * BIT(DecayTypeMc::Ds1ToDStarK0ToDPlusGammaK0s); + } else if (RecoDecay::isMatchedMCGen(particlesMc, candDStarMC, Pdg::kDStar, std::array{static_cast(Pdg::kDPlus), -static_cast(kGamma)}, true, &signDPlus, 1)) { + flag = sign * BIT(DecayTypeMc::Ds1ToDStarK0ToDPlusGammaK0s); + } else if (RecoDecay::isMatchedMCGen(particlesMc, candDStarMC, Pdg::kDStar, std::array{static_cast(Pdg::kDPlus), static_cast(kPi0)}, true, &signDPlus, 1)) { + flag = sign * BIT(DecayTypeMc::Ds1ToDStarK0ToDPlusPi0K0s); + } else if (RecoDecay::isMatchedMCGen(particlesMc, candDStarMC, Pdg::kDStar, std::array{static_cast(Pdg::kDPlus), -static_cast(kPi0)}, true, &signDPlus, 1)) { + flag = sign * BIT(DecayTypeMc::Ds1ToDStarK0ToDPlusPi0K0s); + } + } + } else { + if (std::abs(particle.pdgCode()) == Pdg::kDS2Star) { + origin = RecoDecay::getCharmHadronOrigin(particlesMc, particle, false, &idxBhadMothers); + // LOGF(info, "Found DS2Star that decays into %d, %d", particlesMc.rawIteratorAt(particle.daughtersIds().front()).pdgCode(),particlesMc.rawIteratorAt(particle.daughtersIds().back()).pdgCode()); + registry.fill(HIST("hMCOriginCounterWrongDecay"), origin); + } + } + // save information for task + if (!TESTBIT(std::abs(flag), DecayTypeMc::Ds2StarToDplusK0s) && !TESTBIT(std::abs(flag), DecayTypeMc::Ds1ToDStarK0ToDPlusGammaK0s) && !TESTBIT(std::abs(flag), DecayTypeMc::Ds1ToDStarK0ToDPlusPi0K0s)) { + 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++; + } + registry.fill(HIST("hMCGenCounter"), flag, ptParticle); + rowHfResoMcGenReduced(flag, ptParticle, yParticle, etaParticle, + ptProngs[0], yProngs[0], etaProngs[0], + ptProngs[1], yProngs[1], etaProngs[1]); + } // Dplus V0 + } // for loop + } // gen + void processDplusV0(soa::Join const& collisions, CandsDplusFiltered const& candsDplus, aod::V0s const& V0s, @@ -689,13 +950,38 @@ struct HfDataCreatorCharmResoReduced { auto thisCollId = collision.globalIndex(); auto candsDThisColl = candsDplus.sliceBy(candsDplusPerCollision, thisCollId); auto V0sThisColl = V0s.sliceBy(candsV0PerCollision, thisCollId); - runDataCreation(collision, candsDThisColl, V0sThisColl, tracks, bcs); + runDataCreation(collision, candsDThisColl, V0sThisColl, tracks, tracks, bcs); } // handle normalization by the right number of collisions hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); } PROCESS_SWITCH(HfDataCreatorCharmResoReduced, processDplusV0, "Process Dplus candidates paired with V0s without MC info and without ML info", true); + void processDplusV0MC(soa::Join const& collisions, + CandsDplusFiltered const& candsDplus, + aod::V0s const& V0s, + TracksIUWithPIDAndMC const& tracks, + 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, tracks, 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 DPlus candidates paired with V0s with MC matching and without ML info", false); + void processDplusV0WithMl(soa::Join const& collisions, CandsDplusFilteredWithMl const& candsDplus, aod::V0s const& V0s, @@ -712,13 +998,38 @@ struct HfDataCreatorCharmResoReduced { auto thisCollId = collision.globalIndex(); auto candsDThisColl = candsDplus.sliceBy(candsDplusPerCollisionWithMl, thisCollId); auto V0sThisColl = V0s.sliceBy(candsV0PerCollision, thisCollId); - runDataCreation(collision, candsDThisColl, V0sThisColl, tracks, bcs); + runDataCreation(collision, candsDThisColl, V0sThisColl, tracks, tracks, bcs); } // handle normalization by the right number of collisions hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); } PROCESS_SWITCH(HfDataCreatorCharmResoReduced, processDplusV0WithMl, "Process Dplus candidates paired with V0s with ML info", false); + void processDplusV0MCWithMl(soa::Join const& collisions, + CandsDplusFilteredWithMl const& candsDplus, + aod::V0s const& V0s, + TracksIUWithPIDAndMC const& tracks, + 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, tracks, particlesMc, bcs); + } + runMcGen(particlesMc); + // 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 processDstarV0(soa::Join const& collisions, CandDstarFiltered const& candsDstar, aod::V0s const& V0s, @@ -735,13 +1046,38 @@ struct HfDataCreatorCharmResoReduced { auto thisCollId = collision.globalIndex(); auto candsDThisColl = candsDstar.sliceBy(candsDstarPerCollision, thisCollId); auto V0sThisColl = V0s.sliceBy(candsV0PerCollision, thisCollId); - runDataCreation(collision, candsDThisColl, V0sThisColl, tracks, bcs); + runDataCreation(collision, candsDThisColl, V0sThisColl, tracks, tracks, bcs); } // handle normalization by the right number of collisions hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); } PROCESS_SWITCH(HfDataCreatorCharmResoReduced, processDstarV0, "Process DStar candidates paired with V0s without MC info and without ML info", false); + void processDstarV0MC(soa::Join const& collisions, + CandDstarFiltered const& candsDstar, + aod::V0s const& V0s, + TracksIUWithPIDAndMC const& tracks, + 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, tracks, 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 and without ML info", false); + void processDstarV0WithMl(soa::Join const& collisions, CandDstarFilteredWithMl const& candsDstar, aod::V0s const& V0s, @@ -759,13 +1095,38 @@ struct HfDataCreatorCharmResoReduced { auto thisCollId = collision.globalIndex(); auto candsDThisColl = candsDstar.sliceBy(candsDstarPerCollisionWithMl, thisCollId); auto V0sThisColl = V0s.sliceBy(candsV0PerCollision, thisCollId); - runDataCreation(collision, candsDThisColl, V0sThisColl, tracks, bcs); + runDataCreation(collision, candsDThisColl, V0sThisColl, tracks, tracks, bcs); } // handle normalization by the right number of collisions hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); } PROCESS_SWITCH(HfDataCreatorCharmResoReduced, processDstarV0WithMl, "Process DStar candidates paired with V0s with ML info", false); + void processDstarV0MCWithMl(soa::Join const& collisions, + CandDstarFilteredWithMl const& candsDstar, + aod::V0s const& V0s, + TracksIUWithPIDAndMC const& tracks, + 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, tracks, particlesMc, bcs); + } + runMcGen(particlesMc); + // handle normalization by the right number of collisions + hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); + } + PROCESS_SWITCH(HfDataCreatorCharmResoReduced, processDstarV0MCWithMl, "Process MC DStar candidates paired with V0s with ML info", false); + void processDstarTrack(soa::Join const& collisions, CandDstarFiltered const& candsDstar, aod::TrackAssoc const& trackIndices, @@ -782,7 +1143,7 @@ struct HfDataCreatorCharmResoReduced { auto thisCollId = collision.globalIndex(); auto candsDThisColl = candsDstar.sliceBy(candsDstarPerCollision, thisCollId); auto trackIdsThisColl = trackIndices.sliceBy(trackIndicesPerCollision, thisCollId); - runDataCreation(collision, candsDThisColl, trackIdsThisColl, tracks, bcs); + runDataCreation(collision, candsDThisColl, trackIdsThisColl, tracks, tracks, bcs); } // handle normalization by the right number of collisions hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); @@ -806,7 +1167,7 @@ struct HfDataCreatorCharmResoReduced { auto thisCollId = collision.globalIndex(); auto candsDThisColl = candsDstar.sliceBy(candsDstarPerCollisionWithMl, thisCollId); auto trackIdsThisColl = trackIndices.sliceBy(trackIndicesPerCollision, thisCollId); - runDataCreation(collision, candsDThisColl, trackIdsThisColl, tracks, bcs); + runDataCreation(collision, candsDThisColl, trackIdsThisColl, tracks, tracks, bcs); } // handle normalization by the right number of collisions hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); diff --git a/PWGHF/D2H/Tasks/CMakeLists.txt b/PWGHF/D2H/Tasks/CMakeLists.txt index 70837975a00..da18464f72f 100644 --- a/PWGHF/D2H/Tasks/CMakeLists.txt +++ b/PWGHF/D2H/Tasks/CMakeLists.txt @@ -29,6 +29,11 @@ o2physics_add_dpl_workflow(task-bplus-reduced PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore 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 SOURCES taskBs.cxx PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore diff --git a/PWGHF/D2H/Tasks/taskB0Reduced.cxx b/PWGHF/D2H/Tasks/taskB0Reduced.cxx index 3f4350d93ad..a0f5b14e5cc 100644 --- a/PWGHF/D2H/Tasks/taskB0Reduced.cxx +++ b/PWGHF/D2H/Tasks/taskB0Reduced.cxx @@ -140,7 +140,7 @@ struct HfTaskB0Reduced { 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, doprocessMcWithDecayTypeCheck, doprocessMcWithDmesMl, doprocessMcWithB0Ml, doprocessMcWithB0MlAndDecayTypeCheck}; + std::array processFuncMc{doprocessMc, doprocessMcWithDecayTypeCheck, doprocessMcWithDmesMl, doprocessMcWithDmesMlAndDecayTypeCheck, doprocessMcWithB0Ml, doprocessMcWithB0MlAndDecayTypeCheck}; if ((std::accumulate(processFuncMc.begin(), processFuncMc.end(), 0)) > 1) { LOGP(fatal, "Only one process function for MC can be enabled at a time."); } @@ -334,7 +334,7 @@ struct HfTaskB0Reduced { auto invMassB0 = hfHelper.invMassB0ToDPi(candidate); auto candD = candidate.template prong0_as(); auto ptD = candidate.ptProng0(); - auto invMassD = candD.invMass(); + auto invMassD = candD.invMassHypo0(); std::array posPv{candidate.posX(), candidate.posY(), candidate.posZ()}; std::array posSvD{candD.xSecondaryVertex(), candD.ySecondaryVertex(), candD.zSecondaryVertex()}; std::array momD{candD.pVector()}; diff --git a/PWGHF/D2H/Tasks/taskBplusReduced.cxx b/PWGHF/D2H/Tasks/taskBplusReduced.cxx index 282194f57b5..6f8ec90ad73 100644 --- a/PWGHF/D2H/Tasks/taskBplusReduced.cxx +++ b/PWGHF/D2H/Tasks/taskBplusReduced.cxx @@ -143,11 +143,11 @@ struct HfTaskBplusReduced { void init(InitContext&) { - std::array processFuncData{doprocessData, doprocessDataWithDmesMl}; + std::array processFuncData{doprocessData, doprocessDataWithDmesMl, 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, doprocessMcWithDmesMl}; + std::array processFuncMc{doprocessMc, doprocessMcWithDecayTypeCheck, doprocessMcWithDmesMl, doprocessMcWithBplusMl, doprocessMcWithBplusMlAndDecayTypeCheck}; if ((std::accumulate(processFuncMc.begin(), processFuncMc.end(), 0)) > 1) { LOGP(fatal, "Only one process function for MC can be enabled at a time."); } @@ -351,7 +351,7 @@ struct HfTaskBplusReduced { auto candD0 = candidate.template prong0_as(); auto candPi = candidate.template prong1_as(); auto ptD0 = candidate.ptProng0(); - auto invMassD0 = (candPi.signed1Pt() < 0) ? candD0.invMassD0() : candD0.invMassD0Bar(); + auto invMassD0 = (candPi.signed1Pt() < 0) ? candD0.invMassHypo0() : candD0.invMassHypo1(); std::array posPv{candidate.posX(), candidate.posY(), candidate.posZ()}; std::array posSvD{candD0.xSecondaryVertex(), candD0.ySecondaryVertex(), candD0.zSecondaryVertex()}; std::array momD{candD0.pVector()}; diff --git a/PWGHF/D2H/Tasks/taskBs.cxx b/PWGHF/D2H/Tasks/taskBs.cxx index 29c424f869b..e661c8d739b 100644 --- a/PWGHF/D2H/Tasks/taskBs.cxx +++ b/PWGHF/D2H/Tasks/taskBs.cxx @@ -128,8 +128,8 @@ struct HfTaskBs { if (checkDecayTypeMc) { constexpr uint8_t kNBinsDecayTypeMc = hf_cand_bs::DecayTypeMc::NDecayTypeMc + 1; TString labels[kNBinsDecayTypeMc]; - labels[hf_cand_bs::DecayTypeMc::BsToDsPiToKKPiPi] = "B^{0}_{s} #rightarrow (D^{#mp}_{s} #rightarrow K^{#minus} K^{#plus} #pi^{#mp}) #pi^{#pm}"; - labels[hf_cand_bs::DecayTypeMc::B0ToDsPiToKKPiPi] = "B^{0} #rightarrow (D^{#pm}_{s} #rightarrow K^{#minus} K^{#plus} #pi^{#pm}) #pi^{#mp}"; + 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, ""}; @@ -155,9 +155,6 @@ struct HfTaskBs { TracksWithSel const&) { for (const auto& candidate : candidates) { - if (!TESTBIT(candidate.hfflag(), hf_cand_bs::DecayType::BsToDsPi)) { - continue; - } if (yCandRecoMax >= 0. && std::abs(hfHelper.yBs(candidate)) > yCandRecoMax) { continue; } @@ -194,9 +191,6 @@ struct HfTaskBs { { // MC rec for (const auto& candidate : candidates) { - if (!TESTBIT(candidate.hfflag(), hf_cand_bs::DecayType::BsToDsPi)) { - continue; - } if (yCandRecoMax >= 0. && std::abs(hfHelper.yBs(candidate)) > yCandRecoMax) { continue; } @@ -206,7 +200,7 @@ struct HfTaskBs { auto invMassCandBs = hfHelper.invMassBsToDsPi(candidate); int flagMcMatchRecBs = std::abs(candidate.flagMcMatchRec()); - if (TESTBIT(flagMcMatchRecBs, hf_cand_bs::DecayTypeMc::BsToDsPiToKKPiPi)) { + if (TESTBIT(flagMcMatchRecBs, hf_cand_bs::DecayTypeMc::BsToDsPiToPhiPiPiToKKPiPi)) { auto indexMother = RecoDecay::getMother(mcParticles, candidate.prong1_as().mcParticle_as>(), o2::constants::physics::Pdg::kBS, true); auto particleMother = mcParticles.rawIteratorAt(indexMother); @@ -230,7 +224,7 @@ struct HfTaskBs { registry.fill(HIST("hChi2PCARecSig"), candidate.chi2PCA(), ptCandBs); if (checkDecayTypeMc) { - registry.fill(HIST("hDecayTypeMc"), 1 + hf_cand_bs::DecayTypeMc::BsToDsPiToKKPiPi, invMassCandBs, ptCandBs); + registry.fill(HIST("hDecayTypeMc"), 1 + hf_cand_bs::DecayTypeMc::BsToDsPiToPhiPiPiToKKPiPi, invMassCandBs, ptCandBs); } } else { registry.fill(HIST("hPtRecBg"), ptCandBs); @@ -252,8 +246,8 @@ struct HfTaskBs { registry.fill(HIST("hChi2PCARecBg"), candidate.chi2PCA(), ptCandBs); if (checkDecayTypeMc) { - if (TESTBIT(flagMcMatchRecBs, hf_cand_bs::DecayTypeMc::B0ToDsPiToKKPiPi)) { // B0(bar) → Ds± π∓ → (K- K+ π±) π∓ - registry.fill(HIST("hDecayTypeMc"), 1 + hf_cand_bs::DecayTypeMc::B0ToDsPiToKKPiPi, invMassCandBs, ptCandBs); + if (TESTBIT(flagMcMatchRecBs, hf_cand_bs::DecayTypeMc::B0ToDsPiToPhiPiPiToKKPiPi)) { // 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 registry.fill(HIST("hDecayTypeMc"), 1 + hf_cand_bs::DecayTypeMc::PartlyRecoDecay, invMassCandBs, ptCandBs); } else { @@ -265,7 +259,7 @@ struct HfTaskBs { // MC gen. level for (const auto& particle : mcParticles) { - if (TESTBIT(std::abs(particle.flagMcMatchGen()), hf_cand_bs::DecayTypeMc::BsToDsPiToKKPiPi)) { + if (TESTBIT(std::abs(particle.flagMcMatchGen()), hf_cand_bs::DecayTypeMc::BsToDsPiToPhiPiPiToKKPiPi)) { auto ptParticle = particle.pt(); auto yParticle = RecoDecay::y(particle.pVector(), o2::constants::physics::MassBS); diff --git a/PWGHF/D2H/Tasks/taskBsReduced.cxx b/PWGHF/D2H/Tasks/taskBsReduced.cxx new file mode 100644 index 00000000000..cbe0ddc2fa4 --- /dev/null +++ b/PWGHF/D2H/Tasks/taskBsReduced.cxx @@ -0,0 +1,760 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does 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 taskBsReduced.cxx +/// \brief Bs → Ds- Ï€+ → (K- K+ Ï€-) Ï€+ analysis task +/// +/// \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/DataModel/CandidateReconstructionTables.h" +#include "PWGHF/DataModel/CandidateSelectionTables.h" +#include "PWGHF/D2H/DataModel/ReducedDataModel.h" + +using namespace o2; +using namespace o2::aod; +using namespace o2::analysis; +using namespace o2::framework; +using namespace o2::framework::expressions; + +namespace o2::aod +{ +namespace hf_cand_bs_lite +{ +DECLARE_SOA_COLUMN(PtProng0, ptProng0, float); //! Transverse momentum of prong0 (GeV/c) +DECLARE_SOA_COLUMN(PtProng1, ptProng1, float); //! Transverse momentum of prong1 (GeV/c) +DECLARE_SOA_COLUMN(MProng0, mProng0, float); //! Invariant mass of prong0 (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(NSigTpcPi1, nSigTpcPi1, float); //! TPC Nsigma separation for prong1 with pion mass hypothesis +DECLARE_SOA_COLUMN(NSigTofPi1, nSigTofPi1, float); //! TOF Nsigma separation for prong1 with pion 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(ImpactParameterProduct, impactParameterProduct, float); //! Impact parameter product of candidate +DECLARE_SOA_COLUMN(Cpa, cpa, float); //! Cosine pointing angle of candidate +DECLARE_SOA_COLUMN(CpaXY, cpaXY, float); //! Cosine pointing angle of candidate in transverse plane +DECLARE_SOA_COLUMN(MaxNormalisedDeltaIP, maxNormalisedDeltaIP, float); //! Maximum normalized difference between measured and expected impact parameter of candidate prongs +DECLARE_SOA_COLUMN(MlScoreSig, mlScoreSig, float); //! ML score for signal class +DECLARE_SOA_COLUMN(FlagWrongCollision, flagWrongCollision, int8_t); //! Flag for association with wrong collision +} // namespace hf_cand_bs_lite + +DECLARE_SOA_TABLE(HfRedCandBsLites, "AOD", "HFREDCANDBSLITE", //! Table with some Bs properties + hf_cand::Chi2PCA, + hf_cand_bs_lite::DecayLength, + hf_cand_bs_lite::DecayLengthXY, + hf_cand_bs_lite::DecayLengthNormalised, + hf_cand_bs_lite::DecayLengthXYNormalised, + hf_cand_bs_lite::MProng0, + hf_cand_bs_lite::PtProng0, + hf_cand_bs_lite::PtProng1, + hf_cand::ImpactParameter0, + hf_cand::ImpactParameter1, + hf_cand_bs_lite::ImpactParameterProduct, + hf_cand_bs_lite::NSigTpcPi1, + hf_cand_bs_lite::NSigTofPi1, + hf_cand_bs_reduced::Prong0MlScoreBkg, + hf_cand_bs_reduced::Prong0MlScorePrompt, + hf_cand_bs_reduced::Prong0MlScoreNonprompt, + hf_cand_bs_lite::MlScoreSig, + hf_sel_candidate_bs::IsSelBsToDsPi, + hf_cand_bs_lite::M, + hf_cand_bs_lite::Pt, + hf_cand_bs_lite::Cpa, + hf_cand_bs_lite::CpaXY, + hf_cand_bs_lite::MaxNormalisedDeltaIP, + hf_cand_bs_lite::Eta, + hf_cand_bs_lite::Phi, + hf_cand_bs_lite::Y, + hf_cand_3prong::FlagMcMatchRec, + hf_cand_3prong::OriginMcRec, + hf_cand_bs_lite::FlagWrongCollision, + hf_cand_bs_lite::PtGen); + +DECLARE_SOA_TABLE(HfRedBsMcCheck, "AOD", "HFREDBSMCCHECK", //! Table with MC decay type check + hf_cand_3prong::FlagMcMatchRec, + hf_cand_bs_lite::FlagWrongCollision, + hf_cand_bs_lite::MProng0, + hf_cand_bs_lite::PtProng0, + hf_cand_bs_lite::M, + hf_cand_bs_lite::Pt, + hf_cand_bs_lite::MlScoreSig, + hf_bs_mc::PdgCodeBeautyMother, + hf_bs_mc::PdgCodeCharmMother, + hf_bs_mc::PdgCodeProng0, + hf_bs_mc::PdgCodeProng1, + hf_bs_mc::PdgCodeProng2, + hf_bs_mc::PdgCodeProng3); +} // namespace o2::aod + +/// Bs analysis task +struct HfTaskBsReduced { + 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 for acceptance calculation"}; + Configurable ptTrackMin{"ptTrackMin", 0.1, "min. track transverse momentum for acceptance calculation"}; + Configurable fillHistograms{"fillHistograms", true, "Flag to enable histogram filling"}; + Configurable fillSparses{"fillSparses", false, "Flag to enable sparse filling"}; + Configurable fillTree{"fillTree", false, "Flag to enable tree filling"}; + Configurable fillBackground{"fillBackground", false, "Flag to enable filling of background histograms/sparses/tree (only MC)"}; + Configurable downSampleBkgFactor{"downSampleBkgFactor", 1., "Fraction of background_{s} candidates to keep for ML trainings"}; + Configurable ptMaxForDownSample{"ptMaxForDownSample", 10., "Maximum pt for the application of the downsampling factor"}; + + HfHelper hfHelper; + + Filter filterSelectCandidates = (aod::hf_sel_candidate_bs::isSelBsToDsPi >= selectionFlagBs); + + HistogramRegistry registry{"registry"}; + + using TracksPion = soa::Join; + + void init(InitContext&) + { + std::array processFuncData{doprocessData, doprocessDataWithDmesMl, 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, doprocessMcWithDecayTypeCheck, doprocessMcWithDmesMl, doprocessMcWithDmesMlAndDecayTypeCheck, doprocessMcWithBsMl, doprocessMcWithBsMlAndDecayTypeCheck}; + if ((std::accumulate(processFuncMc.begin(), processFuncMc.end(), 0)) > 1) { + LOGP(fatal, "Only one process function for MC can be enabled at a time."); + } + + const AxisSpec axisMlScore{100, 0.f, 1.f}; + const AxisSpec axisMassBs{300, 4.5f, 6.0f}; + const AxisSpec axisMassDs{300, 1.75f, 2.05f}; + const AxisSpec axisDecayLength{200, 0.f, 0.4f}; + const AxisSpec axisNormDecayLength{100, 0.f, 50.f}; + const AxisSpec axisDca{100, -0.05f, 0.05f}; + const AxisSpec axisCosp{110, 0.f, 1.1f}; + const AxisSpec axisEta{30, -1.5f, 1.5f}; + const AxisSpec axisError{100, 0.f, 1.f}; + const AxisSpec axisImpParProd{100, -1.e-3, 1.e-3}; + const AxisSpec axisPtBs{100, 0.f, 50.f}; + const AxisSpec axisPtDs{100, 0.f, 50.f}; + const AxisSpec axisPtPi{100, 0.f, 10.f}; + + if (doprocessData || doprocessDataWithDmesMl || doprocessDataWithBsMl) { + if (fillHistograms) { + registry.add("hMass", "B^{0}_{s} candidates;#it{p}_{T}(B^{0}_{s}) (GeV/#it{c});#it{M} (D_{s}#pi) (GeV/#it{c}^{2});entries", {HistType::kTH2F, {axisPtBs, axisMassBs}}); + registry.add("hDecLength", "B^{0}_{s} candidates;#it{p}_{T}(B^{0}_{s}) (GeV/#it{c});B^{0}_{s} candidate decay length (cm);entries", {HistType::kTH2F, {axisPtBs, axisDecayLength}}); + registry.add("hDecLengthXy", "B^{0}_{s} candidates;#it{p}_{T}(B^{0}_{s}) (GeV/#it{c});B^{0}_{s} candidate decay length XY (cm);entries", {HistType::kTH2F, {axisPtBs, axisDecayLength}}); + registry.add("hNormDecLengthXy", "B^{0}_{s} candidates;#it{p}_{T}(B^{0}_{s}) (GeV/#it{c});B^{0}_{s} candidate norm. decay length XY (cm);entries", {HistType::kTH2F, {axisPtBs, axisNormDecayLength}}); + registry.add("hDcaProng0", "B^{0}_{s} candidates;#it{p}_{T}(B^{0}_{s}) (GeV/#it{c});prong 0 (D_{s}) DCAxy to prim. vertex (cm);entries", {HistType::kTH2F, {axisPtBs, axisDca}}); + registry.add("hDcaProng1", "B^{0}_{s} candidates;#it{p}_{T}(B^{0}_{s}) (GeV/#it{c});prong 1 (#pi) DCAxy to prim. vertex (cm);entries", {HistType::kTH2F, {axisPtBs, axisDca}}); + registry.add("hPtProng0", "B^{0}_{s} candidates;#it{p}_{T}(B^{0}_{s}) (GeV/#it{c});#it{p}_{T}(D_{s}) (GeV/#it{c});entries", {HistType::kTH2F, {axisPtBs, axisPtDs}}); + registry.add("hPtProng1", "B^{0}_{s} candidates;#it{p}_{T}(B^{0}_{s}) (GeV/#it{c});#it{p}_{T}(#pi) (GeV/#it{c});entries", {HistType::kTH2F, {axisPtBs, axisPtPi}}); + registry.add("hCosp", "B^{0}_{s} candidates;#it{p}_{T}(B^{0}_{s}) (GeV/#it{c});B^{0}_{s} candidate cos(#vartheta_{P});entries", {HistType::kTH2F, {axisPtBs, axisCosp}}); + registry.add("hCospXy", "B^{0}_{s} candidates;#it{p}_{T}(B^{0}_{s}) (GeV/#it{c});B^{0}_{s} candidate cos(#vartheta_{P}^{XY});entries", {HistType::kTH2F, {axisPtBs, axisCosp}}); + registry.add("hEta", "B^{0}_{s} candidates;#it{p}_{T}(B^{0}_{s}) (GeV/#it{c});B^{0}_{s} candidate #it{#eta};entries", {HistType::kTH2F, {axisPtBs, axisEta}}); + registry.add("hRapidity", "B^{0}_{s} candidates;#it{p}_{T}(B^{0}_{s}) (GeV/#it{c});B^{0}_{s} candidate #it{y};entries", {HistType::kTH2F, {axisPtBs, axisEta}}); + registry.add("hImpParProd", "B^{0}_{s} candidates;#it{p}_{T}(B^{0}_{s}) (GeV/#it{c});B^{0}_{s} candidate impact parameter product;entries", {HistType::kTH2F, {axisPtBs, axisImpParProd}}); + registry.add("hInvMassD", "B^{0}_{s} candidates;#it{p}_{T}(D_{s}) (GeV/#it{c});prong0, #it{M}(KK#pi) (GeV/#it{c}^{2});entries", {HistType::kTH2F, {axisPtDs, axisMassDs}}); + registry.add("hDecLengthD", "B^{0}_{s} candidates;#it{p}_{T}(D_{s}) (GeV/#it{c});D_{s} candidate decay length (cm);entries", {HistType::kTH2F, {axisPtDs, axisDecayLength}}); + registry.add("hDecLengthXyD", "B^{0}_{s} candidates;#it{p}_{T}(D_{s}) (GeV/#it{c});D_{s} candidate decay length XY (cm);entries", {HistType::kTH2F, {axisPtDs, axisDecayLength}}); + registry.add("hCospD", "B^{0}_{s} candidates;#it{p}_{T}(D_{s}) (GeV/#it{c});D_{s} candidate cos(#vartheta_{P});entries", {HistType::kTH2F, {axisPtDs, axisCosp}}); + registry.add("hCospXyD", "B^{0}_{s} candidates;#it{p}_{T}(D_{s}) (GeV/#it{c});D_{s} candidate cos(#vartheta_{P}^{XY});entries", {HistType::kTH2F, {axisPtDs, axisCosp}}); + + // ML scores of Ds- daughter + if (doprocessDataWithDmesMl) { + registry.add("hMlScoreBkgDs", "B^{0}_{s} candidates;#it{p}_{T}(D_{s}) (GeV/#it{c});prong0, Ds ML background score;entries", {HistType::kTH2F, {axisPtDs, axisMlScore}}); + registry.add("hMlScorePromptDs", "B^{0}_{s} candidates;#it{p}_{T}(D_{s}) (GeV/#it{c});prong0, Ds ML prompt score;entries", {HistType::kTH2F, {axisPtDs, axisMlScore}}); + registry.add("hMlScoreNonPromptDs", "B^{0}_{s} candidates;#it{p}_{T}(D_{s}) (GeV/#it{c});prong0, Ds ML nonprompt score;entries", {HistType::kTH2F, {axisPtDs, axisMlScore}}); + } + + // ML scores of Bs candidate + if (doprocessDataWithBsMl) { + registry.add("hMlScoreSigBs", "B^{0}_{s} candidates;#it{p}_{T}(B^{0}_{s}) (GeV/#it{c});prong0, B^{0}_{s} ML signal score;entries", {HistType::kTH2F, {axisPtBs, axisMlScore}}); + } + } + if (fillSparses) { + if (!(doprocessDataWithDmesMl || doprocessDataWithBsMl)) { + registry.add("hMassPtCutVars", "B^{0}_{s} candidates;#it{M} (D_{s}#pi) (GeV/#it{c}^{2});#it{p}_{T}(B^{0}_{s}) (GeV/#it{c});B^{0}_{s} candidate decay length (cm);B^{0}_{s} candidate norm. decay length XY (cm);B^{0}_{s} candidate impact parameter product (cm);B^{0}_{s} candidate cos(#vartheta_{P});#it{M} (KK#pi) (GeV/#it{c}^{2});#it{p}_{T}(D_{s}) (GeV/#it{c});D_{s} candidate decay length (cm);D_{s} candidate cos(#vartheta_{P})", {HistType::kTHnSparseF, {axisMassBs, axisPtBs, axisDecayLength, axisNormDecayLength, axisImpParProd, axisCosp, axisMassDs, axisPtDs, axisDecayLength, axisCosp}}); + } else { + registry.add("hMassPtCutVars", "B^{0}_{s} candidates;#it{M} (D_{s}#pi) (GeV/#it{c}^{2});#it{p}_{T}(B^{0}_{s}) (GeV/#it{c});B^{0}_{s} candidate decay length (cm);B^{0}_{s} candidate norm. decay length XY (cm);B^{0}_{s} candidate impact parameter product (cm);B^{0}_{s} candidate cos(#vartheta_{P});#it{M} (KK#pi) (GeV/#it{c}^{2});#it{p}_{T}(D_{s}) (GeV/#it{c});D_{s} candidate ML score bkg;D_{s} candidate ML score nonprompt", {HistType::kTHnSparseF, {axisMassBs, axisPtBs, axisDecayLength, axisNormDecayLength, axisImpParProd, axisCosp, axisMassDs, axisPtDs, axisMlScore, axisMlScore}}); + } + } + } + + if (doprocessMc || doprocessMcWithDecayTypeCheck || doprocessMcWithDmesMl || doprocessMcWithDmesMlAndDecayTypeCheck || doprocessMcWithBsMl || doprocessMcWithBsMlAndDecayTypeCheck) { + if (fillHistograms) { + // gen histos + registry.add("hEtaGen", "B^{0}_{s} particles (generated);#it{p}_{T}^{gen}(B^{0}_{s}) (GeV/#it{c});#it{#eta}^{gen}(B^{0}_{s});entries", {HistType::kTH2F, {axisPtBs, axisEta}}); + registry.add("hYGen", "B^{0}_{s} particles (generated);#it{p}_{T}^{gen}(B^{0}_{s}) (GeV/#it{c});#it{y}^{gen}(B^{0}_{s});entries", {HistType::kTH2F, {axisPtBs, axisEta}}); + registry.add("hYGenWithProngsInAcceptance", "MC particles (generated-daughters in acceptance);#it{p}_{T}^{gen}(B^{0}_{s}) (GeV/#it{c});#it{y}^{gen}(B^{0}_{s});entries", {HistType::kTH2F, {axisPtBs, axisEta}}); + registry.add("hPtProng0Gen", "B^{0}_{s} particles (generated);#it{p}_{T}^{gen}(B^{0}_{s}) (GeV/#it{c});#it{p}_{T}^{gen}(D_{s}) (GeV/#it{c});entries", {HistType::kTH2F, {axisPtBs, axisPtDs}}); + registry.add("hPtProng1Gen", "B^{0}_{s} particles (generated);#it{p}_{T}^{gen}(B^{0}_{s}) (GeV/#it{c});#it{p}_{T}^{gen}(#pi) (GeV/#it{c});entries", {HistType::kTH2F, {axisPtBs, axisPtPi}}); + registry.add("hYProng0Gen", "B^{0}_{s} particles (generated);#it{p}_{T}^{gen}(B^{0}_{s}) (GeV/#it{c});#it{y}^{gen}(D_{s});entries", {HistType::kTH2F, {axisPtBs, axisEta}}); + registry.add("hYProng1Gen", "B^{0}_{s} particles (generated);#it{p}_{T}^{gen}(B^{0}_{s}) (GeV/#it{c});#it{y}^{gen}(#pi);entries", {HistType::kTH2F, {axisPtBs, axisEta}}); + registry.add("hEtaProng0Gen", "B^{0}_{s} particles (generated);#it{p}_{T}^{gen}(B^{0}_{s}) (GeV/#it{c});#it{#eta}^{gen}(D_{s});entries", {HistType::kTH2F, {axisPtBs, axisEta}}); + registry.add("hEtaProng1Gen", "B^{0}_{s} particles (generated);#it{p}_{T}^{gen}(B^{0}_{s}) (GeV/#it{c});#it{#eta}^{gen}(#pi);entries", {HistType::kTH2F, {axisPtBs, axisEta}}); + + // reco histos + // signal + registry.add("hMassRecSig", "B^{0}_{s} candidates (matched);#it{p}_{T}(B^{0}_{s}) (GeV/#it{c});#it{M} (D_{s}#pi) (GeV/#it{c}^{2});entries", {HistType::kTH2F, {axisPtBs, axisMassBs}}); + registry.add("hDecLengthRecSig", "B^{0}_{s} candidates (matched);#it{p}_{T}(B^{0}_{s}) (GeV/#it{c});B^{0}_{s} candidate decay length (cm);entries", {HistType::kTH2F, {axisPtBs, axisDecayLength}}); + registry.add("hDecLengthXyRecSig", "B^{0}_{s} candidates (matched);#it{p}_{T}(B^{0}_{s}) (GeV/#it{c});B^{0}_{s} candidate decay length XY (cm);entries", {HistType::kTH2F, {axisPtBs, axisDecayLength}}); + registry.add("hNormDecLengthXyRecSig", "B^{0}_{s} candidates (matched);#it{p}_{T}(B^{0}_{s}) (GeV/#it{c});B^{0}_{s} candidate norm. decay length XY (cm);entries", {HistType::kTH2F, {axisPtBs, axisNormDecayLength}}); + registry.add("hDcaProng0RecSig", "B^{0}_{s} candidates (matched);#it{p}_{T}(B^{0}_{s}) (GeV/#it{c});prong 0 (D_{s}) DCAxy to prim. vertex (cm);entries", {HistType::kTH2F, {axisPtBs, axisDca}}); + registry.add("hDcaProng1RecSig", "B^{0}_{s} candidates (matched);#it{p}_{T}(B^{0}_{s}) (GeV/#it{c});prong 1 (#pi) DCAxy to prim. vertex (cm);entries", {HistType::kTH2F, {axisPtBs, axisDca}}); + registry.add("hPtProng0RecSig", "B^{0}_{s} candidates (matched);#it{p}_{T}(B^{0}_{s}) (GeV/#it{c});#it{p}_{T}(D_{s}) (GeV/#it{c});entries", {HistType::kTH2F, {axisPtBs, axisPtDs}}); + registry.add("hPtProng1RecSig", "B^{0}_{s} candidates (matched);#it{p}_{T}(B^{0}_{s}) (GeV/#it{c});#it{p}_{T}(#pi) (GeV/#it{c});entries", {HistType::kTH2F, {axisPtBs, axisPtPi}}); + registry.add("hCospRecSig", "B^{0}_{s} candidates (matched);#it{p}_{T}(B^{0}_{s}) (GeV/#it{c});B^{0}_{s} candidate cos(#vartheta_{P});entries", {HistType::kTH2F, {axisPtBs, axisCosp}}); + registry.add("hCospXyRecSig", "B^{0}_{s} candidates (matched);#it{p}_{T}(B^{0}_{s}) (GeV/#it{c});B^{0}_{s} candidate cos(#vartheta_{P}^{XY});entries", {HistType::kTH2F, {axisPtBs, axisCosp}}); + registry.add("hEtaRecSig", "B^{0}_{s} candidates (matched);#it{p}_{T}(B^{0}_{s}) (GeV/#it{c});B^{0}_{s} candidate #it{#eta};entries", {HistType::kTH2F, {axisPtBs, axisEta}}); + registry.add("hRapidityRecSig", "B^{0}_{s} candidates (matched);#it{p}_{T}(B^{0}_{s}) (GeV/#it{c});B^{0}_{s} candidate #it{y};entries", {HistType::kTH2F, {axisPtBs, axisEta}}); + registry.add("hImpParProdRecSig", "B^{0}_{s} candidates (matched);#it{p}_{T}(B^{0}_{s}) (GeV/#it{c});B^{0}_{s} candidate impact parameter product;entries", {HistType::kTH2F, {axisPtBs, axisImpParProd}}); + registry.add("hInvMassDRecSig", "B^{0}_{s} candidates (matched);#it{p}_{T}(D_{s}) (GeV/#it{c});prong0, #it{M}(KK#pi) (GeV/#it{c}^{2});entries", {HistType::kTH2F, {axisPtDs, axisMassDs}}); + registry.add("hDecLengthDRecSig", "B^{0}_{s} candidates (matched);#it{p}_{T}(D_{s}) (GeV/#it{c});D_{s} candidate decay length (cm);entries", {HistType::kTH2F, {axisPtDs, axisDecayLength}}); + registry.add("hDecLengthXyDRecSig", "B^{0}_{s} candidates (matched);#it{p}_{T}(D_{s}) (GeV/#it{c});D_{s} candidate decay length XY (cm);entries", {HistType::kTH2F, {axisPtDs, axisDecayLength}}); + registry.add("hCospDRecSig", "B^{0}_{s} candidates (matched);#it{p}_{T}(D_{s}) (GeV/#it{c});D_{s} candidate cos(#vartheta_{P});entries", {HistType::kTH2F, {axisPtDs, axisCosp}}); + registry.add("hCospXyDRecSig", "B^{0}_{s} candidates (matched);#it{p}_{T}(D_{s}) (GeV/#it{c});D_{s} candidate cos(#vartheta_{P}^{XY});entries", {HistType::kTH2F, {axisPtDs, axisCosp}}); + // background + if (fillBackground) { + registry.add("hMassRecBg", "B^{0}_{s} candidates (unmatched);#it{p}_{T}(B^{0}_{s}) (GeV/#it{c});#it{M} (D_{s}#pi) (GeV/#it{c}^{2});entries", {HistType::kTH2F, {axisPtBs, axisMassBs}}); + registry.add("hDecLengthRecBg", "B^{0}_{s} candidates (unmatched);#it{p}_{T}(B^{0}_{s}) (GeV/#it{c});B^{0}_{s} candidate decay length (cm);entries", {HistType::kTH2F, {axisPtBs, axisDecayLength}}); + registry.add("hDecLengthXyRecBg", "B^{0}_{s} candidates (unmatched);#it{p}_{T}(B^{0}_{s}) (GeV/#it{c});B^{0}_{s} candidate decay length XY (cm);entries", {HistType::kTH2F, {axisPtBs, axisDecayLength}}); + registry.add("hNormDecLengthXyRecBg", "B^{0}_{s} candidates (unmatched);#it{p}_{T}(B^{0}_{s}) (GeV/#it{c});B^{0}_{s} candidate norm. decay length XY (cm);entries", {HistType::kTH2F, {axisPtBs, axisNormDecayLength}}); + registry.add("hDcaProng0RecBg", "B^{0}_{s} candidates (unmatched);#it{p}_{T}(B^{0}_{s}) (GeV/#it{c});prong 0 (D_{s}) DCAxy to prim. vertex (cm);entries", {HistType::kTH2F, {axisPtBs, axisDca}}); + registry.add("hDcaProng1RecBg", "B^{0}_{s} candidates (unmatched);#it{p}_{T}(B^{0}_{s}) (GeV/#it{c});prong 1 (#pi) DCAxy to prim. vertex (cm);entries", {HistType::kTH2F, {axisPtBs, axisDca}}); + registry.add("hPtProng0RecBg", "B^{0}_{s} candidates (unmatched);#it{p}_{T}(B^{0}_{s}) (GeV/#it{c});#it{p}_{T}(D_{s}) (GeV/#it{c});entries", {HistType::kTH2F, {axisPtBs, axisPtDs}}); + registry.add("hPtProng1RecBg", "B^{0}_{s} candidates (unmatched);#it{p}_{T}(B^{0}_{s}) (GeV/#it{c});#it{p}_{T}(#pi) (GeV/#it{c});entries", {HistType::kTH2F, {axisPtBs, axisPtPi}}); + registry.add("hCospRecBg", "B^{0}_{s} candidates (unmatched);#it{p}_{T}(B^{0}_{s}) (GeV/#it{c});B^{0}_{s} candidate cos(#vartheta_{P});entries", {HistType::kTH2F, {axisPtBs, axisCosp}}); + registry.add("hCospXyRecBg", "B^{0}_{s} candidates (unmatched);#it{p}_{T}(B^{0}_{s}) (GeV/#it{c});B^{0}_{s} candidate cos(#vartheta_{P}^{XY});entries", {HistType::kTH2F, {axisPtBs, axisCosp}}); + registry.add("hEtaRecBg", "B^{0}_{s} candidates (unmatched);#it{p}_{T}(B^{0}_{s}) (GeV/#it{c});B^{0}_{s} candidate #it{#eta};entries", {HistType::kTH2F, {axisPtBs, axisEta}}); + registry.add("hRapidityRecBg", "B^{0}_{s} candidates (unmatched);#it{p}_{T}(B^{0}_{s}) (GeV/#it{c});B^{0}_{s} candidate #it{y};entries", {HistType::kTH2F, {axisPtBs, axisEta}}); + registry.add("hImpParProdRecBg", "B^{0}_{s} candidates (unmatched);#it{p}_{T}(B^{0}_{s}) (GeV/#it{c});B^{0}_{s} candidate impact parameter product;entries", {HistType::kTH2F, {axisPtBs, axisImpParProd}}); + registry.add("hInvMassDRecBg", "B^{0}_{s} candidates (unmatched);#it{p}_{T}(D_{s}) (GeV/#it{c});prong0, #it{M}(KK#pi) (GeV/#it{c}^{2});entries", {HistType::kTH2F, {axisPtDs, axisMassDs}}); + registry.add("hDecLengthDRecBg", "B^{0}_{s} candidates (unmatched);#it{p}_{T}(D_{s}) (GeV/#it{c});D_{s} candidate decay length (cm);entries", {HistType::kTH2F, {axisPtDs, axisDecayLength}}); + registry.add("hDecLengthXyDRecBg", "B^{0}_{s} candidates (unmatched);#it{p}_{T}(D_{s}) (GeV/#it{c});D_{s} candidate decay length XY (cm);entries", {HistType::kTH2F, {axisPtDs, axisDecayLength}}); + registry.add("hCospDRecBg", "B^{0}_{s} candidates (unmatched);#it{p}_{T}(D_{s}) (GeV/#it{c});D_{s} candidate cos(#vartheta_{P});entries", {HistType::kTH2F, {axisPtDs, axisCosp}}); + registry.add("hCospXyDRecBg", "B^{0}_{s} candidates (unmatched);#it{p}_{T}(D_{s}) (GeV/#it{c});D_{s} candidate cos(#vartheta_{P}^{XY});entries", {HistType::kTH2F, {axisPtDs, axisCosp}}); + } + // MC checks + if (doprocessMcWithDecayTypeCheck || doprocessMcWithBsMlAndDecayTypeCheck || doprocessMcWithDmesMlAndDecayTypeCheck) { + constexpr uint8_t kNBinsDecayTypeMc = hf_cand_bs::DecayTypeMc::NDecayTypeMc; + TString labels[kNBinsDecayTypeMc]; + labels[hf_cand_bs::DecayTypeMc::BsToDsPiToPhiPiPiToKKPiPi] = "B^{0}_{s} #rightarrow (D_{s} #rightarrow #Phi#pi #rightarrow KK#pi) #pi"; + labels[hf_cand_bs::DecayTypeMc::BsToDsPiToK0starKPiToKKPiPi] = "B^{0}_{s} #rightarrow (D_{s} #rightarrow K^{0*}K #rightarrow KK#pi) #pi"; + labels[hf_cand_bs::DecayTypeMc::B0ToDsPiToPhiPiPiToKKPiPi] = "B^{0} #rightarrow (D_{s} #rightarrow #Phi#pi #rightarrow KK#pi) #pi"; + labels[hf_cand_bs::DecayTypeMc::B0ToDsPiToK0starKPiToKKPiPi] = "B^{0} #rightarrow (D_{s} #rightarrow K^{0*}K #rightarrow KK#pi) #pi"; + labels[hf_cand_bs::DecayTypeMc::PartlyRecoDecay] = "Partly reconstructed decay channel"; + labels[hf_cand_bs::DecayTypeMc::OtherDecay] = "Other decays"; + static const AxisSpec axisDecayType = {kNBinsDecayTypeMc, 0.5, kNBinsDecayTypeMc + 0.5, ""}; + registry.add("hDecayTypeMc", "DecayType", {HistType::kTH3F, {axisDecayType, axisMassBs, axisPtBs}}); + for (uint8_t iBin = 0; iBin < kNBinsDecayTypeMc; ++iBin) { + registry.get(HIST("hDecayTypeMc"))->GetXaxis()->SetBinLabel(iBin + 1, labels[iBin]); + } + } + // ML scores of Ds- daughter + if (doprocessMcWithDmesMl || doprocessMcWithDmesMlAndDecayTypeCheck) { + // signal + registry.add("hMlScoreBkgDsRecSig", "B^{0}_{s} candidates (matched);#it{p}_{T}(D_{s}) (GeV/#it{c});prong0, Ds ML background score;entries", {HistType::kTH2F, {axisPtDs, axisMlScore}}); + registry.add("hMlScorePromptDsRecSig", "B^{0}_{s} candidates (matched);#it{p}_{T}(D_{s}) (GeV/#it{c});prong0, Ds ML prompt score;entries", {HistType::kTH2F, {axisPtDs, axisMlScore}}); + registry.add("hMlScoreNonPromptDsRecSig", "B^{0}_{s} candidates (matched);#it{p}_{T}(D_{s}) (GeV/#it{c});prong0, Ds ML nonprompt score;entries", {HistType::kTH2F, {axisPtDs, axisMlScore}}); + // background + registry.add("hMlScoreBkgDsRecBg", "B^{0}_{s} candidates (unmatched);#it{p}_{T}(D_{s}) (GeV/#it{c});prong0, Ds ML background score;entries", {HistType::kTH2F, {axisPtDs, axisMlScore}}); + registry.add("hMlScorePromptDsRecBg", "B^{0}_{s} candidates (unmatched);#it{p}_{T}(D_{s}) (GeV/#it{c});prong0, Ds ML prompt score;entries", {HistType::kTH2F, {axisPtDs, axisMlScore}}); + registry.add("hMlScoreNonPromptDsRecBg", "B^{0}_{s} candidates (unmatched);#it{p}_{T}(D_{s}) (GeV/#it{c});prong0, Ds ML nonprompt score;entries", {HistType::kTH2F, {axisPtDs, axisMlScore}}); + } + // ML scores of Bs candidate + if (doprocessMcWithBsMl || doprocessMcWithBsMlAndDecayTypeCheck) { + // signal + registry.add("hMlScoreSigBsRecSig", "B^{0}_{s} candidates (matched);#it{p}_{T}(B^{0}_{s}) (GeV/#it{c});prong0, B^{0}_{s} ML signal score;entries", {HistType::kTH2F, {axisPtBs, axisMlScore}}); + // background + registry.add("hMlScoreSigBsRecBg", "B^{0}_{s} candidates (unmatched);#it{p}_{T}(B^{0}_{s}) (GeV/#it{c});prong0, B^{0}_{s} ML signal score;entries", {HistType::kTH2F, {axisPtBs, axisMlScore}}); + } + } + if (fillSparses) { + // gen sparses + registry.add("hPtYGenSig", "B^{0}_{s} particles (generated);#it{p}_{T}(B^{0}_{s}) (GeV/#it{c});#it{y}(B^{0}_{s})", {HistType::kTHnSparseF, {axisPtBs, axisEta}}); + registry.add("hPtYWithProngsInAccepanceGenSig", "B^{0}_{s} particles (generated-daughters in acceptance);#it{p}_{T}(B^{0}_{s}) (GeV/#it{c});#it{y}(B^{0}_{s})", {HistType::kTHnSparseF, {axisPtBs, axisEta}}); + + // reco sparses + if (!(doprocessDataWithDmesMl || doprocessDataWithBsMl)) { + registry.add("hMassPtCutVarsRecSig", "B^{0}_{s} candidates (matched);#it{M} (D_{s}#pi) (GeV/#it{c}^{2});#it{p}_{T}(B^{0}_{s}) (GeV/#it{c});B^{0}_{s} candidate decay length (cm);B^{0}_{s} candidate norm. decay length XY (cm);B^{0}_{s} candidate impact parameter product (cm);B^{0}_{s} candidate cos(#vartheta_{P});#it{M} (KK#pi) (GeV/#it{c}^{2});#it{p}_{T}(D_{s}) (GeV/#it{c});D_{s} candidate decay length (cm);D_{s} candidate cos(#vartheta_{P})", {HistType::kTHnSparseF, {axisMassBs, axisPtBs, axisDecayLength, axisNormDecayLength, axisImpParProd, axisCosp, axisMassDs, axisPtDs, axisDecayLength, axisCosp}}); + if (fillBackground) { + registry.add("hMassPtCutVarsRecBg", "B^{0}_{s} candidates (unmatched);#it{M} (D_{s}#pi) (GeV/#it{c}^{2});#it{p}_{T}(B^{0}_{s}) (GeV/#it{c});B^{0}_{s} candidate decay length (cm);B^{0}_{s} candidate norm. decay length XY (cm);B^{0}_{s} candidate impact parameter product (cm);B^{0}_{s} candidate cos(#vartheta_{P});#it{M} (KK#pi) (GeV/#it{c}^{2});#it{p}_{T}(D_{s}) (GeV/#it{c});D_{s} candidate decay length (cm);D_{s} candidate cos(#vartheta_{P})", {HistType::kTHnSparseF, {axisMassBs, axisPtBs, axisDecayLength, axisNormDecayLength, axisImpParProd, axisCosp, axisMassDs, axisPtDs, axisDecayLength, axisCosp}}); + } + } else { + registry.add("hMassPtCutVarsRecSig", "B^{0}_{s} candidates (matched);#it{M} (D_{s}#pi) (GeV/#it{c}^{2});#it{p}_{T}(B^{0}_{s}) (GeV/#it{c});B^{0}_{s} candidate decay length (cm);B^{0}_{s} candidate norm. decay length XY (cm);B^{0}_{s} candidate impact parameter product (cm);B^{0}_{s} candidate cos(#vartheta_{P});#it{M} (KK#pi) (GeV/#it{c}^{2});#it{p}_{T}(D_{s}) (GeV/#it{c});D_{s} candidate ML score bkg;D_{s} candidate ML score nonprompt", {HistType::kTHnSparseF, {axisMassBs, axisPtBs, axisDecayLength, axisNormDecayLength, axisImpParProd, axisCosp, axisMassDs, axisPtDs, axisMlScore, axisMlScore}}); + if (fillBackground) { + registry.add("hMassPtCutVarsRecBg", "B^{0}_{s} candidates (unmatched);#it{M} (D_{s}#pi) (GeV/#it{c}^{2});#it{p}_{T}(B^{0}_{s}) (GeV/#it{c});B^{0}_{s} candidate decay length (cm);B^{0}_{s} candidate norm. decay length XY (cm);B^{0}_{s} candidate impact parameter product (cm);B^{0}_{s} candidate cos(#vartheta_{P});#it{M} (KK#pi) (GeV/#it{c}^{2});#it{p}_{T}(D_{s}) (GeV/#it{c});D_{s} candidate ML score bkg;D_{s} candidate ML score nonprompt", {HistType::kTHnSparseF, {axisMassBs, axisPtBs, axisDecayLength, axisNormDecayLength, axisImpParProd, axisCosp, axisMassDs, axisPtDs, axisMlScore, axisMlScore}}); + } + } + } + } + } + + /// 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; + } + + /// Fill candidate information at reconstruction level + /// \param doMc is the flag to enable the filling with MC information + /// \param withDecayTypeCheck is the flag to enable MC with decay type check + /// \param withDmesMl is the flag to enable the filling with ML scores for the Ds- daughter + /// \param withBsMl is the flag to enable the filling with ML scores for the Bs candidate + /// \param candidate is the Bs candidate + /// \param candidatesD is the table with Ds- candidates + template + void fillCand(Cand const& candidate, + aod::HfRed3Prongs const&) + { + auto ptCandBs = candidate.pt(); + auto invMassBs = hfHelper.invMassBsToDsPi(candidate); + auto candDs = candidate.template prong0_as(); + auto ptDs = candidate.ptProng0(); + auto invMassDs = candDs.invMassHypo0() > 0 ? candDs.invMassHypo0() : candDs.invMassHypo1(); + // TODO: here we are assuming that only one of the two hypotheses is filled, to be checked + std::array posPv{candidate.posX(), candidate.posY(), candidate.posZ()}; + std::array posSvDs{candDs.xSecondaryVertex(), candDs.ySecondaryVertex(), candDs.zSecondaryVertex()}; + std::array momDs{candDs.pVector()}; + auto cospDs = RecoDecay::cpa(posPv, posSvDs, momDs); + auto cospXyDs = RecoDecay::cpaXY(posPv, posSvDs, momDs); + auto decLenDs = RecoDecay::distance(posPv, posSvDs); + auto decLenXyDs = RecoDecay::distanceXY(posPv, posSvDs); + + int8_t flagMcMatchRec = 0; + int8_t flagWrongCollision = 0; + bool isSignal = false; + if constexpr (doMc) { + flagMcMatchRec = candidate.flagMcMatchRec(); + flagWrongCollision = candidate.flagWrongCollision(); + isSignal = TESTBIT(std::abs(flagMcMatchRec), hf_cand_bs::DecayTypeMc::BsToDsPiToPhiPiPiToKKPiPi); + } + + if (fillHistograms) { + if constexpr (doMc) { + if (isSignal) { + registry.fill(HIST("hMassRecSig"), ptCandBs, invMassBs); + registry.fill(HIST("hPtProng0RecSig"), ptCandBs, candidate.ptProng0()); + registry.fill(HIST("hPtProng1RecSig"), ptCandBs, candidate.ptProng1()); + registry.fill(HIST("hImpParProdRecSig"), ptCandBs, candidate.impactParameterProduct()); + registry.fill(HIST("hDecLengthRecSig"), ptCandBs, candidate.decayLength()); + registry.fill(HIST("hDecLengthXyRecSig"), ptCandBs, candidate.decayLengthXY()); + registry.fill(HIST("hNormDecLengthXyRecSig"), ptCandBs, candidate.decayLengthXY() / candidate.errorDecayLengthXY()); + registry.fill(HIST("hDcaProng0RecSig"), ptCandBs, candidate.impactParameter0()); + registry.fill(HIST("hDcaProng1RecSig"), ptCandBs, candidate.impactParameter1()); + registry.fill(HIST("hCospRecSig"), ptCandBs, candidate.cpa()); + registry.fill(HIST("hCospXyRecSig"), ptCandBs, candidate.cpaXY()); + registry.fill(HIST("hEtaRecSig"), ptCandBs, candidate.eta()); + registry.fill(HIST("hRapidityRecSig"), ptCandBs, hfHelper.yBs(candidate)); + registry.fill(HIST("hInvMassDRecSig"), ptDs, invMassDs); + registry.fill(HIST("hDecLengthDRecSig"), ptDs, decLenDs); + registry.fill(HIST("hDecLengthXyDRecSig"), ptDs, decLenXyDs); + registry.fill(HIST("hCospDRecSig"), ptDs, cospDs); + registry.fill(HIST("hCospXyDRecSig"), ptDs, cospXyDs); + if constexpr (withDecayTypeCheck) { + registry.fill(HIST("hDecayTypeMc"), 1 + hf_cand_bs::DecayTypeMc::BsToDsPiToPhiPiPiToKKPiPi, invMassBs, ptCandBs); + } + if constexpr (withDmesMl) { + registry.fill(HIST("hMlScoreBkgDsRecSig"), ptDs, candidate.prong0MlScoreBkg()); + registry.fill(HIST("hMlScorePromptDsRecSig"), ptDs, candidate.prong0MlScorePrompt()); + registry.fill(HIST("hMlScoreNonPromptDsRecSig"), ptDs, candidate.prong0MlScoreNonprompt()); + } + if constexpr (withBsMl) { + registry.fill(HIST("hMlScoreSigBsRecSig"), ptCandBs, candidate.mlProbBsToDsPi()[1]); + } + } else if (fillBackground) { + registry.fill(HIST("hMassRecBg"), ptCandBs, invMassBs); + registry.fill(HIST("hPtProng0RecBg"), ptCandBs, candidate.ptProng0()); + registry.fill(HIST("hPtProng1RecBg"), ptCandBs, candidate.ptProng1()); + registry.fill(HIST("hImpParProdRecBg"), ptCandBs, candidate.impactParameterProduct()); + registry.fill(HIST("hDecLengthRecBg"), ptCandBs, candidate.decayLength()); + registry.fill(HIST("hDecLengthXyRecBg"), ptCandBs, candidate.decayLengthXY()); + registry.fill(HIST("hNormDecLengthXyRecBg"), ptCandBs, candidate.decayLengthXY() / candidate.errorDecayLengthXY()); + registry.fill(HIST("hDcaProng0RecBg"), ptCandBs, candidate.impactParameter0()); + registry.fill(HIST("hDcaProng1RecBg"), ptCandBs, candidate.impactParameter1()); + registry.fill(HIST("hCospRecBg"), ptCandBs, candidate.cpa()); + registry.fill(HIST("hCospXyRecBg"), ptCandBs, candidate.cpaXY()); + registry.fill(HIST("hEtaRecBg"), ptCandBs, candidate.eta()); + registry.fill(HIST("hRapidityRecBg"), ptCandBs, hfHelper.yBs(candidate)); + registry.fill(HIST("hInvMassDRecBg"), ptDs, invMassDs); + registry.fill(HIST("hDecLengthDRecBg"), ptDs, decLenDs); + registry.fill(HIST("hDecLengthXyDRecBg"), ptDs, decLenXyDs); + registry.fill(HIST("hCospDRecBg"), ptDs, cospDs); + registry.fill(HIST("hCospXyDRecBg"), ptDs, cospXyDs); + if constexpr (withDmesMl) { + registry.fill(HIST("hMlScoreBkgDsRecBg"), ptDs, candidate.prong0MlScoreBkg()); + registry.fill(HIST("hMlScorePromptDsRecBg"), ptDs, candidate.prong0MlScorePrompt()); + registry.fill(HIST("hMlScoreNonPromptDsRecBg"), ptDs, candidate.prong0MlScoreNonprompt()); + } + if constexpr (withBsMl) { + registry.fill(HIST("hMlScoreSigBsRecBg"), ptCandBs, candidate.mlProbBsToDsPi()[1]); + } + } else if constexpr (withDecayTypeCheck) { + for (uint8_t iFlag = 1; iFlag < hf_cand_bs::DecayTypeMc::NDecayTypeMc; ++iFlag) { + if (TESTBIT(flagMcMatchRec, iFlag)) { + registry.fill(HIST("hDecayTypeMc"), 1 + iFlag, invMassBs, ptCandBs); + } + } + } + } else { + registry.fill(HIST("hMass"), ptCandBs, invMassBs); + registry.fill(HIST("hPtProng0"), ptCandBs, candidate.ptProng0()); + registry.fill(HIST("hPtProng1"), ptCandBs, candidate.ptProng1()); + registry.fill(HIST("hImpParProd"), ptCandBs, candidate.impactParameterProduct()); + registry.fill(HIST("hDecLength"), ptCandBs, candidate.decayLength()); + registry.fill(HIST("hDecLengthXy"), ptCandBs, candidate.decayLengthXY()); + registry.fill(HIST("hNormDecLengthXy"), ptCandBs, candidate.decayLengthXY() / candidate.errorDecayLengthXY()); + registry.fill(HIST("hDcaProng0"), ptCandBs, candidate.impactParameter0()); + registry.fill(HIST("hDcaProng1"), ptCandBs, candidate.impactParameter1()); + registry.fill(HIST("hCosp"), ptCandBs, candidate.cpa()); + registry.fill(HIST("hCospXy"), ptCandBs, candidate.cpaXY()); + registry.fill(HIST("hEta"), ptCandBs, candidate.eta()); + registry.fill(HIST("hRapidity"), ptCandBs, hfHelper.yBs(candidate)); + registry.fill(HIST("hInvMassD"), ptDs, invMassDs); + registry.fill(HIST("hDecLengthD"), ptDs, decLenDs); + registry.fill(HIST("hDecLengthXyD"), ptDs, decLenXyDs); + registry.fill(HIST("hCospD"), ptDs, cospDs); + registry.fill(HIST("hCospXyD"), ptDs, cospXyDs); + + if constexpr (withDmesMl) { + registry.fill(HIST("hMlScoreBkgDs"), ptDs, candidate.prong0MlScoreBkg()); + registry.fill(HIST("hMlScorePromptDs"), ptDs, candidate.prong0MlScorePrompt()); + registry.fill(HIST("hMlScoreNonPromptDs"), ptDs, candidate.prong0MlScoreNonprompt()); + } + if constexpr (withBsMl) { + registry.fill(HIST("hMlScoreSigBs"), ptCandBs, candidate.mlProbBsToDsPi()[1]); + } + } + } + if (fillSparses) { + if constexpr (withDmesMl) { + 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()); + } else { + registry.fill(HIST("hMassPtCutVarsRecSig"), invMassBs, ptCandBs, candidate.decayLength(), candidate.decayLengthXY() / candidate.errorDecayLengthXY(), candidate.impactParameterProduct(), candidate.cpa(), invMassDs, ptDs, decLenDs, cospDs); + } + } else if (fillBackground) { + if constexpr (withDmesMl) { + registry.fill(HIST("hMassPtCutVarsRecBg"), invMassBs, ptCandBs, candidate.decayLength(), candidate.decayLengthXY() / candidate.errorDecayLengthXY(), candidate.impactParameterProduct(), candidate.cpa(), invMassDs, ptDs, candidate.prong0MlScoreBkg(), candidate.prong0MlScoreNonprompt()); + } else { + registry.fill(HIST("hMassPtCutVarsRecBg"), invMassBs, ptCandBs, candidate.decayLength(), candidate.decayLengthXY() / candidate.errorDecayLengthXY(), candidate.impactParameterProduct(), candidate.cpa(), invMassDs, ptDs, decLenDs, cospDs); + } + } + } else { + if constexpr (withDmesMl) { + registry.fill(HIST("hMassPtCutVars"), invMassBs, ptCandBs, candidate.decayLength(), candidate.decayLengthXY() / candidate.errorDecayLengthXY(), candidate.impactParameterProduct(), candidate.cpa(), invMassDs, ptDs, candidate.prong0MlScoreBkg(), candidate.prong0MlScoreNonprompt()); + } else { + registry.fill(HIST("hMassPtCutVars"), invMassBs, ptCandBs, candidate.decayLength(), candidate.decayLengthXY() / candidate.errorDecayLengthXY(), candidate.impactParameterProduct(), candidate.cpa(), invMassDs, ptDs, decLenDs, cospDs); + } + } + } + if (fillTree) { + float pseudoRndm = ptDs * 1000. - (int64_t)(ptDs * 1000); + if (flagMcMatchRec != 0 || (((doMc && fillBackground) || !doMc) && (ptCandBs >= ptMaxForDownSample || pseudoRndm < downSampleBkgFactor))) { + float prong0MlScoreBkg = -1.; + float prong0MlScorePrompt = -1.; + float prong0MlScoreNonprompt = -1.; + float candidateMlScoreSig = -1; + if constexpr (withDmesMl) { + prong0MlScoreBkg = candidate.prong0MlScoreBkg(); + prong0MlScorePrompt = candidate.prong0MlScorePrompt(); + prong0MlScoreNonprompt = candidate.prong0MlScoreNonprompt(); + } + if constexpr (withBsMl) { + candidateMlScoreSig = candidate.mlProbBsToDsPi()[1]; + } + auto prong1 = candidate.template prong1_as(); + + float ptMother = -1.; + if constexpr (doMc) { + ptMother = candidate.ptMother(); + } + + hfRedCandBsLite( + candidate.chi2PCA(), + candidate.decayLength(), + candidate.decayLengthXY(), + candidate.decayLengthNormalised(), + candidate.decayLengthXYNormalised(), + invMassDs, + ptDs, + candidate.ptProng1(), + candidate.impactParameter0(), + candidate.impactParameter1(), + candidate.impactParameterProduct(), + prong1.tpcNSigmaPi(), + prong1.tofNSigmaPi(), + prong0MlScoreBkg, + prong0MlScorePrompt, + prong0MlScoreNonprompt, + candidateMlScoreSig, + candidate.isSelBsToDsPi(), + invMassBs, + ptCandBs, + candidate.cpa(), + candidate.cpaXY(), + candidate.maxNormalisedDeltaIP(), + candidate.eta(), + candidate.phi(), + hfHelper.yBs(candidate), + flagMcMatchRec, + isSignal, + flagWrongCollision, + ptMother); + + if constexpr (withDecayTypeCheck) { + float candidateMlScoreSig = -1; + if constexpr (withBsMl) { + candidateMlScoreSig = candidate.mlProbBsToDsPi()[1]; + } + hfRedBsMcCheck( + flagMcMatchRec, + flagWrongCollision, + invMassDs, + ptDs, + invMassBs, + ptCandBs, + candidateMlScoreSig, + candidate.pdgCodeBeautyMother(), + candidate.pdgCodeCharmMother(), + candidate.pdgCodeProng0(), + candidate.pdgCodeProng1(), + candidate.pdgCodeProng2(), + candidate.pdgCodeProng3()); + } + } + } + } + + /// Fill particle histograms (gen MC truth) + void fillCandMcGen(aod::HfMcGenRedBss::iterator const& particle) + { + // keep only generated Bs with the analysis decay channel + if (!TESTBIT(std::abs(particle.flagMcMatchGen()), hf_cand_bs::DecayTypeMc::BsToDsPiToPhiPiPiToKKPiPi)) { + return; + } + auto ptParticle = particle.ptTrack(); + auto yParticle = particle.yTrack(); + auto etaParticle = particle.etaTrack(); + if (yCandGenMax >= 0. && std::abs(yParticle) > yCandGenMax) { + return; + } + std::array ptProngs = {particle.ptProng0(), particle.ptProng1()}; + std::array yProngs = {particle.yProng0(), particle.yProng1()}; + std::array etaProngs = {particle.etaProng0(), particle.etaProng1()}; + bool prongsInAcc = isProngInAcceptance(etaProngs[0], ptProngs[0]) && isProngInAcceptance(etaProngs[1], ptProngs[1]); + + if (fillHistograms) { + registry.fill(HIST("hPtProng0Gen"), ptParticle, ptProngs[0]); + registry.fill(HIST("hPtProng1Gen"), ptParticle, ptProngs[1]); + registry.fill(HIST("hYProng0Gen"), ptParticle, yProngs[0]); + registry.fill(HIST("hYProng1Gen"), ptParticle, yProngs[1]); + registry.fill(HIST("hEtaProng0Gen"), ptParticle, etaProngs[0]); + registry.fill(HIST("hEtaProng1Gen"), ptParticle, etaProngs[1]); + + registry.fill(HIST("hYGen"), ptParticle, yParticle); + registry.fill(HIST("hEtaGen"), ptParticle, etaParticle); + + // generated Bs with daughters in geometrical acceptance + if (prongsInAcc) { + registry.fill(HIST("hYGenWithProngsInAcceptance"), ptParticle, yParticle); + } + } + if (fillSparses) { + registry.fill(HIST("hPtYGenSig"), ptParticle, yParticle); + if (prongsInAcc) { + registry.fill(HIST("hPtYWithProngsInAccepanceGenSig"), ptParticle, yParticle); + } + } + } + + // Process functions + void processData(soa::Filtered> const& candidates, + aod::HfRed3Prongs const& candidatesD, + TracksPion const&) + { + for (const auto& candidate : candidates) { + if (yCandRecoMax >= 0. && std::abs(hfHelper.yBs(candidate)) > yCandRecoMax) { + continue; + } + fillCand(candidate, candidatesD); + } // candidate loop + } // processData + PROCESS_SWITCH(HfTaskBsReduced, processData, "Process data without ML scores for Bs and D daughter", true); + + void processDataWithDmesMl(soa::Filtered> const& candidates, + aod::HfRed3Prongs const& candidatesD, + TracksPion const&) + { + for (const auto& candidate : candidates) { + if (yCandRecoMax >= 0. && std::abs(hfHelper.yBs(candidate)) > yCandRecoMax) { + continue; + } + fillCand(candidate, candidatesD); + } // candidate loop + } // processDataWithDmesMl + PROCESS_SWITCH(HfTaskBsReduced, processDataWithDmesMl, "Process data with(out) ML scores for D daughter (Bs)", false); + + void processDataWithBsMl(soa::Filtered> const& candidates, + aod::HfRed3Prongs const& candidatesD, + TracksPion const&) + { + for (const auto& candidate : candidates) { + if (yCandRecoMax >= 0. && std::abs(hfHelper.yBs(candidate)) > yCandRecoMax) { + continue; + } + fillCand(candidate, candidatesD); + } // candidate loop + } // processDataWithBsMl + PROCESS_SWITCH(HfTaskBsReduced, processDataWithBsMl, "Process data with(out) ML scores for Bs (D daughter)", false); + + void processMc(soa::Filtered> const& candidates, + aod::HfMcGenRedBss const& mcParticles, + aod::HfRed3Prongs const& candidatesD, + TracksPion const&) + { + // MC rec + for (const auto& candidate : candidates) { + if (yCandRecoMax >= 0. && std::abs(hfHelper.yBs(candidate)) > yCandRecoMax) { + continue; + } + fillCand(candidate, candidatesD); + } // rec + + // MC gen. level + for (const auto& particle : mcParticles) { + fillCandMcGen(particle); + } // gen + } // processMc + PROCESS_SWITCH(HfTaskBsReduced, processMc, "Process MC without ML scores for Bs and D daughter", false); + + void processMcWithDecayTypeCheck(soa::Filtered> const& candidates, + aod::HfMcGenRedBss const& mcParticles, + aod::HfRed3Prongs const& candidatesD, + TracksPion const&) + { + // MC rec + for (const auto& candidate : candidates) { + if (yCandRecoMax >= 0. && std::abs(hfHelper.yBs(candidate)) > yCandRecoMax) { + continue; + } + fillCand(candidate, candidatesD); + } // rec + + // MC gen. level + for (const auto& particle : mcParticles) { + fillCandMcGen(particle); + } // gen + } // processMc + PROCESS_SWITCH(HfTaskBsReduced, processMcWithDecayTypeCheck, "Process MC with decay type check and without ML scores for Bs and D daughter", false); + + void processMcWithDmesMl(soa::Filtered> const& candidates, + aod::HfMcGenRedBss const& mcParticles, + aod::HfRed3Prongs const& candidatesD, + TracksPion const&) + { + // MC rec + for (const auto& candidate : candidates) { + if (yCandRecoMax >= 0. && std::abs(hfHelper.yBs(candidate)) > yCandRecoMax) { + continue; + } + fillCand(candidate, candidatesD); + } // rec + + // MC gen. level + for (const auto& particle : mcParticles) { + fillCandMcGen(particle); + } // gen + } // processMcWithDmesMl + PROCESS_SWITCH(HfTaskBsReduced, processMcWithDmesMl, "Process MC with(out) ML scores for D daughter (Bs)", false); + + void processMcWithDmesMlAndDecayTypeCheck(soa::Filtered> const& candidates, + aod::HfMcGenRedBss const& mcParticles, + aod::HfRed3Prongs const& candidatesD, + TracksPion const&) + { + // MC rec + for (const auto& candidate : candidates) { + if (yCandRecoMax >= 0. && std::abs(hfHelper.yBs(candidate)) > yCandRecoMax) { + continue; + } + fillCand(candidate, candidatesD); + } // rec + + // MC gen. level + for (const auto& particle : mcParticles) { + fillCandMcGen(particle); + } // gen + } // processMc + PROCESS_SWITCH(HfTaskBsReduced, processMcWithDmesMlAndDecayTypeCheck, "Process MC with decay type check and with(out) ML scores for Bs (D daughter)", false); + + void processMcWithBsMl(soa::Filtered> const& candidates, + aod::HfMcGenRedBss const& mcParticles, + aod::HfRed3Prongs const& candidatesD, + TracksPion const&) + { + // MC rec + for (const auto& candidate : candidates) { + if (yCandRecoMax >= 0. && std::abs(hfHelper.yBs(candidate)) > yCandRecoMax) { + continue; + } + fillCand(candidate, candidatesD); + } // rec + + // MC gen. level + for (const auto& particle : mcParticles) { + fillCandMcGen(particle); + } // gen + } // processMcWithBsMl + PROCESS_SWITCH(HfTaskBsReduced, processMcWithBsMl, "Process MC with(out) ML scores for Bs (D daughter)", false); + + void processMcWithBsMlAndDecayTypeCheck(soa::Filtered> const& candidates, + aod::HfMcGenRedBss const& mcParticles, + aod::HfRed3Prongs const& candidatesD, + TracksPion const&) + { + // MC rec + for (const auto& candidate : candidates) { + if (yCandRecoMax >= 0. && std::abs(hfHelper.yBs(candidate)) > yCandRecoMax) { + continue; + } + fillCand(candidate, candidatesD); + } // rec + + // MC gen. level + for (const auto& particle : mcParticles) { + fillCandMcGen(particle); + } // gen + } // processMc + PROCESS_SWITCH(HfTaskBsReduced, processMcWithBsMlAndDecayTypeCheck, "Process MC with decay type check and with(out) ML scores for B0 (D daughter)", false); +}; // struct + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc)}; +} diff --git a/PWGHF/D2H/Tasks/taskDs.cxx b/PWGHF/D2H/Tasks/taskDs.cxx index e113c5fef63..f962cc5acfc 100644 --- a/PWGHF/D2H/Tasks/taskDs.cxx +++ b/PWGHF/D2H/Tasks/taskDs.cxx @@ -524,7 +524,7 @@ struct HfTaskDs { unsigned maxNumContrib = 0; const auto& recoCollsPerMcColl = recoCollisions.sliceBy(std::get>(colPerMcCollisionMap.at(centDetector)), particle.mcCollision().globalIndex()); - for (const auto& recCol : recoCollisions) { + for (const auto& recCol : recoCollsPerMcColl) { maxNumContrib = recCol.numContrib() > maxNumContrib ? recCol.numContrib() : maxNumContrib; } diff --git a/PWGHF/D2H/Utils/utilsRedDataFormat.h b/PWGHF/D2H/Utils/utilsRedDataFormat.h index 2d99105e474..9740e55d372 100644 --- a/PWGHF/D2H/Utils/utilsRedDataFormat.h +++ b/PWGHF/D2H/Utils/utilsRedDataFormat.h @@ -10,7 +10,7 @@ // or submit itself to any jurisdiction. /// \file utilsRedDataFormat.h -/// \brief Event selection utilities for reduced data format analyses +/// \brief Utilities for reduced data format analyses /// \author Luca Aglietta , UniTO Turin #ifndef PWGHF_D2H_UTILS_UTILSREDDATAFORMAT_H_ @@ -51,4 +51,31 @@ void checkEvSel(Coll const& collision, o2::hf_evsel::HfEventSelection& hfEvSel, } } // namespace o2::hf_evsel +namespace o2::pid_tpc_tof_utils +{ +/// Helper function to retrive PID information of bachelor pion from b-hadron decay +/// \param prong1 pion track from reduced data format, soa::Join +template +float getTpcTofNSigmaPi1(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.tpcNSigmaPi(); + float tofNSigma = prong1.tofNSigmaPi(); + return std::sqrt(.5f * tpcNSigma * tpcNSigma + .5f * tofNSigma * tofNSigma); + } + if (hasTpc) { + return std::abs(prong1.tpcNSigmaPi()); + } + if (hasTof) { + return std::abs(prong1.tofNSigmaPi()); + } + 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 13bdd7b378e..a2c2c6e3f88 100644 --- a/PWGHF/DataModel/CandidateReconstructionTables.h +++ b/PWGHF/DataModel/CandidateReconstructionTables.h @@ -1735,16 +1735,23 @@ 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(FlagMcMatchGen, flagMcMatchGen, int8_t); // generator level +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 // mapping of decay types enum DecayType { BsToDsPi }; -enum DecayTypeMc : uint8_t { BsToDsPiToKKPiPi = 0, // Bs(bar) → Ds∓ π± → (Phi π∓) π± → (K- K+ π∓) π± - B0ToDsPiToKKPiPi, // B0(bar) → Ds± π∓ → (Phi π±) π∓ → (K- K+ π±) π∓ - PartlyRecoDecay, // 4 final state particles have another common b-hadron ancestor - NDecayTypeMc }; // counter of differentiated MC decay types +enum DecayTypeMc : uint8_t { BsToDsPiToPhiPiPiToKKPiPi = 0, // Bs(bar) → Ds∓ π± → (Phi π∓) π± → (K- K+ π∓) π± + BsToDsPiToK0starKPiToKKPiPi, // Bs(bar) → Ds∓ π± → (K0* K∓) π± → (K- K+ π∓) π± + B0ToDsPiToPhiPiPiToKKPiPi, // B0(bar) → Ds± π∓ → (Phi π±) π∓ → (K- K+ π±) π∓ + B0ToDsPiToK0starKPiToKKPiPi, // B0(bar) → Ds± π∓ → (K0* K±) π∓ → (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 @@ -1757,8 +1764,6 @@ DECLARE_SOA_TABLE(HfCandBsBase, "AOD", "HFCANDBSBASE", hf_cand::PxProng1, hf_cand::PyProng1, hf_cand::PzProng1, hf_cand::ImpactParameter0, hf_cand::ImpactParameter1, hf_cand::ErrorImpactParameter0, hf_cand::ErrorImpactParameter1, - hf_cand_bs::Prong0Id, hf_track_index::Prong1Id, - hf_track_index::HFflag, /* dynamic columns */ hf_cand_2prong::M, hf_cand_2prong::M2, @@ -1780,13 +1785,17 @@ DECLARE_SOA_TABLE(HfCandBsBase, "AOD", "HFCANDBSBASE", hf_cand::Phi, hf_cand::Y, hf_cand::E, - hf_cand::E2); + hf_cand::E2, + o2::soa::Marker<1>); // extended table with expression columns that can be used as arguments of dynamic columns DECLARE_SOA_EXTENDED_TABLE_USER(HfCandBsExt, HfCandBsBase, "HFCANDBSEXT", hf_cand_2prong::Px, hf_cand_2prong::Py, hf_cand_2prong::Pz); -using HfCandBs = HfCandBsExt; +DECLARE_SOA_TABLE(HfCandBsProngs, "AOD", "HFCANDBSPRONGS", + hf_cand_bs::Prong0Id, hf_track_index::Prong1Id); + +using HfCandBs = soa::Join; // table with results of reconstruction level MC matching DECLARE_SOA_TABLE(HfCandBsMcRec, "AOD", "HFCANDBSMCREC", diff --git a/PWGHF/HFC/TableProducer/correlatorDMesonPairs.cxx b/PWGHF/HFC/TableProducer/correlatorDMesonPairs.cxx index 6288d7388b5..64c2043bdb8 100644 --- a/PWGHF/HFC/TableProducer/correlatorDMesonPairs.cxx +++ b/PWGHF/HFC/TableProducer/correlatorDMesonPairs.cxx @@ -202,6 +202,9 @@ struct HfCorrelatorDMesonPairs { registry.add("hInputCheckD0OrD0barMcGen", "Check on input D0 | D0bar meson candidates/event MC Gen", {HistType::kTH1F, {axisInputD0}}); registry.add("hMass", "D Meson pair candidates;inv. mass (#pi K) (GeV/#it{c}^{2});entries", {HistType::kTH2F, {{120, 1.5848, 2.1848}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); + registry.add("hMassMcRecPrompt", "D Meson pair candidates;inv. mass (#pi K) (GeV/#it{c}^{2});entries", {HistType::kTH2F, {{120, 1.5848, 2.1848}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); + registry.add("hMassMcRecNonPrompt", "D Meson pair candidates;inv. mass (#pi K) (GeV/#it{c}^{2});entries", {HistType::kTH2F, {{120, 1.5848, 2.1848}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); + registry.add("hMassMcRecReflections", "D Meson pair candidates;inv. mass (#pi K) (GeV/#it{c}^{2});entries", {HistType::kTH2F, {{120, 1.5848, 2.1848}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); } /// Sets bits to select candidate type for D0 @@ -329,7 +332,6 @@ struct HfCorrelatorDMesonPairs { registry.fill(HIST("hPhi"), candidate.phi()); registry.fill(HIST("hY"), candidate.y(MassD0)); registry.fill(HIST("hPtCandAfterCut"), candidate.pt()); - registry.fill(HIST("hMass"), hfHelper.invMassD0ToPiK(candidate), candidate.pt()); bool isDCand1 = isD(candidateType1); bool isDbarCand1 = isDbar(candidateType1); @@ -463,6 +465,13 @@ struct HfCorrelatorDMesonPairs { bool isDCand1 = isD(candidateType1); bool isDbarCand1 = isDbar(candidateType1); + if (isDCand1) { + registry.fill(HIST("hMass"), hfHelper.invMassD0ToPiK(candidate1), candidate1.pt()); + } + if (isDbarCand1) { + registry.fill(HIST("hMass"), hfHelper.invMassD0barToKPi(candidate1), candidate1.pt()); + } + for (auto candidate2 = candidate1 + 1; candidate2 != selectedD0CandidatesGrouped.end(); ++candidate2) { if (abs(hfHelper.yD0(candidate2)) > yCandMax) { continue; @@ -545,6 +554,31 @@ struct HfCorrelatorDMesonPairs { registry.fill(HIST("hStatusSinglePart"), 6); } + if (isDCand1) { + if (isTrueDCand1) { + registry.fill(HIST("hMass"), hfHelper.invMassD0ToPiK(candidate1), candidate1.pt()); + if (originRec1 == 1) { + registry.fill(HIST("hMassMcRecPrompt"), hfHelper.invMassD0ToPiK(candidate1), candidate1.pt()); + } else if (originRec1 == 2) { + registry.fill(HIST("hMassMcRecNonPrompt"), hfHelper.invMassD0ToPiK(candidate1), candidate1.pt()); + } + } else if (isTrueDbarCand1) { + registry.fill(HIST("hMassMcRecReflections"), hfHelper.invMassD0ToPiK(candidate1), candidate1.pt()); + } + } + if (isDbarCand1) { + if (isTrueDbarCand1) { + registry.fill(HIST("hMass"), hfHelper.invMassD0barToKPi(candidate1), candidate1.pt()); + if (originRec1 == 1) { + registry.fill(HIST("hMassMcRecPrompt"), hfHelper.invMassD0barToKPi(candidate1), candidate1.pt()); + } else if (originRec1 == 2) { + registry.fill(HIST("hMassMcRecNonPrompt"), hfHelper.invMassD0barToKPi(candidate1), candidate1.pt()); + } + } else if (isTrueDCand1) { + registry.fill(HIST("hMassMcRecReflections"), hfHelper.invMassD0barToKPi(candidate1), candidate1.pt()); + } + } + for (auto candidate2 = candidate1 + 1; candidate2 != selectedD0CandidatesGroupedMc.end(); ++candidate2) { auto ptCandidate2 = candidate2.pt(); auto yCandidate2 = hfHelper.yD0(candidate2); diff --git a/PWGHF/HFC/Tasks/taskCharmHadronsFemtoDream.cxx b/PWGHF/HFC/Tasks/taskCharmHadronsFemtoDream.cxx index f1d3e5aaf70..103ac3f3884 100644 --- a/PWGHF/HFC/Tasks/taskCharmHadronsFemtoDream.cxx +++ b/PWGHF/HFC/Tasks/taskCharmHadronsFemtoDream.cxx @@ -125,8 +125,8 @@ struct HfTaskCharmHadronsFemtoDream { FemtoDreamContainer sameEventCont; FemtoDreamContainer mixedEventCont; FemtoDreamPairCleaner pairCleaner; - FemtoDreamDetaDphiStar pairCloseRejection; - + 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 >= charmHadCandSel.value; @@ -205,7 +205,8 @@ struct HfTaskCharmHadronsFemtoDream { mixedEventCont.setPDGCodes(pdgCodeTrack1, charmHadPDGCode); pairCleaner.init(®istry); if (useCPR.value) { - pairCloseRejection.init(®istry, ®istry, cprDeltaPhiMax.value, cprDeltaEtaMax.value, cprPlotPerRadii.value); + pairCloseRejectionSE.init(®istry, ®istry, cprDeltaPhiMax.value, cprDeltaEtaMax.value, cprPlotPerRadii.value, 1); + pairCloseRejectionME.init(®istry, ®istry, cprDeltaPhiMax.value, cprDeltaEtaMax.value, cprPlotPerRadii.value, 2); } } @@ -221,6 +222,17 @@ struct HfTaskCharmHadronsFemtoDream { } for (auto const& [p1, p2] : combinations(CombinationsFullIndexPolicy(sliceTrk1, sliceCharmHad))) { + + if (useCPR.value) { + if (pairCloseRejectionSE.isClosePair(p1, p2, parts, col.magField())) { + continue; + } + } + + if (!pairCleaner.isCleanPair(p1, p2, parts)) { + continue; + } + // proton track charge float chargeTrack = 0.; if ((p1.cut() & 2) == 2) { @@ -247,16 +259,6 @@ struct HfTaskCharmHadronsFemtoDream { // partSign = 1 << 1; // } - if (useCPR.value) { - if (pairCloseRejection.isClosePair(p1, p2, parts, col.magField())) { - continue; - } - } - - if (!pairCleaner.isCleanPair(p1, p2, parts)) { - continue; - } - float invMass; if (p2.candidateSelFlag() == 1) { invMass = p2.m(std::array{o2::constants::physics::MassProton, o2::constants::physics::MassKPlus, o2::constants::physics::MassPiPlus}); @@ -303,14 +305,28 @@ struct HfTaskCharmHadronsFemtoDream { template void doMixedEvent(CollisionType const& cols, PartType const& parts, PartitionType1& part1, PartitionType2& part2, BinningType policy) { - processType = 1 << 1; // for mixed event - for (auto const& [collision1, collision2] : soa::selfCombinations(policy, mixingDepth.value, -1, cols, cols)) { + // Mixed events that contain the pair of interest + processType = 2; // for mixed event + for (auto const& [collision1, collision2] : combinations(soa::CombinationsBlockFullSameIndexPolicy(policy, mixingDepth.value, -1, cols, cols))) { + // make sure that tracks in the same events are not mixed + if (collision1.globalIndex() == collision2.globalIndex()) { + continue; + } 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))) { + if (useCPR.value) { + if (pairCloseRejectionME.isClosePair(p1, p2, parts, collision1.magField())) { + continue; + } + } + if (!pairCleaner.isCleanPair(p1, p2, parts)) { + continue; + } + float chargeTrack = 0.; if ((p1.cut() & 2) == 2) { chargeTrack = PositiveCharge; @@ -361,14 +377,6 @@ struct HfTaskCharmHadronsFemtoDream { charmHadMc, originType); - if (useCPR.value) { - if (pairCloseRejection.isClosePair(p1, p2, parts, collision1.magField())) { - continue; - } - } - if (!pairCleaner.isCleanPair(p1, p2, parts)) { - continue; - } // if constexpr (!isMc) mixedEventCont.setPair(p1, p2, collision1.multNtr(), collision1.multV0M(), use4D, extendedPlots, smearingByOrigin); mixedEventCont.setPair(p1, p2, collision1.multNtr(), collision1.multV0M(), use4D, extendedPlots, smearingByOrigin); } diff --git a/PWGHF/HFC/Tasks/taskFlow.cxx b/PWGHF/HFC/Tasks/taskFlow.cxx index 5f6a5b2a95a..5fcdb7a7878 100644 --- a/PWGHF/HFC/Tasks/taskFlow.cxx +++ b/PWGHF/HFC/Tasks/taskFlow.cxx @@ -23,6 +23,7 @@ #include "Framework/AnalysisTask.h" #include "Framework/ASoAHelpers.h" #include "Framework/HistogramRegistry.h" +#include "Framework/O2DatabasePDGPlugin.h" #include "Framework/runDataProcessing.h" #include "Framework/RunningWorkflowInfo.h" #include "Framework/StepTHn.h" @@ -47,6 +48,7 @@ using namespace o2::framework; using namespace o2::framework::expressions; struct HfTaskFlow { + // configurables for processing options Configurable processRun2{"processRun2", false, "Flag to run on Run 2 data"}; Configurable processRun3{"processRun3", true, "Flag to run on Run 3 data"}; @@ -63,25 +65,82 @@ struct HfTaskFlow { Configurable yCandMax{"yCandMax", -1., "max. cand. rapidity"}; Configurable> binsPt{"binsPt", std::vector{hf_cuts_d0_to_pi_k::vecBinsPt}, "pT bin limits"}; + Service pdg; HfHelper hfHelper; SliceCache cache; + // ========================= + // using declarations : DATA + // ========================= + using FilteredCollisionsWSelMult = soa::Filtered>; - using TracksWDcaSel = soa::Filtered>; using HfCandidatesSel = soa::Filtered>; + using TracksWDcaSel = soa::Filtered>; + + // ========================= + // using declarations : MC + // ========================= + + // Even add McCollisions in the join ? + // Kata adds subscribes to it but do not add it in the join + // using FilteredCollisionsWSelMultMC = soa::Filtered>; + using FilteredCollisionsWSelMultMC = soa::Filtered>; + using FilteredMcCollisions = soa::Filtered; + using FilteredMcParticles = soa::Filtered; + using TracksWDcaSelMC = soa::Filtered>; + + // Remnants, need Katarina's info + // using FilteredCollisionsWDcaSelMcLabels = soa::Filtered>; + // using FilteredTracksWDcaSelMcLabels = soa::Filtered>; + + // ========================= + // Filters & partitions : DATA + // ========================= + + // HF candidate filter + // TODO: use Partition instead of filter + Filter candidateFilter = aod::hf_sel_candidate_d0::isSelD0 >= selectionFlagD0 || + aod::hf_sel_candidate_d0::isSelD0bar >= selectionFlagD0bar; // Collision filters // FIXME: The filter is applied also on the candidates! Beware! Filter collisionVtxZFilter = nabs(aod::collision::posZ) < zVertexMax; - // Charged track filters + Filter trackFilter = (nabs(aod::track::eta) < etaTrackAssocMax) && (aod::track::pt > ptTrackAssocMin) && requireGlobalTrackWoPtEtaInFilter(); - // HF candidate filter - // TODO: use Partition instead of filter - Filter candidateFilter = aod::hf_sel_candidate_d0::isSelD0 >= selectionFlagD0 || aod::hf_sel_candidate_d0::isSelD0bar >= selectionFlagD0bar; - Preslice perCol = aod::track::collisionId; + // Katarina had this in her code : + // Charged track filters + // Filter trackFilter = (nabs(aod::track::eta) < etaTrackAssocMax) && + // (aod::track::pt > ptTrackAssocMin) && + // requireGlobalTrackWoPtEtaInFilter(); + + // ========================= + // Filters & partitions : MC + // ========================= + + // From Katarina's code, but not sure if I use it + Filter mcCollisionFilter = nabs(aod::mccollision::posZ) < zVertexMax; + + // From Katarina's code + Filter mcParticlesFilter = (nabs(aod::mcparticle::eta) < etaTrackAssocMax) && + (aod::mcparticle::pt > ptTrackAssocMin); //&& + //(aod::mcparticle::sign != 0) + + // ========================= + // Preslice : DATA + // ========================= + + Preslice dataPerCol = aod::track::collisionId; + + // ========================= + // Preslice : MC + // ========================= + + Preslice mcTruthPerCol = aod::mcparticle::mcCollisionId; + // Do I have to adapt this preslice to MC ? How does it work exactly ? + // Preslice mcRecPerCol = aod::track::collisionId; // configurables for containers ConfigurableAxis axisVertex{"axisVertex", {14, -7, 7}, "vertex axis for histograms"}; @@ -100,19 +159,29 @@ struct HfTaskFlow { HistogramRegistry registry{"registry"}; + // Correlation containers used for data OutputObj sameTPCTPCChCh{"sameTPCTPCChCh"}; OutputObj mixedTPCTPCChCh{"mixedTPCTPCChCh"}; OutputObj sameTPCTPCHfCh{"sameTPCTPCHfCh"}; OutputObj mixedTPCTPCHfCh{"mixedTPCTPCHfCh"}; OutputObj sameTPCMFTChCh{"sameTPCMFTChCh"}; OutputObj mixedTPCMFTChCh{"mixedTPCMFTChCh"}; + OutputObj sameTPCMFTHfCh{"sameTPCMFTHfCh"}; + OutputObj mixedTPCMFTHfCh{"mixedTPCMFTHfCh"}; + + // Correlation containers used for Monte-Carlo + OutputObj sameTPCTPCChChMC{"sameTPCTPCChChMC"}; + OutputObj mixedTPCTPCChChMC{"mixedTPCTPCChChMC"}; // ========================= // init() // ========================= void init(InitContext&) { - // EVENT HISTOGRAMS + // ========================= + // Event histograms + // TO-DO : do i have to separate event histograms between DATA and MC ? + // ========================= constexpr int kNBinsEvents = 3; registry.add("Data/hEventCounter", "hEventCounter", {HistType::kTH1F, {{kNBinsEvents, 0.5, 0.5 + kNBinsEvents}}}); // set axes of the event counter histogram @@ -120,70 +189,232 @@ struct HfTaskFlow { labels[0] = "all"; labels[1] = "after trigger selection (Run 2)"; labels[2] = "after Physics selection"; + + const int nBinsMix = axisMultiplicity->size() * 14; // 14 bins for z-vertex + for (int iBin = 0; iBin < kNBinsEvents; iBin++) { registry.get(HIST("Data/hEventCounter"))->GetXaxis()->SetBinLabel(iBin + 1, labels[iBin].data()); } + + // ========================= + // DATA : histograms for TPC-TPC h-h case + // ========================= + + // DATA : event histograms for TPC-TPC h-h same event registry.add("Data/TpcTpc/HadronHadron/SameEvent/hMultiplicity", "hMultiplicity", {HistType::kTH1F, {{500, 0, 500}}}); registry.add("Data/TpcTpc/HadronHadron/SameEvent/hVtxZ", "hVtxZ", {HistType::kTH1F, {{400, -50, 50}}}); + registry.add("Data/TpcTpc/HadronHadron/SameEvent/hEventCountSame", "bin", {HistType::kTH1F, {{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, {{100, 0, 10, "p_{T}"}}}); + registry.add("Data/TpcTpc/HadronHadron/SameEvent/hEta", "eta", {HistType::kTH1F, {{100, -4, 4, "#eta"}}}); + registry.add("Data/TpcTpc/HadronHadron/SameEvent/hPhi", "phi", {HistType::kTH1F, {{100, 0, TwoPI, "#varphi"}}}); + registry.add("Data/TpcTpc/HadronHadron/SameEvent/hYields", "multiplicity vs pT vs eta", {HistType::kTH3F, {{200, 0, 200, "multiplicity"}, {40, 0, 20, "p_{T}"}, {100, -2, 2, "#eta"}}}); + registry.add("Data/TpcTpc/HadronHadron/SameEvent/hEtaPhi", "multiplicity vs eta vs phi", {HistType::kTH3F, {{200, 0, 200, "multiplicity"}, {100, -2, 2, "#eta"}, {200, 0, TwoPI, "#varphi"}}}); registry.add("Data/TpcTpc/HadronHadron/SameEvent/hNtracks", "hNtracks", {HistType::kTH1F, {{500, 0, 500}}}); - // histograms for event mixing - const int maxMixBin = axisMultiplicity->size() * 14; // 14 bins for z-vertex - registry.add("Data/TpcTpc/HadronHadron/MixedEvent/hEventCountMixing", "bin", {HistType::kTH1F, {{maxMixBin + 2, -2.5, -0.5 + maxMixBin, "bin"}}}); - registry.add("Data/TpcTpc/HfHadron/MixedEvent/hEventCountHFMixing", "bin", {HistType::kTH1F, {{maxMixBin + 2, -2.5, -0.5 + maxMixBin, "bin"}}}); - registry.add("Data/TpcTpc/HadronHadron/SameEvent/hEventCountSame", "bin", {HistType::kTH1F, {{maxMixBin + 2, -2.5, -0.5 + maxMixBin, "bin"}}}); + // Katarina had this : + registry.add("Data/TpcTpc/HadronHadron/SameEvent/hVzEta", "eta vs. Vz", {HistType::kTH2F, {{100, -4, 4, "#eta"}, {20, -10, 10, "Vz"}}}); + + // 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/hMultiplicityMixing", "hMultiplicityMixing", {HistType::kTH1F, {{500, 0, 500}}}); registry.add("Data/TpcTpc/HadronHadron/MixedEvent/hVtxZMixing", "hVtxZMixing", {HistType::kTH1F, {{100, -10, 10}}}); registry.add("Data/TpcTpc/HadronHadron/MixedEvent/hNtracksMixing", "hNtracksMixing", {HistType::kTH1F, {{500, 0, 500}}}); - registry.add("Data/TpcTpc/HfHadron/MixedEvent/hMultiplicityHFMixing", "hMultiplicityHFMixing", {HistType::kTH1F, {{500, 0, 500}}}); - registry.add("Data/TpcTpc/HfHadron/MixedEvent/hVtxZHFMixing", "hVtxZHFMixing", {HistType::kTH1F, {{100, -10, 10}}}); - registry.add("Data/TpcTpc/HfHadron/MixedEvent/hNtracksHFMixing", "hNtracksHFMixing", {HistType::kTH1F, {{500, 0, 500}}}); - // TRACK HISTOGRAMS - // histograms for associated particles - registry.add("Data/TpcTpc/HadronHadron/SameEvent/hYields", "multiplicity vs pT vs eta", {HistType::kTH3F, {{200, 0, 200, "multiplicity"}, {40, 0, 20, "p_{T}"}, {100, -2, 2, "#eta"}}}); - registry.add("Data/TpcTpc/HadronHadron/SameEvent/hEtaPhi", "multiplicity vs eta vs phi", {HistType::kTH3F, {{200, 0, 200, "multiplicity"}, {100, -2, 2, "#eta"}, {200, 0, TwoPI, "#varphi"}}}); - registry.add("Data/TpcTpc/HadronHadron/SameEvent/hPt", "pT", {HistType::kTH1F, {{100, 0, 10, "p_{T}"}}}); - registry.add("Data/TpcTpc/HadronHadron/SameEvent/hEta", "eta", {HistType::kTH1F, {{100, -4, 4, "#eta"}}}); - registry.add("Data/TpcTpc/HadronHadron/SameEvent/hPhi", "phi", {HistType::kTH1F, {{100, 0, TwoPI, "#varphi"}}}); - - // histograms for particles in event mixing + // DATA : particles histograms for TPC-TPC h-h mixed event registry.add("Data/TpcTpc/HadronHadron/MixedEvent/hPtMixing", "pT", {HistType::kTH1F, {{100, 0, 10, "p_{T}"}}}); registry.add("Data/TpcTpc/HadronHadron/MixedEvent/hEtaMixing", "eta", {HistType::kTH1F, {{100, -4, 4, "#eta"}}}); registry.add("Data/TpcTpc/HadronHadron/MixedEvent/hPhiMixing", "phi", {HistType::kTH1F, {{100, 0, TwoPI, "#varphi"}}}); - // histograms for MFT tracks - registry.add("Data/TpcMft/HadronHadron/hEtaPhiMFT", "multiplicity vs eta vs phi in MFT", {HistType::kTH3F, {{200, 0, 200, "multiplicity"}, {100, -2, 2, "#eta"}, {200, 0, TwoPI, "#varphi"}}}); - registry.add("Data/TpcMft/HadronHadron/hEtaMFT", "etaMFT", {HistType::kTH1F, {{100, -4, 4, "#eta"}}}); - registry.add("Data/TpcMft/HadronHadron/hPhiMFT", "phiMFT", {HistType::kTH1F, {{100, 0, TwoPI, "#varphi"}}}); + // ========================= + // DATA : histograms for TPC-TPC HF-h case + // ========================= - // histograms for candidates - auto vbins = (std::vector)binsPt; + // DATA : event histograms for TPC-TPC HF-h same event + registry.add("Data/TpcTpc/HfHadron/MixedEvent/hEventCountHFMixing", "bin", {HistType::kTH1F, {{nBinsMix + 2, -2.5, -0.5 + nBinsMix, "bin"}}}); + registry.add("Data/TpcTpc/HfHadron/MixedEvent/hMultiplicityHFMixing", "hMultiplicityHFMixing", {HistType::kTH1F, {{500, 0, 500}}}); + registry.add("Data/TpcTpc/HfHadron/MixedEvent/hVtxZHFMixing", "hVtxZHFMixing", {HistType::kTH1F, {{100, -10, 10}}}); + registry.add("Data/TpcTpc/HfHadron/MixedEvent/hNtracksHFMixing", "hNtracksHFMixing", {HistType::kTH1F, {{500, 0, 500}}}); - registry.add("Data/TpcTpc/HfHadron/hPtCand", "2-prong candidates;candidate #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {{100, 0, 10.}}}); - registry.add("Data/TpcTpc/HfHadron/hPtProng0", "2-prong candidates;prong 0 #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {{100, 0, 10.}}}); - registry.add("Data/TpcTpc/HfHadron/hPtProng1", "2-prong candidates;prong 1 #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {{100, 0, 10.}}}); - registry.add("Data/TpcTpc/HfHadron/hMass", "2-prong candidates;inv. mass (#pi K) (GeV/#it{c}^{2});entries", {HistType::kTH2F, {{500, 0., 5.}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); - registry.add("Data/TpcTpc/HfHadron/hDecLength", "2-prong candidates;decay length (cm);entries", {HistType::kTH2F, {{200, 0., 2.}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); - registry.add("Data/TpcTpc/HfHadron/hDecLengthXY", "2-prong candidates;decay length xy (cm);entries", {HistType::kTH2F, {{200, 0., 2.}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); - registry.add("Data/TpcTpc/HfHadron/hd0Prong0", "2-prong candidates;prong 0 DCAxy to prim. vertex (cm);entries", {HistType::kTH2F, {{100, -1., 1.}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); - registry.add("Data/TpcTpc/HfHadron/hd0Prong1", "2-prong candidates;prong 1 DCAxy to prim. vertex (cm);entries", {HistType::kTH2F, {{100, -1., 1.}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); - registry.add("Data/TpcTpc/HfHadron/hd0d0", "2-prong candidates;product of DCAxy to prim. vertex (cm^{2});entries", {HistType::kTH2F, {{500, -1., 1.}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); - registry.add("Data/TpcTpc/HfHadron/hCTS", "2-prong candidates;cos #it{#theta}* (D^{0});entries", {HistType::kTH2F, {{110, -1.1, 1.1}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); - registry.add("Data/TpcTpc/HfHadron/hCt", "2-prong candidates;proper lifetime (D^{0}) * #it{c} (cm);entries", {HistType::kTH2F, {{120, -20., 100.}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); - registry.add("Data/TpcTpc/HfHadron/hCPA", "2-prong candidates;cosine of pointing angle;entries", {HistType::kTH2F, {{110, -1.1, 1.1}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); - registry.add("Data/TpcTpc/HfHadron/hEtaCand", "2-prong candidates;candidate #it{#eta};entries", {HistType::kTH2F, {{100, -2., 2.}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); - registry.add("Data/TpcTpc/HfHadron/hSelectionStatus", "2-prong candidates;selection status;entries", {HistType::kTH2F, {{5, -0.5, 4.5}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); - registry.add("Data/TpcTpc/HfHadron/hImpParErr", "2-prong candidates;impact parameter error (cm);entries", {HistType::kTH2F, {{100, -1., 1.}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); - registry.add("Data/TpcTpc/HfHadron/hDecLenErr", "2-prong candidates;decay length error (cm);entries", {HistType::kTH2F, {{100, 0., 1.}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); - registry.add("Data/TpcTpc/HfHadron/hDecLenXYErr", "2-prong candidates;decay length xy error (cm);entries", {HistType::kTH2F, {{100, 0., 1.}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); - - // histograms for candidates in event mixing + // DATA : trigger particles (candidates) histograms for TPC-TPC h-h same event + auto vbins = (std::vector)binsPt; + registry.add("Data/TpcTpc/HfHadron/SameEvent/hPtCand", "2-prong candidates;candidate #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {{100, 0, 10.}}}); + registry.add("Data/TpcTpc/HfHadron/SameEvent/hPtProng0", "2-prong candidates;prong 0 #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {{100, 0, 10.}}}); + registry.add("Data/TpcTpc/HfHadron/SameEvent/hPtProng1", "2-prong candidates;prong 1 #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {{100, 0, 10.}}}); + registry.add("Data/TpcTpc/HfHadron/SameEvent/hMassVsPt", "2-prong candidates;inv. mass (#pi K) (GeV/#it{c}^{2});entries", {HistType::kTH2F, {{500, 0., 5.}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); + registry.add("Data/TpcTpc/HfHadron/SameEvent/hMass", "2-prong candidates;inv. mass (#pi K) (GeV/#it{c}^{2});entries", {HistType::kTH1F, {{100, 0., 10.}}}); + registry.add("Data/TpcTpc/HfHadron/SameEvent/hDecLength", "2-prong candidates;decay length (cm);entries", {HistType::kTH2F, {{200, 0., 2.}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); + registry.add("Data/TpcTpc/HfHadron/SameEvent/hDecLengthXY", "2-prong candidates;decay length xy (cm);entries", {HistType::kTH2F, {{200, 0., 2.}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); + registry.add("Data/TpcTpc/HfHadron/SameEvent/hd0Prong0", "2-prong candidates;prong 0 DCAxy to prim. vertex (cm);entries", {HistType::kTH2F, {{100, -1., 1.}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); + registry.add("Data/TpcTpc/HfHadron/SameEvent/hd0Prong1", "2-prong candidates;prong 1 DCAxy to prim. vertex (cm);entries", {HistType::kTH2F, {{100, -1., 1.}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); + registry.add("Data/TpcTpc/HfHadron/SameEvent/hd0d0", "2-prong candidates;product of DCAxy to prim. vertex (cm^{2});entries", {HistType::kTH2F, {{500, -1., 1.}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); + registry.add("Data/TpcTpc/HfHadron/SameEvent/hCTS", "2-prong candidates;cos #it{#theta}* (D^{0});entries", {HistType::kTH2F, {{110, -1.1, 1.1}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); + registry.add("Data/TpcTpc/HfHadron/SameEvent/hCt", "2-prong candidates;proper lifetime (D^{0}) * #it{c} (cm);entries", {HistType::kTH2F, {{120, -20., 100.}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); + registry.add("Data/TpcTpc/HfHadron/SameEvent/hCPA", "2-prong candidates;cosine of pointing angle;entries", {HistType::kTH2F, {{110, -1.1, 1.1}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); + registry.add("Data/TpcTpc/HfHadron/SameEvent/hEtaCand", "2-prong candidates;candidate #it{#eta};entries", {HistType::kTH2F, {{100, -2., 2.}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); + registry.add("Data/TpcTpc/HfHadron/SameEvent/hSelectionStatus", "2-prong candidates;selection status;entries", {HistType::kTH2F, {{5, -0.5, 4.5}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); + registry.add("Data/TpcTpc/HfHadron/SameEvent/hImpParErr", "2-prong candidates;impact parameter error (cm);entries", {HistType::kTH2F, {{100, -1., 1.}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); + registry.add("Data/TpcTpc/HfHadron/SameEvent/hDecLenErr", "2-prong candidates;decay length error (cm);entries", {HistType::kTH2F, {{100, 0., 1.}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); + registry.add("Data/TpcTpc/HfHadron/SameEvent/hDecLenXYErr", "2-prong candidates;decay length xy error (cm);entries", {HistType::kTH2F, {{100, 0., 1.}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); + + // DATA : trigger particles (candidates) histograms for TPC-TPC h-h mixed event registry.add("Data/TpcTpc/HfHadron/MixedEvent/hPtHFMixing", "pT", {HistType::kTH1F, {{100, 0, 10, "p_{T}"}}}); registry.add("Data/TpcTpc/HfHadron/MixedEvent/hEtaHFMixing", "eta", {HistType::kTH1F, {{100, -4, 4, "#eta"}}}); registry.add("Data/TpcTpc/HfHadron/MixedEvent/hPhiHFMixing", "phi", {HistType::kTH1F, {{100, 0, TwoPI, "#varphi"}}}); - // set axes of the correlation container + // ========================= + // DATA : histograms for TPC-MFT h-h case + // ========================= + + // DATA : trigger particles (TPC tracks) histograms for TPC-MFT h-h same event + registry.add("Data/TpcMft/HadronHadron/SameEvent/hEtaPhiTPC", "multiplicity vs eta vs phi in TPC", {HistType::kTH3F, {{200, 0, 200, "multiplicity"}, {100, -2, 2, "#eta"}, {200, 0, TwoPI, "#varphi"}}}); + registry.add("Data/TpcMft/HadronHadron/SameEvent/hEtaTPC", "etaTPC", {HistType::kTH1F, {{100, -4, 4, "#eta"}}}); + registry.add("Data/TpcMft/HadronHadron/SameEvent/hPhiTPC", "phiTPC", {HistType::kTH1F, {{100, 0, TwoPI, "#varphi"}}}); + registry.add("Data/TpcMft/HadronHadron/SameEvent/hPtTPC", "pT", {HistType::kTH1F, {{100, 0, 10, "p_{T}"}}}); + registry.add("Data/TpcMft/HadronHadron/SameEvent/hYieldsTPC", "multiplicity vs pT vs eta", {HistType::kTH3F, {{200, 0, 200, "multiplicity"}, {40, 0, 20, "p_{T}"}, {100, -2, 2, "#eta"}}}); + registry.add("Data/TpcTpc/HadronHadron/SameEvent/hNtracksTPC", "hNtracks", {HistType::kTH1F, {{500, 0, 500}}}); + + // 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, {{200, 0, 200, "multiplicity"}, {100, -2, 2, "#eta"}, {200, 0, TwoPI, "#varphi"}}}); + registry.add("Data/TpcMft/HadronHadron/SameEvent/hEtaMFT", "etaMFT", {HistType::kTH1F, {{100, -4, 4, "#eta"}}}); + registry.add("Data/TpcMft/HadronHadron/SameEvent/hPhiMFT", "phiMFT", {HistType::kTH1F, {{100, 0, TwoPI, "#varphi"}}}); + registry.add("Data/TpcMft/HadronHadron/SameEvent/hPtMFT", "pT", {HistType::kTH1F, {{100, 0, 10, "p_{T}"}}}); + registry.add("Data/TpcMft/HadronHadron/SameEvent/hYieldsMFT", "multiplicity vs pT vs eta", {HistType::kTH3F, {{200, 0, 200, "multiplicity"}, {40, 0, 20, "p_{T}"}, {100, -2, 2, "#eta"}}}); + registry.add("Data/TpcTpc/HadronHadron/SameEvent/hNtracksMFT", "hNtracks", {HistType::kTH1F, {{500, 0, 500}}}); + + // DATA : histograms for TPC-MFT h-h event mixing for TPC tracks + registry.add("Data/TpcMft/HadronHadron/MixedEvent/hMultiplicityMixingTPC", "hMultiplicityMixing", {HistType::kTH1F, {{500, 0, 500}}}); + registry.add("Data/TpcMft/HadronHadron/MixedEvent/hVtxZMixingTPC", "hVtxZMixing", {HistType::kTH1F, {{100, -10, 10}}}); + registry.add("Data/TpcMft/HadronHadron/MixedEvent/hPtMixingTPC", "pT", {HistType::kTH1F, {{100, 0, 10, "p_{T}"}}}); + registry.add("Data/TpcMft/HadronHadron/MixedEvent/hEtaMixingTPC", "eta", {HistType::kTH1F, {{100, -4, 4, "#eta"}}}); + registry.add("Data/TpcMft/HadronHadron/MixedEvent/hPhiMixingTPC", "phi", {HistType::kTH1F, {{100, 0, TwoPI, "#varphi"}}}); + registry.add("Data/TpcMft/HadronHadron/MixedEvent/hNtracksMixingTPC", "hNtracksMixing", {HistType::kTH1F, {{500, 0, 500}}}); + + // DATA : histograms for TPC-MFT h-h event mixing for MFT tracks + registry.add("Data/TpcMft/HadronHadron/MixedEvent/hMultiplicityMixingMFT", "hMultiplicityMixing", {HistType::kTH1F, {{500, 0, 500}}}); + registry.add("Data/TpcMft/HadronHadron/MixedEvent/hVtxZMixingMFT", "hVtxZMixing", {HistType::kTH1F, {{100, -10, 10}}}); + registry.add("Data/TpcMft/HadronHadron/MixedEvent/hPtMixingMFT", "pT", {HistType::kTH1F, {{100, 0, 10, "p_{T}"}}}); + registry.add("Data/TpcMft/HadronHadron/MixedEvent/hEtaMixingMFT", "eta", {HistType::kTH1F, {{100, -4, 4, "#eta"}}}); + registry.add("Data/TpcMft/HadronHadron/MixedEvent/hPhiMixingMFT", "phi", {HistType::kTH1F, {{100, 0, TwoPI, "#varphi"}}}); + registry.add("Data/TpcMft/HadronHadron/MixedEvent/hNtracksMixingMFT", "hNtracksMixing", {HistType::kTH1F, {{500, 0, 500}}}); + + // 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"}}}); + + // ========================= + // DATA : histograms for TPC-MFT HF-h case + // ========================= + + // DATA : trigger particles (candidates) histograms for TPC-MFT HF-h same event + registry.add("Data/TpcMft/HfHadron/SameEvent/SameEvent/hEtaPhiCandidate", "multiplicity vs eta vs phi in TPC", {HistType::kTH3F, {{200, 0, 200, "multiplicity"}, {100, -2, 2, "#eta"}, {200, 0, TwoPI, "#varphi"}}}); + registry.add("Data/TpcMft/HfHadron/SameEvent/SameEvent/hEtaCandidate", "etaTPC", {HistType::kTH1F, {{100, -4, 4, "#eta"}}}); + registry.add("Data/TpcMft/HfHadron/SameEvent/SameEvent/hPhiCandidate", "phiTPC", {HistType::kTH1F, {{100, 0, TwoPI, "#varphi"}}}); + registry.add("Data/TpcMft/HfHadron/SameEvent/SameEvent/hPtCandidate", "pT", {HistType::kTH1F, {{100, 0, 10, "p_{T}"}}}); + registry.add("Data/TpcMft/HfHadron/SameEvent/SameEvent/hYieldsCandidate", "multiplicity vs pT vs eta", {HistType::kTH3F, {{200, 0, 200, "multiplicity"}, {40, 0, 20, "p_{T}"}, {100, -2, 2, "#eta"}}}); + registry.add("Data/TpcTpc/HfHadron/SameEvent/SameEvent/hNtracksCandidate", "hNtracks", {HistType::kTH1F, {{500, 0, 500}}}); + + // DATA : trigger particles (candidates) histograms for TPC-TPC h-h same event + registry.add("Data/TpcMft/HfHadron/SameEvent/hPtCand", "2-prong candidates;candidate #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {{100, 0, 10.}}}); + registry.add("Data/TpcMft/HfHadron/SameEvent/hPtProng0", "2-prong candidates;prong 0 #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {{100, 0, 10.}}}); + registry.add("Data/TpcMft/HfHadron/SameEvent/hPtProng1", "2-prong candidates;prong 1 #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {{100, 0, 10.}}}); + registry.add("Data/TpcMft/HfHadron/SameEvent/hMassVsPt", "2-prong candidates;inv. mass (#pi K) (GeV/#it{c}^{2});entries", {HistType::kTH2F, {{500, 0., 5.}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); + registry.add("Data/TpcMft/HfHadron/SameEvent/hMass", "2-prong candidates;inv. mass (#pi K) (GeV/#it{c}^{2});entries", {HistType::kTH1F, {{100, 0., 10.}}}); + registry.add("Data/TpcMft/HfHadron/SameEvent/hDecLength", "2-prong candidates;decay length (cm);entries", {HistType::kTH2F, {{200, 0., 2.}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); + registry.add("Data/TpcMft/HfHadron/SameEvent/hDecLengthXY", "2-prong candidates;decay length xy (cm);entries", {HistType::kTH2F, {{200, 0., 2.}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); + registry.add("Data/TpcMft/HfHadron/SameEvent/hd0Prong0", "2-prong candidates;prong 0 DCAxy to prim. vertex (cm);entries", {HistType::kTH2F, {{100, -1., 1.}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); + registry.add("Data/TpcMft/HfHadron/SameEvent/hd0Prong1", "2-prong candidates;prong 1 DCAxy to prim. vertex (cm);entries", {HistType::kTH2F, {{100, -1., 1.}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); + registry.add("Data/TpcMft/HfHadron/SameEvent/hd0d0", "2-prong candidates;product of DCAxy to prim. vertex (cm^{2});entries", {HistType::kTH2F, {{500, -1., 1.}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); + registry.add("Data/TpcMft/HfHadron/SameEvent/hCTS", "2-prong candidates;cos #it{#theta}* (D^{0});entries", {HistType::kTH2F, {{110, -1.1, 1.1}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); + registry.add("Data/TpcMft/HfHadron/SameEvent/hCt", "2-prong candidates;proper lifetime (D^{0}) * #it{c} (cm);entries", {HistType::kTH2F, {{120, -20., 100.}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); + registry.add("Data/TpcMft/HfHadron/SameEvent/hCPA", "2-prong candidates;cosine of pointing angle;entries", {HistType::kTH2F, {{110, -1.1, 1.1}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); + registry.add("Data/TpcMft/HfHadron/SameEvent/hEtaCand", "2-prong candidates;candidate #it{#eta};entries", {HistType::kTH2F, {{100, -2., 2.}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); + registry.add("Data/TpcMft/HfHadron/SameEvent/hSelectionStatus", "2-prong candidates;selection status;entries", {HistType::kTH2F, {{5, -0.5, 4.5}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); + registry.add("Data/TpcMft/HfHadron/SameEvent/hImpParErr", "2-prong candidates;impact parameter error (cm);entries", {HistType::kTH2F, {{100, -1., 1.}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); + registry.add("Data/TpcMft/HfHadron/SameEvent/hDecLenErr", "2-prong candidates;decay length error (cm);entries", {HistType::kTH2F, {{100, 0., 1.}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); + registry.add("Data/TpcMft/HfHadron/SameEvent/hDecLenXYErr", "2-prong candidates;decay length xy error (cm);entries", {HistType::kTH2F, {{100, 0., 1.}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); + + // DATA : associated particles (MFT tracks) histograms for TPC-MFT h-h same event + registry.add("Data/TpcMft/HfHadron/SameEvent/SameEvent/hEtaPhiMFT", "multiplicity vs eta vs phi in MFT", {HistType::kTH3F, {{200, 0, 200, "multiplicity"}, {100, -2, 2, "#eta"}, {200, 0, TwoPI, "#varphi"}}}); + registry.add("Data/TpcMft/HfHadron/SameEvent/SameEvent/hEtaMFT", "etaMFT", {HistType::kTH1F, {{100, -4, 4, "#eta"}}}); + registry.add("Data/TpcMft/HfHadron/SameEvent/SameEvent/hPhiMFT", "phiMFT", {HistType::kTH1F, {{100, 0, TwoPI, "#varphi"}}}); + registry.add("Data/TpcMft/HfHadron/SameEvent/SameEvent/hPtMFT", "pT", {HistType::kTH1F, {{100, 0, 10, "p_{T}"}}}); + registry.add("Data/TpcMft/HfHadron/SameEvent/SameEvent/hYieldsMFT", "multiplicity vs pT vs eta", {HistType::kTH3F, {{200, 0, 200, "multiplicity"}, {40, 0, 20, "p_{T}"}, {100, -2, 2, "#eta"}}}); + registry.add("Data/TpcTpc/HfHadron/SameEvent/SameEvent/hNtracksMFT", "hNtracks", {HistType::kTH1F, {{500, 0, 500}}}); + + // DATA : histograms for TPC-MFT h-h event mixing for candidates + registry.add("Data/TpcMft/HfHadron/MixedEvent/hMultiplicityMixingCandidate", "hMultiplicityMixing", {HistType::kTH1F, {{500, 0, 500}}}); + registry.add("Data/TpcMft/HfHadron/MixedEvent/hVtxZMixingCandidate", "hVtxZMixing", {HistType::kTH1F, {{100, -10, 10}}}); + registry.add("Data/TpcMft/HfHadron/MixedEvent/hPtMixingCandidate", "pT", {HistType::kTH1F, {{100, 0, 10, "p_{T}"}}}); + registry.add("Data/TpcMft/HfHadron/MixedEvent/hEtaMixingCandidate", "eta", {HistType::kTH1F, {{100, -4, 4, "#eta"}}}); + registry.add("Data/TpcMft/HfHadron/MixedEvent/hPhiMixingCandidate", "phi", {HistType::kTH1F, {{100, 0, TwoPI, "#varphi"}}}); + registry.add("Data/TpcMft/HfHadron/MixedEvent/hNtracksMixingCandidate", "hNtracksMixing", {HistType::kTH1F, {{500, 0, 500}}}); + + // DATA : histograms for TPC-MFT h-h event mixing for MFT tracks + registry.add("Data/TpcMft/HfHadron/MixedEvent/hMultiplicityMixingMFT", "hMultiplicityMixing", {HistType::kTH1F, {{500, 0, 500}}}); + registry.add("Data/TpcMft/HfHadron/MixedEvent/hVtxZMixingMFT", "hVtxZMixing", {HistType::kTH1F, {{100, -10, 10}}}); + registry.add("Data/TpcMft/HfHadron/MixedEvent/hPtMixingMFT", "pT", {HistType::kTH1F, {{100, 0, 10, "p_{T}"}}}); + registry.add("Data/TpcMft/HfHadron/MixedEvent/hEtaMixingMFT", "eta", {HistType::kTH1F, {{100, -4, 4, "#eta"}}}); + registry.add("Data/TpcMft/HfHadron/MixedEvent/hPhiMixingMFT", "phi", {HistType::kTH1F, {{100, 0, TwoPI, "#varphi"}}}); + registry.add("Data/TpcMft/HfHadron/MixedEvent/hNtracksMixingMFT", "hNtracksMixing", {HistType::kTH1F, {{500, 0, 500}}}); + + // 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"}}}); + + // ========================= + // MC : histograms for TPC-MFT h-h case + // ========================= + + // MC reconstructed + + registry.add("MC/Rec/TpcTpc/HadronHadron/SameEvent/hMultiplicity", "hMultiplicity", {HistType::kTH1F, {{500, 0, 500}}}); + registry.add("MC/Rec/TpcTpc/HadronHadron/SameEvent/hVtxZ", "hVtxZ", {HistType::kTH1F, {{400, -50, 50}}}); + registry.add("MC/Rec/TpcTpc/HadronHadron/SameEvent/hEventCountSame", "hNtracks", {HistType::kTH1F, {{500, 0, 500}}}); + // Katarina had this : + registry.add("MC/Rec/TpcTpc/HadronHadron/SameEvent/hMultiplicityPrimary", "hMultiplicityPrimary", {HistType::kTH1F, {{500, 0, 500}}}); + // histograms for MC associated particles + registry.add("MC/Rec/TpcTpc/HadronHadron/SameEvent/hPt", "pT", {HistType::kTH1F, {{100, 0, 10, "p_{T}"}}}); + registry.add("MC/Rec/TpcTpc/HadronHadron/SameEvent/hEta", "eta", {HistType::kTH1F, {{100, -4, 4, "#eta"}}}); + registry.add("MC/Rec/TpcTpc/HadronHadron/SameEvent/hPhi", "phi", {HistType::kTH1F, {{100, 0, TwoPI, "#varphi"}}}); + registry.add("MC/Rec/TpcTpc/HadronHadron/SameEvent/hYields", "multiplicity vs pT vs eta", {HistType::kTH3F, {{200, 0, 200, "multiplicity"}, {40, 0, 20, "p_{T}"}, {100, -2, 2, "#eta"}}}); + registry.add("MC/Rec/TpcTpc/HadronHadron/SameEvent/hEtaPhi", "multiplicity vs eta vs phi", {HistType::kTH3F, {{200, 0, 200, "multiplicity"}, {100, -2, 2, "#eta"}, {200, 0, TwoPI, "#varphi"}}}); + registry.add("MC/Rec/TpcTpc/HadronHadron/SameEvent/hNtracks", "hNtracks", {HistType::kTH1F, {{500, 0, 500}}}); + // histograms for MC particles in event mixing + registry.add("MC/Rec/TpcTpc/HadronHadron/MixedEvent/hEventCountMixing", "bin", {HistType::kTH1F, {{nBinsMix + 2, -2.5, -0.5 + nBinsMix, "bin"}}}); + registry.add("MC/Rec/TpcTpc/HadronHadron/MixedEvent/hMultiplicityMixing", "hMultiplicityMixing", {HistType::kTH1F, {{500, 0, 500}}}); + registry.add("MC/Rec/TpcTpc/HadronHadron/MixedEvent/hVtxZMixing", "hVtxZMixing", {HistType::kTH1F, {{100, -10, 10}}}); + registry.add("MC/Rec/TpcTpc/HadronHadron/MixedEvent/hPtMixing", "pT", {HistType::kTH1F, {{100, 0, 10, "p_{T}"}}}); + registry.add("MC/Rec/TpcTpc/HadronHadron/MixedEvent/hEtaMixing", "eta", {HistType::kTH1F, {{100, -4, 4, "#eta"}}}); + registry.add("MC/Rec/TpcTpc/HadronHadron/MixedEvent/hPhiMixing", "phi", {HistType::kTH1F, {{100, 0, TwoPI, "#varphi"}}}); + registry.add("MC/Rec/TpcTpc/HadronHadron/MixedEvent/hNtracksMixing", "hNtracksMixing", {HistType::kTH1F, {{500, 0, 500}}}); + + // MC Truth + + registry.add("MC/Gen/TpcTpc/HadronHadron/SameEvent/hMultiplicity", "hMultiplicity", {HistType::kTH1F, {{500, 0, 500}}}); + registry.add("MC/Gen/TpcTpc/HadronHadron/SameEvent/hVtxZ", "hVtxZ", {HistType::kTH1F, {{400, -50, 50}}}); + registry.add("MC/Gen/TpcTpc/HadronHadron/SameEvent/hEventCountSame", "hNtracks", {HistType::kTH1F, {{500, 0, 500}}}); + // Katarina had this : + registry.add("MC/Gen/TpcTpc/HadronHadron/SameEvent/hMultiplicityPrimary", "hMultiplicityPrimary", {HistType::kTH1F, {{500, 0, 500}}}); + // histograms for MC associated particles + registry.add("MC/Gen/TpcTpc/HadronHadron/SameEvent/hPt", "pT", {HistType::kTH1F, {{100, 0, 10, "p_{T}"}}}); + registry.add("MC/Gen/TpcTpc/HadronHadron/SameEvent/hEta", "eta", {HistType::kTH1F, {{100, -4, 4, "#eta"}}}); + registry.add("MC/Gen/TpcTpc/HadronHadron/SameEvent/hPhi", "phi", {HistType::kTH1F, {{100, 0, TwoPI, "#varphi"}}}); + registry.add("MC/Gen/TpcTpc/HadronHadron/SameEvent/hYields", "multiplicity vs pT vs eta", {HistType::kTH3F, {{200, 0, 200, "multiplicity"}, {40, 0, 20, "p_{T}"}, {100, -2, 2, "#eta"}}}); + registry.add("MC/Gen/TpcTpc/HadronHadron/SameEvent/hEtaPhi", "multiplicity vs eta vs phi", {HistType::kTH3F, {{200, 0, 200, "multiplicity"}, {100, -2, 2, "#eta"}, {200, 0, TwoPI, "#varphi"}}}); + registry.add("MC/Gen/TpcTpc/HadronHadron/SameEvent/hNtracks", "hNtracks", {HistType::kTH1F, {{500, 0, 500}}}); + // histograms for MC particles in event mixing + registry.add("MC/Gen/TpcTpc/HadronHadron/MixedEvent/hEventCountMixing", "bin", {HistType::kTH1F, {{nBinsMix + 2, -2.5, -0.5 + nBinsMix, "bin"}}}); + registry.add("MC/Gen/TpcTpc/HadronHadron/MixedEvent/hMultiplicityMixing", "hMultiplicityMixing", {HistType::kTH1F, {{500, 0, 500}}}); + registry.add("MC/Gen/TpcTpc/HadronHadron/MixedEvent/hVtxZMixing", "hVtxZMixing", {HistType::kTH1F, {{100, -10, 10}}}); + registry.add("MC/Gen/TpcTpc/HadronHadron/MixedEvent/hPtMixing", "pT", {HistType::kTH1F, {{100, 0, 10, "p_{T}"}}}); + registry.add("MC/Gen/TpcTpc/HadronHadron/MixedEvent/hEtaMixing", "eta", {HistType::kTH1F, {{100, -4, 4, "#eta"}}}); + registry.add("MC/Gen/TpcTpc/HadronHadron/MixedEvent/hPhiMixing", "phi", {HistType::kTH1F, {{100, 0, TwoPI, "#varphi"}}}); + registry.add("MC/Gen/TpcTpc/HadronHadron/MixedEvent/hNtracksMixing", "hNtracksMixing", {HistType::kTH1F, {{500, 0, 500}}}); + + // ========================= + // Declaration of correlation containers and their respective axis + // ========================= + std::vector corrAxis = {{axisDeltaEta, "#Delta#eta"}, {axisPtAssoc, "p_{T} (GeV/c)"}, {axisPtTrigger, "p_{T} (GeV/c)"}, @@ -195,107 +426,286 @@ struct HfTaskFlow { {axisVertexEfficiency, "z-vtx (cm)"}}; std::vector userAxis = {{axisMass, "m_{inv} (GeV/c^{2})"}}; + // initialization of correlation containers for data sameTPCTPCChCh.setObject(new CorrelationContainer("sameTPCTPCChCh", "sameTPCTPCChCh", corrAxis, effAxis, {})); mixedTPCTPCChCh.setObject(new CorrelationContainer("mixedTPCTPCChCh", "mixedTPCTPCChCh", corrAxis, effAxis, {})); sameTPCTPCHfCh.setObject(new CorrelationContainer("sameTPCTPCHfCh", "sameTPCTPCHfCh", corrAxis, effAxis, userAxis)); mixedTPCTPCHfCh.setObject(new CorrelationContainer("mixedTPCTPCHfCh", "mixedTPCTPCHfCh", corrAxis, effAxis, userAxis)); sameTPCMFTChCh.setObject(new CorrelationContainer("sameTPCMFTChCh", "sameTPCMFTChCh", corrAxis, effAxis, {})); mixedTPCMFTChCh.setObject(new CorrelationContainer("mixedTPCMFTChCh", "mixedTPCMFTChCh", corrAxis, effAxis, {})); - } + sameTPCMFTHfCh.setObject(new CorrelationContainer("sameTPCMFTHfCh", "sameTPCMFTHfCh", corrAxis, effAxis, userAxis)); + mixedTPCMFTHfCh.setObject(new CorrelationContainer("mixedTPCMFTHfCh", "mixedTPCMFTHfCh", corrAxis, effAxis, userAxis)); - // --------------- + // initialization of correlation containes for monte-carlo + sameTPCTPCChChMC.setObject(new CorrelationContainer("sameTPCTPCChChMC", "sameTPCTPCChChMC", corrAxis, effAxis, {})); + mixedTPCTPCChChMC.setObject(new CorrelationContainer("mixedTPCTPCChChMC", "mixedTPCTPCChChMC", corrAxis, effAxis, {})); + } // End of init() function + + // ========================= // templates // FIXME: Some collisions are rejected here, what causes (part of) differences with the D0 task - // --------------- + // ========================= template bool isCollisionSelected(TCollision const& collision, bool fillHistograms = false) { - if (processRun2 == true) { - // Run 2: trigger selection for data case - if (fillHistograms) - registry.fill(HIST("Data/hEventCounter"), 1); - if (!processMc) { - if (!collision.alias_bit(kINT7)) { - return false; - } - } - // Run 2: further offline selection - if (fillHistograms) - registry.fill(HIST("Data/hEventCounter"), 2); - if (!collision.sel7()) { - return false; - } - if (fillHistograms) - registry.fill(HIST("Data/hEventCounter"), 3); - } else { - // Run 3: selection - if (fillHistograms) - registry.fill(HIST("Data/hEventCounter"), 1); + if (fillHistograms) + registry.fill(HIST("Data/hEventCounter"), 1); + + if (processMc == false) { if (!collision.sel8()) { return false; } - if (fillHistograms) - registry.fill(HIST("Data/hEventCounter"), 3); } + + if (fillHistograms) + registry.fill(HIST("Data/hEventCounter"), 3); + return true; } + // ========================= + // Quality Assesment plots + // ========================= + + // ---- DATA : TPC-TPC h-h Same Event QA ---- template - void fillQA(float multiplicity, TTracks const& tracks) + void fillTpcTpcChChSameEventQa(float multiplicity, TTracks const& tracks) { - int Ntracks = 0; + int nTracks = tracks.size(); for (const auto& track1 : tracks) { - Ntracks++; registry.fill(HIST("Data/TpcTpc/HadronHadron/SameEvent/hPt"), track1.pt()); registry.fill(HIST("Data/TpcTpc/HadronHadron/SameEvent/hEta"), track1.eta()); registry.fill(HIST("Data/TpcTpc/HadronHadron/SameEvent/hPhi"), track1.phi()); registry.fill(HIST("Data/TpcTpc/HadronHadron/SameEvent/hYields"), multiplicity, track1.pt(), track1.eta()); registry.fill(HIST("Data/TpcTpc/HadronHadron/SameEvent/hEtaPhi"), multiplicity, track1.eta(), track1.phi()); } - registry.fill(HIST("Data/TpcTpc/HadronHadron/SameEvent/hNtracks"), Ntracks); + registry.fill(HIST("Data/TpcTpc/HadronHadron/SameEvent/hNtracks"), nTracks); + } + + // ---- MC : TPC-TPC h-h Same Event QA ---- + // Changed quickly void for int type + added the return for a test + template + int fillTpcTpcChChSameEventQaMc(float multiplicity, TTracks const& tracks) + { + int nTracks = tracks.size(); + for (const auto& track1 : tracks) { + + // in case of MC-generated, do additional selection on MCparticles : charge and isPhysicalPrimary + if constexpr (std::is_same_v) { + if (!isMcParticleSelected(track1)) { + continue; + } + // TO-DO : add other if constexpr conditions when I will have more MC cases + } + + if constexpr (std::is_same_v) { // if MC Rec + registry.fill(HIST("MC/Rec/TpcTpc/HadronHadron/SameEvent/hPt"), track1.pt()); + registry.fill(HIST("MC/Rec/TpcTpc/HadronHadron/SameEvent/hEta"), track1.eta()); + registry.fill(HIST("MC/Rec/TpcTpc/HadronHadron/SameEvent/hPhi"), track1.phi()); + registry.fill(HIST("MC/Rec/TpcTpc/HadronHadron/SameEvent/hYields"), multiplicity, track1.pt(), track1.eta()); + registry.fill(HIST("MC/Rec/TpcTpc/HadronHadron/SameEvent/hEtaPhi"), multiplicity, track1.eta(), track1.phi()); + } else { // if MC Gen + registry.fill(HIST("MC/Gen/TpcTpc/HadronHadron/SameEvent/hPt"), track1.pt()); + registry.fill(HIST("MC/Gen/TpcTpc/HadronHadron/SameEvent/hEta"), track1.eta()); + registry.fill(HIST("MC/Gen/TpcTpc/HadronHadron/SameEvent/hPhi"), track1.phi()); + registry.fill(HIST("MC/Gen/TpcTpc/HadronHadron/SameEvent/hYields"), multiplicity, track1.pt(), track1.eta()); + registry.fill(HIST("MC/Gen/TpcTpc/HadronHadron/SameEvent/hEtaPhi"), multiplicity, track1.eta(), track1.phi()); + } + } + if constexpr (std::is_same_v) { // if MC Rec + registry.fill(HIST("MC/Rec/TpcTpc/HadronHadron/SameEvent/hNtracks"), nTracks); + registry.fill(HIST("MC/Rec/TpcTpc/HadronHadron/SameEvent/hMultiplicityPrimary"), nTracks); + } else { // if MC Gen + registry.fill(HIST("MC/Gen/TpcTpc/HadronHadron/SameEvent/hNtracks"), nTracks); + registry.fill(HIST("MC/Gen/TpcTpc/HadronHadron/SameEvent/hMultiplicityPrimary"), nTracks); + } + return nTracks; } + // ---- DATA : TPC-TPC h-h Mixed Event QA ---- template - void fillMixingQA(float multiplicity, float vz, TTracks const& tracks) + void fillTpcTpcChChMixedEventQa(float multiplicity, float vz, TTracks const& tracks) { registry.fill(HIST("Data/TpcTpc/HadronHadron/MixedEvent/hMultiplicityMixing"), multiplicity); registry.fill(HIST("Data/TpcTpc/HadronHadron/MixedEvent/hVtxZMixing"), vz); - int Ntracks = 0; + int nTracks = tracks.size(); for (const auto& track1 : tracks) { - Ntracks++; registry.fill(HIST("Data/TpcTpc/HadronHadron/MixedEvent/hPtMixing"), track1.pt()); registry.fill(HIST("Data/TpcTpc/HadronHadron/MixedEvent/hEtaMixing"), track1.eta()); registry.fill(HIST("Data/TpcTpc/HadronHadron/MixedEvent/hPhiMixing"), track1.phi()); } - registry.fill(HIST("Data/TpcTpc/HadronHadron/MixedEvent/hNtracksMixing"), Ntracks); + registry.fill(HIST("Data/TpcTpc/HadronHadron/MixedEvent/hNtracksMixing"), nTracks); + } + + // ---- MC : TPC-TPC h-h Mixed Event QA ---- + template + void fillTpcTpcChChMixedEventQaMc(float multiplicity, float vz, TTracks const& tracks) + { + if constexpr (std::is_same_v) { // if MC Rec + registry.fill(HIST("MC/Rec/TpcTpc/HadronHadron/MixedEvent/hMultiplicityMixing"), multiplicity); + registry.fill(HIST("MC/Rec/TpcTpc/HadronHadron/MixedEvent/hVtxZMixing"), vz); + } else { // if MC Gen + registry.fill(HIST("MC/Gen/TpcTpc/HadronHadron/MixedEvent/hMultiplicityMixing"), multiplicity); + registry.fill(HIST("MC/Gen/TpcTpc/HadronHadron/MixedEvent/hVtxZMixing"), vz); + } + + int nTracks = tracks.size(); + for (const auto& track1 : tracks) { + if constexpr (std::is_same_v) { // if MC Rec + registry.fill(HIST("MC/Rec/TpcTpc/HadronHadron/MixedEvent/hPtMixing"), track1.pt()); + registry.fill(HIST("MC/Rec/TpcTpc/HadronHadron/MixedEvent/hEtaMixing"), track1.eta()); + registry.fill(HIST("MC/Rec/TpcTpc/HadronHadron/MixedEvent/hPhiMixing"), track1.phi()); + } else { // if MC Gen + registry.fill(HIST("MC/Gen/TpcTpc/HadronHadron/MixedEvent/hPtMixing"), track1.pt()); + registry.fill(HIST("MC/Gen/TpcTpc/HadronHadron/MixedEvent/hEtaMixing"), track1.eta()); + registry.fill(HIST("MC/Gen/TpcTpc/HadronHadron/MixedEvent/hPhiMixing"), track1.phi()); + } + } + if constexpr (std::is_same_v) { // if MC Rec + registry.fill(HIST("MC/Rec/TpcTpc/HadronHadron/MixedEvent/hNtracksMixing"), nTracks); + } else { // if MC Gen + registry.fill(HIST("MC/Gen/TpcTpc/HadronHadron/MixedEvent/hNtracksMixing"), nTracks); + } } + // ---- DATA : TPC-TPC HF-h Mixed Event QA ---- template - void fillHFMixingQA(float multiplicity, float vz, TTracks const& tracks) + void fillTpcTpcHfChMixedEventQa(float multiplicity, float vz, TTracks const& tracks) { registry.fill(HIST("Data/TpcTpc/HfHadron/MixedEvent/hMultiplicityHFMixing"), multiplicity); registry.fill(HIST("Data/TpcTpc/HfHadron/MixedEvent/hVtxZHFMixing"), vz); - int Ntracks = 0; + int nTracks = tracks.size(); for (const auto& track1 : tracks) { - Ntracks++; registry.fill(HIST("Data/TpcTpc/HfHadron/MixedEvent/hPtHFMixing"), track1.pt()); registry.fill(HIST("Data/TpcTpc/HfHadron/MixedEvent/hEtaHFMixing"), track1.eta()); registry.fill(HIST("Data/TpcTpc/HfHadron/MixedEvent/hPhiHFMixing"), track1.phi()); } - registry.fill(HIST("Data/TpcTpc/HfHadron/MixedEvent/hNtracksHFMixing"), Ntracks); + registry.fill(HIST("Data/TpcTpc/HfHadron/MixedEvent/hNtracksHFMixing"), nTracks); } + // ---- DATA : TPC-MFT h-h Same Event QA ---- template - void fillMFTQA(float multiplicity, TTracks const& tracks) + void fillTpcMftChChSameEventQa(float multiplicity, TTracks const& tracks) { + int nTracks = tracks.size(); + bool isMFT = false; for (const auto& track1 : tracks) { - registry.fill(HIST("Data/TpcMft/HadronHadron/hEtaMFT"), track1.eta()); - float phi = track1.phi(); - o2::math_utils::bringTo02Pi(phi); - registry.fill(HIST("Data/TpcMft/HadronHadron/hPhiMFT"), phi); - registry.fill(HIST("Data/TpcMft/HadronHadron/hEtaPhiMFT"), multiplicity, track1.eta(), phi); + if constexpr (std::is_same_v) { // if MFT tracks + isMFT = true; + registry.fill(HIST("Data/TpcMft/HadronHadron/SameEvent/hEtaMFT"), track1.eta()); + float phi = track1.phi(); + o2::math_utils::bringTo02Pi(phi); + registry.fill(HIST("Data/TpcMft/HadronHadron/SameEvent/hPhiMFT"), phi); + registry.fill(HIST("Data/TpcMft/HadronHadron/SameEvent/hEtaPhiMFT"), multiplicity, track1.eta(), phi); + registry.fill(HIST("Data/TpcMft/HadronHadron/SameEvent/hPtMFT"), track1.pt()); + registry.fill(HIST("Data/TpcMft/HadronHadron/SameEvent/hYieldsMFT"), multiplicity, track1.pt(), track1.eta()); + } else { // if TPC tracks + registry.fill(HIST("Data/TpcMft/HadronHadron/SameEvent/hEtaTPC"), track1.eta()); + float phi = track1.phi(); + o2::math_utils::bringTo02Pi(phi); + registry.fill(HIST("Data/TpcMft/HadronHadron/SameEvent/hPhiTPC"), phi); + registry.fill(HIST("Data/TpcMft/HadronHadron/SameEvent/hEtaPhiTPC"), multiplicity, track1.eta(), phi); + registry.fill(HIST("Data/TpcMft/HadronHadron/SameEvent/hPtTPC"), track1.pt()); + registry.fill(HIST("Data/TpcMft/HadronHadron/SameEvent/hYieldsTPC"), multiplicity, track1.pt(), track1.eta()); + } + if (isMFT) { + registry.fill(HIST("Data/TpcTpc/HadronHadron/SameEvent/hNtracksMFT"), nTracks); + } else { + registry.fill(HIST("Data/TpcTpc/HadronHadron/SameEvent/hNtracksTPC"), nTracks); + } + } + } + + // ---- DATA : TPC-MFT HF-h Same Event QA ---- + template + void fillTpcMftHfChSameEventQa(float multiplicity, TTracks const& tracks) + { + int nTracks = tracks.size(); + bool isMFT = false; + for (const auto& track1 : tracks) { + if constexpr (std::is_same_v) { // if MFT tracks + isMFT = true; + registry.fill(HIST("Data/TpcMft/HfHadron/SameEvent/SameEvent/hEtaMFT"), track1.eta()); + float phi = track1.phi(); + o2::math_utils::bringTo02Pi(phi); + registry.fill(HIST("Data/TpcMft/HfHadron/SameEvent/SameEvent/hPhiMFT"), phi); + registry.fill(HIST("Data/TpcMft/HfHadron/SameEvent/SameEvent/hEtaPhiMFT"), multiplicity, track1.eta(), phi); + registry.fill(HIST("Data/TpcMft/HfHadron/SameEvent/SameEvent/hPtMFT"), track1.pt()); + registry.fill(HIST("Data/TpcMft/HfHadron/SameEvent/SameEvent/hYieldsMFT"), multiplicity, track1.pt(), track1.eta()); + } else { // if TPC tracks + registry.fill(HIST("Data/TpcMft/HfHadron/SameEvent/SameEvent/hEtaCandidate"), track1.eta()); + float phi = track1.phi(); + o2::math_utils::bringTo02Pi(phi); + registry.fill(HIST("Data/TpcMft/HfHadron/SameEvent/SameEvent/hPhiCandidate"), phi); + registry.fill(HIST("Data/TpcMft/HfHadron/SameEvent/SameEvent/hEtaPhiCandidate"), multiplicity, track1.eta(), phi); + registry.fill(HIST("Data/TpcMft/HfHadron/SameEvent/SameEvent/hPtCandidate"), track1.pt()); + registry.fill(HIST("Data/TpcMft/HfHadron/SameEvent/SameEvent/hYieldsCandidate"), multiplicity, track1.pt(), track1.eta()); + } + if (isMFT) { + registry.fill(HIST("Data/TpcTpc/HfHadron/SameEvent/SameEvent/hNtracksMFT"), nTracks); + } else { + registry.fill(HIST("Data/TpcTpc/HfHadron/SameEvent/SameEvent/hNtracksCandidate"), nTracks); + } + } + } + + // ---- DATA : TPC-MFT h-h Mixed Event QA ---- + template + void fillTpcMftChChMixedEventQa(float multiplicity, float vz, TTracks const& tracks) + { + if constexpr (std::is_same_v) { // if MFT tracks + registry.fill(HIST("Data/TpcMft/HadronHadron/MixedEvent/hMultiplicityMixingMFT"), multiplicity); + registry.fill(HIST("Data/TpcMft/HadronHadron/MixedEvent/hVtxZMixingMFT"), vz); + + int nTracks = tracks.size(); + for (const auto& track1 : tracks) { + registry.fill(HIST("Data/TpcMft/HadronHadron/MixedEvent/hPtMixingMFT"), track1.pt()); + registry.fill(HIST("Data/TpcMft/HadronHadron/MixedEvent/hEtaMixingMFT"), track1.eta()); + registry.fill(HIST("Data/TpcMft/HadronHadron/MixedEvent/hPhiMixingMFT"), track1.phi()); + } + registry.fill(HIST("Data/TpcMft/HadronHadron/MixedEvent/hNtracksMixingMFT"), nTracks); + } else { // if TPC tracks + registry.fill(HIST("Data/TpcMft/HadronHadron/MixedEvent/hMultiplicityMixingTPC"), multiplicity); + registry.fill(HIST("Data/TpcMft/HadronHadron/MixedEvent/hVtxZMixingTPC"), vz); + + int nTracks = tracks.size(); + for (const auto& track1 : tracks) { + registry.fill(HIST("Data/TpcMft/HadronHadron/MixedEvent/hPtMixingTPC"), track1.pt()); + registry.fill(HIST("Data/TpcMft/HadronHadron/MixedEvent/hEtaMixingTPC"), track1.eta()); + registry.fill(HIST("Data/TpcMft/HadronHadron/MixedEvent/hPhiMixingTPC"), track1.phi()); + } + registry.fill(HIST("Data/TpcMft/HadronHadron/MixedEvent/hNtracksMixingTPC"), nTracks); + } + } + + // ---- DATA : TPC-MFT h-h Mixed Event QA ---- + template + void fillTpcMftHfChMixedEventQa(float multiplicity, float vz, TTracks const& tracks) + { + if constexpr (std::is_same_v) { // if MFT tracks + registry.fill(HIST("Data/TpcMft/HfHadron/MixedEvent/hMultiplicityMixingMFT"), multiplicity); + registry.fill(HIST("Data/TpcMft/HfHadron/MixedEvent/hVtxZMixingMFT"), vz); + + int nTracks = tracks.size(); + for (const auto& track1 : tracks) { + registry.fill(HIST("Data/TpcMft/HfHadron/MixedEvent/hPtMixingMFT"), track1.pt()); + registry.fill(HIST("Data/TpcMft/HfHadron/MixedEvent/hEtaMixingMFT"), track1.eta()); + registry.fill(HIST("Data/TpcMft/HfHadron/MixedEvent/hPhiMixingMFT"), track1.phi()); + } + registry.fill(HIST("Data/TpcMft/HfHadron/MixedEvent/hNtracksMixingMFT"), nTracks); + } else { // if candidate tracks + registry.fill(HIST("Data/TpcMft/HfHadron/MixedEvent/hMultiplicityMixingCandidate"), multiplicity); + registry.fill(HIST("Data/TpcMft/HfHadron/MixedEvent/hVtxZMixingCandidate"), vz); + + int nTracks = tracks.size(); + for (const auto& track1 : tracks) { + registry.fill(HIST("Data/TpcMft/HfHadron/MixedEvent/hPtMixingCandidate"), track1.pt()); + registry.fill(HIST("Data/TpcMft/HfHadron/MixedEvent/hEtaMixingCandidate"), track1.eta()); + registry.fill(HIST("Data/TpcMft/HfHadron/MixedEvent/hPhiMixingCandidate"), track1.phi()); + } + registry.fill(HIST("Data/TpcMft/HfHadron/MixedEvent/hNtracksMixingCandidate"), nTracks); } } @@ -312,9 +722,68 @@ struct HfTaskFlow { return true; } + // 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 + bool isMcParticleSelected(TMcParticles& mcParticles) + { + // remove MC particles with charge = 0 + TParticlePDG* pdgparticle = pdg->GetParticle(mcParticles.pdgCode()); + if (pdgparticle != nullptr) { + if (pdgparticle->Charge() == 0) { + return false; + } + } + + // MC particle has to be primary + if constexpr (step <= CorrelationContainer::kCFStepAnaTopology) { + return mcParticles.isPhysicalPrimary(); + } + return true; + } + + // ---- DATA : TPC-TPC HF-h Same Event (Candidates) QA ---- + // TODO: Note: we do not need all these plots since they are in D0 and Lc task -> remove it after we are sure this works + template + void fillTpcTpcCandidateQa(TTracks const& candidates) + { + for (const auto& candidate : candidates) { + if (!isAcceptedCandidate(candidate)) { + continue; + } + + if (candidate.isSelD0() >= selectionFlagD0) { + registry.fill(HIST("Data/TpcTpc/HfHadron/SameEvent/hMassVsPt"), hfHelper.invMassD0ToPiK(candidate), candidate.pt()); + registry.fill(HIST("Data/TpcTpc/HfHadron/SameEvent/hMass"), hfHelper.invMassD0ToPiK(candidate)); + } + if (candidate.isSelD0bar() >= selectionFlagD0bar) { + registry.fill(HIST("Data/TpcTpc/HfHadron/SameEvent/hMassVsPt"), hfHelper.invMassD0barToKPi(candidate), candidate.pt()); + registry.fill(HIST("Data/TpcTpc/HfHadron/SameEvent/hMass"), hfHelper.invMassD0barToKPi(candidate)); + } + + registry.fill(HIST("Data/TpcTpc/HfHadron/SameEvent/hPtCand"), candidate.pt()); + registry.fill(HIST("Data/TpcTpc/HfHadron/SameEvent/hPtProng0"), candidate.ptProng0()); + registry.fill(HIST("Data/TpcTpc/HfHadron/SameEvent/hPtProng1"), candidate.ptProng1()); + registry.fill(HIST("Data/TpcTpc/HfHadron/SameEvent/hDecLength"), candidate.decayLength(), candidate.pt()); + registry.fill(HIST("Data/TpcTpc/HfHadron/SameEvent/hDecLengthXY"), candidate.decayLengthXY(), candidate.pt()); + registry.fill(HIST("Data/TpcTpc/HfHadron/SameEvent/hd0Prong0"), candidate.impactParameter0(), candidate.pt()); + registry.fill(HIST("Data/TpcTpc/HfHadron/SameEvent/hd0Prong1"), candidate.impactParameter1(), candidate.pt()); + registry.fill(HIST("Data/TpcTpc/HfHadron/SameEvent/hd0d0"), candidate.impactParameterProduct(), candidate.pt()); + registry.fill(HIST("Data/TpcTpc/HfHadron/SameEvent/hCTS"), hfHelper.cosThetaStarD0(candidate), candidate.pt()); + registry.fill(HIST("Data/TpcTpc/HfHadron/SameEvent/hCt"), hfHelper.ctD0(candidate), candidate.pt()); + registry.fill(HIST("Data/TpcTpc/HfHadron/SameEvent/hCPA"), candidate.cpa(), candidate.pt()); + registry.fill(HIST("Data/TpcTpc/HfHadron/SameEvent/hEtaCand"), candidate.eta(), candidate.pt()); + registry.fill(HIST("Data/TpcTpc/HfHadron/SameEvent/hSelectionStatus"), candidate.isSelD0() + (candidate.isSelD0bar() * 2), candidate.pt()); + registry.fill(HIST("Data/TpcTpc/HfHadron/SameEvent/hImpParErr"), candidate.errorImpactParameter0(), candidate.pt()); + registry.fill(HIST("Data/TpcTpc/HfHadron/SameEvent/hImpParErr"), candidate.errorImpactParameter1(), candidate.pt()); + registry.fill(HIST("Data/TpcTpc/HfHadron/SameEvent/hDecLenErr"), candidate.errorDecayLength(), candidate.pt()); + registry.fill(HIST("Data/TpcTpc/HfHadron/SameEvent/hDecLenXYErr"), candidate.errorDecayLengthXY(), candidate.pt()); + } + } + + // ---- DATA : TPC-MFT HF-h Same Event (Candidates) QA ---- // TODO: Note: we do not need all these plots since they are in D0 and Lc task -> remove it after we are sure this works template - void fillCandidateQA(TTracks const& candidates) + void fillTpcMftCandidateQa(TTracks const& candidates) { for (const auto& candidate : candidates) { if (!isAcceptedCandidate(candidate)) { @@ -322,33 +791,39 @@ struct HfTaskFlow { } if (candidate.isSelD0() >= selectionFlagD0) { - registry.fill(HIST("Data/TpcTpc/HfHadron/hMass"), hfHelper.invMassD0ToPiK(candidate), candidate.pt()); + registry.fill(HIST("Data/TpcMft/HfHadron/SameEvent/hMassVsPt"), hfHelper.invMassD0ToPiK(candidate), candidate.pt()); + registry.fill(HIST("Data/TpcMft/HfHadron/SameEvent/hMass"), hfHelper.invMassD0ToPiK(candidate)); } if (candidate.isSelD0bar() >= selectionFlagD0bar) { - registry.fill(HIST("Data/TpcTpc/HfHadron/hMass"), hfHelper.invMassD0barToKPi(candidate), candidate.pt()); + registry.fill(HIST("Data/TpcMft/HfHadron/SameEvent/hMassVsPt"), hfHelper.invMassD0barToKPi(candidate), candidate.pt()); + registry.fill(HIST("Data/TpcMft/HfHadron/SameEvent/hMass"), hfHelper.invMassD0barToKPi(candidate)); } - registry.fill(HIST("Data/TpcTpc/HfHadron/hPtCand"), candidate.pt()); - registry.fill(HIST("Data/TpcTpc/HfHadron/hPtProng0"), candidate.ptProng0()); - registry.fill(HIST("Data/TpcTpc/HfHadron/hPtProng1"), candidate.ptProng1()); - registry.fill(HIST("Data/TpcTpc/HfHadron/hDecLength"), candidate.decayLength(), candidate.pt()); - registry.fill(HIST("Data/TpcTpc/HfHadron/hDecLengthXY"), candidate.decayLengthXY(), candidate.pt()); - registry.fill(HIST("Data/TpcTpc/HfHadron/hd0Prong0"), candidate.impactParameter0(), candidate.pt()); - registry.fill(HIST("Data/TpcTpc/HfHadron/hd0Prong1"), candidate.impactParameter1(), candidate.pt()); - registry.fill(HIST("Data/TpcTpc/HfHadron/hd0d0"), candidate.impactParameterProduct(), candidate.pt()); - registry.fill(HIST("Data/TpcTpc/HfHadron/hCTS"), hfHelper.cosThetaStarD0(candidate), candidate.pt()); - registry.fill(HIST("Data/TpcTpc/HfHadron/hCt"), hfHelper.ctD0(candidate), candidate.pt()); - registry.fill(HIST("Data/TpcTpc/HfHadron/hCPA"), candidate.cpa(), candidate.pt()); - registry.fill(HIST("Data/TpcTpc/HfHadron/hEtaCand"), candidate.eta(), candidate.pt()); - registry.fill(HIST("Data/TpcTpc/HfHadron/hSelectionStatus"), candidate.isSelD0() + (candidate.isSelD0bar() * 2), candidate.pt()); - registry.fill(HIST("Data/TpcTpc/HfHadron/hImpParErr"), candidate.errorImpactParameter0(), candidate.pt()); - registry.fill(HIST("Data/TpcTpc/HfHadron/hImpParErr"), candidate.errorImpactParameter1(), candidate.pt()); - registry.fill(HIST("Data/TpcTpc/HfHadron/hDecLenErr"), candidate.errorDecayLength(), candidate.pt()); - registry.fill(HIST("Data/TpcTpc/HfHadron/hDecLenXYErr"), candidate.errorDecayLengthXY(), candidate.pt()); + registry.fill(HIST("Data/TpcMft/HfHadron/SameEvent/hPtCand"), candidate.pt()); + registry.fill(HIST("Data/TpcMft/HfHadron/SameEvent/hPtProng0"), candidate.ptProng0()); + registry.fill(HIST("Data/TpcMft/HfHadron/SameEvent/hPtProng1"), candidate.ptProng1()); + registry.fill(HIST("Data/TpcMft/HfHadron/SameEvent/hDecLength"), candidate.decayLength(), candidate.pt()); + registry.fill(HIST("Data/TpcMft/HfHadron/SameEvent/hDecLengthXY"), candidate.decayLengthXY(), candidate.pt()); + registry.fill(HIST("Data/TpcMft/HfHadron/SameEvent/hd0Prong0"), candidate.impactParameter0(), candidate.pt()); + registry.fill(HIST("Data/TpcMft/HfHadron/SameEvent/hd0Prong1"), candidate.impactParameter1(), candidate.pt()); + registry.fill(HIST("Data/TpcMft/HfHadron/SameEvent/hd0d0"), candidate.impactParameterProduct(), candidate.pt()); + registry.fill(HIST("Data/TpcMft/HfHadron/SameEvent/hCTS"), hfHelper.cosThetaStarD0(candidate), candidate.pt()); + registry.fill(HIST("Data/TpcMft/HfHadron/SameEvent/hCt"), hfHelper.ctD0(candidate), candidate.pt()); + registry.fill(HIST("Data/TpcMft/HfHadron/SameEvent/hCPA"), candidate.cpa(), candidate.pt()); + registry.fill(HIST("Data/TpcMft/HfHadron/SameEvent/hEtaCand"), candidate.eta(), candidate.pt()); + registry.fill(HIST("Data/TpcMft/HfHadron/SameEvent/hSelectionStatus"), candidate.isSelD0() + (candidate.isSelD0bar() * 2), candidate.pt()); + registry.fill(HIST("Data/TpcMft/HfHadron/SameEvent/hImpParErr"), candidate.errorImpactParameter0(), candidate.pt()); + registry.fill(HIST("Data/TpcMft/HfHadron/SameEvent/hImpParErr"), candidate.errorImpactParameter1(), candidate.pt()); + registry.fill(HIST("Data/TpcMft/HfHadron/SameEvent/hDecLenErr"), candidate.errorDecayLength(), candidate.pt()); + registry.fill(HIST("Data/TpcMft/HfHadron/SameEvent/hDecLenXYErr"), candidate.errorDecayLengthXY(), candidate.pt()); } } - template + // ========================= + // Correlation functions + // ========================= + + template void fillCorrelations(TTarget target, TTracksTrig const& tracks1, TTracksAssoc const& tracks2, float multiplicity, float posZ) { auto triggerWeight = 1; @@ -365,6 +840,7 @@ struct HfTaskFlow { // 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) { @@ -376,11 +852,22 @@ struct HfTaskFlow { invmass = hfHelper.invMassD0ToPiK(track1); } + // From Katarina's code + // in case of MC-generated, do additional selection on MCparticles : charge and isPhysicalPrimary + // if (processMc) { + // NOTE : this version with FilteredMcParticles is only for Katarina's way of doing MC + if constexpr (std::is_same_v || std::is_same_v) { + if (!isMcParticleSelected(track1)) { + continue; + } + // TO-DO : add other if constexpr conditions when I will have more MC cases + } + // fill single-track distributions if (!fillingHFcontainer) { - target->getTriggerHist()->Fill(CorrelationContainer::kCFStepReconstructed, pt1, multiplicity, posZ, triggerWeight); + target->getTriggerHist()->Fill(step, pt1, multiplicity, posZ, triggerWeight); } else { - target->getTriggerHist()->Fill(CorrelationContainer::kCFStepReconstructed, pt1, multiplicity, posZ, invmass, triggerWeight); + target->getTriggerHist()->Fill(step, pt1, multiplicity, posZ, invmass, triggerWeight); } for (const auto& track2 : tracks2) { @@ -394,13 +881,22 @@ struct HfTaskFlow { } // in case of HF-h correlations, remove candidate daughters from the pool of associated hadrons - // with which the candidate is being correlated + // with which the candidate is being correlated (will not have to do it for TPC-MFT case) if constexpr (std::is_same_v) { if ((track1.prong0Id() == track2.globalIndex()) || (track1.prong1Id() == track2.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 (!isMcParticleSelected(track2)) { + continue; + } + // Note : no need for HF if condition as this will always be normal track, but maybe for MFT + } + float eta2 = track2.eta(); float pt2 = track2.pt(); float phi2 = track2.phi(); @@ -416,57 +912,133 @@ struct HfTaskFlow { if (!fillingHFcontainer) { // fill pair correlations - target->getPairHist()->Fill(CorrelationContainer::kCFStepReconstructed, - eta1 - eta2, pt2, pt1, multiplicity, deltaPhi, posZ, + target->getPairHist()->Fill(step, eta1 - eta2, pt2, pt1, multiplicity, deltaPhi, posZ, triggerWeight * associatedWeight); } else { - target->getPairHist()->Fill(CorrelationContainer::kCFStepReconstructed, - eta1 - eta2, pt2, pt1, multiplicity, deltaPhi, posZ, invmass, + target->getPairHist()->Fill(step, eta1 - eta2, pt2, pt1, multiplicity, deltaPhi, posZ, invmass, triggerWeight * associatedWeight); } } } } - template - void mixCollisions(FilteredCollisionsWSelMult const& collisions, TTracksTrig const& tracks1, TTracksAssoc const& tracks2, TLambda getPartsSize, OutputObj& corrContainer) + // template + // void mixCollisions(FilteredCollisionsWSelMult const& collisions, TTracksTrig const& tracks1, TTracksAssoc const& tracks2, TLambda getPartsSize, OutputObj& corrContainer) + template + void mixCollisions(TCollisions const& collisions, TTracksTrig const& tracks1, TTracksAssoc const& tracks2, TLambda getPartsSize, OutputObj& corrContainer) { - using BinningType = FlexibleBinningPolicy, aod::collision::PosZ, decltype(getPartsSize)>; - BinningType binningWithTracksSize{{getPartsSize}, {axisVertex, axisMultiplicity}, true}; + // 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}, {axisVertex, axisMultiplicity}, true}; auto tracksTuple = std::make_tuple(tracks1, tracks2); - Pair pair{binningWithTracksSize, nMixedEvents, -1, collisions, tracksTuple, &cache}; + Pair pair{binningWithTracksSize, nMixedEvents, -1, collisions, tracksTuple, &cache}; for (const auto& [collision1, tracks1, collision2, tracks2] : pair) { - if (!(isCollisionSelected(collision1, false))) { - continue; - } - if (!(isCollisionSelected(collision2, false))) { - continue; + if constexpr (!std::is_same_v) { + if (!(isCollisionSelected(collision1, false))) { + continue; + } + if (!(isCollisionSelected(collision2, false))) { + continue; + } } auto binningValues = binningWithTracksSize.getBinningValues(collision1, collisions); int bin = binningWithTracksSize.getBin(binningValues); - const auto multiplicity = tracks2.size(); // get multiplicity of charged hadrons, which is used for slicing in mixing + const auto multiplicityTracks2 = tracks2.size(); // get multiplicity of charged hadrons, which is used for slicing in mixing + const auto multiplicityTracks1 = tracks1.size(); // get multiplicity of charged hadrons, which is used for slicing in mixing const auto vz = collision1.posZ(); - if constexpr (std::is_same_v) { - registry.fill(HIST("Data/TpcTpc/HfHadron/MixedEvent/hEventCountHFMixing"), bin); - fillHFMixingQA(multiplicity, vz, tracks1); - } else { - registry.fill(HIST("Data/TpcTpc/HadronHadron/MixedEvent/hEventCountMixing"), bin); - fillMixingQA(multiplicity, vz, tracks1); + if constexpr (std::is_same_v) { // If MC + registry.fill(HIST("MC/Rec/TpcTpc/HadronHadron/MixedEvent/hEventCountMixing"), bin); + fillTpcTpcChChMixedEventQaMc(multiplicityTracks2, vz, tracks1); + + // if constexpr (std::is_same_v) { + // registry.fill(HIST("Data/TpcTpc/HfHadron/MixedEvent/hEventCountHFMixing"), bin); + // fillHFMixingQA(multiplicity, vz, tracks1); + // } else { + // registry.fill(HIST("Data/TpcTpc/HadronHadron/MixedEvent/hEventCountMixing"), bin); + // fillMixingQA(multiplicity, vz, tracks1); + // } + + } else { // If not MC + if constexpr (std::is_same_v) { // DATA : If TPC-TPC Hf-h case + registry.fill(HIST("Data/TpcTpc/HfHadron/MixedEvent/hEventCountHFMixing"), bin); + fillTpcTpcHfChMixedEventQa(multiplicityTracks2, vz, tracks1); + } else if constexpr (std::is_same_v) { // DATA : If TPC-MFT h-h case + registry.fill(HIST("Data/TpcMft/HadronHadron/MixedEvent/hEventCountMixing"), bin); + fillTpcMftChChMixedEventQa(multiplicityTracks1, vz, tracks1); // TPC tracks + fillTpcMftChChMixedEventQa(multiplicityTracks2, vz, tracks2); // MFT tracks + } else if constexpr (std::is_same_v && std::is_same_v) { // DATA : If TPC-MFT HF-h case + registry.fill(HIST("Data/TpcMft/HfHadron/MixedEvent/hEventCountMixing"), bin); + fillTpcMftHfChMixedEventQa(multiplicityTracks1, vz, tracks1); // Candidates + fillTpcMftHfChMixedEventQa(multiplicityTracks2, vz, tracks2); // MFT tracks + } else { // DATA : If TPC-TPC h-h case + registry.fill(HIST("Data/TpcTpc/HadronHadron/MixedEvent/hEventCountMixing"), bin); + fillTpcTpcChChMixedEventQa(multiplicityTracks2, vz, tracks1); + } } - corrContainer->fillEvent(multiplicity, CorrelationContainer::kCFStepReconstructed); - fillCorrelations(corrContainer, tracks1, tracks2, multiplicity, collision1.posZ()); + corrContainer->fillEvent(multiplicityTracks2, CorrelationContainer::kCFStepReconstructed); + fillCorrelations(corrContainer, tracks1, tracks2, multiplicityTracks2, collision1.posZ()); + } + } + + // template + // void mixCollisions(FilteredCollisionsWSelMult const& collisions, TTracksTrig const& tracks1, TTracksAssoc const& tracks2, TLambda getPartsSize, OutputObj& corrContainer) + template + void mixCollisionsMcTruth(TCollisions const& collisions, TTracksTrig const& tracks1, TTracksAssoc const& tracks2, TLambda getPartsSize, OutputObj& corrContainer) + { + using BinningTypeMcTruth = FlexibleBinningPolicy, aod::mccollision::PosZ, decltype(getPartsSize)>; + + BinningTypeMcTruth binningWithTracksSize{{getPartsSize}, {axisVertex, axisMultiplicity}, true}; + auto tracksTuple = std::make_tuple(tracks1, tracks2); + Pair pair{binningWithTracksSize, nMixedEvents, -1, collisions, tracksTuple, &cache}; + + for (const auto& [collision1, tracks1, collision2, tracks2] : pair) { + + // added this to try to compile when doing mixed event with FilteredMcParticles and FilteredMcCollisions (MC truth) + // TODO : GET RID OF THE COLLISION SELECTION FOR MC TRUTH + // if constexpr (!std::is_same_v) { + // if (!(isCollisionSelected(collision1, false))) { + // continue; + // } + // if (!(isCollisionSelected(collision2, false))) { + // continue; + // } + //} + + auto binningValues = binningWithTracksSize.getBinningValues(collision1, collisions); + int bin = binningWithTracksSize.getBin(binningValues); + + const auto multiplicity = tracks2.size(); // get multiplicity of charged hadrons, which is used for slicing in mixing + const auto vz = collision1.posZ(); + + // TO BE DONE : ADD ONE MORE IF CONDITION TO FILL THE MC CASE + // TODO : FILL NEW PLOTS FOR MCTRUTH ONLY + registry.fill(HIST("MC/Gen/TpcTpc/HadronHadron/MixedEvent/hEventCountMixing"), bin); + fillTpcTpcChChMixedEventQaMc(multiplicity, vz, tracks1); + + // if constexpr (std::is_same_v) { + // registry.fill(HIST("Data/TpcTpc/HfHadron/MixedEvent/hEventCountHFMixing"), bin); + // fillHFMixingQA(multiplicity, vz, tracks1); + // } else { + // registry.fill(HIST("Data/TpcTpc/HadronHadron/MixedEvent/hEventCountMixing"), bin); + // fillMixingQA(multiplicity, vz, tracks1); + // } + + corrContainer->fillEvent(multiplicity, CorrelationContainer::kCFStepAll); + fillCorrelations(corrContainer, tracks1, tracks2, multiplicity, collision1.posZ()); } } // ===================================== - // process same event correlations: h-h case + // DATA : process same event correlations: TPC-TPC h-h case // ===================================== + void processSameTpcTpcChCh(FilteredCollisionsWSelMult::iterator const& collision, TracksWDcaSel const& tracks) { @@ -489,14 +1061,16 @@ struct HfTaskFlow { sameTPCTPCChCh->fillEvent(multiplicity, CorrelationContainer::kCFStepReconstructed); - fillQA(multiplicity, tracks); - fillCorrelations(sameTPCTPCChCh, tracks, tracks, multiplicity, collision.posZ()); + fillTpcTpcChChSameEventQa(multiplicity, tracks); + // TO-DO : add if condition for when we will implant corrected correlations (kCFStepReconstructed -> kCFStepCorrected) + fillCorrelations(sameTPCTPCChCh, tracks, tracks, multiplicity, collision.posZ()); } - PROCESS_SWITCH(HfTaskFlow, processSameTpcTpcChCh, "Process same-event correlations for TPC-TPC h-h case", true); + PROCESS_SWITCH(HfTaskFlow, processSameTpcTpcChCh, "DATA : Process same-event correlations for TPC-TPC h-h case", true); // ===================================== - // process same event correlations: HF-h case + // DATA : process same event correlations: TPC-TPC HF-h case // ===================================== + void processSameTpcTpcHfCh(FilteredCollisionsWSelMult::iterator const& collision, TracksWDcaSel const& tracks, HfCandidatesSel const& candidates) @@ -508,33 +1082,131 @@ struct HfTaskFlow { sameTPCTPCHfCh->fillEvent(multiplicity, CorrelationContainer::kCFStepReconstructed); - fillCandidateQA(candidates); - fillCorrelations(sameTPCTPCHfCh, candidates, tracks, multiplicity, collision.posZ()); + fillTpcTpcCandidateQa(candidates); + fillCorrelations(sameTPCTPCHfCh, candidates, tracks, multiplicity, collision.posZ()); } - PROCESS_SWITCH(HfTaskFlow, processSameTpcTpcHfCh, "Process same-event correlations for TPC-TPC HF-h case", true); + PROCESS_SWITCH(HfTaskFlow, processSameTpcTpcHfCh, "DATA : Process same-event correlations for TPC-TPC HF-h case", true); // ===================================== - // process same event correlations: h-MFT case + // DATA : process same event correlations: TPC-MFT h-h case // ===================================== + void processSameTpcMftChCh(FilteredCollisionsWSelMult::iterator const& collision, TracksWDcaSel const& tracks, - aod::MFTTracks const& mfttracks) + aod::MFTTracks const& mftTracks) { if (!(isCollisionSelected(collision, true))) { return; } - const auto multiplicity = tracks.size(); + const auto multiplicityTPC = tracks.size(); + const auto multiplicityMFT = mftTracks.size(); + + sameTPCMFTChCh->fillEvent(multiplicityTPC, CorrelationContainer::kCFStepReconstructed); + fillTpcMftChChSameEventQa(multiplicityTPC, tracks); + fillTpcMftChChSameEventQa(multiplicityMFT, mftTracks); + fillCorrelations(sameTPCMFTChCh, tracks, mftTracks, multiplicityTPC, collision.posZ()); + } + PROCESS_SWITCH(HfTaskFlow, processSameTpcMftChCh, "DATA : Process same-event correlations for TPC-MFT h-h case", true); + + // ===================================== + // DATA : process same event correlations: TPC-MFT HF-h case + // ===================================== - sameTPCMFTChCh->fillEvent(multiplicity, CorrelationContainer::kCFStepReconstructed); - fillMFTQA(multiplicity, mfttracks); - fillCorrelations(sameTPCMFTChCh, tracks, mfttracks, multiplicity, collision.posZ()); + void processSameTpcMftHfCh(FilteredCollisionsWSelMult::iterator const& collision, + HfCandidatesSel const& candidates, + aod::MFTTracks const& mftTracks) + { + if (!(isCollisionSelected(collision, true))) { + return; + } + + const auto multiplicityCandidates = candidates.size(); + const auto multiplicityMFT = mftTracks.size(); + + sameTPCMFTHfCh->fillEvent(multiplicityCandidates, CorrelationContainer::kCFStepReconstructed); + fillTpcMftCandidateQa(candidates); + fillTpcMftHfChSameEventQa(multiplicityMFT, mftTracks); + fillCorrelations(sameTPCMFTHfCh, candidates, mftTracks, multiplicityCandidates, collision.posZ()); + } + PROCESS_SWITCH(HfTaskFlow, processSameTpcMftHfCh, "DATA : Process same-event correlations for TPC-MFT HF-h case", true); + + // ===================================== + // MONTE-CARLO : process same event correlations: TPC-TPC h-h case + // ===================================== + + void processSameTpcTpcChChmcREC(FilteredCollisionsWSelMultMC::iterator const& mcCollision, + TracksWDcaSelMC const& mcTracks) + { + + // NEED TO COMMENT THIS + // if (!(isCollisionSelected(mcCollision, true))) { + // return; + //} + + const auto multiplicity = mcTracks.size(); + registry.fill(HIST("MC/Rec/TpcTpc/HadronHadron/SameEvent/hMultiplicity"), multiplicity); + registry.fill(HIST("MC/Rec/TpcTpc/HadronHadron/SameEvent/hVtxZ"), mcCollision.posZ()); + + BinningPolicyBase<2> baseBinning{{axisVertex, axisMultiplicity}, true}; + int bin = baseBinning.getBin(std::make_tuple(mcCollision.posZ(), multiplicity)); + registry.fill(HIST("MC/Rec/TpcTpc/HadronHadron/SameEvent/hEventCountSame"), bin); + + sameTPCTPCChChMC->fillEvent(multiplicity, CorrelationContainer::kCFStepReconstructed); + + fillTpcTpcChChSameEventQaMc(multiplicity, mcTracks); + fillCorrelations(sameTPCTPCChChMC, mcTracks, mcTracks, multiplicity, mcCollision.posZ()); + } + PROCESS_SWITCH(HfTaskFlow, processSameTpcTpcChChmcREC, "MONTE-CARLO : Process same-event correlations for TPC-TPC h-h case", true); + + // Katarina's version = MC Truth + void processSameTpcTpcChChmcGEN(FilteredMcCollisions::iterator const& mcCollision, + FilteredMcParticles const& mcParticles) + { + + // if (!(isCollisionSelected(mcCollision, true))) { + // return; + // } + + // Not sure why to use this + // if (collisions.size() == 0) { + // return; + //} + + // if (!collision.has_mcCollision()) { + // LOGF(warning, "No MC collision for this collision, skip..."); + // return; + // } + + const auto multiplicity = mcParticles.size(); // Note: these are all MC particles after selection (not only primary) + registry.fill(HIST("MC/Gen/TpcTpc/HadronHadron/SameEvent/hMultiplicity"), multiplicity); + registry.fill(HIST("MC/Gen/TpcTpc/HadronHadron/SameEvent/hVtxZ"), mcCollision.posZ()); + + // fill correlations for all MC collisions + // In Katka's code, the first time doing this does not fill the histograms, right now will be filled two times.. + auto multPrimaryCharge0 = fillTpcTpcChChSameEventQaMc(multiplicity, mcParticles); + sameTPCTPCChChMC->fillEvent(multPrimaryCharge0, CorrelationContainer::kCFStepAll); + fillCorrelations(sameTPCTPCChChMC, mcParticles, mcParticles, multPrimaryCharge0, mcCollision.posZ()); + + // NOT USED BY KATARINA APPARENTLY + // BinningPolicyBase<2> baseBinning{{axisVertex, axisMultiplicity}, true}; + // int bin = baseBinning.getBin(std::make_tuple(mcCollision.posZ(), multiplicity)); + // registry.fill(HIST("MC/Gen/TpcTpc/HadronHadron/SameEvent/hEventCountSame"), bin); + + // TO-DO : fill correlation container for MC collisions that have a reconstructed collision + // got rid of the second const auto for multPrimaryCharge0 + // This line below for sure induce that some plots are filled two times + // multPrimaryCharge0 = fillTpcTpcChChSameEventQaMc(multiplicity, mcParticles); + // sameTPCTPCChChMC->fillEvent(multPrimaryCharge0, CorrelationContainer::kCFStepVertex); + // fillCorrelations(sameTPCTPCChChMC, mcParticles, mcParticles, multPrimaryCharge0, mcCollision.posZ()); } - PROCESS_SWITCH(HfTaskFlow, processSameTpcMftChCh, "Process same-event correlations for TPC-MFT h-h case", true); + PROCESS_SWITCH(HfTaskFlow, processSameTpcTpcChChmcGEN, "MONTE-CARLO : Process same-event correlations for TPC-TPC h-h case", true); // ===================================== - // process mixed event correlations: h-h case + // DATA : process mixed event correlations:TPC-TPC h-h case // ===================================== + // TO BECOME DATA & MC REC ? + void processMixedTpcTpcChCh(FilteredCollisionsWSelMult const& collisions, TracksWDcaSel const& tracks) { @@ -547,11 +1219,12 @@ struct HfTaskFlow { mixCollisions(collisions, tracks, tracks, getTracksSize, mixedTPCTPCChCh); } - PROCESS_SWITCH(HfTaskFlow, processMixedTpcTpcChCh, "Process mixed-event correlations for TPC-TPC h-h case", true); + PROCESS_SWITCH(HfTaskFlow, processMixedTpcTpcChCh, "DATA : Process mixed-event correlations for TPC-TPC h-h case", true); // ===================================== - // process mixed event correlations: h-HF case + // DATA : process mixed event correlations: TPC-TPC HF-h case // ===================================== + void processMixedTpcTpcHfCh(FilteredCollisionsWSelMult const& collisions, TracksWDcaSel const& tracks, HfCandidatesSel const& candidates) @@ -563,16 +1236,23 @@ struct HfTaskFlow { return size; }; + // auto getTracksSize = [&candidates, this](FilteredCollisionsWSelMult::iterator const& col) { + // auto associatedTracks = candidates.sliceByCached(o2::aod::track::collisionId, col.globalIndex(), this->cache); + // auto size = associatedTracks.size(); + // return size; + // }; + mixCollisions(collisions, candidates, tracks, getTracksSize, mixedTPCTPCHfCh); } - PROCESS_SWITCH(HfTaskFlow, processMixedTpcTpcHfCh, "Process mixed-event correlations for TPC-TPC HF-h case", true); + PROCESS_SWITCH(HfTaskFlow, processMixedTpcTpcHfCh, "DATA : Process mixed-event correlations for TPC-TPC HF-h case", true); // ===================================== - // process mixed event correlations: h-MFT case + // DATA : process mixed event correlations: TPC-MFT h-h case // ===================================== + void processMixedTpcMftChCh(FilteredCollisionsWSelMult const& collisions, TracksWDcaSel const& tracks, - aod::MFTTracks const& mfttracks) + aod::MFTTracks const& mftTracks) { // we want to group collisions based on charged-track multiplicity auto getTracksSize = [&tracks, this](FilteredCollisionsWSelMult::iterator const& col) { @@ -581,9 +1261,70 @@ struct HfTaskFlow { return size; }; - mixCollisions(collisions, tracks, mfttracks, getTracksSize, mixedTPCMFTChCh); + mixCollisions(collisions, tracks, mftTracks, getTracksSize, mixedTPCMFTChCh); + } + PROCESS_SWITCH(HfTaskFlow, processMixedTpcMftChCh, "DATA : Process mixed-event correlations for TPC-MFT h-h case", true); + + // ===================================== + // DATA : process mixed event correlations: TPC-MFT HF-h case + // ===================================== + + void processMixedTpcMftHfCh(FilteredCollisionsWSelMult const& collisions, + HfCandidatesSel const& candidates, + aod::MFTTracks const& mftTracks) + { + // we want to group collisions based on charged-track multiplicity + auto getTracksSize = [&candidates, this](FilteredCollisionsWSelMult::iterator const& col) { + // Still o2::aod::track::collisionId with HF ??? + auto associatedTracks = candidates.sliceByCached(o2::aod::track::collisionId, col.globalIndex(), this->cache); + auto size = associatedTracks.size(); + return size; + }; + + mixCollisions(collisions, candidates, mftTracks, getTracksSize, mixedTPCMFTHfCh); + } + PROCESS_SWITCH(HfTaskFlow, processMixedTpcMftHfCh, "DATA : Process mixed-event correlations for TPC-MFT HF-h case", true); + + // ===================================== + // MONTE-CARLO : process mixed event correlations: TPC-TPC h-h case + // ===================================== + + // MC rec + void processMixedTpcTpcChChmcREC(FilteredCollisionsWSelMultMC const& mcCollisions, + TracksWDcaSelMC const& mcTracks) + { + // use normal index instead of globalIndex for MixedEvent ?? + + // we want to group collisions based on charged-track multiplicity + auto getTracksSize = [&mcTracks, this](FilteredCollisionsWSelMultMC::iterator const& mcCol) { + auto associatedTracks = mcTracks.sliceByCached(o2::aod::track::collisionId, mcCol.globalIndex(), this->cache); // it's cached, so slicing/grouping happens only once + auto size = associatedTracks.size(); + return size; + }; + + mixCollisions(mcCollisions, mcTracks, mcTracks, getTracksSize, mixedTPCTPCChChMC); + } + PROCESS_SWITCH(HfTaskFlow, processMixedTpcTpcChChmcREC, "MONTE-CARLO : Process mixed-event correlations for TPC-TPC h-h case", true); + + // MC gen + void processMixedTpcTpcChChmcGEN(FilteredMcCollisions const& mcCollisions, + FilteredMcParticles const& mcParticles, + FilteredCollisionsWSelMultMC const& collisions) + { + // use normal index instead of globalIndex for MixedEvent ?? + + // we want to group collisions based on charged-track multiplicity + auto getTracksSize = [&mcParticles, this](FilteredMcCollisions::iterator const& mcCol) { + auto associatedTracks = mcParticles.sliceByCached(o2::aod::mcparticle::mcCollisionId, mcCol.globalIndex(), this->cache); // it's cached, so slicing/grouping happens only once + auto size = associatedTracks.size(); + return size; + }; + + mixCollisionsMcTruth(mcCollisions, mcParticles, mcParticles, getTracksSize, mixedTPCTPCChChMC); + + // TO-DO : mixed event for particles that have a reconstructed collision kCFStepVertex } - PROCESS_SWITCH(HfTaskFlow, processMixedTpcMftChCh, "Process mixed-event correlations for TPC-MFT h-h case", true); + PROCESS_SWITCH(HfTaskFlow, processMixedTpcTpcChChmcGEN, "MONTE-CARLO : Process mixed-event correlations for TPC-TPC h-h case", true); }; // End of struct WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGHF/TableProducer/CMakeLists.txt b/PWGHF/TableProducer/CMakeLists.txt index 80810f73b11..4f8f1ba49cf 100644 --- a/PWGHF/TableProducer/CMakeLists.txt +++ b/PWGHF/TableProducer/CMakeLists.txt @@ -236,7 +236,7 @@ o2physics_add_dpl_workflow(tree-creator-lc-to-p-k-pi o2physics_add_dpl_workflow(tree-creator-omegac-st SOURCES treeCreatorOmegacSt.cxx - PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2::DCAFitter + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2::DCAFitter O2Physics::EventFilteringUtils COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(tree-creator-omegac0-to-omega-ka diff --git a/PWGHF/TableProducer/candidateCreatorBs.cxx b/PWGHF/TableProducer/candidateCreatorBs.cxx index 69fb0c3f178..e9aef03fd30 100644 --- a/PWGHF/TableProducer/candidateCreatorBs.cxx +++ b/PWGHF/TableProducer/candidateCreatorBs.cxx @@ -42,6 +42,7 @@ using namespace o2::hf_trkcandsel; /// Reconstruction of Bs candidates struct HfCandidateCreatorBs { Produces rowCandidateBase; // table defined in CandidateReconstructionTables.h + Produces rowCandidateProngs; // table defined in CandidateReconstructionTables.h // vertexing Configurable propagateToPCA{"propagateToPCA", true, "create tracks version propagated to PCA"}; @@ -320,8 +321,6 @@ struct HfCandidateCreatorBs { auto errorDecayLength = std::sqrt(getRotatedCovMatrixXX(covMatrixPV, phi, theta) + getRotatedCovMatrixXX(covMatrixPCA, phi, theta)); auto errorDecayLengthXY = std::sqrt(getRotatedCovMatrixXX(covMatrixPV, phi, 0.) + getRotatedCovMatrixXX(covMatrixPCA, phi, 0.)); - int hfFlag = BIT(hf_cand_bs::DecayType::BsToDsPi); - // fill output histograms for Bs candidates hMassDsToKKPi->Fill(hfHelper.invMassDsToKKPi(candDs), candDs.pt()); hCovSVXX->Fill(covMatrixPCA[0]); @@ -340,9 +339,9 @@ struct HfCandidateCreatorBs { pVecDs[0], pVecDs[1], pVecDs[2], pVecPion[0], pVecPion[1], pVecPion[2], dcaDs.getY(), dcaPion.getY(), - std::sqrt(dcaDs.getSigmaY2()), std::sqrt(dcaPion.getSigmaY2()), - candDs.globalIndex(), trackPion.globalIndex(), - hfFlag); + std::sqrt(dcaDs.getSigmaY2()), std::sqrt(dcaPion.getSigmaY2())); + + rowCandidateProngs(candDs.globalIndex(), trackPion.globalIndex()); } // pi loop } // Ds loop } // collision loop @@ -357,13 +356,11 @@ struct HfCandidateCreatorBsExpressions { void init(InitContext const&) {} - void processMc(aod::HfCand3Prong const& ds, - aod::TracksWMc const& tracks, - aod::McParticles const& mcParticles) + void processMc(aod::HfCand3Prong const&, + aod::TracksWMc const&, + aod::McParticles const& mcParticles, + aod::HfCandBsProngs const& candsBs) { - rowCandidateBs->bindExternalIndices(&tracks); - rowCandidateBs->bindExternalIndices(&ds); - int indexRec = -1; int8_t sign = 0; int8_t flag = 0; @@ -372,8 +369,7 @@ struct HfCandidateCreatorBsExpressions { std::array arrPDGResonantDsPhiPi = {Pdg::kPhi, kPiPlus}; // Ds± → Phi π± // Match reconstructed candidates. - // Spawned table can be used directly - for (const auto& candidate : *rowCandidateBs) { + for (const auto& candidate : candsBs) { flag = 0; arrDaughDsIndex.clear(); auto candDs = candidate.prong0(); @@ -398,7 +394,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::BsToDsPiToKKPiPi); + flag = sign * BIT(hf_cand_bs::DecayTypeMc::BsToDsPiToPhiPiPiToKKPiPi); } } } @@ -418,7 +414,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::B0ToDsPiToKKPiPi); + flag = sign * BIT(hf_cand_bs::DecayTypeMc::B0ToDsPiToPhiPiPiToKKPiPi); } } } @@ -471,7 +467,7 @@ 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::BsToDsPiToKKPiPi); + flag = sign * BIT(hf_cand_bs::DecayTypeMc::BsToDsPiToPhiPiPiToKKPiPi); } } } @@ -490,7 +486,7 @@ 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::B0ToDsPiToKKPiPi); + flag = sign * BIT(hf_cand_bs::DecayTypeMc::B0ToDsPiToPhiPiPiToKKPiPi); } } } @@ -499,7 +495,7 @@ struct HfCandidateCreatorBsExpressions { rowMcMatchGen(flag); } // gen - } // processMc + } // processMc PROCESS_SWITCH(HfCandidateCreatorBsExpressions, processMc, "Process MC", false); }; // struct diff --git a/PWGHF/TableProducer/candidateCreatorCascade.cxx b/PWGHF/TableProducer/candidateCreatorCascade.cxx index d7a974e4798..b8846c23e19 100644 --- a/PWGHF/TableProducer/candidateCreatorCascade.cxx +++ b/PWGHF/TableProducer/candidateCreatorCascade.cxx @@ -264,10 +264,10 @@ struct HfCandidateCreatorCascade { if (df.process(trackV0, trackBach) == 0) { continue; } else { - // LOG(info) << "Vertexing succeeded for Lc candidate"; + LOG(debug) << "Vertexing succeeded for Lc candidate"; } } catch (const std::runtime_error& error) { - LOG(info) << "Run time error found: " << error.what() << ". DCAFitterN cannot work, skipping the candidate."; + LOG(debug) << "Run time error found: " << error.what() << ". DCAFitterN cannot work, skipping the candidate."; hCandidates->Fill(SVFitting::Fail); continue; } @@ -478,17 +478,14 @@ struct HfCandidateCreatorCascadeMc { aod::McCollisions const& mcCollisions, BCsInfo const&) { - int8_t sign = 0; - int8_t origin = 0; - int indexRec = -1; - std::vector arrDaughLcIndex; - std::array arrDaughLcPDG; - std::array arrDaughLcPDGRef = {+kProton, +kPiPlus, -kPiPlus}; - // Match reconstructed candidates. rowCandidateCasc->bindExternalIndices(&tracks); for (const auto& candidate : *rowCandidateCasc) { - origin = 0; + + int8_t sign = 0; + int8_t origin = 0; + int indexRec = -1; + std::vector idxBhadMothers{}; const auto& bach = candidate.prong0_as(); @@ -515,14 +512,14 @@ struct HfCandidateCreatorCascadeMc { } } - RecoDecay::getMatchedMCRec(mcParticles, arrayDaughtersV0, kK0Short, std::array{+kPiPlus, -kPiPlus}, false, &sign, 1); - if (sign != 0) { // we have already positively checked the K0s + int indexK0SRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughtersV0, kK0Short, std::array{+kPiPlus, -kPiPlus}, false, &sign, 1); + if (indexK0SRec >= 0) { // we have already positively checked the K0s // then we check the Lc - indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughtersLc, Pdg::kLambdaCPlus, std::array{+kProton, +kPiPlus, -kPiPlus}, true, &sign, 3); // 3-levels Lc --> p + K0 --> p + K0s --> p + pi+ pi- + indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughtersLc, Pdg::kLambdaCPlus, std::array{+kProton, +kPiPlus, -kPiPlus}, true, &sign, 3); // 3-levels Lc --> p + K0 --> p + K0s --> p + pi+ pi- } // Check whether the particle is non-prompt (from a b quark). - if (sign != 0) { + if (indexRec >= 0) { auto particle = mcParticles.rawIteratorAt(indexRec); origin = RecoDecay::getCharmHadronOrigin(mcParticles, particle, false, &idxBhadMothers); } @@ -562,7 +559,11 @@ struct HfCandidateCreatorCascadeMc { // Match generated particles. for (const auto& particle : mcParticlesPerMcColl) { - origin = 0; + + int8_t sign = 0; + int8_t origin = 0; + int8_t flag = 0; + std::vector idxBhadMothers{}; // Reject particles from background events if (particle.fromBackgroundEvent() && rejectBackground) { @@ -570,35 +571,35 @@ struct HfCandidateCreatorCascadeMc { continue; } // checking if I have a Lc --> K0S + p - RecoDecay::isMatchedMCGen(mcParticles, particle, Pdg::kLambdaCPlus, std::array{+kProton, +kK0Short}, false, &sign, 2); + RecoDecay::isMatchedMCGen(mcParticles, particle, Pdg::kLambdaCPlus, std::array{+kProton, +kK0Short}, false, &sign, 2); if (sign == 0) { // now check for anti-Lc - RecoDecay::isMatchedMCGen(mcParticles, particle, -Pdg::kLambdaCPlus, std::array{-kProton, +kK0Short}, false, &sign, 2); + RecoDecay::isMatchedMCGen(mcParticles, particle, -Pdg::kLambdaCPlus, std::array{-kProton, +kK0Short}, false, &sign, 2); sign = -sign; } if (sign != 0) { - arrDaughLcIndex.clear(); - // checking that the final daughters (decay depth = 3) are p, pi+, pi- - RecoDecay::getDaughters(particle, &arrDaughLcIndex, arrDaughLcPDGRef, 3); // best would be to check the K0S daughters - if (arrDaughLcIndex.size() == 3) { - for (std::size_t iProng = 0; iProng < arrDaughLcIndex.size(); ++iProng) { - auto daughI = mcParticles.rawIteratorAt(arrDaughLcIndex[iProng]); - arrDaughLcPDG[iProng] = daughI.pdgCode(); + // we check the K0S + for (const auto& daughterK0 : particle.daughters_as()) { + if (std::abs(daughterK0.pdgCode()) != kK0) { + continue; } - if (!(arrDaughLcPDG[0] == sign * arrDaughLcPDGRef[0] && arrDaughLcPDG[1] == arrDaughLcPDGRef[1] && arrDaughLcPDG[2] == arrDaughLcPDGRef[2])) { // this should be the condition, first bach, then v0 - sign = 0; - } else { - LOG(debug) << "Lc --> K0S+p found in MC table"; + for (const auto& daughterK0S : daughterK0.daughters_as()) { + if (daughterK0S.pdgCode() != kK0Short) { + continue; + } + if (RecoDecay::isMatchedMCGen(mcParticles, daughterK0S, kK0Short, std::array{+kPiPlus, -kPiPlus}, true)) { + flag = sign; + } } } } // Check whether the particle is non-prompt (from a b quark). - if (sign != 0) { + if (flag != 0) { origin = RecoDecay::getCharmHadronOrigin(mcParticles, particle, false, &idxBhadMothers); } if (origin == RecoDecay::OriginType::NonPrompt) { - rowMcMatchGen(sign, origin, idxBhadMothers[0]); + rowMcMatchGen(flag, origin, idxBhadMothers[0]); } else { - rowMcMatchGen(sign, origin, -1); + rowMcMatchGen(flag, origin, -1); } } } diff --git a/PWGHF/TableProducer/candidateSelectorBsToDsPi.cxx b/PWGHF/TableProducer/candidateSelectorBsToDsPi.cxx index 5c0c230c11f..d17f0ada8a0 100644 --- a/PWGHF/TableProducer/candidateSelectorBsToDsPi.cxx +++ b/PWGHF/TableProducer/candidateSelectorBsToDsPi.cxx @@ -116,7 +116,6 @@ struct HfCandidateSelectorBsToDsPi { hfMlResponse.setModelPathsLocal(onnxFileNames); } hfMlResponse.init(); - outputMl.assign(((std::vector)cutDirMl).size(), -1.f); // dummy value for ML output } int selectionFlagDs = -1; @@ -147,19 +146,9 @@ struct HfCandidateSelectorBsToDsPi { { for (const auto& hfCandBs : hfCandsBs) { int statusBsToDsPi = 0; + outputMl.clear(); auto ptCandBs = hfCandBs.pt(); - // check if flagged as Bs → Ds Ï€ - if (!TESTBIT(hfCandBs.hfflag(), hf_cand_bs::DecayType::BsToDsPi)) { - hfSelBsToDsPiCandidate(statusBsToDsPi); - if (applyMl) { - hfMlBsToDsPiCandidate(outputMl); - } - if (activateQA) { - registry.fill(HIST("hSelections"), 1, ptCandBs); - } - continue; - } SETBIT(statusBsToDsPi, SelectionStep::RecoSkims); // RecoSkims = 0 --> statusBsToDsPi = 1 if (activateQA) { registry.fill(HIST("hSelections"), 2 + SelectionStep::RecoSkims, ptCandBs); diff --git a/PWGHF/TableProducer/candidateSelectorDplusToPiKPi.cxx b/PWGHF/TableProducer/candidateSelectorDplusToPiKPi.cxx index b911656d114..638a25aaf7c 100644 --- a/PWGHF/TableProducer/candidateSelectorDplusToPiKPi.cxx +++ b/PWGHF/TableProducer/candidateSelectorDplusToPiKPi.cxx @@ -60,6 +60,8 @@ 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"}; @@ -223,7 +225,7 @@ struct HfCandidateSelectorDplusToPiKPi { auto ptCand = candidate.pt(); - if (!TESTBIT(candidate.hfflag(), aod::hf_cand_3prong::DecayType::DplusToPiKPi)) { + 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∓ π± hfSelDplusToPiKPiCandidate(statusDplusToPiKPi); if (applyMl) { hfMlDplusToPiKPiCandidate(outputMlNotPreselected); diff --git a/PWGHF/TableProducer/candidateSelectorDsToKKPi.cxx b/PWGHF/TableProducer/candidateSelectorDsToKKPi.cxx index 9720f270469..91df36d441c 100644 --- a/PWGHF/TableProducer/candidateSelectorDsToKKPi.cxx +++ b/PWGHF/TableProducer/candidateSelectorDsToKKPi.cxx @@ -25,6 +25,7 @@ #include "PWGHF/Core/HfMlResponseDsToKKPi.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" +#include "PWGHF/Utils/utilsAnalysis.h" using namespace o2; using namespace o2::analysis; @@ -73,6 +74,8 @@ struct HfCandidateSelectorDsToKKPi { Configurable> onnxFileNames{"onnxFileNames", std::vector{"ModelHandler_onnx_DsToKKPi.onnx"}, "ONNX file names for each pT bin (if not from CCDB full path)"}; Configurable timestampCCDB{"timestampCCDB", -1, "timestamp of the ONNX file for ML model used to query in CCDB"}; Configurable loadModelsFromCCDB{"loadModelsFromCCDB", false, "Flag to enable or disable the loading of models from CCDB"}; + // Mass cut for trigger analysis + Configurable useTriggerMassCut{"useTriggerMassCut", false, "Flag to enable parametrized pT differential mass cut for triggered data"}; HfHelper hfHelper; o2::analysis::HfMlResponseDsToKKPi hfMlResponse; @@ -81,6 +84,7 @@ struct HfCandidateSelectorDsToKKPi { o2::ccdb::CcdbApi ccdbApi; TrackSelectorPi selectorPion; TrackSelectorKa selectorKaon; + HfTrigger3ProngCuts hfTriggerCuts; using TracksSel = soa::Join; @@ -200,6 +204,9 @@ struct HfCandidateSelectorDsToKKPi { if (std::abs(hfHelper.invMassDsToKKPi(candidate) - o2::constants::physics::MassDS) > cuts->get(pTBin, "deltaM")) { return false; } + if (useTriggerMassCut && !isCandidateInMassRange(hfHelper.invMassDsToKKPi(candidate), o2::constants::physics::MassDS, candidate.pt(), hfTriggerCuts)) { + return false; + } if (hfHelper.deltaMassPhiDsToKKPi(candidate) > cuts->get(pTBin, "deltaM Phi")) { return false; } @@ -229,6 +236,9 @@ struct HfCandidateSelectorDsToKKPi { if (std::abs(hfHelper.invMassDsToPiKK(candidate) - o2::constants::physics::MassDS) > cuts->get(pTBin, "deltaM")) { return false; } + if (useTriggerMassCut && !isCandidateInMassRange(hfHelper.invMassDsToPiKK(candidate), o2::constants::physics::MassDS, candidate.pt(), hfTriggerCuts)) { + return false; + } if (hfHelper.deltaMassPhiDsToPiKK(candidate) > cuts->get(pTBin, "deltaM Phi")) { return false; } diff --git a/PWGHF/TableProducer/candidateSelectorLc.cxx b/PWGHF/TableProducer/candidateSelectorLc.cxx index db6e6a90836..6e50e1262a9 100644 --- a/PWGHF/TableProducer/candidateSelectorLc.cxx +++ b/PWGHF/TableProducer/candidateSelectorLc.cxx @@ -447,11 +447,11 @@ struct HfCandidateSelectorLc { isSelectedMlLcToPiKP = false; if (pidLcToPKPi == 1 && pidBayesLcToPKPi == 1 && topolLcToPKPi) { - std::vector inputFeaturesLcToPKPi = hfMlResponse.getInputFeatures(candidate, trackPos1, trackNeg, trackPos2); + std::vector inputFeaturesLcToPKPi = hfMlResponse.getInputFeatures(candidate, trackPos1, trackNeg, trackPos2, true); isSelectedMlLcToPKPi = hfMlResponse.isSelectedMl(inputFeaturesLcToPKPi, candidate.pt(), outputMlLcToPKPi); } if (pidLcToPiKP == 1 && pidBayesLcToPiKP == 1 && topolLcToPiKP) { - std::vector inputFeaturesLcToPiKP = hfMlResponse.getInputFeatures(candidate, trackPos1, trackNeg, trackPos2); + std::vector inputFeaturesLcToPiKP = hfMlResponse.getInputFeatures(candidate, trackPos1, trackNeg, trackPos2, false); isSelectedMlLcToPiKP = hfMlResponse.isSelectedMl(inputFeaturesLcToPiKP, candidate.pt(), outputMlLcToPiKP); } diff --git a/PWGHF/TableProducer/candidateSelectorXicToPKPi.cxx b/PWGHF/TableProducer/candidateSelectorXicToPKPi.cxx index 14e9bef0bd6..cb032518305 100644 --- a/PWGHF/TableProducer/candidateSelectorXicToPKPi.cxx +++ b/PWGHF/TableProducer/candidateSelectorXicToPKPi.cxx @@ -313,11 +313,11 @@ struct HfCandidateSelectorXicToPKPi { bool isSelectedMlXicToPiKP = false; if (topolXicToPKPi && pidXicToPKPi) { - std::vector inputFeaturesXicToPKPi = hfMlResponse.getInputFeatures(candidate, trackPos1, trackNeg, trackPos2); + std::vector inputFeaturesXicToPKPi = hfMlResponse.getInputFeatures(candidate, trackPos1, trackNeg, trackPos2, true); isSelectedMlXicToPKPi = hfMlResponse.isSelectedMl(inputFeaturesXicToPKPi, ptCand, outputMlXicToPKPi); } if (topolXicToPiKP && pidXicToPiKP) { - std::vector inputFeaturesXicToPiKP = hfMlResponse.getInputFeatures(candidate, trackPos1, trackNeg, trackPos2); + std::vector inputFeaturesXicToPiKP = hfMlResponse.getInputFeatures(candidate, trackPos1, trackNeg, trackPos2, false); isSelectedMlXicToPiKP = hfMlResponse.isSelectedMl(inputFeaturesXicToPiKP, ptCand, outputMlXicToPiKP); } diff --git a/PWGHF/TableProducer/treeCreatorBsToDsPi.cxx b/PWGHF/TableProducer/treeCreatorBsToDsPi.cxx index aac534e265e..542ed264892 100644 --- a/PWGHF/TableProducer/treeCreatorBsToDsPi.cxx +++ b/PWGHF/TableProducer/treeCreatorBsToDsPi.cxx @@ -172,8 +172,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::BsToDsPiToKKPiPi); - Partition recBg = nabs(aod::hf_cand_bs::flagMcMatchRec) != (int8_t)BIT(aod::hf_cand_bs::DecayTypeMc::BsToDsPiToKKPiPi); + 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); void init(InitContext const&) { @@ -351,7 +351,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::BsToDsPiToKKPiPi)) { + if (TESTBIT(std::abs(particle.flagMcMatchGen()), aod::hf_cand_bs::DecayTypeMc::BsToDsPiToPhiPiPiToKKPiPi)) { rowCandidateFullParticles( particle.mcCollision().bcId(), particle.pt(), diff --git a/PWGHF/TableProducer/treeCreatorDplusToPiKPi.cxx b/PWGHF/TableProducer/treeCreatorDplusToPiKPi.cxx index b7e66144251..5933bda7118 100644 --- a/PWGHF/TableProducer/treeCreatorDplusToPiKPi.cxx +++ b/PWGHF/TableProducer/treeCreatorDplusToPiKPi.cxx @@ -124,7 +124,8 @@ DECLARE_SOA_TABLE(HfCandDpLites, "AOD", "HFCANDDPLITE", full::Phi, full::Y, hf_cand_3prong::FlagMcMatchRec, - hf_cand_3prong::OriginMcRec) + hf_cand_3prong::OriginMcRec, + hf_cand_3prong::FlagMcDecayChanRec) DECLARE_SOA_TABLE(HfCandDpFulls, "AOD", "HFCANDDPFULL", collision::BCId, @@ -204,7 +205,8 @@ DECLARE_SOA_TABLE(HfCandDpFulls, "AOD", "HFCANDDPFULL", full::Y, full::E, hf_cand_3prong::FlagMcMatchRec, - hf_cand_3prong::OriginMcRec); + hf_cand_3prong::OriginMcRec, + hf_cand_3prong::FlagMcDecayChanRec); DECLARE_SOA_TABLE(HfCandDpFullEvs, "AOD", "HFCANDDPFULLEV", collision::BCId, @@ -249,7 +251,7 @@ struct HfTreeCreatorDplusToPiKPi { Filter filterSelectCandidates = aod::hf_sel_candidate_dplus::isSelDplusToPiKPi >= selectionFlagDplus; Filter filterMcGenMatching = nabs(o2::aod::hf_cand_3prong::flagMcMatchGen) == static_cast(BIT(aod::hf_cand_3prong::DecayType::DplusToPiKPi)); - Partition reconstructedCandSig = nabs(aod::hf_cand_3prong::flagMcMatchRec) == static_cast(BIT(aod::hf_cand_3prong::DecayType::DplusToPiKPi)); + Partition reconstructedCandSig = nabs(aod::hf_cand_3prong::flagMcMatchRec) == static_cast(BIT(aod::hf_cand_3prong::DecayType::DplusToPiKPi)) || nabs(aod::hf_cand_3prong::flagMcMatchRec) == static_cast(BIT(aod::hf_cand_3prong::DecayType::DsToKKPi)); // DecayType::DsToKKPi is used to flag both Ds± → K± K∓ π± and D± → K± K∓ π± Partition reconstructedCandBkg = nabs(aod::hf_cand_3prong::flagMcMatchRec) != static_cast(BIT(aod::hf_cand_3prong::DecayType::DplusToPiKPi)); void init(InitContext const&) @@ -274,9 +276,11 @@ struct HfTreeCreatorDplusToPiKPi { { int8_t flagMc = 0; int8_t originMc = 0; + int8_t channelMc = 0; if constexpr (doMc) { flagMc = candidate.flagMcMatchRec(); originMc = candidate.originMcRec(); + channelMc = candidate.flagMcDecayChanRec(); } auto prong0 = candidate.template prong0_as(); @@ -327,7 +331,8 @@ struct HfTreeCreatorDplusToPiKPi { candidate.phi(), hfHelper.yDplus(candidate), flagMc, - originMc); + originMc, + channelMc); } else { rowCandidateFull( candidate.collision().bcId(), @@ -407,7 +412,8 @@ struct HfTreeCreatorDplusToPiKPi { hfHelper.yDplus(candidate), hfHelper.eDplus(candidate), flagMc, - originMc); + originMc, + channelMc); } } diff --git a/PWGHF/TableProducer/treeCreatorDsToKKPi.cxx b/PWGHF/TableProducer/treeCreatorDsToKKPi.cxx index 9d5273c14b2..99428bf1e42 100644 --- a/PWGHF/TableProducer/treeCreatorDsToKKPi.cxx +++ b/PWGHF/TableProducer/treeCreatorDsToKKPi.cxx @@ -133,6 +133,7 @@ DECLARE_SOA_TABLE(HfCandDsLites, "AOD", "HFCANDDSLITE", hf_cand_3prong::FlagMcMatchRec, hf_cand_3prong::OriginMcRec, hf_cand_3prong::FlagMcDecayChanRec, + hf_cand_3prong::IsCandidateSwapped, full::Sign); DECLARE_SOA_TABLE(HfCandDsFulls, "AOD", "HFCANDDSFULL", @@ -205,6 +206,7 @@ DECLARE_SOA_TABLE(HfCandDsFulls, "AOD", "HFCANDDSFULL", hf_cand_3prong::FlagMcMatchRec, hf_cand_3prong::OriginMcRec, hf_cand_3prong::FlagMcDecayChanRec, + hf_cand_3prong::IsCandidateSwapped, full::Sign); DECLARE_SOA_TABLE(HfCandDsFullEvs, "AOD", "HFCANDDSFULLEV", @@ -294,6 +296,7 @@ struct HfTreeCreatorDsToKKPi { 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; @@ -301,6 +304,7 @@ struct HfTreeCreatorDsToKKPi { flagMc = candidate.flagMcMatchRec(); originMc = candidate.originMcRec(); channelMc = candidate.flagMcDecayChanRec(); + isSwapped = candidate.isCandidateSwapped(); if (fillDplusMc && candidate.flagMcDecayChanRec() == (decayChannel + offsetDplusDecayChannel)) { yCand = hfHelper.yDplus(candidate); eCand = hfHelper.eDplus(candidate); @@ -358,8 +362,8 @@ struct HfTreeCreatorDsToKKPi { prong2.tofNSigmaKa(), prong2.tpcTofNSigmaPi(), prong2.tpcTofNSigmaKa(), - candidate.isSelDsToKKPi(), - candidate.isSelDsToPiKK(), + massHypo == 0 ? candidate.isSelDsToKKPi() : -1, + massHypo == 1 ? candidate.isSelDsToPiKK() : -1, invMassDs, candidate.pt(), candidate.eta(), @@ -381,6 +385,7 @@ struct HfTreeCreatorDsToKKPi { flagMc, originMc, channelMc, + isSwapped, prong0.sign() + prong1.sign() + prong2.sign()); } else { rowCandidateFull( @@ -425,8 +430,8 @@ struct HfTreeCreatorDsToKKPi { prong2.tofNSigmaKa(), prong2.tpcTofNSigmaPi(), prong2.tpcTofNSigmaKa(), - candidate.isSelDsToKKPi(), - candidate.isSelDsToPiKK(), + massHypo == 0 ? candidate.isSelDsToKKPi() : -1, + massHypo == 1 ? candidate.isSelDsToPiKK() : -1, candidate.xSecondaryVertex(), candidate.ySecondaryVertex(), candidate.zSecondaryVertex(), @@ -453,6 +458,7 @@ struct HfTreeCreatorDsToKKPi { flagMc, originMc, channelMc, + isSwapped, prong0.sign() + prong1.sign() + prong2.sign()); } } diff --git a/PWGHF/TableProducer/treeCreatorOmegacSt.cxx b/PWGHF/TableProducer/treeCreatorOmegacSt.cxx index 71a8e2e8b0a..e2af6b5cff8 100644 --- a/PWGHF/TableProducer/treeCreatorOmegacSt.cxx +++ b/PWGHF/TableProducer/treeCreatorOmegacSt.cxx @@ -23,6 +23,8 @@ #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" @@ -192,6 +194,9 @@ struct HfTreeCreatorOmegacSt { Produces outputTable; Produces outputTableGen; + Zorro zorro; + OutputObj zorroSummary{"zorroSummary"}; + Configurable materialCorrectionType{"materialCorrectionType", static_cast(o2::base::Propagator::MatCorrType::USEMatCorrLUT), "Type of material correction"}; Configurable ccdbUrl{"ccdbUrl", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; Configurable grpMagPath{"grpMagPath", "GLO/Config/GRPMagField", "CCDB path of the GRPMagField object"}; @@ -199,6 +204,7 @@ struct HfTreeCreatorOmegacSt { Configurable matLutPath{"matLutPath", "GLO/Param/MatLUT", "Path of the material LUT"}; Configurable propToDCA{"propToDCA", true, "create tracks version propagated to PCA"}; Configurable useAbsDCA{"useAbsDCA", true, "Minimise abs. distance rather than chi2"}; + Configurable skimmedProcessing{"skimmedProcessing", false, "Put true if you are processing apass*_skimmed datasets"}; Configurable maxR{"maxR", 200., "reject PCA's above this radius"}; Configurable maxDZIni{"maxDZIni", 4., "reject (if>0) PCA candidate if tracks DZ exceeds threshold"}; Configurable minParamChange{"minParamChange", 1.e-3, "stop iterations if largest change of any X is smaller than this"}; @@ -366,6 +372,13 @@ struct HfTreeCreatorOmegacSt { for (const auto& collision : collisions) { const auto bc = collision.bc_as(); if (runNumber != bc.runNumber()) { + if (skimmedProcessing) { + if (runNumber == 0) { + zorroSummary.setObject(zorro.getZorroSummary()); + } + zorro.initCCDB(ccdb.service, bc.runNumber(), bc.timestamp(), "fTrackedOmega"); + zorro.populateHistRegistry(registry, bc.runNumber()); + } runNumber = bc.runNumber(); auto timestamp = bc.timestamp(); @@ -380,6 +393,9 @@ struct HfTreeCreatorOmegacSt { } df2.setBz(bz); } + if (skimmedProcessing) { + zorro.isSelected(collision.bc().globalBC()); + } const auto primaryVertex = getPrimaryVertex(collision); const std::array primaryVertexPos = {primaryVertex.getX(), primaryVertex.getY(), primaryVertex.getZ()}; diff --git a/PWGHF/Tasks/taskMcValidation.cxx b/PWGHF/Tasks/taskMcValidation.cxx index cc18c2d6924..6b7c68317fb 100644 --- a/PWGHF/Tasks/taskMcValidation.cxx +++ b/PWGHF/Tasks/taskMcValidation.cxx @@ -111,13 +111,15 @@ struct HfTaskMcValidationGen { AxisSpec axisResiduals{100, -0.01, 0.01}; AxisSpec axisPt{100, 0., 50.}; AxisSpec axisY{100, -5., 5.}; + AxisSpec axisCent{100, 0., 100.}; AxisSpec axisMesonSpecies{nMesonChannels, -0.5, static_cast(nMesonChannels) - 0.5}; AxisSpec axisBaryonSpecies{nChannels - nMesonChannels, -0.5, static_cast(nChannels - nMesonChannels) - 0.5}; AxisSpec axisDecLen{100, 0., 10000.}; HistogramRegistry registry{ "registry", - {{"hMomentumCheck", "Mom. Conservation (1 = true, 0 = false) (#it{#epsilon} = 1 MeV/#it{c}); Mom. Conservation result; entries", {HistType::kTH1F, {{2, -0.5, +1.5}}}}, + {{"hNevGen", "Generated events counter; Gen. events; entries", {HistType::kTH1F, {{1, -0.5, +0.5}}}}, + {"hMomentumCheck", "Mom. Conservation (1 = true, 0 = false) (#it{#epsilon} = 1 MeV/#it{c}); Mom. Conservation result; entries", {HistType::kTH1F, {{2, -0.5, +1.5}}}}, {"hPtDiffMotherDaughterGen", "Pt Difference Mother-Daughters; #Delta#it{p}_{T}^{gen} (GeV/#it{c}); entries", {HistType::kTH1F, {axisResiduals}}}, {"hPxDiffMotherDaughterGen", "Px Difference Mother-Daughters; #Delta#it{p}_{x}^{gen} (GeV/#it{c}); entries", {HistType::kTH1F, {axisResiduals}}}, {"hPyDiffMotherDaughterGen", "Py Difference Mother-Daughters; #Delta#it{p}_{y}^{gen} (GeV/#it{c}); entries", {HistType::kTH1F, {axisResiduals}}}, @@ -130,15 +132,19 @@ struct HfTaskMcValidationGen { {"Quarks/hPtVsYCharmQuark", "Y vs. Pt - charm quarks ; #it{p}_{T}^{gen} (GeV/#it{c}); #it{y}^{gen}", {HistType::kTH2F, {axisPt, axisY}}}, {"Quarks/hPtVsYBeautyQuark", "Y vs. Pt - beauty quarks ; #it{p}_{T}^{gen} (GeV/#it{c}); #it{y}^{gen}", {HistType::kTH2F, {axisPt, axisY}}}, {"PromptCharmMesons/hPromptMesonsPtDistr", "Pt distribution vs prompt charm meson in |#it{y}^{gen}|<0.5; ; #it{p}_{T}^{gen} (GeV/#it{c})", {HistType::kTH2F, {axisMesonSpecies, axisPt}}}, + {"PromptCharmMesons/hPromptMesonsPtCentDistr", "Pt vs Cent vs distribution vs prompt charm meson in |#it{y}^{gen}|<0.5; ; #it{p}_{T}^{gen} (GeV/#it{c}); Centrality (%);", {HistType::kTH3F, {axisMesonSpecies, axisPt, axisCent}}}, {"PromptCharmMesons/hPromptMesonsYDistr", "Y distribution vs prompt charm meson; ; #it{y}^{gen}", {HistType::kTH2F, {axisMesonSpecies, axisY}}}, {"PromptCharmMesons/hPromptMesonsDecLenDistr", "Decay length distribution vs prompt charm meson; ; decay length (#mum)", {HistType::kTH2F, {axisMesonSpecies, axisDecLen}}}, {"NonPromptCharmMesons/hNonPromptMesonsPtDistr", "Pt distribution vs non-prompt charm meson in |#it{y}^{gen}|<0.5; ; #it{p}_{T}^{gen} (GeV/#it{c})", {HistType::kTH2F, {axisMesonSpecies, axisPt}}}, + {"NonPromptCharmMesons/hNonPromptMesonsPtCentDistr", "Pt vs Cent vs distribution vs non-prompt charm meson in |#it{y}^{gen}|<0.5; ; #it{p}_{T}^{gen} (GeV/#it{c}); Centrality (%);", {HistType::kTH3F, {axisMesonSpecies, axisPt, axisCent}}}, {"NonPromptCharmMesons/hNonPromptMesonsYDistr", "Y distribution vs non-prompt charm meson; ; #it{y}^{gen}", {HistType::kTH2F, {axisMesonSpecies, axisY}}}, {"NonPromptCharmMesons/hNonPromptMesonsDecLenDistr", "Decay length distribution vs non-prompt charm meson; ; decay length (#mum)", {HistType::kTH2F, {axisMesonSpecies, axisDecLen}}}, {"PromptCharmBaryons/hPromptBaryonsPtDistr", "Pt distribution vs prompt charm baryon in |#it{y}^{gen}|<0.5; ; #it{p}_{T}^{gen} (GeV/#it{c})", {HistType::kTH2F, {axisBaryonSpecies, axisPt}}}, + {"PromptCharmBaryons/hPromptBaryonsPtCentDistr", "Pt vs Cent vs distribution vs prompt charm baryons in |#it{y}^{gen}|<0.5; ; #it{p}_{T}^{gen} (GeV/#it{c}); Centrality (%);", {HistType::kTH3F, {axisBaryonSpecies, axisPt, axisCent}}}, {"PromptCharmBaryons/hPromptBaryonsYDistr", "Y distribution vs prompt charm baryon; ; #it{y}^{gen}", {HistType::kTH2F, {axisBaryonSpecies, axisY}}}, {"PromptCharmBaryons/hPromptBaryonsDecLenDistr", "Decay length distribution vs prompt charm baryon; ; decay length (#mum)", {HistType::kTH2F, {axisBaryonSpecies, axisDecLen}}}, {"NonPromptCharmBaryons/hNonPromptBaryonsPtDistr", "Pt distribution vs non-prompt charm baryon in |#it{y}^{gen}|<0.5; ; #it{p}_{T}^{gen} (GeV/#it{c})", {HistType::kTH2F, {axisBaryonSpecies, axisPt}}}, + {"NonPromptCharmBaryons/hNonPromptBaryonsPtCentDistr", "Pt vs Cent vs distribution vs prompt charm baryons in |#it{y}^{gen}|<0.5; ; #it{p}_{T}^{gen} (GeV/#it{c}); Centrality (%);", {HistType::kTH3F, {axisBaryonSpecies, axisPt, axisCent}}}, {"NonPromptCharmBaryons/hNonPromptBaryonsYDistr", "Y distribution vs non-prompt charm baryon; ; #it{y}^{gen}", {HistType::kTH2F, {axisBaryonSpecies, axisY}}}, {"NonPromptCharmBaryons/hNonPromptBaryonsDecLenDistr", "Decay length distribution vs non-prompt charm baryon; ; decay length (#mum)", {HistType::kTH2F, {axisBaryonSpecies, axisDecLen}}}}}; @@ -164,17 +170,21 @@ struct HfTaskMcValidationGen { for (auto iBin = 1; iBin <= nMesonChannels; ++iBin) { registry.get(HIST("PromptCharmMesons/hPromptMesonsPtDistr"))->GetXaxis()->SetBinLabel(iBin, labels[iBin - 1].data()); + registry.get(HIST("PromptCharmMesons/hPromptMesonsPtCentDistr"))->GetXaxis()->SetBinLabel(iBin, labels[iBin - 1].data()); registry.get(HIST("PromptCharmMesons/hPromptMesonsYDistr"))->GetXaxis()->SetBinLabel(iBin, labels[iBin - 1].data()); registry.get(HIST("PromptCharmMesons/hPromptMesonsDecLenDistr"))->GetXaxis()->SetBinLabel(iBin, labels[iBin - 1].data()); registry.get(HIST("NonPromptCharmMesons/hNonPromptMesonsPtDistr"))->GetXaxis()->SetBinLabel(iBin, labels[iBin - 1].data()); + registry.get(HIST("NonPromptCharmMesons/hNonPromptMesonsPtCentDistr"))->GetXaxis()->SetBinLabel(iBin, labels[iBin - 1].data()); registry.get(HIST("NonPromptCharmMesons/hNonPromptMesonsYDistr"))->GetXaxis()->SetBinLabel(iBin, labels[iBin - 1].data()); registry.get(HIST("NonPromptCharmMesons/hNonPromptMesonsDecLenDistr"))->GetXaxis()->SetBinLabel(iBin, labels[iBin - 1].data()); } for (auto iBin = 1; iBin <= nChannels - nMesonChannels; ++iBin) { registry.get(HIST("PromptCharmBaryons/hPromptBaryonsPtDistr"))->GetXaxis()->SetBinLabel(iBin, labels[iBin + nMesonChannels - 1].data()); + registry.get(HIST("PromptCharmBaryons/hPromptBaryonsPtCentDistr"))->GetXaxis()->SetBinLabel(iBin, labels[iBin + nMesonChannels - 1].data()); registry.get(HIST("PromptCharmBaryons/hPromptBaryonsYDistr"))->GetXaxis()->SetBinLabel(iBin, labels[iBin + nMesonChannels - 1].data()); registry.get(HIST("PromptCharmBaryons/hPromptBaryonsDecLenDistr"))->GetXaxis()->SetBinLabel(iBin, labels[iBin + nMesonChannels - 1].data()); registry.get(HIST("NonPromptCharmBaryons/hNonPromptBaryonsPtDistr"))->GetXaxis()->SetBinLabel(iBin, labels[iBin + nMesonChannels - 1].data()); + registry.get(HIST("NonPromptCharmBaryons/hNonPromptBaryonsPtCentDistr"))->GetXaxis()->SetBinLabel(iBin, labels[iBin + nMesonChannels - 1].data()); registry.get(HIST("NonPromptCharmBaryons/hNonPromptBaryonsYDistr"))->GetXaxis()->SetBinLabel(iBin, labels[iBin + nMesonChannels - 1].data()); registry.get(HIST("NonPromptCharmBaryons/hNonPromptBaryonsDecLenDistr"))->GetXaxis()->SetBinLabel(iBin, labels[iBin + nMesonChannels - 1].data()); } @@ -197,6 +207,7 @@ struct HfTaskMcValidationGen { if (eventGeneratorType >= 0 && mcCollision.getSubGeneratorId() != eventGeneratorType) { return; } + registry.fill(HIST("hNevGen"), 1); // Slice the collisions table to get the collision info for the current MC collision float centrality{-1.f}; @@ -379,12 +390,14 @@ struct HfTaskMcValidationGen { if (origin == RecoDecay::OriginType::Prompt) { if (std::abs(particle.y()) < 0.5) { registry.fill(HIST("PromptCharmMesons/hPromptMesonsPtDistr"), iD, particle.pt()); + registry.fill(HIST("PromptCharmMesons/hPromptMesonsPtCentDistr"), iD, particle.pt(), centrality); } registry.fill(HIST("PromptCharmMesons/hPromptMesonsYDistr"), iD, particle.y()); registry.fill(HIST("PromptCharmMesons/hPromptMesonsDecLenDistr"), iD, decayLength * 10000); } else if (origin == RecoDecay::OriginType::NonPrompt) { if (std::abs(particle.y()) < 0.5) { registry.fill(HIST("NonPromptCharmMesons/hNonPromptMesonsPtDistr"), iD, particle.pt()); + registry.fill(HIST("NonPromptCharmMesons/hNonPromptMesonsPtCentDistr"), iD, particle.pt(), centrality); } registry.fill(HIST("NonPromptCharmMesons/hNonPromptMesonsYDistr"), iD, particle.y()); registry.fill(HIST("NonPromptCharmMesons/hNonPromptMesonsDecLenDistr"), iD, decayLength * 10000); @@ -393,12 +406,14 @@ struct HfTaskMcValidationGen { if (origin == RecoDecay::OriginType::Prompt) { if (std::abs(particle.y()) < 0.5) { registry.fill(HIST("PromptCharmBaryons/hPromptBaryonsPtDistr"), iD - nMesonChannels, particle.pt()); + registry.fill(HIST("PromptCharmBaryons/hPromptBaryonsPtCentDistr"), iD - nMesonChannels, particle.pt(), centrality); } registry.fill(HIST("PromptCharmBaryons/hPromptBaryonsYDistr"), iD - nMesonChannels, particle.y()); registry.fill(HIST("PromptCharmBaryons/hPromptBaryonsDecLenDistr"), iD - nMesonChannels, decayLength * 10000); } else if (origin == RecoDecay::OriginType::NonPrompt) { if (std::abs(particle.y()) < 0.5) { registry.fill(HIST("NonPromptCharmBaryons/hNonPromptBaryonsPtDistr"), iD - nMesonChannels, particle.pt()); + registry.fill(HIST("NonPromptCharmBaryons/hNonPromptBaryonsPtCentDistr"), iD - nMesonChannels, particle.pt(), centrality); } registry.fill(HIST("NonPromptCharmBaryons/hNonPromptBaryonsYDistr"), iD - nMesonChannels, particle.y()); registry.fill(HIST("NonPromptCharmBaryons/hNonPromptBaryonsDecLenDistr"), iD - nMesonChannels, decayLength * 10000); @@ -497,14 +512,15 @@ struct HfTaskMcValidationRec { 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)"}; std::array, nChannels> histDeltaPt, histDeltaPx, histDeltaPy, histDeltaPz, histDeltaSecondaryVertexX, histDeltaSecondaryVertexY, histDeltaSecondaryVertexZ, histDeltaDecayLength; + std::array, 2>, nChannels> histPtCentReco; std::array, 5>, 2>, nChannels> histPtDau, histEtaDau, histImpactParameterDau; - std::array, 2>, nChannels> histPtReco; std::array, 4> histOriginTracks; std::shared_ptr histAmbiguousTracks, histTracks; std::shared_ptr histContributors; using HfCand2ProngWithMCRec = soa::Join; using HfCand3ProngWithMCRec = soa::Join; + using CandMcGen = soa::Join; using CollisionsWithMCLabels = soa::Join; using CollisionsWithMCLabelsAndCentFT0C = soa::Join; using CollisionsWithMCLabelsAndCentFT0M = soa::Join; @@ -513,6 +529,9 @@ struct HfTaskMcValidationRec { Partition tracksFilteredGlobalTrackWoDCA = requireGlobalTrackWoDCAInFilter(); Partition tracksInAcc = requireTrackCutInFilter(TrackSelectionFlags::kInAcceptanceTracks); + Preslice cand2ProngPerCollision = aod::hf_cand::collisionId; + Preslice cand3ProngPerCollision = aod::hf_cand::collisionId; + Service ccdb; HfEventSelection hfEvSel; // event selection and monitoring @@ -521,6 +540,7 @@ struct HfTaskMcValidationRec { AxisSpec axisEta{40, -1., 1.}; AxisSpec axisPt{50, 0., 10.}; AxisSpec axisPtD{100, 0., 50.}; + AxisSpec axisCent{100, 0., 100.}; AxisSpec axisDeltaVtx{200, -1, 1.}; AxisSpec axisDecision{2, -0.5, 1.5}; AxisSpec axisITShits{8, -0.5, 7.5}; @@ -531,6 +551,7 @@ struct HfTaskMcValidationRec { HistogramRegistry registry{ "registry", {{"histNtracks", "Number of global tracks w/o DCA requirement;#it{N}_{tracks};entries", {HistType::kTH1F, {axisMult}}}, + {"hNevReco", "Reconstructed events counter; Reco. events; entries", {HistType::kTH1F, {{1, -0.5, +0.5}}}}, {"histXvtxReco", "Position of reco PV in #it{X};#it{X}^{reco} (cm);entries", {HistType::kTH1F, {axisDeltaVtx}}}, {"histYvtxReco", "Position of reco PV in #it{Y};#it{Y}^{reco} (cm);entries", {HistType::kTH1F, {axisDeltaVtx}}}, {"histZvtxReco", "Position of reco PV in #it{Z};#it{Z}^{reco} (cm);entries", {HistType::kTH1F, {{200, -20, 20.}}}}, @@ -563,8 +584,9 @@ struct HfTaskMcValidationRec { /// \param mother is mother particle /// \param whichHad int indicating charm-hadron and decay channel, see enum DecayChannels /// \param whichOrigin int indicating origin: prompt or non-prompt + /// \param centrality is collision centrality template - void fillHisto(const T& candidate, const U& mother, int whichHad, int whichOrigin) + void fillHisto(const T& candidate, const U& mother, int whichHad, int whichOrigin, float centrality) { histDeltaPt[whichHad]->Fill(candidate.pt() - mother.pt()); histDeltaPx[whichHad]->Fill(candidate.px() - mother.px()); @@ -586,7 +608,7 @@ struct HfTaskMcValidationRec { std::array momDau1 = {candidate.pxProng1(), candidate.pyProng1(), candidate.pzProng1()}; - histPtReco[whichHad][whichOrigin]->Fill(candidate.pt()); + histPtCentReco[whichHad][whichOrigin]->Fill(candidate.pt(), centrality); histPtDau[whichHad][whichOrigin][0]->Fill(RecoDecay::pt(momDau0)); histEtaDau[whichHad][whichOrigin][0]->Fill(RecoDecay::eta(momDau0)); histImpactParameterDau[whichHad][whichOrigin][0]->Fill(candidate.impactParameter0()); @@ -638,7 +660,7 @@ struct HfTaskMcValidationRec { histDeltaSecondaryVertexZ[iHad] = registryMesons.add(Form("%s/histDeltaSecondaryVertexZ", particleNames[iHad].data()), Form("Sec. Vertex difference reco - MC (MC matched) - %s; #Delta z (cm); entries", labels[iHad].data()), HistType::kTH1F, {axisDeltaVtx}); histDeltaDecayLength[iHad] = registryMesons.add(Form("%s/histDeltaDecayLength", particleNames[iHad].data()), Form("Decay length difference reco - MC (%s); #Delta L (cm); entries", labels[iHad].data()), HistType::kTH1F, {axisDeltaVtx}); for (auto iOrigin = 0; iOrigin < 2; ++iOrigin) { - histPtReco[iHad][iOrigin] = registryMesons.add(Form("%s/histPtReco%s", particleNames[iHad].data(), originNames[iOrigin].data()), Form("Pt reco %s %s; #it{p}_{T}^{reco} (GeV/#it{c}); entries", originNames[iOrigin].data(), labels[iHad].data()), HistType::kTH1F, {axisPtD}); + histPtCentReco[iHad][iOrigin] = registryMesons.add(Form("%s/histPtCentReco%s", particleNames[iHad].data(), originNames[iOrigin].data()), Form("Pt Cent reco %s %s; #it{p}_{T}^{reco} (GeV/#it{c}); Centrality (%); entries", originNames[iOrigin].data(), labels[iHad].data()), HistType::kTH2F, {axisPtD, axisCent}); for (unsigned int iDau = 0; iDau < nDaughters[iHad]; ++iDau) { histPtDau[iHad][iOrigin][iDau] = registryMesons.add(Form("%s/histPtDau%d%s", particleNames[iHad].data(), iDau, originNames[iOrigin].data()), Form("Daughter %d Pt reco - %s %s; #it{p}_{T}^{dau, reco} (GeV/#it{c}); entries", iDau, originNames[iOrigin].data(), labels[iHad].data()), HistType::kTH1F, {axisPt}); histEtaDau[iHad][iOrigin][iDau] = registryMesons.add(Form("%s/histEtaDau%d%s", particleNames[iHad].data(), iDau, originNames[iOrigin].data()), Form("Daughter %d Eta reco - %s %s; #it{#eta}^{dau, reco}; entries", iDau, originNames[iOrigin].data(), labels[iHad].data()), HistType::kTH1F, {{100, -1., 1.}}); @@ -655,7 +677,7 @@ struct HfTaskMcValidationRec { histDeltaSecondaryVertexZ[iHad] = registryBaryons.add(Form("%s/histDeltaSecondaryVertexZ", particleNames[iHad].data()), Form("Sec. Vertex difference reco - MC (MC matched) - %s; #Delta z (cm); entries", labels[iHad].data()), HistType::kTH1F, {axisDeltaVtx}); histDeltaDecayLength[iHad] = registryBaryons.add(Form("%s/histDeltaDecayLength", particleNames[iHad].data()), Form("Decay length difference reco - MC (%s); #Delta L (cm); entries", labels[iHad].data()), HistType::kTH1F, {axisDeltaVtx}); for (auto iOrigin = 0; iOrigin < 2; ++iOrigin) { - histPtReco[iHad][iOrigin] = registryBaryons.add(Form("%s/histPtReco%s", particleNames[iHad].data(), originNames[iOrigin].data()), Form("Pt reco %s %s; #it{p}_{T}^{reco} (GeV/#it{c}); entries", originNames[iOrigin].data(), labels[iHad].data()), HistType::kTH1F, {axisPtD}); + histPtCentReco[iHad][iOrigin] = registryBaryons.add(Form("%s/histPtCentReco%s", particleNames[iHad].data(), originNames[iOrigin].data()), Form("Pt Cent reco %s %s; #it{p}_{T}^{reco} (GeV/#it{c}); Centrality (%); entries", originNames[iOrigin].data(), labels[iHad].data()), HistType::kTH2F, {axisPtD, axisCent}); for (unsigned int iDau = 0; iDau < nDaughters[iHad]; ++iDau) { histPtDau[iHad][iOrigin][iDau] = registryBaryons.add(Form("%s/histPtDau%d%s", particleNames[iHad].data(), iDau, originNames[iOrigin].data()), Form("Daughter %d Pt reco - %s %s; #it{p}_{T}^{dau, reco} (GeV/#it{c}); entries", iDau, originNames[iOrigin].data(), labels[iHad].data()), HistType::kTH1F, {axisPt}); histEtaDau[iHad][iOrigin][iDau] = registryBaryons.add(Form("%s/histEtaDau%d%s", particleNames[iHad].data(), iDau, originNames[iOrigin].data()), Form("Daughter %d Eta reco - %s %s; #it{#eta}^{dau, reco}; entries", iDau, originNames[iOrigin].data(), labels[iHad].data()), HistType::kTH1F, {{100, -1., 1.}}); @@ -696,6 +718,7 @@ struct HfTaskMcValidationRec { return; } + registry.fill(HIST("hNevReco"), 1); registry.fill(HIST("histXvtxReco"), collision.posX()); registry.fill(HIST("histYvtxReco"), collision.posY()); registry.fill(HIST("histZvtxReco"), collision.posZ()); @@ -899,116 +922,145 @@ struct HfTaskMcValidationRec { } PROCESS_SWITCH(HfTaskMcValidationRec, processCollAssocWithCentFTOM, "Process collision-association information with centrality selection with FT0M, requires extra table from TrackToCollisionAssociation task (fillTableOfCollIdsPerTrack=true)", false); + template void processEff(HfCand2ProngWithMCRec const& cand2Prongs, HfCand3ProngWithMCRec const& cand3Prongs, aod::TracksWMc const&, aod::McParticles const& mcParticles, aod::McCollisions const&, - CollisionsWithMCLabels const& /*collisions*/) + aod::BCsWithTimestamps const&, + Coll const& collisions, + Preslice cand2ProngsPerCollision, + Preslice cand3ProngsPerCollision) { - // loop over 2-prong candidates - for (const auto& cand2Prong : cand2Prongs) { - - if (cand2Prong.collision_as().has_mcCollision()) { - auto mcCollision = cand2Prong.collision_as().mcCollision_as(); - if (eventGeneratorType >= 0 && mcCollision.getSubGeneratorId() != eventGeneratorType) { - continue; - } - } - - // determine which kind of candidate it is - bool isD0Sel = TESTBIT(cand2Prong.hfflag(), o2::aod::hf_cand_2prong::DecayType::D0ToPiK); - if (!isD0Sel) { - continue; - } - int whichHad = -1; - if (isD0Sel && TESTBIT(std::abs(cand2Prong.flagMcMatchRec()), hf_cand_2prong::DecayType::D0ToPiK)) { - whichHad = DzeroToKPi; + // loop over collisions + for (const auto& collision : collisions) { + // apply event selection + float centrality{-1.f}; + const auto rejectionMask = hfEvSel.getHfCollisionRejectionMask(collision, centrality, ccdb, registry); // only needed to update centrality, no bitmask selection applied + if (!collision.has_mcCollision()) { + return; } - int whichOrigin; - if (cand2Prong.originMcRec() == RecoDecay::OriginType::Prompt) { - whichOrigin = 0; - } else { - whichOrigin = 1; + auto mcCollision = collision.template mcCollision_as(); + if (eventGeneratorType >= 0 && mcCollision.getSubGeneratorId() != eventGeneratorType) { + return; } - if (whichHad >= 0) { - int indexParticle = -1; - if (cand2Prong.prong0_as().has_mcParticle()) { - indexParticle = RecoDecay::getMother(mcParticles, cand2Prong.prong0_as().mcParticle(), PDGArrayParticle[whichHad], true); - } - if (indexParticle < 0) { - continue; - } - auto mother = mcParticles.rawIteratorAt(indexParticle); - fillHisto(cand2Prong, mother, whichHad, whichOrigin); - } - } // end loop on 2-prong candidates + // group 2- and 3-prongs for collision + auto thisCollId = collision.globalIndex(); + auto grouped2ProngCandidates = cand2Prongs.sliceBy(cand2ProngsPerCollision, thisCollId); + auto grouped3ProngCandidates = cand3Prongs.sliceBy(cand3ProngsPerCollision, thisCollId); - // loop over 3-prong candidates - for (const auto& cand3Prong : cand3Prongs) { + // loop over 2-prong candidates + for (const auto& cand2Prong : grouped2ProngCandidates) { - if (cand3Prong.collision_as().has_mcCollision()) { - auto mcCollision = cand3Prong.collision_as().mcCollision_as(); - if (eventGeneratorType >= 0 && mcCollision.getSubGeneratorId() != eventGeneratorType) { + // determine which kind of candidate it is + bool isD0Sel = TESTBIT(cand2Prong.hfflag(), o2::aod::hf_cand_2prong::DecayType::D0ToPiK); + if (!isD0Sel) { continue; } - } - - // determine which kind of candidate it is - // FIXME: add D* and decays with cascades - bool isDPlusSel = TESTBIT(cand3Prong.hfflag(), hf_cand_3prong::DecayType::DplusToPiKPi); - bool isDsSel = TESTBIT(cand3Prong.hfflag(), hf_cand_3prong::DecayType::DsToKKPi); - bool isLcSel = TESTBIT(cand3Prong.hfflag(), hf_cand_3prong::DecayType::LcToPKPi); - bool isXicSel = TESTBIT(cand3Prong.hfflag(), hf_cand_3prong::DecayType::XicToPKPi); - if (!isDPlusSel && !isDsSel && !isLcSel && !isXicSel) { - continue; - } - int whichHad = -1; - if (isDPlusSel && TESTBIT(std::abs(cand3Prong.flagMcMatchRec()), hf_cand_3prong::DecayType::DplusToPiKPi)) { - whichHad = DplusToPiKPi; - } else if (isDsSel && TESTBIT(std::abs(cand3Prong.flagMcMatchRec()), hf_cand_3prong::DecayType::DsToKKPi)) { - if (cand3Prong.flagMcDecayChanRec() == hf_cand_3prong::DecayChannelDToKKPi::DsToPhiPi) { - whichHad = DsToPhiPiToKKPi; - } - if (cand3Prong.flagMcDecayChanRec() == hf_cand_3prong::DecayChannelDToKKPi::DsToK0starK) { - whichHad = DsToK0starKToKKPi; + int whichHad = -1; + if (isD0Sel && TESTBIT(std::abs(cand2Prong.flagMcMatchRec()), hf_cand_2prong::DecayType::D0ToPiK)) { + whichHad = DzeroToKPi; } - if (cand3Prong.flagMcDecayChanRec() == hf_cand_3prong::DecayChannelDToKKPi::DplusToPhiPi) { - whichHad = DplusToPhiPiToKKPi; + int whichOrigin; + if (cand2Prong.originMcRec() == RecoDecay::OriginType::Prompt) { + whichOrigin = 0; + } else { + whichOrigin = 1; } - } else if (isLcSel && TESTBIT(std::abs(cand3Prong.flagMcMatchRec()), hf_cand_3prong::DecayType::LcToPKPi)) { - whichHad = LcToPKPi; - } else if (isXicSel && TESTBIT(std::abs(cand3Prong.flagMcMatchRec()), hf_cand_3prong::DecayType::XicToPKPi)) { - whichHad = XiCplusToPKPi; - } - int whichOrigin; - if (cand3Prong.originMcRec() == RecoDecay::OriginType::Prompt) { - whichOrigin = 0; - } else { - whichOrigin = 1; - } - if (whichHad >= 0) { - int indexParticle = -1; - if (cand3Prong.prong0_as().has_mcParticle()) { - indexParticle = RecoDecay::getMother(mcParticles, cand3Prong.prong0_as().mcParticle(), PDGArrayParticle[whichHad], true); + if (whichHad >= 0) { + int indexParticle = -1; + indexParticle = RecoDecay::getMother(mcParticles, cand2Prong.template prong0_as().template mcParticle_as(), PDGArrayParticle[whichHad], true); + if (indexParticle < 0) { + continue; + } + auto mother = mcParticles.rawIteratorAt(indexParticle); + fillHisto(cand2Prong, mother, whichHad, whichOrigin, centrality); } - if (indexParticle < 0) { + } // end loop on 2-prong candidates + + // loop over 3-prong candidates + for (const auto& cand3Prong : grouped3ProngCandidates) { + + // determine which kind of candidate it is + // FIXME: add D* and decays with cascades + bool isDPlusSel = TESTBIT(cand3Prong.hfflag(), hf_cand_3prong::DecayType::DplusToPiKPi); + bool isDsSel = TESTBIT(cand3Prong.hfflag(), hf_cand_3prong::DecayType::DsToKKPi); + bool isLcSel = TESTBIT(cand3Prong.hfflag(), hf_cand_3prong::DecayType::LcToPKPi); + bool isXicSel = TESTBIT(cand3Prong.hfflag(), hf_cand_3prong::DecayType::XicToPKPi); + if (!isDPlusSel && !isDsSel && !isLcSel && !isXicSel) { continue; } - auto mother = mcParticles.rawIteratorAt(indexParticle); - fillHisto(cand3Prong, mother, whichHad, whichOrigin); - std::array momDau2 = {cand3Prong.pxProng2(), - cand3Prong.pyProng2(), - cand3Prong.pzProng2()}; - histPtDau[whichHad][whichOrigin][2]->Fill(RecoDecay::pt(momDau2)); - histEtaDau[whichHad][whichOrigin][2]->Fill(RecoDecay::eta(momDau2)); - histImpactParameterDau[whichHad][whichOrigin][2]->Fill(cand3Prong.impactParameter2()); - } - } // end loop on 3-prong candidates + int whichHad = -1; + if (isDPlusSel && TESTBIT(std::abs(cand3Prong.flagMcMatchRec()), hf_cand_3prong::DecayType::DplusToPiKPi)) { + whichHad = DplusToPiKPi; + } else if (isDsSel && TESTBIT(std::abs(cand3Prong.flagMcMatchRec()), hf_cand_3prong::DecayType::DsToKKPi)) { + if (cand3Prong.flagMcDecayChanRec() == hf_cand_3prong::DecayChannelDToKKPi::DsToPhiPi) { + whichHad = DsToPhiPiToKKPi; + } + if (cand3Prong.flagMcDecayChanRec() == hf_cand_3prong::DecayChannelDToKKPi::DsToK0starK) { + whichHad = DsToK0starKToKKPi; + } + if (cand3Prong.flagMcDecayChanRec() == hf_cand_3prong::DecayChannelDToKKPi::DplusToPhiPi) { + whichHad = DplusToPhiPiToKKPi; + } + } else if (isLcSel && TESTBIT(std::abs(cand3Prong.flagMcMatchRec()), hf_cand_3prong::DecayType::LcToPKPi)) { + whichHad = LcToPKPi; + } else if (isXicSel && TESTBIT(std::abs(cand3Prong.flagMcMatchRec()), hf_cand_3prong::DecayType::XicToPKPi)) { + whichHad = XiCplusToPKPi; + } + int whichOrigin; + if (cand3Prong.originMcRec() == RecoDecay::OriginType::Prompt) { + whichOrigin = 0; + } else { + whichOrigin = 1; + } + + if (whichHad >= 0) { + int indexParticle = -1; + if (cand3Prong.template prong0_as().has_mcParticle()) { + indexParticle = RecoDecay::getMother(mcParticles, cand3Prong.template prong0_as().template mcParticle_as(), PDGArrayParticle[whichHad], true); + } + if (indexParticle < 0) { + continue; + } + auto mother = mcParticles.rawIteratorAt(indexParticle); + fillHisto(cand3Prong, mother, whichHad, whichOrigin, centrality); + std::array momDau2 = {cand3Prong.pxProng2(), + cand3Prong.pyProng2(), + cand3Prong.pzProng2()}; + histPtDau[whichHad][whichOrigin][2]->Fill(RecoDecay::pt(momDau2)); + histEtaDau[whichHad][whichOrigin][2]->Fill(RecoDecay::eta(momDau2)); + histImpactParameterDau[whichHad][whichOrigin][2]->Fill(cand3Prong.impactParameter2()); + } + } // end loop on 3-prong candidates + } // end loop on collisions + } + void processEffNoCent(HfCand2ProngWithMCRec const& cand2Prongs, + HfCand3ProngWithMCRec const& cand3Prongs, + aod::TracksWMc const& mcTracks, + aod::McParticles const& mcParticles, + aod::McCollisions const& mcCollisions, + aod::BCsWithTimestamps const& bcs, + CollisionsWithMCLabels const& collsWithLabels) + { + processEff(cand2Prongs, cand3Prongs, mcTracks, mcParticles, mcCollisions, bcs, collsWithLabels, cand2ProngPerCollision, cand3ProngPerCollision); + } + PROCESS_SWITCH(HfTaskMcValidationRec, processEffNoCent, "Compute charm-hadron efficiencies (not all of them are implemented), requires HF candidate creators w/o information on centrality", false); + + void processEffCentFT0C(HfCand2ProngWithMCRec const& cand2Prongs, + HfCand3ProngWithMCRec const& cand3Prongs, + aod::TracksWMc const& mcTracks, + aod::McParticles const& mcParticles, + aod::McCollisions const& mcCollisions, + aod::BCsWithTimestamps const& bcs, + CollisionsWithMCLabelsAndCentFT0C const& collsWithLabels) + { + processEff(cand2Prongs, cand3Prongs, mcTracks, mcParticles, mcCollisions, bcs, collsWithLabels, cand2ProngPerCollision, cand3ProngPerCollision); } - PROCESS_SWITCH(HfTaskMcValidationRec, processEff, "Compute charm-hadron efficiencies (not all of them are implemented), requires HF candidate creators", false); + PROCESS_SWITCH(HfTaskMcValidationRec, processEffCentFT0C, "Compute charm-hadron efficiencies (not all of them are implemented), requires HF candidate creators with information on centrality from FT0C", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGHF/Utils/utilsEvSelHf.h b/PWGHF/Utils/utilsEvSelHf.h index 3a3426e8d21..d1ffe2038e2 100644 --- a/PWGHF/Utils/utilsEvSelHf.h +++ b/PWGHF/Utils/utilsEvSelHf.h @@ -26,6 +26,7 @@ #include "Framework/HistogramSpec.h" #include "Framework/OutputObjHeader.h" +#include "Common/CCDB/EventSelectionParams.h" #include "EventFiltering/Zorro.h" #include "EventFiltering/ZorroSummary.h" #include "PWGHF/Core/CentralityEstimation.h" diff --git a/PWGJE/Core/JetTaggingUtilities.h b/PWGJE/Core/JetTaggingUtilities.h index ff25b30e055..059c559e553 100644 --- a/PWGJE/Core/JetTaggingUtilities.h +++ b/PWGJE/Core/JetTaggingUtilities.h @@ -384,17 +384,15 @@ bool trackAcceptanceWithDca(T const& track, float trackDcaXYMax, float trackDcaZ } /** - * retrun acceptance of prong about chi2 and error of decay length due to cut for high quality secondary vertex + * retrun acceptance of prong due to cut for high quality secondary vertex */ template -bool prongAcceptance(T const& prong, float prongChi2PCAMin, float prongChi2PCAMax, float prongsigmaLxyMax, float prongIPxyMin, float prongIPxyMax, float prongDispersionMax, bool doXYZ) +bool prongAcceptance(T const& prong, float prongChi2PCAMin, float prongChi2PCAMax, float prongsigmaLxyMax, float prongIPxyMin, float prongIPxyMax, bool doXYZ) { if (prong.chi2PCA() < prongChi2PCAMin) return false; if (prong.chi2PCA() > prongChi2PCAMax) return false; - if (prong.dispersion() > prongDispersionMax) - return false; if (!doXYZ) { if (prong.errorDecayLengthXY() > prongsigmaLxyMax) return false; @@ -414,6 +412,17 @@ bool prongAcceptance(T const& prong, float prongChi2PCAMin, float prongChi2PCAMa return true; } +/** + * retrun acceptance of secondary vertex due to cut for high quality secondary vertex + */ +template +bool svAcceptance(T const& sv, float svDispersionMax) +{ + if (sv.dispersion() > svDispersionMax) + return false; + return true; +} + /** * return geometric sign which is calculated scalar product between jet axis with DCA (track propagated to PV ) * positive and negative value are expected from primary vertex @@ -569,166 +578,27 @@ float getJetProbability(T const& fResoFuncjet, U const& jet, V const& jtracks, f } // For secaondy vertex method utilites -class bjetCandSV -{ - public: - bjetCandSV() = default; - - bjetCandSV(float xpv, float ypv, float zpv, float xsv, float ysv, float zsv, - float pxVal, float pyVal, float pzVal, float eVal, float mVal, float chi2Val, - float dispersion, float errDecayLength, float errDecayLengthXY, - float rSecVertex, float ptVal, float pVal, - std::array pVec, float etaVal, float phiVal, - float yVal, float decayLen, float decayLenXY, - float decayLenNorm, float decayLenXYNorm, - float cpaVal, float impParXY) - : m_xPVertex(xpv), m_yPVertex(ypv), m_zPVertex(zpv), m_xSecondaryVertex(xsv), m_ySecondaryVertex(ysv), m_zSecondaryVertex(zsv), m_px(pxVal), m_py(pyVal), m_pz(pzVal), m_e(eVal), m_m(mVal), m_chi2PCA(chi2Val), m_dispersion(dispersion), m_errorDecayLength(errDecayLength), m_errorDecayLengthXY(errDecayLengthXY), m_rSecondaryVertex(rSecVertex), m_pt(ptVal), m_p(pVal), m_pVector(pVec), m_eta(etaVal), m_phi(phiVal), m_y(yVal), m_decayLength(decayLen), m_decayLengthXY(decayLenXY), m_decayLengthNormalised(decayLenNorm), m_decayLengthXYNormalised(decayLenXYNorm), m_cpa(cpaVal), m_impactParameterXY(impParXY) - { - } - - float xPVertex() const { return m_xPVertex; } - float yPVertex() const { return m_yPVertex; } - float zPVertex() const { return m_zPVertex; } - - float xSecondaryVertex() const { return m_xSecondaryVertex; } - float ySecondaryVertex() const { return m_ySecondaryVertex; } - float zSecondaryVertex() const { return m_zSecondaryVertex; } - - float px() const { return m_px; } - float py() const { return m_py; } - float pz() const { return m_pz; } - float e() const { return m_e; } - float m() const { return m_m; } - float chi2PCA() const { return m_chi2PCA; } - float dispersion() const { return m_dispersion; } - - float errorDecayLength() const { return m_errorDecayLength; } - float errorDecayLengthXY() const { return m_errorDecayLengthXY; } - - float rSecondaryVertex() const { return m_rSecondaryVertex; } - float pt() const { return m_pt; } - float p() const { return m_p; } - - std::array pVector() const { return m_pVector; } - - float eta() const { return m_eta; } - float phi() const { return m_phi; } - float y() const { return m_y; } - - float decayLength() const { return m_decayLength; } - float decayLengthXY() const { return m_decayLengthXY; } - float decayLengthNormalised() const { return m_decayLengthNormalised; } - float decayLengthXYNormalised() const { return m_decayLengthXYNormalised; } - - float cpa() const { return m_cpa; } - float impactParameterXY() const { return m_impactParameterXY; } - - private: - float m_xPVertex, m_yPVertex, m_zPVertex; - float m_xSecondaryVertex, m_ySecondaryVertex, m_zSecondaryVertex; - float m_px, m_py, m_pz, m_e, m_m, m_chi2PCA, m_dispersion; - float m_errorDecayLength, m_errorDecayLengthXY; - float m_rSecondaryVertex, m_pt, m_p; - std::array m_pVector; - float m_eta, m_phi, m_y; - float m_decayLength, m_decayLengthXY, m_decayLengthNormalised, m_decayLengthXYNormalised; - float m_cpa, m_impactParameterXY; -}; - template -bjetCandSV jetFromProngMaxDecayLength(const JetType& jet, float const& prongChi2PCAMin, float const& prongChi2PCAMax, float const& prongsigmaLxyMax, float const& prongIPxyMin, float const& prongIPxyMax, const bool& doXYZ = false) +typename ProngType::iterator jetFromProngMaxDecayLength(const JetType& jet, float const& prongChi2PCAMin, float const& prongChi2PCAMax, float const& prongsigmaLxyMax, float const& prongIPxyMin, float const& prongIPxyMax, const bool& doXYZ = false) { - float xPVertex = 0.0f; - float yPVertex = 0.0f; - float zPVertex = 0.0f; - float xSecondaryVertex = 0.0f; - float ySecondaryVertex = 0.0f; - float zSecondaryVertex = 0.0f; - float px = 0.0f; - float py = 0.0f; - float pz = 0.0f; - float e = 0.0f; - float m = 0.0f; - float chi2PCA = 0.0f; - float dispersion = 0.0f; - float errorDecayLength = 0.0f; - float errorDecayLengthXY = 0.0f; - - float rSecondaryVertex = 0.0f; - float pt = 0.0f; - float p = 0.0f; - std::array pVector = {0.0f, 0.0f, 0.0f}; - float eta = 0.0f; - float phi = 0.0f; - float y = 0.0f; - float decayLength = 0.0f; - float decayLengthXY = 0.0f; - float decayLengthNormalised = 0.0f; - float decayLengthXYNormalised = 0.0f; - float cpa = 0.0f; - float impactParameterXY = 0.0f; - float maxSxy = -1.0f; - + typename ProngType::iterator bjetCand; for (const auto& prong : jet.template secondaryVertices_as()) { - float Sxy = -1.; - if (!doXYZ) { - Sxy = prong.decayLengthXY() / prong.errorDecayLengthXY(); - } else { - Sxy = prong.decayLength() / prong.errorDecayLength(); - } - + if (!prongAcceptance(prong, prongChi2PCAMin, prongChi2PCAMax, prongsigmaLxyMax, prongIPxyMin, prongIPxyMax, doXYZ)) + continue; + auto Sxy = prong.decayLengthXY() / prong.errorDecayLengthXY(); if (maxSxy < Sxy) { - maxSxy = Sxy; - - xPVertex = prong.xPVertex(); - yPVertex = prong.yPVertex(); - zPVertex = prong.zPVertex(); - xSecondaryVertex = prong.xSecondaryVertex(); - ySecondaryVertex = prong.ySecondaryVertex(); - zSecondaryVertex = prong.zSecondaryVertex(); - px = prong.px(); - py = prong.py(); - pz = prong.pz(); - e = prong.e(); - m = prong.m(); - chi2PCA = prong.chi2PCA(); - dispersion = prong.dispersion(); - errorDecayLength = prong.errorDecayLength(); - errorDecayLengthXY = prong.errorDecayLengthXY(); - rSecondaryVertex = prong.rSecondaryVertex(); - pt = prong.pt(); - p = prong.p(); - pVector = prong.pVector(); - eta = prong.eta(); - phi = prong.phi(); - y = prong.y(); - decayLength = prong.decayLength(); - decayLengthXY = prong.decayLengthXY(); - decayLengthNormalised = prong.decayLengthNormalised(); - decayLengthXYNormalised = prong.decayLengthXYNormalised(); - cpa = prong.cpa(); - impactParameterXY = prong.impactParameterXY(); + bjetCand = prong; } } - - return bjetCandSV( - xPVertex, yPVertex, zPVertex, - xSecondaryVertex, ySecondaryVertex, zSecondaryVertex, - px, py, pz, e, m, chi2PCA, - dispersion, errorDecayLength, errorDecayLengthXY, - rSecondaryVertex, pt, p, - pVector, eta, phi, - y, decayLength, decayLengthXY, - decayLengthNormalised, decayLengthXYNormalised, - cpa, impactParameterXY); + return bjetCand; } template bool isTaggedJetSV(T const jet, U const& /*prongs*/, float const& prongChi2PCAMin, float const& prongChi2PCAMax, float const& prongsigmaLxyMax, float const& prongIPxyMin, float const& prongIPxyMax, float prongDispersionMax, float const& doXYZ = false, float const& tagPointForSV = 15.) { auto bjetCand = jetFromProngMaxDecayLength(jet, prongChi2PCAMin, prongChi2PCAMax, prongsigmaLxyMax, prongIPxyMin, prongIPxyMax, doXYZ); - if (!prongAcceptance(bjetCand, prongChi2PCAMin, prongChi2PCAMax, prongsigmaLxyMax, prongIPxyMin, prongIPxyMax, prongDispersionMax, doXYZ)) + if (!svAcceptance(bjetCand, prongDispersionMax)) return false; if (!doXYZ) { auto maxSxy = bjetCand.decayLengthXY() / bjetCand.errorDecayLengthXY(); diff --git a/PWGJE/TableProducer/jettaggerhf.cxx b/PWGJE/TableProducer/jettaggerhf.cxx index 20183a2e149..a60815ab175 100644 --- a/PWGJE/TableProducer/jettaggerhf.cxx +++ b/PWGJE/TableProducer/jettaggerhf.cxx @@ -197,15 +197,15 @@ struct JetTaggerHFTask { break; case 4: // TODO vecParamsData = (std::vector)paramsResoFuncData; - vecParamsCharmJetMC = {281446.003, -0.063, 0.894, 11.598, 0.943, 8.025, 0.130, 6.227, 0.027}; - vecParamsBeautyJetMC = {74839.065, -0.081, 0.875, 10.314, 0.939, 7.326, 0.101, 6.309, 0.024}; - vecParamsLfJetMC = {1531580.038, -0.062, -0.896, 13.267, 1.034, 5.866, 0.004, 7.836, 0.090}; - LOG(info) << "defined parameters of resolution function: PYTHIA8, JJ, LHC23d4"; + vecParamsCharmJetMC = {743719.121, -0.960, -0.240, 13.765, 1.314, 10.761, 0.293, 8.538, 0.052}; + vecParamsBeautyJetMC = {88888.418, 0.256, 1.003, 10.185, 0.740, 8.216, 0.147, 7.228, 0.040}; + vecParamsLfJetMC = {414860.372, -1.000, 0.285, 14.561, 1.464, 11.693, 0.339, 9.183, 0.052}; + LOG(info) << "defined parameters of resolution function: PYTHIA8, JJ, weighted, LHC24g4"; break; case 5: // TODO vecParamsData = (std::vector)paramsResoFuncData; - vecParamsIncJetMC = {1900387.527, -0.059, 0.895, 13.461, 1.004, 8.860, 0.098, 6.931, 0.011}; - LOG(info) << "defined parameters of resolution function: PYTHIA8, JJ, LHC23d4 & use inclusive distribution"; + vecParamsIncJetMC = {2211391.862, 0.360, 1.028, 13.019, 0.650, 11.151, 0.215, 9.462, 0.044}; + LOG(info) << "defined parameters of resolution function: PYTHIA8, JJ, weighted, LHC24g4 & use inclusive distribution"; useResoFuncFromIncJet = true; break; default: diff --git a/PWGJE/Tasks/PhotonIsolationQA.cxx b/PWGJE/Tasks/PhotonIsolationQA.cxx index 763ac8521c6..878d404236c 100644 --- a/PWGJE/Tasks/PhotonIsolationQA.cxx +++ b/PWGJE/Tasks/PhotonIsolationQA.cxx @@ -89,6 +89,7 @@ struct PhotonIsolationQA { // Preslices Preslice collisionsPerBC = aod::collision::bcId; + Preslice TracksPercollision = aod::track::collisionId; Preslice perClusterMatchedTracks = o2::aod::emcalclustercell::emcalclusterId; Preslice ClustersPerCol = aod::emcalcluster::collisionId; Preslice CellsPerCluster = aod::emcalclustercell::emcalclusterId; @@ -113,7 +114,7 @@ struct PhotonIsolationQA { const o2Axis NCells_Axis{50, 0, 50, "N Cells"}; const o2Axis Num_Track_Axis{20, -0.5, 19.5, "N Tracks"}; const o2Axis PtIso_Axis{100, -10, 15, "P_{T, Iso} (GeV/c)"}; - const o2Axis Rho_Axis{50, 5, 4995, "#rho (#frac{GeV/c}{A})"}; + const o2Axis Rho_Axis{200, 0, 200, "#rho (#frac{GeV/c}{A})"}; const o2Axis ABCD_Axis{5, 0, 5, "ABCD"}; const o2Axis NLM_Axis{50, -0.5, 49.5, "NLM"}; const o2Axis PDG_Axis{20000, -10000.5, 9999.5, "PDG Code"}; @@ -138,6 +139,7 @@ struct PhotonIsolationQA { Data_Info.add("hABCDControlRegion", "Yield Control Regions", o2HistType::kTH2F, {{ABCD_Axis}, {Energy_Axis}}); Data_Info.add("hCollperBC", "collisions per BC", o2HistType::kTH1F, {BC_Axis}); Data_Info.add("hEnergy_NLM_Flag", "Energy vs NLM", o2HistType::kTH3F, {{Energy_Axis}, {NLM_Axis}, {SM_Flag_Axis}}); + Data_Info.add("hNCells_NLM_Flag", "Energy vs NLM", o2HistType::kTH3F, {{NCells_Axis}, {NLM_Axis}, {SM_Flag_Axis}}); MC_Info.add("hPosZ", "Z Position of collision", o2HistType::kTH1F, {PosZ_Axis}); MC_Info.add("hNumClusters", "Number of cluster per collision", o2HistType::kTH1F, {Num_Cluster_Axis}); @@ -159,6 +161,8 @@ struct PhotonIsolationQA { MC_Info.add("hMotherStatusCodeVsPDG", "Statuscode of candidate photons mother", o2HistType::kTH2F, {{Status_Code_Axis}, {PDG_Axis}}); MC_Info.add("hCollperBC", "collisions per BC", o2HistType::kTH1F, {BC_Axis}); MC_Info.add("hEnergy_NLM_Flag", "Energy vs NLM", o2HistType::kTH3F, {{Energy_Axis}, {NLM_Axis}, {SM_Flag_Axis}}); + MC_Info.add("hNCells_NLM_Flag", "Energy vs NLM", o2HistType::kTH3F, {{NCells_Axis}, {NLM_Axis}, {SM_Flag_Axis}}); + MC_Info.add("hPromtPhoton", "Energy vs m02 vs NCells, PtIso", o2HistType::kTHnSparseF, {{Energy_Axis}, {Shower_Shape_Long_Axis}, {NCells_Axis}, {PtIso_Axis}}); std::vector bin_names = {"A", "B", "C", "D", "True Bckgr A"}; for (size_t i = 0; i < bin_names.size(); i++) { @@ -356,6 +360,7 @@ struct PhotonIsolationQA { for (const auto& Collision : collisionsInBC) { MC_Info.fill(HIST("hPosZ"), Collision.posZ()); auto ClustersInCol = mcclusters.sliceBy(ClustersPerCol, Collision.globalIndex()); + auto tracksInCol = tracks.sliceBy(TracksPercollision, Collision.globalIndex()); if (ClustersInCol.size() > 0) { MC_Info.fill(HIST("hNumClusters"), ClustersInCol.size()); @@ -369,32 +374,36 @@ struct PhotonIsolationQA { auto CellsInCluster = ClusterCells.sliceBy(CellsPerCluster, mccluster.globalIndex()); auto [NLM, flag] = CalculateNLM(CellsInCluster); MC_Info.fill(HIST("hEnergy_NLM_Flag"), mccluster.energy(), NLM, flag); + MC_Info.fill(HIST("hNCells_NLM_Flag"), mccluster.nCells(), NLM, flag); if (!track_matching(mccluster, tracksofcluster)) { // no track with significant momentum is matched to cluster - double Pt_Cone = sum_Pt_tracks_in_cone(mccluster, tracks); - double Rho_Perpen_Cone = Rho_Perpendicular_Cone(mccluster, tracks); - double Pt_iso = Pt_Iso(Pt_Cone, Rho_Perpen_Cone); - - MC_Info.fill(HIST("hEvsPtIso"), mccluster.energy(), Pt_iso); - MC_Info.fill(HIST("hRho_Perpen_Cone"), mccluster.energy(), Rho_Perpen_Cone); - MC_Info.fill(HIST("hSigmaLongvsPtIso"), mccluster.m02(), Pt_iso); - fillABCDHisto(MC_Info, mccluster, Pt_iso); - - // acces mc true info - auto ClusterParticles = mccluster.mcParticle_as(); - bool background = true; - for (auto& clusterparticle : ClusterParticles) { - if (clusterparticle.pdgCode() == 22) { - MC_Info.fill(HIST("hClusterEnergy_MCParticleEnergy"), mccluster.energy(), clusterparticle.e()); - int first_mother_status_code = getOriginalMotherIndex(clusterparticle); - if (abs(first_mother_status_code) == 23) { - background = false; + if (NLM <= maxNLM) { + double Pt_Cone = sum_Pt_tracks_in_cone(mccluster, tracksInCol); + double Rho_Perpen_Cone = Rho_Perpendicular_Cone(mccluster, tracksInCol); + double Pt_iso = Pt_Iso(Pt_Cone, Rho_Perpen_Cone); + + MC_Info.fill(HIST("hEvsPtIso"), mccluster.energy(), Pt_iso); + MC_Info.fill(HIST("hRho_Perpen_Cone"), mccluster.energy(), Rho_Perpen_Cone); + MC_Info.fill(HIST("hSigmaLongvsPtIso"), mccluster.m02(), Pt_iso); + fillABCDHisto(MC_Info, mccluster, Pt_iso); + + // acces mc true info + auto ClusterParticles = mccluster.mcParticle_as(); + bool background = true; + for (auto& clusterparticle : ClusterParticles) { + if (clusterparticle.pdgCode() == 22) { + MC_Info.fill(HIST("hClusterEnergy_MCParticleEnergy"), mccluster.energy(), clusterparticle.e()); + int first_mother_status_code = getOriginalMotherIndex(clusterparticle); + if (abs(first_mother_status_code) == 23) { + background = false; + MC_Info.fill(HIST("hPromtPhoton"), mccluster.energy(), mccluster.m02(), mccluster.nCells(), Pt_iso); + } } } - } - if (background) { - if ((Pt_iso < 1.5) && (mccluster.m02() < 0.3) && (mccluster.m02() > 0.1)) { - MC_Info.fill(HIST("hABCDControlRegion"), 4.5, mccluster.energy()); + if (background) { + if ((Pt_iso < 1.5) && (mccluster.m02() < 0.3) && (mccluster.m02() > 0.1)) { + MC_Info.fill(HIST("hABCDControlRegion"), 4.5, mccluster.energy()); + } } } } @@ -415,6 +424,7 @@ struct PhotonIsolationQA { for (const auto& Collision : collisionsInBC) { Data_Info.fill(HIST("hPosZ"), Collision.posZ()); auto ClustersInCol = clusters.sliceBy(ClustersPerCol, Collision.globalIndex()); + auto tracksInCol = tracks.sliceBy(TracksPercollision, Collision.globalIndex()); if (ClustersInCol.size() > 0) { Data_Info.fill(HIST("hNumClusters"), ClustersInCol.size()); @@ -428,16 +438,19 @@ struct PhotonIsolationQA { auto CellsInCluster = ClusterCells.sliceBy(CellsPerCluster, cluster.globalIndex()); auto [NLM, flag] = CalculateNLM(CellsInCluster); Data_Info.fill(HIST("hEnergy_NLM_Flag"), cluster.energy(), NLM, flag); + Data_Info.fill(HIST("hNCells_NLM_Flag"), cluster.nCells(), NLM, flag); if (!track_matching(cluster, tracksofcluster)) { // no track with significant momentum is matched to cluster - double Pt_Cone = sum_Pt_tracks_in_cone(cluster, tracks); - double Rho_Perpen_Cone = Rho_Perpendicular_Cone(cluster, tracks); - double Pt_iso = Pt_Iso(Pt_Cone, Rho_Perpen_Cone); - - Data_Info.fill(HIST("hEvsPtIso"), cluster.energy(), Pt_iso); - Data_Info.fill(HIST("hRho_Perpen_Cone"), cluster.energy(), Rho_Perpen_Cone); - Data_Info.fill(HIST("hSigmaLongvsPtIso"), cluster.m02(), Pt_iso); - fillABCDHisto(Data_Info, cluster, Pt_iso); + if (NLM < maxNLM) { + double Pt_Cone = sum_Pt_tracks_in_cone(cluster, tracksInCol); + double Rho_Perpen_Cone = Rho_Perpendicular_Cone(cluster, tracksInCol); + double Pt_iso = Pt_Iso(Pt_Cone, Rho_Perpen_Cone); + + Data_Info.fill(HIST("hEvsPtIso"), cluster.energy(), Pt_iso); + Data_Info.fill(HIST("hRho_Perpen_Cone"), cluster.energy(), Rho_Perpen_Cone); + Data_Info.fill(HIST("hSigmaLongvsPtIso"), cluster.m02(), Pt_iso); + fillABCDHisto(Data_Info, cluster, Pt_iso); + } } } } diff --git a/PWGJE/Tasks/jetTutorial.cxx b/PWGJE/Tasks/jetTutorial.cxx index 0065726bae2..8be44b71c72 100644 --- a/PWGJE/Tasks/jetTutorial.cxx +++ b/PWGJE/Tasks/jetTutorial.cxx @@ -9,7 +9,7 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -// jet tutorial task for hands on tutorial session (09/11/2023) +// jet tutorial task for hands on tutorial session (16/11/2024) // /// \author Nima Zardoshti // @@ -26,6 +26,7 @@ #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" @@ -45,12 +46,14 @@ struct JetTutorialTask { {"h_jet_pt", "jet pT;#it{p}_{T,jet} (GeV/#it{c});entries", {HistType::kTH1F, {{200, 0., 200.}}}}, {"h_jet_eta", "jet #eta;#eta_{jet};entries", {HistType::kTH1F, {{100, -1.0, 1.0}}}}, {"h_jet_phi", "jet #phi;#phi_{jet};entries", {HistType::kTH1F, {{80, -1.0, 7.}}}}, - {"h_jet_pt_bkgsub", "jet pT bkg sub;#it{p}_{T,jet} (GeV/#it{c});entries", {HistType::kTH1F, {{200, 0., 200.}}}}, + {"h_jet_pt_rhosub", "jet pT bkg sub;#it{p}_{T,jet} (GeV/#it{c});entries", {HistType::kTH1F, {{200, 0., 200.}}}}, + {"h_jet_pt_constsub", "jet pT bkg sub;#it{p}_{T,jet} (GeV/#it{c});entries", {HistType::kTH1F, {{200, 0., 200.}}}}, {"h_part_jet_pt", "particle level jet pT;#it{p}_{T,jet part} (GeV/#it{c});entries", {HistType::kTH1F, {{200, 0., 200.}}}}, {"h_part_jet_eta", "particle level jet #eta;#eta_{jet part};entries", {HistType::kTH1F, {{100, -1.0, 1.0}}}}, {"h_part_jet_phi", "particle level jet #phi;#phi_{jet part};entries", {HistType::kTH1F, {{80, -1.0, 7.}}}}, {"h_jet_ntracks", "jet N tracks;N_{jet tracks};entries", {HistType::kTH1F, {{40, -0.5, 39.5}}}}, {"h_jet_angularity", "jet angularity ;#lambda_{1};entries", {HistType::kTH1F, {{5, 0.0, 0.5}}}}, + {"h_jet_angularity_constsub", "jet angularity bkg sub;#lambda_{1};entries", {HistType::kTH1F, {{5, 0.0, 0.5}}}}, {"h_full_jet_pt", "jet pT;#it{p}_{T,jet} (GeV/#it{c});entries", {HistType::kTH1F, {{200, 0., 200.}}}}, {"h_full_jet_eta", "jet #eta;#eta_{jet};entries", {HistType::kTH1F, {{100, -1.0, 1.0}}}}, {"h_full_jet_phi", "jet #phi;#phi_{jet};entries", {HistType::kTH1F, {{80, -1.0, 7.}}}}, @@ -66,22 +69,35 @@ struct JetTutorialTask { {"h_matched_jets_eta", "#eta_{jet part}; #eta_{jet det}", {HistType::kTH2F, {{100, -1.0, 1.0}, {100, -1.0, 1.0}}}}, {"h_matched_jets_phi", "#phi_{jet part}; #phi_{jet det}", {HistType::kTH2F, {{80, -1.0, 7.}, {80, -1.0, 7.}}}}}}; + Configurable vertexZCut{"vertexZCut", 10.0f, "Accepted z-vertex range"}; + Configurable jetPtMin{"jetPtMin", 5.0, "minimum jet pT cut"}; Configurable jetR{"jetR", 0.4, "jet resolution parameter"}; Configurable eventSelections{"eventSelections", "sel8", "choose event selection"}; Configurable trackSelections{"trackSelections", "globalTracks", "set track selections"}; + Configurable kappa{"kappa", 1.0, "angularity kappa"}; + Configurable alpha{"alpha", 1.0, "angularity alpha"}; + + 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"}; + int eventSelection = -1; int trackSelection = -1; + std::vector triggerMaskBits; void init(o2::framework::InitContext&) { eventSelection = jetderiveddatautilities::initialiseEventSelection(static_cast(eventSelections)); trackSelection = jetderiveddatautilities::initialiseTrackSelection(static_cast(trackSelections)); + triggerMaskBits = jetderiveddatautilities::initialiseTriggerMaskBits(triggerMasks); } Filter jetCuts = aod::jet::pt > jetPtMin&& aod::jet::r == nround(jetR.node() * 100.0f); + Filter collisionFilter = nabs(aod::jcollision::posZ) < vertexZCut; + Filter mcCollisionFilter = nabs(aod::jmccollision::posZ) < vertexZCut; + + Preslice> perMcCollisionJets = aod::jet::mcCollisionId; void processCollisions(JetCollision const& collision, JetTracks const& tracks) { @@ -100,9 +116,9 @@ struct JetTutorialTask { registry.fill(HIST("h_track_phi"), track.phi()); } } - PROCESS_SWITCH(JetTutorialTask, processCollisions, "process self contained collisions", true); + PROCESS_SWITCH(JetTutorialTask, processCollisions, "process JE collisions", false); - void processCollisionsWithExternalTracks(JetCollision const& collision, soa::Join const& tracks, soa::Join const&) + void processCollisionsWithExternalTracks(soa::Filtered::iterator const& collision, soa::Join const& tracks, soa::Join const&) { registry.fill(HIST("h_collisions"), 0.5); @@ -121,126 +137,167 @@ struct JetTutorialTask { registry.fill(HIST("h_track_chi2PerCluster"), originalTrack.tpcChi2NCl()); } } - PROCESS_SWITCH(JetTutorialTask, processCollisionsWithExternalTracks, "process non self contained collisions", true); + PROCESS_SWITCH(JetTutorialTask, processCollisionsWithExternalTracks, "process JE collisions with access to the original track table", false); - void processDataCharged(soa::Filtered::iterator const& jet) + void processDataCharged(soa::Filtered::iterator const& collision, soa::Filtered const& jets) { - registry.fill(HIST("h_jet_pt"), jet.pt()); - registry.fill(HIST("h_jet_eta"), jet.eta()); - registry.fill(HIST("h_jet_phi"), jet.phi()); + if (!jetderiveddatautilities::selectCollision(collision, eventSelection)) { + return; + } + for (auto& jet : jets) { + registry.fill(HIST("h_jet_pt"), jet.pt()); + registry.fill(HIST("h_jet_eta"), jet.eta()); + registry.fill(HIST("h_jet_phi"), jet.phi()); + } } - PROCESS_SWITCH(JetTutorialTask, processDataCharged, "jets data", true); + PROCESS_SWITCH(JetTutorialTask, processDataCharged, "charged jets in data", false); - void processMCDetectorLevelCharged(soa::Filtered::iterator const& jet) + void processMCDetectorLevelCharged(soa::Filtered::iterator const& collision, soa::Filtered const& jets) { - registry.fill(HIST("h_jet_pt"), jet.pt()); - registry.fill(HIST("h_jet_eta"), jet.eta()); - registry.fill(HIST("h_jet_phi"), jet.phi()); + if (!jetderiveddatautilities::selectCollision(collision, eventSelection)) { + return; + } + for (auto& jet : jets) { + registry.fill(HIST("h_jet_pt"), jet.pt()); + registry.fill(HIST("h_jet_eta"), jet.eta()); + registry.fill(HIST("h_jet_phi"), jet.phi()); + } } - PROCESS_SWITCH(JetTutorialTask, processMCDetectorLevelCharged, "jets on detector level MC", false); + PROCESS_SWITCH(JetTutorialTask, processMCDetectorLevelCharged, "charged jets in detector level MC", false); - void processMCParticleLevel(soa::Filtered::iterator const& jet) + void processMCDetectorLevelWeightedCharged(soa::Filtered::iterator const& collision, JetMcCollisions const&, soa::Filtered const& jets) { - registry.fill(HIST("h_part_jet_pt"), jet.pt()); - registry.fill(HIST("h_part_jet_eta"), jet.eta()); - registry.fill(HIST("h_part_jet_phi"), jet.phi()); + if (!jetderiveddatautilities::selectCollision(collision, eventSelection)) { + return; + } + for (auto& jet : jets) { + registry.fill(HIST("h_jet_pt"), jet.pt(), collision.mcCollision().weight()); + registry.fill(HIST("h_jet_eta"), jet.eta(), collision.mcCollision().weight()); + registry.fill(HIST("h_jet_phi"), jet.phi(), collision.mcCollision().weight()); + } } - PROCESS_SWITCH(JetTutorialTask, processMCParticleLevel, "jets on particle level MC", false); + PROCESS_SWITCH(JetTutorialTask, processMCDetectorLevelWeightedCharged, "charged jets in weighted detector level MC", false); - void processMCCharged(JetCollision const&, soa::Filtered const& mcdjets, soa::Filtered const& mcpjets) + void processMCParticleLevelCharged(soa::Filtered::iterator const& mcCollision, soa::Filtered const& jets) { + for (auto& jet : jets) { + registry.fill(HIST("h_part_jet_pt"), jet.pt(), mcCollision.weight()); + registry.fill(HIST("h_part_jet_eta"), jet.eta(), mcCollision.weight()); + registry.fill(HIST("h_part_jet_phi"), jet.phi(), mcCollision.weight()); + } + } + PROCESS_SWITCH(JetTutorialTask, processMCParticleLevelCharged, "charged jets in particle level MC", false); + + void processMCCharged(soa::Filtered::iterator const& collision, JetMcCollisions const&, soa::Filtered const& mcdjets, soa::Filtered const& mcpjets) + { + if (!jetderiveddatautilities::selectCollision(collision, eventSelection)) { + return; + } for (auto& mcdjet : mcdjets) { - registry.fill(HIST("h_jet_pt"), mcdjet.pt()); - registry.fill(HIST("h_jet_eta"), mcdjet.eta()); - registry.fill(HIST("h_jet_phi"), mcdjet.phi()); + registry.fill(HIST("h_jet_pt"), mcdjet.pt(), collision.mcCollision().weight()); + registry.fill(HIST("h_jet_eta"), mcdjet.eta(), collision.mcCollision().weight()); + registry.fill(HIST("h_jet_phi"), mcdjet.phi(), collision.mcCollision().weight()); } - for (auto& mcpjet : mcpjets) { - registry.fill(HIST("h_part_jet_pt"), mcpjet.pt()); - registry.fill(HIST("h_part_jet_eta"), mcpjet.eta()); - registry.fill(HIST("h_part_jet_phi"), mcpjet.phi()); + auto mcpjetsPerCollision = mcpjets.sliceBy(perMcCollisionJets, collision.mcCollisionId()); + for (auto& mcpjet : mcpjetsPerCollision) { + registry.fill(HIST("h_part_jet_pt"), mcpjet.pt(), collision.mcCollision().weight()); + registry.fill(HIST("h_part_jet_eta"), mcpjet.eta(), collision.mcCollision().weight()); + registry.fill(HIST("h_part_jet_phi"), mcpjet.phi(), collision.mcCollision().weight()); } } - PROCESS_SWITCH(JetTutorialTask, processMCCharged, "jets on detector and particle level MC", false); + PROCESS_SWITCH(JetTutorialTask, processMCCharged, "charged jets in detector and particle level MC", false); using JetMCPTable = soa::Filtered>; - void processMCChargedMatched(JetCollision const&, + void processMCMatchedCharged(soa::Filtered::iterator const& collision, soa::Filtered> const& mcdjets, JetMCPTable const&, JetTracks const&, JetParticles const&) { + if (!jetderiveddatautilities::selectCollision(collision, eventSelection)) { + return; + } for (const auto& mcdjet : mcdjets) { - for (auto& mcpjet : mcdjet.template matchedJetGeo_as()) { - // for (auto& mcpjet : mcdjet.template matchedJetPt_as()) { - - registry.fill(HIST("h_matched_jets_pt"), mcpjet.pt(), mcdjet.pt()); - registry.fill(HIST("h_matched_jets_pt"), mcpjet.phi(), mcdjet.phi()); - registry.fill(HIST("h_matched_jets_pt"), mcpjet.eta(), mcdjet.eta()); + registry.fill(HIST("h_matched_jets_pt"), mcpjet.pt(), mcdjet.pt(), collision.mcCollision().weight()); + registry.fill(HIST("h_matched_jets_pt"), mcpjet.phi(), mcdjet.phi(), collision.mcCollision().weight()); + registry.fill(HIST("h_matched_jets_pt"), mcpjet.eta(), mcdjet.eta(), collision.mcCollision().weight()); } } } - PROCESS_SWITCH(JetTutorialTask, processMCChargedMatched, "jet finder QA matched mcp and mcd", false); + PROCESS_SWITCH(JetTutorialTask, processMCMatchedCharged, "matched detector and particle level charged jets", false); - void processDataChargedSubstructure(soa::Filtered>::iterator const& jet, JetTracks const&) + void processDataSubstructureCharged(soa::Filtered::iterator const& collision, soa::Filtered> const& jets, JetTracks const&) { - // add aditional selection on jet eta - registry.fill(HIST("h_jet_pt"), jet.pt()); - registry.fill(HIST("h_jet_eta"), jet.eta()); - registry.fill(HIST("h_jet_phi"), jet.phi()); - registry.fill(HIST("h_jet_ntracks"), jet.tracksIds().size()); - double angularity = 0.0; - for (auto& jetConstituent : jet.tracks_as()) { - angularity += jetConstituent.pt() * TMath::Sqrt(TMath::Power(jet.phi() - jetConstituent.phi(), 2.0) + TMath::Power(jet.eta() - jetConstituent.eta(), 2.0)); - } - registry.fill(HIST("h_jet_angularity"), angularity / (jet.pt() * round(jet.r() / 100.0f))); + if (!jetderiveddatautilities::selectCollision(collision, eventSelection)) { + return; + } + for (auto& jet : jets) { + registry.fill(HIST("h_jet_pt"), jet.pt()); + registry.fill(HIST("h_jet_eta"), jet.eta()); + registry.fill(HIST("h_jet_phi"), jet.phi()); + registry.fill(HIST("h_jet_ntracks"), jet.tracksIds().size()); + double angularity = 0.0; + for (auto& jetConstituent : jet.tracks_as()) { + angularity += std::pow(jetConstituent.pt(), kappa) * std::pow(jetutilities::deltaR(jet, jetConstituent), alpha); + } + angularity /= (jet.pt() * (jet.r() / 100.f)); + registry.fill(HIST("h_jet_angularity"), angularity); + } } - PROCESS_SWITCH(JetTutorialTask, processDataChargedSubstructure, "jet substructure charged jets", false); + PROCESS_SWITCH(JetTutorialTask, processDataSubstructureCharged, "charged jet substructure", false); - void processMCParticleSubstructure(soa::Filtered>::iterator const& jet, JetParticles const&) + void processDataFull(soa::Filtered::iterator const&, soa::Filtered const& jets) { - double angularity = 0.0; - for (auto& jetConstituents : jet.tracks_as()) { - angularity += jetConstituents.pt() * TMath::Sqrt(TMath::Power(jet.phi() - jetConstituents.phi(), 2.0) + TMath::Power(jet.eta() - jetConstituents.eta(), 2.0)); + for (auto& jet : jets) { + registry.fill(HIST("h_jet_pt"), jet.pt()); + registry.fill(HIST("h_jet_eta"), jet.eta()); + registry.fill(HIST("h_jet_phi"), jet.phi()); } - registry.fill(HIST("h_part_jet_angularity"), angularity / (jet.pt() * round(jet.r() / 100.0f))); } - PROCESS_SWITCH(JetTutorialTask, processMCParticleSubstructure, "jet substructure particle level full jets", false); + PROCESS_SWITCH(JetTutorialTask, processDataFull, "full jets in data", false); - void processDataFull(soa::Filtered::iterator const& jet) + void processDataSubstructureFull(soa::Filtered::iterator const&, soa::Filtered> const& jets, JetTracks const&, JetClusters const&) { - registry.fill(HIST("h_jet_pt"), jet.pt()); - registry.fill(HIST("h_jet_eta"), jet.eta()); - registry.fill(HIST("h_jet_phi"), jet.phi()); - } - PROCESS_SWITCH(JetTutorialTask, processDataFull, "jets data", true); + for (auto& jet : jets) { + registry.fill(HIST("h_full_jet_pt"), jet.pt()); + registry.fill(HIST("h_full_jet_eta"), jet.eta()); + registry.fill(HIST("h_full_jet_phi"), jet.phi()); + registry.fill(HIST("h_full_jet_ntracks"), jet.tracksIds().size()); + registry.fill(HIST("h_full_jet_nclusters"), jet.clustersIds().size()); + double angularity = 0.0; + for (auto& jetConstituent : jet.tracks_as()) { + angularity += std::pow(jetConstituent.pt(), kappa) * std::pow(jetutilities::deltaR(jet, jetConstituent), alpha); + } - void processDataFullSubstructure(soa::Filtered>::iterator const& jet, JetTracks const&, JetClusters const&) - { - // add aditional selection on jet eta - registry.fill(HIST("h_full_jet_pt"), jet.pt()); - registry.fill(HIST("h_full_jet_eta"), jet.eta()); - registry.fill(HIST("h_full_jet_phi"), jet.phi()); - registry.fill(HIST("h_full_jet_ntracks"), jet.tracksIds().size()); - registry.fill(HIST("h_full_jet_nclusters"), jet.clustersIds().size()); - double angularity = 0.0; - for (auto& jetTrack : jet.tracks_as()) { - angularity += jetTrack.pt() * TMath::Sqrt(TMath::Power(jet.phi() - jetTrack.phi(), 2.0) + TMath::Power(jet.eta() - jetTrack.eta(), 2.0)); - } + for (auto& jetCluster : jet.tracks_as()) { + angularity += std::pow(jetCluster.energy(), kappa) * std::pow(jetutilities::deltaR(jet, jetCluster), alpha); + } - for (auto& jetCluster : jet.clusters_as()) { - angularity += jetCluster.energy() * TMath::Sqrt(TMath::Power(jet.phi() - jetCluster.phi(), 2.0) + TMath::Power(jet.eta() - jetCluster.eta(), 2.0)); + registry.fill(HIST("h_full_jet_angularity"), angularity / (jet.pt() * round(jet.r() * 100.0f))); } + } + PROCESS_SWITCH(JetTutorialTask, processDataSubstructureFull, "full jet substructure", false); - registry.fill(HIST("h_full_jet_angularity"), angularity / (jet.pt() * round(jet.r() * 100.0f))); + void processMCParticleLevelSubstructureFull(soa::Filtered::iterator const& mcCollision, soa::Filtered> const& jets, JetParticles const&) + { + for (auto& jet : jets) { + double angularity = 0.0; + for (auto& jetConstituent : jet.tracks_as()) { + angularity += std::pow(jetConstituent.pt(), kappa) * std::pow(jetutilities::deltaR(jet, jetConstituent), alpha); + } + angularity /= (jet.pt() * (jet.r() / 100.f)); + registry.fill(HIST("h_part_jet_angularity"), angularity, mcCollision.weight()); + } } - PROCESS_SWITCH(JetTutorialTask, processDataFullSubstructure, "jet substructure full jets", false); + PROCESS_SWITCH(JetTutorialTask, processMCParticleLevelSubstructureFull, "full particle level jet substructure", false); - void processDataRecoil(JetCollision const& collision, soa::Filtered const& jets, JetTracks const& tracks) + void processRecoilDataCharged(soa::Filtered::iterator const& collision, soa::Filtered const& jets, JetTracks const& tracks) { if (!jetderiveddatautilities::selectCollision(collision, eventSelection)) { return; } + bool selectedEvent = false; double leadingTrackpT = 0.0; double leadingTrackPhi = 0.0; for (auto& track : tracks) { @@ -248,11 +305,13 @@ struct JetTutorialTask { if (track.pt() > leadingTrackpT) { leadingTrackpT = track.pt(); leadingTrackPhi = track.phi(); + selectedEvent = true; } } } - if (leadingTrackpT == 0.0) + if (!selectedEvent) { return; + } for (auto& jet : jets) { if (TMath::Abs(RecoDecay::constrainAngle(RecoDecay::constrainAngle(jet.phi(), -o2::constants::math::PIHalf) - RecoDecay::constrainAngle(leadingTrackPhi, -o2::constants::math::PIHalf), -o2::constants::math::PIHalf) > 0.6)) { registry.fill(HIST("h_recoil_jet_pt"), jet.pt()); @@ -262,18 +321,67 @@ struct JetTutorialTask { } } } - PROCESS_SWITCH(JetTutorialTask, processDataRecoil, "hadron-recoil jets", false); + PROCESS_SWITCH(JetTutorialTask, processRecoilDataCharged, "hadron-recoil charged jets", false); + + void processDataRhoAreaSubtractedCharged(soa::Filtered>::iterator const& collision, soa::Filtered const& jets) + { + if (!jetderiveddatautilities::selectCollision(collision, eventSelection)) { + return; + } + for (auto jet : jets) { + registry.fill(HIST("h_jet_pt"), jet.pt()); + registry.fill(HIST("h_jet_pt_rhosub"), jet.pt() - (collision.rho() * jet.area())); + registry.fill(HIST("h_jet_eta"), jet.eta()); + registry.fill(HIST("h_jet_phi"), jet.phi()); + } + } + PROCESS_SWITCH(JetTutorialTask, processDataRhoAreaSubtractedCharged, "charged rho-area subtracted jets", false); + + void processDataConstituentSubtractedCharged(soa::Filtered::iterator const& collision, soa::Filtered const& jets) + { + if (!jetderiveddatautilities::selectCollision(collision, eventSelection)) { + return; + } + for (auto jet : jets) { + registry.fill(HIST("h_jet_pt_constsub"), jet.pt()); + registry.fill(HIST("h_jet_eta"), jet.eta()); + registry.fill(HIST("h_jet_phi"), jet.phi()); + } + } + PROCESS_SWITCH(JetTutorialTask, processDataConstituentSubtractedCharged, "charged constituent subtracted jets", false); - /*void processDataBackgroundSubtracted(soa::Join::iterator const& collision, soa::Filtered const& jets) + void processDataConstituentSubtractedSubstructureCharged(soa::Filtered::iterator const& collision, soa::Filtered> const& jets, JetTracksSub const&) { + if (!jetderiveddatautilities::selectCollision(collision, eventSelection)) { + return; + } for (auto jet : jets) { + registry.fill(HIST("h_jet_pt_constsub"), jet.pt()); + registry.fill(HIST("h_jet_eta"), jet.eta()); + registry.fill(HIST("h_jet_phi"), jet.phi()); + registry.fill(HIST("h_jet_ntracks"), jet.tracksIds().size()); + double angularity = 0.0; + for (auto& jetConstituent : jet.tracks_as()) { + angularity += std::pow(jetConstituent.pt(), kappa) * std::pow(jetutilities::deltaR(jet, jetConstituent), alpha); + } + angularity /= (jet.pt() * (jet.r() / 100.f)); + registry.fill(HIST("h_jet_angularity_constsub"), angularity); + } + } + PROCESS_SWITCH(JetTutorialTask, processDataConstituentSubtractedSubstructureCharged, "charged constituent subtracted jet substructure", false); + + void processDataTriggered(soa::Filtered::iterator const& collision, soa::Filtered const& jets) + { + if (!jetderiveddatautilities::selectCollision(collision, eventSelection) || !jetderiveddatautilities::selectTrigger(collision, triggerMaskBits)) { + return; + } + for (auto& jet : jets) { registry.fill(HIST("h_jet_pt"), jet.pt()); - registry.fill(HIST("h_jet_pt_bkgsub"), jet.pt() - (collision.rho() * jet.area())); registry.fill(HIST("h_jet_eta"), jet.eta()); registry.fill(HIST("h_jet_phi"), jet.phi()); } } - PROCESS_SWITCH(JetTutorialTask, processDataBackgroundSubtracted, "baackground subtracted jets", false);*/ + PROCESS_SWITCH(JetTutorialTask, processDataTriggered, "jets triggered", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { return WorkflowSpec{adaptAnalysisTask(cfgc, TaskName{"jet-tutorial"})}; } diff --git a/PWGJE/Tasks/jetTutorialSkeleton.cxx b/PWGJE/Tasks/jetTutorialSkeleton.cxx index ba5310ef535..ba329c54a2d 100644 --- a/PWGJE/Tasks/jetTutorialSkeleton.cxx +++ b/PWGJE/Tasks/jetTutorialSkeleton.cxx @@ -9,7 +9,7 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -// jet tutorial skeleton task for hands on tutorial session (09/11/2023) +// jet tutorial task for hands on tutorial session (16/11/2024) // /// \author Nima Zardoshti // @@ -26,6 +26,7 @@ #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" @@ -45,12 +46,14 @@ struct JetTutorialSkeletonTask { {"h_jet_pt", "jet pT;#it{p}_{T,jet} (GeV/#it{c});entries", {HistType::kTH1F, {{200, 0., 200.}}}}, {"h_jet_eta", "jet #eta;#eta_{jet};entries", {HistType::kTH1F, {{100, -1.0, 1.0}}}}, {"h_jet_phi", "jet #phi;#phi_{jet};entries", {HistType::kTH1F, {{80, -1.0, 7.}}}}, - {"h_jet_pt_bkgsub", "jet pT bkg sub;#it{p}_{T,jet} (GeV/#it{c});entries", {HistType::kTH1F, {{200, 0., 200.}}}}, + {"h_jet_pt_rhosub", "jet pT bkg sub;#it{p}_{T,jet} (GeV/#it{c});entries", {HistType::kTH1F, {{200, 0., 200.}}}}, + {"h_jet_pt_constsub", "jet pT bkg sub;#it{p}_{T,jet} (GeV/#it{c});entries", {HistType::kTH1F, {{200, 0., 200.}}}}, {"h_part_jet_pt", "particle level jet pT;#it{p}_{T,jet part} (GeV/#it{c});entries", {HistType::kTH1F, {{200, 0., 200.}}}}, {"h_part_jet_eta", "particle level jet #eta;#eta_{jet part};entries", {HistType::kTH1F, {{100, -1.0, 1.0}}}}, {"h_part_jet_phi", "particle level jet #phi;#phi_{jet part};entries", {HistType::kTH1F, {{80, -1.0, 7.}}}}, {"h_jet_ntracks", "jet N tracks;N_{jet tracks};entries", {HistType::kTH1F, {{40, -0.5, 39.5}}}}, {"h_jet_angularity", "jet angularity ;#lambda_{1};entries", {HistType::kTH1F, {{5, 0.0, 0.5}}}}, + {"h_jet_angularity_constsub", "jet angularity bkg sub;#lambda_{1};entries", {HistType::kTH1F, {{5, 0.0, 0.5}}}}, {"h_full_jet_pt", "jet pT;#it{p}_{T,jet} (GeV/#it{c});entries", {HistType::kTH1F, {{200, 0., 200.}}}}, {"h_full_jet_eta", "jet #eta;#eta_{jet};entries", {HistType::kTH1F, {{100, -1.0, 1.0}}}}, {"h_full_jet_phi", "jet #phi;#phi_{jet};entries", {HistType::kTH1F, {{80, -1.0, 7.}}}}, @@ -66,92 +69,153 @@ struct JetTutorialSkeletonTask { {"h_matched_jets_eta", "#eta_{jet part}; #eta_{jet det}", {HistType::kTH2F, {{100, -1.0, 1.0}, {100, -1.0, 1.0}}}}, {"h_matched_jets_phi", "#phi_{jet part}; #phi_{jet det}", {HistType::kTH2F, {{80, -1.0, 7.}, {80, -1.0, 7.}}}}}}; + Configurable vertexZCut{"vertexZCut", 10.0f, "Accepted z-vertex range"}; + Configurable jetPtMin{"jetPtMin", 5.0, "minimum jet pT cut"}; Configurable jetR{"jetR", 0.4, "jet resolution parameter"}; Configurable eventSelections{"eventSelections", "sel8", "choose event selection"}; Configurable trackSelections{"trackSelections", "globalTracks", "set track selections"}; + Configurable kappa{"kappa", 1.0, "angularity kappa"}; + Configurable alpha{"alpha", 1.0, "angularity alpha"}; + + 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"}; + int eventSelection = -1; int trackSelection = -1; + std::vector triggerMaskBits; void init(o2::framework::InitContext&) { eventSelection = jetderiveddatautilities::initialiseEventSelection(static_cast(eventSelections)); trackSelection = jetderiveddatautilities::initialiseTrackSelection(static_cast(trackSelections)); + triggerMaskBits = jetderiveddatautilities::initialiseTriggerMaskBits(triggerMasks); } Filter jetCuts = aod::jet::pt > jetPtMin&& aod::jet::r == nround(jetR.node() * 100.0f); + Filter collisionFilter = nabs(aod::jcollision::posZ) < vertexZCut; + Filter mcCollisionFilter = nabs(aod::jmccollision::posZ) < vertexZCut; - void processCollisions(aod::JCollision const&, aod::JTracks const&) - { - } - PROCESS_SWITCH(JetTutorialSkeletonTask, processCollisions, "process self contained collisions", true); + Preslice> perMcCollisionJets = aod::jet::mcCollisionId; - void processCollisionsWithExternalTracks(aod::JCollision const&, soa::Join const&, soa::Join const&) + void processDummy(aod::JDummys const&) { } - PROCESS_SWITCH(JetTutorialSkeletonTask, processCollisionsWithExternalTracks, "process non self contained collisions", true); + PROCESS_SWITCH(JetTutorialSkeletonTask, processDummy, "dummy process", false); - void processDataCharged(soa::Filtered::iterator const&) - { - } - PROCESS_SWITCH(JetTutorialSkeletonTask, processDataCharged, "jets data", true); + /* + void processCollisions(JetCollision const& collision, JetTracks const& tracks) + { - void processMCDetectorLevelCharged(soa::Filtered::iterator const&) - { - } - PROCESS_SWITCH(JetTutorialSkeletonTask, processMCDetectorLevelCharged, "jets on detector level MC", false); + } + PROCESS_SWITCH(JetTutorialSkeletonTask, processCollisions, "process JE collisions", false); - void processMCParticleLevel(soa::Filtered::iterator const&) - { - } - PROCESS_SWITCH(JetTutorialSkeletonTask, processMCParticleLevel, "jets on particle level MC", false); + void processCollisionsWithExternalTracks(soa::Filtered::iterator const& collision, soa::Join const& tracks, soa::Join const&) + { - void processMCCharged(aod::JCollisions const&, soa::Filtered const&, soa::Filtered const&) - { - } - PROCESS_SWITCH(JetTutorialSkeletonTask, processMCCharged, "jets on detector and particle level MC", false); - - using JetMCPTable = soa::Filtered>; - void processMCChargedMatched(aod::JCollision const&, - soa::Filtered> const&, - JetMCPTable const&, - aod::JTracks const&, - aod::JMcParticles const&) - { - } - PROCESS_SWITCH(JetTutorialSkeletonTask, processMCChargedMatched, "jet finder QA matched mcp and mcd", false); + } + PROCESS_SWITCH(JetTutorialSkeletonTask, processCollisionsWithExternalTracks, "process JE collisions with access to the original track table", false); - void processDataChargedSubstructure(soa::Filtered>::iterator const&, aod::JTracks const&) - { - } - PROCESS_SWITCH(JetTutorialSkeletonTask, processDataChargedSubstructure, "jet substructure charged jets", false); + void processDataCharged(soa::Filtered::iterator const& collision, soa::Filtered const& jets) + { - void processMCParticleSubstructure(soa::Filtered>::iterator const&, aod::JMcParticles const&) - { - } - PROCESS_SWITCH(JetTutorialSkeletonTask, processMCParticleSubstructure, "jet substructure particle level full jets", false); + } + PROCESS_SWITCH(JetTutorialSkeletonTask, processDataCharged, "charged jets in data", false); - void processDataFull(soa::Filtered::iterator const&) - { - } - PROCESS_SWITCH(JetTutorialSkeletonTask, processDataFull, "jets data", true); + void processMCDetectorLevelCharged(soa::Filtered::iterator const& collision, soa::Filtered const& jets) + { - void processDataFullSubstructure(soa::Filtered>::iterator const&, aod::JTracks const&, aod::JClusters const&) - { - } - PROCESS_SWITCH(JetTutorialSkeletonTask, processDataFullSubstructure, "jet substructure full jets", false); + } + PROCESS_SWITCH(JetTutorialSkeletonTask, processMCDetectorLevelCharged, "charged jets in detector level MC", false); - void processDataRecoil(aod::JCollision const&, soa::Filtered const&, aod::JTracks const&) - { - } - PROCESS_SWITCH(JetTutorialSkeletonTask, processDataRecoil, "hadron-recoil jets", false); + void processMCDetectorLevelWeightedCharged(soa::Filtered::iterator const& collision, JetMcCollisions const& ,soa::Filtered const& jets) + { - /*void processDataBackgroundSubtracted(soa::Join::iterator const& collision, soa::Filtered const& jets) - { - } - PROCESS_SWITCH(JetTutorialSkeletonTask, processDataBackgroundSubtracted, "baackground subtracted jets", false);*/ + } + PROCESS_SWITCH(JetTutorialSkeletonTask, processMCDetectorLevelWeightedCharged, "charged jets in weighted detector level MC", false); + + void processMCParticleLevelCharged(soa::Filtered::iterator const& mcCollision, soa::Filtered const& jets) + { + + } + PROCESS_SWITCH(JetTutorialSkeletonTask, processMCParticleLevelCharged, "charged jets in particle level MC", false); + + void processMCCharged(soa::Filtered::iterator const& collision, JetMcCollisions const& , soa::Filtered const& mcdjets, soa::Filtered const& mcpjets) + { + + } + PROCESS_SWITCH(JetTutorialSkeletonTask, processMCCharged, "charged jets in detector and particle level MC", false); + + + using JetMCPTable = soa::Filtered>; + void processMCMatchedCharged(soa::Filtered::iterator const& collision, + soa::Filtered> const& mcdjets, + JetMCPTable const&, + JetTracks const&, + JetParticles const&) + { + + } + PROCESS_SWITCH(JetTutorialSkeletonTask, processMCMatchedCharged, "matched detector and particle level charged jets", false); + + void processDataSubstructureCharged(soa::Filtered::iterator const& collision, soa::Filtered>const& jets, JetTracks const&) + { + + } + PROCESS_SWITCH(JetTutorialSkeletonTask, processDataSubstructureCharged, "charged jet substructure", false); + + void processDataFull(soa::Filtered::iterator const& , soa::Filtered const& jets) + { + + } + PROCESS_SWITCH(JetTutorialSkeletonTask, processDataFull, "full jets in data", false); + + void processDataSubstructureFull(soa::Filtered::iterator const& , soa::Filtered> const& jets, JetTracks const&, JetClusters const&) + { + + } + PROCESS_SWITCH(JetTutorialSkeletonTask, processDataSubstructureFull, "full jet substructure", false); + + + void processMCParticleLevelSubstructureFull(soa::Filtered::iterator const& mcCollision, soa::Filtered> const& jets, JetParticles const&) + { + + } + PROCESS_SWITCH(JetTutorialSkeletonTask, processMCParticleLevelSubstructureFull, "full particle level jet substructure", false); + + + void processRecoilDataCharged(soa::Filtered::iterator const& collision, soa::Filtered const& jets, JetTracks const& tracks) + { + + } + PROCESS_SWITCH(JetTutorialSkeletonTask, processRecoilDataCharged, "hadron-recoil charged jets", false); + + void processDataRhoAreaSubtractedCharged(soa::Filtered>::iterator const& collision, soa::Filtered const& jets) + { + + } + PROCESS_SWITCH(JetTutorialSkeletonTask, processDataRhoAreaSubtractedCharged, "charged rho-area subtracted jets", false); + + void processDataConstituentSubtractedCharged(soa::Filtered::iterator const& collision, soa::Filtered const& jets) + { + + } + PROCESS_SWITCH(JetTutorialSkeletonTask, processDataConstituentSubtractedCharged, "charged constituent subtracted jets", false); + + + void processDataConstituentSubtractedSubstructureCharged(soa::Filtered::iterator const& collision, soa::Filtered>const& jets, JetTracksSub const&) + { + + } + PROCESS_SWITCH(JetTutorialSkeletonTask, processDataConstituentSubtractedSubstructureCharged, "charged constituent subtracted jet substructure", false); + + void processDataTriggered(soa::Filtered::iterator const& collision, soa::Filtered const& jets) + { + + } + PROCESS_SWITCH(JetTutorialSkeletonTask, processDataTriggered, "jets triggered", false); + */ }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { return WorkflowSpec{adaptAnalysisTask(cfgc, TaskName{"jet-tutorial-skeleton"})}; } diff --git a/PWGJE/Tasks/jettaggerhfQA.cxx b/PWGJE/Tasks/jettaggerhfQA.cxx index 56ab3075ece..fde73a8a0b4 100644 --- a/PWGJE/Tasks/jettaggerhfQA.cxx +++ b/PWGJE/Tasks/jettaggerhfQA.cxx @@ -283,6 +283,16 @@ struct JetTaggerHFQA { registry.add("h3_jet_pt_JP_N3_flavour", "jet pt jet probability flavour N3", {HistType::kTH3F, {{jetPtAxis}, {JetProbabilityAxis}, {jetFlavourAxis}}}); registry.add("h3_jet_pt_neg_log_JP_N3_flavour", "jet pt log jet probability flavour N3", {HistType::kTH3F, {{jetPtAxis}, {JetProbabilityLogAxis}, {jetFlavourAxis}}}); } + if (doprocessJPMCPMCDMatched || doprocessJPMCPMCDMatchedWeighted) { + registry.add("h3_jet_pt_JP_flavour_run2", "jet pt jet probability flavour untagged", {HistType::kTH3F, {{jetPtAxis}, {JetProbabilityAxis}, {jetFlavourAxis}}}); + registry.add("h3_jet_pt_neg_log_JP_flavour_run2", "jet pt log jet probability flavour untagged", {HistType::kTH3F, {{jetPtAxis}, {JetProbabilityLogAxis}, {jetFlavourAxis}}}); + registry.add("h3_jet_pt_JP_N1_flavour_run2", "jet pt jet probability flavour N1", {HistType::kTH3F, {{jetPtAxis}, {JetProbabilityAxis}, {jetFlavourAxis}}}); + registry.add("h3_jet_pt_neg_log_JP_N1_flavour_run2", "jet pt log jet probability flavour N1", {HistType::kTH3F, {{jetPtAxis}, {JetProbabilityLogAxis}, {jetFlavourAxis}}}); + registry.add("h3_jet_pt_JP_N2_flavour_run2", "jet pt jet probability flavour N2", {HistType::kTH3F, {{jetPtAxis}, {JetProbabilityAxis}, {jetFlavourAxis}}}); + registry.add("h3_jet_pt_neg_log_JP_N2_flavour_run2", "jet pt log jet probability flavour N2", {HistType::kTH3F, {{jetPtAxis}, {JetProbabilityLogAxis}, {jetFlavourAxis}}}); + registry.add("h3_jet_pt_JP_N3_flavour_run2", "jet pt jet probability flavour N3", {HistType::kTH3F, {{jetPtAxis}, {JetProbabilityAxis}, {jetFlavourAxis}}}); + registry.add("h3_jet_pt_neg_log_JP_N3_flavour_run2", "jet pt log jet probability flavour N3", {HistType::kTH3F, {{jetPtAxis}, {JetProbabilityLogAxis}, {jetFlavourAxis}}}); + } if (doprocessSV2ProngData) { registry.add("h_2prong_nprongs", "", {HistType::kTH1F, {{nprongsAxis}}}); registry.add("h2_jet_pt_2prong_Lxy", "", {HistType::kTH2F, {{jetPtAxis}, {LxyAxis}}}); @@ -702,7 +712,7 @@ struct JetTaggerHFQA { std::vector vecImpXY[numberOfJetFlavourSpecies], vecSignImpXY[numberOfJetFlavourSpecies], vecImpXYSig[numberOfJetFlavourSpecies], vecSignImpXYSig[numberOfJetFlavourSpecies]; int jetflavour = mcdjet.origin(); if (jetflavour == JetTaggingSpecies::none) - jetflavour = JetTaggingSpecies::lightflavour; + jetflavour = JetTaggingSpecies::lightflavour; // TODO int jetflavourRun2Def = -1; // if (!mcdjet.has_matchedJetGeo()) continue; for (auto& mcpjet : mcdjet.template matchedJetGeo_as()) { @@ -798,6 +808,32 @@ struct JetTaggerHFQA { registry.fill(HIST("h3_jet_pt_neg_log_JP_N3_flavour"), mcdjet.pt(), -1 * TMath::Log(mcdjet.jetProb()[3]), mcdjet.origin(), eventWeight); } + template + void fillHistogramJPMatched(T const& mcdjet, U const&, V const& particlesPerColl, float eventWeight = 1.0) + { + float pTHat = 10. / (std::pow(eventWeight, 1.0 / pTHatExponent)); + if (mcdjet.pt() > pTHatMaxMCD * pTHat) { + return; + } + int jetflavour = mcdjet.origin(); + if (jetflavour == JetTaggingSpecies::none) + jetflavour = JetTaggingSpecies::lightflavour; // TODO + int jetflavourRun2Def = -1; + for (auto& mcpjet : mcdjet.template matchedJetGeo_as()) { + jetflavourRun2Def = jettaggingutilities::getJetFlavor(mcpjet, particlesPerColl); + } + if (jetflavourRun2Def < 0) + return; + registry.fill(HIST("h3_jet_pt_JP_flavour_run2"), mcdjet.pt(), mcdjet.jetProb()[0], jetflavourRun2Def, eventWeight); + registry.fill(HIST("h3_jet_pt_neg_log_JP_flavour_run2"), mcdjet.pt(), -1 * TMath::Log(mcdjet.jetProb()[0]), jetflavourRun2Def, eventWeight); + registry.fill(HIST("h3_jet_pt_JP_N1_flavour_run2"), mcdjet.pt(), mcdjet.jetProb()[1], jetflavourRun2Def, eventWeight); + registry.fill(HIST("h3_jet_pt_neg_log_JP_N1_flavour_run2"), mcdjet.pt(), -1 * TMath::Log(mcdjet.jetProb()[1]), jetflavourRun2Def, eventWeight); + registry.fill(HIST("h3_jet_pt_JP_N2_flavour_run2"), mcdjet.pt(), mcdjet.jetProb()[2], jetflavourRun2Def, eventWeight); + registry.fill(HIST("h3_jet_pt_neg_log_JP_N2_flavour_run2"), mcdjet.pt(), -1 * TMath::Log(mcdjet.jetProb()[2]), jetflavourRun2Def, eventWeight); + registry.fill(HIST("h3_jet_pt_JP_N3_flavour_run2"), mcdjet.pt(), mcdjet.jetProb()[3], jetflavourRun2Def, eventWeight); + registry.fill(HIST("h3_jet_pt_neg_log_JP_N3_flavour_run2"), mcdjet.pt(), -1 * TMath::Log(mcdjet.jetProb()[3]), jetflavourRun2Def, eventWeight); + } + template void fillHistogramSV2ProngData(T const& jet, U const& /*prongs*/) { @@ -820,7 +856,7 @@ struct JetTaggerHFQA { registry.fill(HIST("h2_jet_pt_2prong_sigmaLxyz"), jet.pt(), prong.errorDecayLength()); } auto bjetCand = jettaggingutilities::jetFromProngMaxDecayLength(jet, prongChi2PCAMin, prongChi2PCAMax, prongsigmaLxyMax, prongIPxyMin, prongIPxyMax); - if (!jettaggingutilities::prongAcceptance(bjetCand, prongChi2PCAMin, prongChi2PCAMax, prongsigmaLxyMax, prongIPxyMin, prongIPxyMax, prongDispersionMax, false)) { + if (!jettaggingutilities::svAcceptance(bjetCand, prongDispersionMax)) { return; } auto maxSxy = bjetCand.decayLengthXY() / bjetCand.errorDecayLengthXY(); @@ -858,7 +894,7 @@ struct JetTaggerHFQA { registry.fill(HIST("h2_jet_pt_3prong_sigmaLxyz"), jet.pt(), prong.errorDecayLength()); } auto bjetCand = jettaggingutilities::jetFromProngMaxDecayLength(jet, prongChi2PCAMin, prongChi2PCAMax, prongsigmaLxyMax, prongIPxyMin, prongIPxyMax); - if (!jettaggingutilities::prongAcceptance(bjetCand, prongChi2PCAMin, prongChi2PCAMax, prongsigmaLxyMax, prongIPxyMin, prongIPxyMax, prongDispersionMax, false)) { + if (!jettaggingutilities::svAcceptance(bjetCand, prongDispersionMax)) { return; } auto maxSxy = bjetCand.decayLengthXY() / bjetCand.errorDecayLengthXY(); @@ -898,7 +934,7 @@ struct JetTaggerHFQA { registry.fill(HIST("h3_jet_pt_2prong_sigmaLxyz_flavour"), mcdjet.pt(), prong.errorDecayLength(), origin, eventWeight); } auto bjetCand = jettaggingutilities::jetFromProngMaxDecayLength(mcdjet, prongChi2PCAMin, prongChi2PCAMax, prongsigmaLxyMax, prongIPxyMin, prongIPxyMax); - if (!jettaggingutilities::prongAcceptance(bjetCand, prongChi2PCAMin, prongChi2PCAMax, prongsigmaLxyMax, prongIPxyMin, prongIPxyMax, prongDispersionMax, false)) { + if (!jettaggingutilities::svAcceptance(bjetCand, prongDispersionMax)) { return; } auto maxSxy = bjetCand.decayLengthXY() / bjetCand.errorDecayLengthXY(); @@ -943,7 +979,7 @@ struct JetTaggerHFQA { registry.fill(HIST("h3_jet_pt_2prong_sigmaLxyz_flavour_run2"), mcdjet.pt(), prong.errorDecayLength(), jetflavourRun2Def, eventWeight); } auto bjetCand = jettaggingutilities::jetFromProngMaxDecayLength(mcdjet, prongChi2PCAMin, prongChi2PCAMax, prongsigmaLxyMax, prongIPxyMin, prongIPxyMax); - if (!jettaggingutilities::prongAcceptance(bjetCand, prongChi2PCAMin, prongChi2PCAMax, prongsigmaLxyMax, prongIPxyMin, prongIPxyMax, prongDispersionMax, false)) { + if (!jettaggingutilities::svAcceptance(bjetCand, prongDispersionMax)) { return; } auto maxSxy = bjetCand.decayLengthXY() / bjetCand.errorDecayLengthXY(); @@ -980,7 +1016,7 @@ struct JetTaggerHFQA { registry.fill(HIST("h3_jet_pt_3prong_sigmaLxyz_flavour"), mcdjet.pt(), prong.errorDecayLength(), origin, eventWeight); } auto bjetCand = jettaggingutilities::jetFromProngMaxDecayLength(mcdjet, prongChi2PCAMin, prongChi2PCAMax, prongsigmaLxyMax, prongIPxyMin, prongIPxyMax); - if (!jettaggingutilities::prongAcceptance(bjetCand, prongChi2PCAMin, prongChi2PCAMax, prongsigmaLxyMax, prongIPxyMin, prongIPxyMax, prongDispersionMax, false)) { + if (!jettaggingutilities::svAcceptance(bjetCand, prongDispersionMax)) { return; } auto maxSxy = bjetCand.decayLengthXY() / bjetCand.errorDecayLengthXY(); @@ -1025,10 +1061,9 @@ struct JetTaggerHFQA { registry.fill(HIST("h3_jet_pt_3prong_sigmaLxyz_flavour_run2"), mcdjet.pt(), prong.errorDecayLength(), jetflavourRun2Def, eventWeight); } auto bjetCand = jettaggingutilities::jetFromProngMaxDecayLength(mcdjet, prongChi2PCAMin, prongChi2PCAMax, prongsigmaLxyMax, prongIPxyMin, prongIPxyMax); - if (!jettaggingutilities::prongAcceptance(bjetCand, prongChi2PCAMin, prongChi2PCAMax, prongsigmaLxyMax, prongIPxyMin, prongIPxyMax, prongDispersionMax, false)) { + if (!jettaggingutilities::svAcceptance(bjetCand, prongDispersionMax)) { return; } - auto maxSxy = bjetCand.decayLengthXY() / bjetCand.errorDecayLengthXY(); auto massSV = bjetCand.m(); auto bjetCandForXYZ = jettaggingutilities::jetFromProngMaxDecayLength(mcdjet, prongChi2PCAMin, prongChi2PCAMax, prongsigmaLxyzMax, prongIPxyMin, prongIPxyMax, true); @@ -1054,7 +1089,6 @@ struct JetTaggerHFQA { if (!jetderiveddatautilities::selectTrack(jtrack, trackSelection)) { continue; } - float varImpXY, varImpXYSig, varImpZ, varImpZSig, varImpXYZ, varImpXYZSig; varImpXY = jtrack.dcaXY() * jettaggingutilities::cmTomum; varImpXYSig = jtrack.dcaXY() / jtrack.sigmadcaXY(); @@ -1252,6 +1286,42 @@ struct JetTaggerHFQA { } PROCESS_SWITCH(JetTaggerHFQA, processJPMCDWeighted, "Fill jet probability imformation for mcd jets", false); + void processJPMCPMCDMatched(soa::Filtered>::iterator const& collision, soa::Join const& mcdjets, soa::Join const& mcpjets, JetTagTracksMCD const&, JetParticles& particles) + { + if (collision.trackOccupancyInTimeRange() < trackOccupancyInTimeRangeMin || trackOccupancyInTimeRangeMax < collision.trackOccupancyInTimeRange()) { + return; + } + for (auto mcdjet : mcdjets) { + auto const particlesPerColl = particles.sliceBy(particlesPerCollision, collision.mcCollisionId()); + if (!jetfindingutilities::isInEtaAcceptance(mcdjet, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax)) { + continue; + } + if (!isAcceptedJet(mcdjet)) { + continue; + } + fillHistogramJPMatched(mcdjet, mcpjets, particlesPerColl); + } + } + PROCESS_SWITCH(JetTaggerHFQA, processJPMCPMCDMatched, "Fill jet probability imformation for mcd jets", false); + + void processJPMCPMCDMatchedWeighted(soa::Filtered>::iterator const& collision, soa::Join const& mcdjets, soa::Join const& mcpjets, JetTagTracksMCD const&, JetParticles& particles) + { + if (collision.trackOccupancyInTimeRange() < trackOccupancyInTimeRangeMin || trackOccupancyInTimeRangeMax < collision.trackOccupancyInTimeRange()) { + return; + } + for (auto mcdjet : mcdjets) { + auto const particlesPerColl = particles.sliceBy(particlesPerCollision, collision.mcCollisionId()); + if (!jetfindingutilities::isInEtaAcceptance(mcdjet, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax)) { + continue; + } + if (!isAcceptedJet(mcdjet)) { + continue; + } + fillHistogramJPMatched(mcdjet, mcpjets, particlesPerColl, mcdjet.eventWeight()); + } + } + PROCESS_SWITCH(JetTaggerHFQA, processJPMCPMCDMatchedWeighted, "Fill jet probability imformation for mcd jets", false); + void processSV2ProngData(soa::Filtered::iterator const& collision, soa::Join const& jets, aod::DataSecondaryVertex2Prongs const& prongs) { if (collision.trackOccupancyInTimeRange() < trackOccupancyInTimeRangeMin || trackOccupancyInTimeRangeMax < collision.trackOccupancyInTimeRange()) { diff --git a/PWGJE/Tasks/statPromptPhoton.cxx b/PWGJE/Tasks/statPromptPhoton.cxx index 1228d2498b5..2ff07bcb11f 100644 --- a/PWGJE/Tasks/statPromptPhoton.cxx +++ b/PWGJE/Tasks/statPromptPhoton.cxx @@ -83,13 +83,32 @@ struct statPromptPhoton { // INIT void init(InitContext const&) { - std::vector ptBinning = {0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0, 2.5, 3.0, 4.0, 5.0, 6.0, 8.0, 12.0}; + 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]"}; histos.add("REC_nEvents", "REC_nEvents", kTH1F, {{4, 0.0, 4.0}}); + histos.add("REC_Cluster_QA", "REC_Cluster_QA", kTH1F, {{10, -0.5, 9.5}}); histos.add("REC_PtHadSum_Photon", "REC_PtHadSum_Photon", kTH1F, {pthadAxis}); - + histos.add("REC_TrackPhi_photontrigger", "REC_TrackPhi_photontrigger", kTH1F, {{64, 0, 2 * TMath::Pi()}}); + histos.add("REC_TrackEta_photontrigger", "REC_TrackEta_photontrigger", kTH1F, {{100, -1, 1}}); + histos.add("REC_True_v_Cluster_Phi", "REC_True_v_Cluster_Phi", kTH1F, {{628, -2 * TMath::Pi(), 2 * TMath::Pi()}}); + histos.add("REC_True_v_Cluster_Eta", "REC_True_v_Cluster_Eta", kTH1F, {{628, -2 * TMath::Pi(), 2 * TMath::Pi()}}); + histos.add("REC_Track_v_Cluster_Phi", "REC_Track_v_Cluster_Phi", kTH1F, {{628, -2 * TMath::Pi(), 2 * TMath::Pi()}}); + histos.add("REC_Track_v_Cluster_Eta", "REC_Track_v_Cluster_Eta", kTH1F, {{628, -2 * TMath::Pi(), 2 * TMath::Pi()}}); + histos.add("REC_Track_v_Cluster_Phi_AC", "REC_Track_v_Cluster_Phi_AC", kTH1F, {{628, -2 * TMath::Pi(), 2 * TMath::Pi()}}); + histos.add("REC_Track_v_Cluster_Eta_AC", "REC_Track_v_Cluster_Eta_AC", kTH1F, {{628, -2 * TMath::Pi(), 2 * TMath::Pi()}}); + histos.add("REC_SumPt_BC", "REC_SumPt_BC", kTH1F, {{628, -2 * TMath::Pi(), 2 * TMath::Pi()}}); + histos.add("REC_SumPt_AC", "REC_SumPt_AC", kTH1F, {{628, -2 * TMath::Pi(), 2 * TMath::Pi()}}); + histos.add("REC_M02_BC", "REC_M02_BC", kTH1F, {{628, -2 * TMath::Pi(), 2 * TMath::Pi()}}); + histos.add("REC_M02_AC", "REC_M02_AC", kTH1F, {{628, -2 * TMath::Pi(), 2 * TMath::Pi()}}); + + histos.add("REC_Trigger_Purity", "REC_Trigger_Purity", kTH1F, {{4, 0.0, 4.0}}); histos.add("REC_Trigger_Energy", "REC_Trigger_Energy", kTH1F, {{82, -1.0, 40.0}}); + + histos.add("REC_Trigger_Energy_GOOD", "REC_Trigger_Energy_GOOD", kTH1F, {{82, -1.0, 40.0}}); + histos.add("REC_Trigger_Energy_MISS", "REC_Trigger_Energy_MISS", kTH1F, {{82, -1.0, 40.0}}); + histos.add("REC_Trigger_Energy_FAKE", "REC_Trigger_Energy_FAKE", kTH1F, {{82, -1.0, 40.0}}); + histos.add("REC_All_Energy", "REC_All_Energy", kTH1F, {{82, -1.0, 40.0}}); histos.add("REC_True_Trigger_Energy", "REC_True_Trigger_Energy", kTH1F, {{82, -1.0, 40.0}}); histos.add("REC_True_Prompt_Trigger_Energy", "REC_True_Prompt_Trigger_Energy", kTH1F, {{82, -1.0, 40.0}}); @@ -272,114 +291,12 @@ struct statPromptPhoton { ///////////////////////////////////////////////////////////////////////////// // PROCESS - - // int nEvents = 0; - int nEventsRecMC = 0; - int nEventsGenMC = 0; - // aod::StoredMcParticles_001 const& - void processMCRec(filteredCollisions::iterator const& collision, filteredMCClusters const& mcclusters, aod::McParticles const&, o2::aod::EMCALClusterCells const& /*emccluscells*/, o2::aod::EMCALMatchedTracks const& matchedtracks, TrackCandidates const& tracks) - { - - nEventsRecMC++; - if ((nEventsRecMC + 1) % 10000 == 0) { - std::cout << "Processed Rec MC Events: " << nEventsRecMC << std::endl; - } - histos.fill(HIST("REC_nEvents"), 0.5); - - if (fabs(collision.posZ()) > cfgVtxCut) - return; - if (!collision.sel8()) - return; - - histos.fill(HIST("REC_nEvents"), 1.5); - - if (!collision.alias_bit(kTVXinEMC)) - return; - - histos.fill(HIST("REC_nEvents"), 2.5); - - // now we do clusters - - for (auto& mccluster : mcclusters) { - histos.fill(HIST("REC_All_Energy"), mccluster.energy()); - bool photontrigger = false; - double photonPt = 0.0; - double truephotonPt = 0.0; - auto tracksofcluster = matchedtracks.sliceBy(perClusterMatchedTracks, mccluster.globalIndex()); - - // first, we do the data-level analysis - if (tracksofcluster.size() < 1) { - if (mccluster.energy() > cfgMinTrig && mccluster.energy() < cfgMaxTrig) { - if (fabs(mccluster.eta()) <= cfgtrkMaxEta) { - photontrigger = true; - photonPt = mccluster.energy(); - } - } - } - - if (photontrigger) { - double pthadsum = GetPtHadSum(tracks, mccluster, cfgMinR, cfgMaxR, false, false, true); - histos.fill(HIST("REC_Trigger_V_PtHadSum_Photon"), photonPt, pthadsum); - histos.fill(HIST("REC_PtHadSum_Photon"), pthadsum); - histos.fill(HIST("REC_Trigger_Energy"), mccluster.energy()); - - // now we check the realness of our prompt photons - auto ClusterParticles = mccluster.mcParticle_as(); - for (auto& clusterparticle : ClusterParticles) { - if (clusterparticle.pdgCode() == 22) { - histos.fill(HIST("REC_True_Trigger_Energy"), clusterparticle.e()); - if (std::abs(clusterparticle.getGenStatusCode()) > 19 && std::abs(clusterparticle.getGenStatusCode()) < 70) { - histos.fill(HIST("REC_True_Prompt_Trigger_Energy"), clusterparticle.e()); - TLorentzVector lRealPhoton; - lRealPhoton.SetPxPyPzE(clusterparticle.px(), clusterparticle.py(), clusterparticle.pz(), clusterparticle.e()); - double truepthadsum = GetPtHadSum(tracks, lRealPhoton, cfgMinR, cfgMaxR, false, false, false); - truephotonPt = clusterparticle.e(); - histos.fill(HIST("REC_TrueTrigger_V_PtHadSum_Photon"), truephotonPt, truepthadsum); - } - } // photon check - } // photon trigger loop - } // clusterparticle loop - - } // cluster loop - - // clusters done, now we do the sternheimer tracks - - for (auto& track : tracks) { - bool sterntrigger = false; - double sternPt = 0.0; - if (!trackSelection(track)) { - continue; - } - if (track.pt() > cfgMinTrig && track.pt() < cfgMaxTrig) { - if (fabs(track.eta()) <= cfgtrkMaxEta) { - sterntrigger = true; - sternPt = track.pt(); - } - } - - if (sterntrigger) { - bool doStern = true; - double sterncount = 1.0; - while (doStern) { - double pthadsum = GetPtHadSum(tracks, track, cfgMinR, cfgMaxR, true, false, true); - histos.fill(HIST("REC_Trigger_V_PtHadSum_Stern"), sterncount, pthadsum, 2.0 / sternPt); - if (sterncount < sternPt) { - sterncount++; - } else { - doStern = false; - } - } // While sternin' - } // stern trigger loop - } // track loop - - } // end of process - - PROCESS_SWITCH(statPromptPhoton, processMCRec, "process MC data", true); ///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// + int nEventsGenMC = 0; - void processMCGen(filteredMCCollisions::iterator const& collision, soa::SmallGroups> const& recocolls, aod::McParticles const& mcParticles, filteredMCClusters const& mcclusters) + void processMCGen(filteredMCCollisions::iterator const& collision, soa::SmallGroups> const& recocolls, aod::McParticles const& mcParticles, filteredMCClusters const&) { nEventsGenMC++; if ((nEventsGenMC + 1) % 10000 == 0) { @@ -483,12 +400,12 @@ struct statPromptPhoton { using jTrackCandidates = soa::Join; using jMCClusters = o2::soa::Join; - using jselectedCollisions = soa::Join; + using jselectedCollisions = soa::Join; using jfilteredCollisions = soa::Filtered; using jfilteredMCClusters = soa::Filtered; int nEventsRecMC_JE = 0; - void processMCRec_JE(jfilteredCollisions::iterator const& collision, jfilteredMCClusters const& mcclusters, jTrackCandidates const& tracks, aod::JMcParticles const&, TrackCandidates const&, aod::JTracks const&) + void processMCRec_JE(jfilteredCollisions::iterator const& collision, jfilteredMCClusters const& mcclusters, jTrackCandidates const& tracks, soa::Join const& caltracks, aod::JMcParticles const&, TrackCandidates const&) { nEventsRecMC_JE++; @@ -503,47 +420,171 @@ struct statPromptPhoton { if (!collision.sel8()) return; - bool clustertrigger = false; + histos.fill(HIST("REC_nEvents"), 1.5); + + if (!collision.isEmcalReadout()) + return; + + histos.fill(HIST("REC_nEvents"), 2.5); + // now we do clusters + bool clustertrigger = false; for (auto& mccluster : mcclusters) { - clustertrigger = true; + histos.fill(HIST("REC_M02_BC"), mccluster.energy()); + if (mccluster.m02() < 0.1) + continue; + histos.fill(HIST("REC_Cluster_QA"), 0.5); + histos.fill(HIST("REC_M02_AC"), mccluster.energy()); histos.fill(HIST("REC_All_Energy"), mccluster.energy()); - bool photontrigger = false; + bool photontrigger = false; // is a neutral cluster + bool nonvetotrigger = false; // probably is not a neutral cluster + bool vetotrigger = false; // might be a neutral cluster + bool chargetrigger = false; // is definitely not a neutral cluster double photonPt = 0.0; double truephotonPt = 0.0; - // auto tracksofcluster = mccluster.matchedTracks(); - auto tracksofcluster = mccluster.matchedTracks_as(); - // first, we do the data-level analysis - if (tracksofcluster.size() < 1) { - if (mccluster.energy() > cfgMinTrig && mccluster.energy() < cfgMaxTrig) { - if (fabs(mccluster.eta()) <= cfgtrkMaxEta) { - photontrigger = true; - photonPt = mccluster.energy(); - } + auto tracksofcluster = mccluster.matchedTracks_as>(); + + // first, we check if veto is required + double sumptT = 0; + double sumptTAC = 0; + for (auto& ctrack : tracksofcluster) { + auto ogtrack = ctrack.track_as(); + if (!trackSelection(ogtrack)) { + continue; + } + if (!ogtrack.isGlobalTrack()) { + continue; } + + double ptT = ctrack.pt(); + sumptT += ptT; + double phidiff = TVector2::Phi_mpi_pi(mccluster.phi() - ctrack.phi()); + double etadiff = mccluster.eta() - ctrack.eta(); + histos.fill(HIST("REC_Track_v_Cluster_Phi"), phidiff); + histos.fill(HIST("REC_Track_v_Cluster_Eta"), etadiff); + } + + if (sumptT > 0) { + double mccluster_over_sumptT = mccluster.energy() / sumptT; + histos.fill(HIST("REC_SumPt_BC"), mccluster_over_sumptT); + if (mccluster_over_sumptT < 1.7) { + histos.fill(HIST("REC_Cluster_QA"), 2.5); + vetotrigger = true; + } else { + nonvetotrigger = true; + photontrigger = true; + histos.fill(HIST("REC_Cluster_QA"), 1.5); + } + } else { + photontrigger = true; } - if (photontrigger) { + + // veto is required + if (vetotrigger) { + for (auto& ctrack : tracksofcluster) { + auto ogtrack = ctrack.track_as(); + if (!trackSelection(ogtrack)) { + continue; + } + if (!ogtrack.isGlobalTrack()) { + continue; + } + + double etaT = ctrack.eta(); + double etaC = mccluster.eta(); + double phiT = ctrack.phi(); + double phiC = mccluster.phi(); + double ptT = ctrack.pt(); + + if (fabs(etaT - etaC) < (0.010 + pow(ptT + 4.07, -2.5))) { + chargetrigger = true; + } + if (fabs(TVector2::Phi_mpi_pi(phiT - phiC)) < (0.015 + pow(ptT + 3.65, -2.0))) { + chargetrigger = true; + } + if (chargetrigger) { + histos.fill(HIST("REC_Cluster_QA"), 3.5); + break; + } + } // tracks + } // veto + + // check if cluster is good + if (!chargetrigger) { + for (auto& ctrack : tracksofcluster) { + auto ogtrack = ctrack.track_as(); + if (!trackSelection(ogtrack)) { + continue; + } + if (!ogtrack.isGlobalTrack()) { + continue; + } + + double ptT = ctrack.pt(); + sumptTAC += ptT; + double phidiff = TVector2::Phi_mpi_pi(mccluster.phi() - ctrack.phi()); + double etadiff = mccluster.eta() - ctrack.eta(); + histos.fill(HIST("REC_Track_v_Cluster_Phi_AC"), phidiff); + histos.fill(HIST("REC_Track_v_Cluster_Eta_AC"), etadiff); + } // tracks + + if (sumptTAC > 0) { + double mccluster_over_sumptTAC = mccluster.energy() / sumptTAC; + histos.fill(HIST("REC_SumPt_AC"), mccluster_over_sumptTAC); + } + + photontrigger = true; + } // check if there is no charge trigger + + if (photontrigger) { // if no charge trigger, cluster is good! + 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"), photonPt, pthadsum); histos.fill(HIST("REC_PtHadSum_Photon"), pthadsum); histos.fill(HIST("REC_Trigger_Energy"), mccluster.energy()); + } - // now we check the realness of our prompt photons - auto ClusterParticles = mccluster.mcParticle_as(); - for (auto& clusterparticle : ClusterParticles) { - if (clusterparticle.pdgCode() == 22) { - histos.fill(HIST("REC_True_Trigger_Energy"), clusterparticle.e()); - if (std::abs(clusterparticle.getGenStatusCode()) > 19 && std::abs(clusterparticle.getGenStatusCode()) < 70) { - histos.fill(HIST("REC_True_Prompt_Trigger_Energy"), clusterparticle.e()); - TLorentzVector lRealPhoton; - lRealPhoton.SetPxPyPzE(clusterparticle.px(), clusterparticle.py(), clusterparticle.pz(), clusterparticle.e()); - double truepthadsum = GetPtHadSum(tracks, lRealPhoton, cfgMinR, cfgMaxR, false, false, false); - truephotonPt = clusterparticle.e(); - histos.fill(HIST("REC_TrueTrigger_V_PtHadSum_Photon"), truephotonPt, truepthadsum); - } - } // photon check - } // photon trigger loop + // now we check the realness of our prompt photons + auto ClusterParticles = mccluster.mcParticle_as(); + bool goodgentrigger = true; + for (auto& clusterparticle : ClusterParticles) { + if (clusterparticle.pdgCode() == 211 || clusterparticle.pdgCode() == 321 || clusterparticle.pdgCode() == 2212) { + goodgentrigger = false; + } + + double phidiff = TVector2::Phi_mpi_pi(mccluster.phi() - clusterparticle.phi()); + double etadiff = mccluster.eta() - clusterparticle.eta(); + histos.fill(HIST("REC_True_v_Cluster_Phi"), phidiff); + histos.fill(HIST("REC_True_v_Cluster_Eta"), etadiff); + + if (!photontrigger) { + continue; + } + if (clusterparticle.pdgCode() == 22) { + histos.fill(HIST("REC_True_Trigger_Energy"), clusterparticle.e()); + if (std::abs(clusterparticle.getGenStatusCode()) > 19 && std::abs(clusterparticle.getGenStatusCode()) < 70) { + histos.fill(HIST("REC_True_Prompt_Trigger_Energy"), clusterparticle.e()); + TLorentzVector lRealPhoton; + lRealPhoton.SetPxPyPzE(clusterparticle.px(), clusterparticle.py(), clusterparticle.pz(), clusterparticle.e()); + double truepthadsum = GetPtHadSum(tracks, lRealPhoton, cfgMinR, cfgMaxR, false, false, false); + truephotonPt = clusterparticle.e(); + histos.fill(HIST("REC_TrueTrigger_V_PtHadSum_Photon"), truephotonPt, truepthadsum); + } + } // photon check } // clusterparticle loop + if (goodgentrigger && photontrigger) { + histos.fill(HIST("REC_Trigger_Purity"), 0.5); + histos.fill(HIST("REC_Trigger_Energy_GOOD"), mccluster.energy()); + } + if (goodgentrigger && !photontrigger) { + histos.fill(HIST("REC_Trigger_Purity"), 1.5); + histos.fill(HIST("REC_Trigger_Energy_MISS"), mccluster.energy()); + } + if (!goodgentrigger && photontrigger) { + histos.fill(HIST("REC_Trigger_Purity"), 2.5); + histos.fill(HIST("REC_Trigger_Energy_FAKE"), mccluster.energy()); + } } // cluster loop // clusters done, now we do the sternheimer tracks @@ -554,6 +595,10 @@ struct statPromptPhoton { if (!trackSelection(ogtrack)) { continue; } + if (clustertrigger) { + histos.fill(HIST("REC_TrackPhi_photontrigger"), track.phi()); + histos.fill(HIST("REC_TrackEta_photontrigger"), track.eta()); + } if (track.pt() > cfgMinTrig && track.pt() < cfgMaxTrig) { if (fabs(track.eta()) <= cfgtrkMaxEta) { sterntrigger = true; @@ -576,8 +621,6 @@ struct statPromptPhoton { } // stern trigger loop } // track loop - histos.fill(HIST("REC_nEvents"), 1.5); - } // end of process PROCESS_SWITCH(statPromptPhoton, processMCRec_JE, "processJE MC data", false); diff --git a/PWGLF/DataModel/LFStrangenessTables.h b/PWGLF/DataModel/LFStrangenessTables.h index 9bdbe5d29f5..cdb3047a4a0 100644 --- a/PWGLF/DataModel/LFStrangenessTables.h +++ b/PWGLF/DataModel/LFStrangenessTables.h @@ -27,6 +27,15 @@ namespace o2::aod { +// for DF name follow-up and debug +namespace straorigin +{ +DECLARE_SOA_COLUMN(DataframeID, dataframeID, uint64_t); //! Data frame ID (what is usually found in directory name in the AO2D.root, i.e. +} // namespace straorigin + +DECLARE_SOA_TABLE(StraOrigins, "AOD", "STRAORIGIN", //! Table which contains the IDs of all dataframes merged into this dataframe + o2::soa::Index<>, straorigin::DataframeID); + namespace stracollision { DECLARE_SOA_DYNAMIC_COLUMN(IsUPC, isUPC, //! check whether this is a UPC or hadronic collision diff --git a/PWGLF/TableProducer/Nuspex/ebyeMaker.cxx b/PWGLF/TableProducer/Nuspex/ebyeMaker.cxx index c98a4a423fa..e909a575a89 100644 --- a/PWGLF/TableProducer/Nuspex/ebyeMaker.cxx +++ b/PWGLF/TableProducer/Nuspex/ebyeMaker.cxx @@ -276,6 +276,8 @@ struct ebyeMaker { Configurable v0setting_nsigmatpc{"v0setting_nsigmatpc", 4.f, "nsigmatpc"}; 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"}; @@ -359,6 +361,11 @@ struct ebyeMaker { return sum / track.itsNCls(); } + float dcaSigma(float const& pt) + { + return 0.0105 + 0.0350 / std::pow(std::abs(pt), 1.1); + } + template void initCCDB(Bc const& bc) { @@ -477,9 +484,9 @@ struct ebyeMaker { mask |= kChi2TPCTight; else if (track.tpcchi2 < cfgTrackSels->get("chi2TpcMid")) mask |= kChi2TPCMid; - if (std::abs(track.dcaxypv) < cfgTrackSels->get("dcaxyTight")) + if (std::abs(track.dcaxypv) < cfgTrackSels->get("dcaxyTight") * (constDCASel ? 1. : dcaSigma(track.pt))) mask |= kDCAxyTight; - else if (std::abs(track.dcaxypv) < cfgTrackSels->get("dcaxyMid")) + else if (std::abs(track.dcaxypv) < cfgTrackSels->get("dcaxyMid") * (constDCASel ? 1. : dcaSigma(track.pt))) mask |= kDCAxyMid; if (std::abs(track.dcazpv) < cfgTrackSels->get("dcazTight")) mask |= kDCAzTight; @@ -591,7 +598,10 @@ struct ebyeMaker { if (dca > cfgDcaSels->get("dca")) { // dca continue; } - if (std::abs(dcaInfo[0]) > cfgDcaSels->get("dcaxy") || std::abs(dcaInfo[1]) > cfgDcaSels->get("dcaz")) { // dcaxy and dcaz + if (std::abs(dcaInfo[1]) > cfgDcaSels->get("dcaz")) { // dcaz + continue; + } + if (std::abs(dcaInfo[0]) > cfgDcaSels->get("dcaxy") * (constDCASel ? 1. : dcaSigma(track.pt()))) { // dcaxy continue; } histos.fill(HIST("QA/tpcSignal"), track.tpcInnerParam(), track.tpcSignal()); diff --git a/PWGLF/TableProducer/Nuspex/lithium4analysis.cxx b/PWGLF/TableProducer/Nuspex/lithium4analysis.cxx index 74048772641..9d9156131c2 100644 --- a/PWGLF/TableProducer/Nuspex/lithium4analysis.cxx +++ b/PWGLF/TableProducer/Nuspex/lithium4analysis.cxx @@ -150,15 +150,17 @@ struct lithium4analysis { // Selections Configurable setting_cutVertex{"setting_cutVertex", 10.0f, "Accepted z-vertex range"}; - Configurable setting_cutPT{"setting_cutPT", 0.2, "PT cut on daughter track"}; - Configurable setting_cutMaxPrPT{"setting_cutMaxPrPT", 1.8, "Max PT cut on proton"}; - Configurable setting_cutEta{"setting_cutEta", 0.9, "Eta cut on daughter track"}; + Configurable setting_cutRigidityMinHe3{"setting_cutRigidityMinHe3", 0.8f, "Minimum rigidity for He3"}; + Configurable setting_cutEta{"setting_cutEta", 0.9f, "Eta cut on daughter track"}; Configurable setting_cutDCAxy{"setting_cutDCAxy", 2.0f, "DCAxy range for tracks"}; Configurable setting_cutDCAz{"setting_cutDCAz", 2.0f, "DCAz range for tracks"}; - Configurable setting_cutInvMass{"setting_cutInvMass", 0., "Invariant mass upper limit"}; - Configurable setting_cutPtMinLi{"setting_cutPtMinLi", 0.0, "Minimum PT cut on Li4"}; - Configurable setting_nsigmaCutTPC{"setting_nsigmaCutTPC", 3.0, "Value of the TPC Nsigma cut"}; - Configurable setting_nsigmaCutTOF{"setting_nsigmaCutTOF", 3.0, "Value of the TOF Nsigma cut"}; + Configurable setting_cutChi2tpcLow{"setting_cutChi2tpcLow", 0.5f, "Low cut on TPC chi2"}; + Configurable setting_cutInvMass{"setting_cutInvMass", 0.0f, "Invariant mass upper limit"}; + Configurable setting_cutPtMinLi{"setting_cutPtMinLi", 0.0f, "Minimum PT cut on Li4"}; + Configurable setting_cutClSizeItsHe3{"setting_cutClSizeItsHe3", 4.0f, "Minimum ITS cluster size for He3"}; + Configurable setting_cutNsigmaTPC{"setting_cutNsigmaTPC", 3.0f, "Value of the TPC Nsigma cut"}; + Configurable setting_cutPtMinTOFPr{"setting_cutPtMinTOFPr", 0.5f, "Minimum pT to apply the TOF cut on protons"}; + Configurable setting_cutNsigmaTOF{"setting_cutNsigmaTOF", 3.0f, "Value of the TOF Nsigma cut"}; Configurable setting_noMixedEvents{"setting_noMixedEvents", 5, "Number of mixed events per event"}; Configurable setting_enableBkgUS{"setting_enableBkgUS", false, "Enable US background"}; Configurable setting_isMC{"setting_isMC", false, "Run MC"}; @@ -214,6 +216,9 @@ struct lithium4analysis { Zorro m_zorro; OutputObj m_zorroSummary{"zorroSummary"}; + // check for mixed event to same event distribution compatibility + std::vector m_trackIdx2; + HistogramRegistry m_qaRegistry{ "QA", { @@ -227,10 +232,11 @@ struct lithium4analysis { {"hLitInvMass", "; M(^{3}He + p) (GeV/#it{c}^{2})", {HistType::kTH1F, {{50, 3.74f, 3.85f}}}}, {"hHe3Pt", "#it{p}_{T} distribution; #it{p}_{T} (GeV/#it{c})", {HistType::kTH1F, {{200, -6.0f, 6.0f}}}}, {"hProtonPt", "Pt distribution; #it{p}_{T} (GeV/#it{c})", {HistType::kTH1F, {{200, -3.0f, 3.0f}}}}, - {"h2dEdxHe3candidates", "dEdx distribution; Signed #it{p} (GeV/#it{c}); dE/dx (a.u.)", {HistType::kTH2F, {{200, -5.0f, 5.0f}, {100, 0.0f, 2000.0f}}}}, - {"h2NsigmaHe3TPC", "NsigmaHe3 TPC distribution; Signed #it{p}/#it{z} (GeV/#it{c}); n#sigma_{TPC}({}^{3}He)", {HistType::kTH2F, {{20, -5.0f, 5.0f}, {200, -5.0f, 5.0f}}}}, - {"h2NsigmaProtonTPC", "NsigmaProton TPC distribution; Signed #it{p}/#it{z} (GeV/#it{c}); n#sigma_{TPC}(p)", {HistType::kTH2F, {{20, -5.0f, 5.0f}, {200, -5.0f, 5.0f}}}}, - {"h2NsigmaProtonTPC_preselection", "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}}}}, + {"h2dEdxHe3candidates", "dEdx distribution; #it{p} (GeV/#it{c}); dE/dx (a.u.)", {HistType::kTH2F, {{200, -5.0f, 5.0f}, {100, 0.0f, 2000.0f}}}}, + {"h2ClSizeCosLamHe3", "; n#sigma_{TPC} ; #LT ITS Cluster Size #GT #LT cos#lambda #GT (^{3}He)", {HistType::kTH2F, {{100, -5.0f, 5.0f}, {120, 0.0f, 15.0f}}}}, + {"h2NsigmaHe3TPC", "NsigmaHe3 TPC distribution; #it{p}/z (GeV/#it{c}); n#sigma_{TPC}(^{3}He)", {HistType::kTH2F, {{20, -5.0f, 5.0f}, {200, -5.0f, 5.0f}}}}, + {"h2NsigmaProtonTPC", "NsigmaProton TPC distribution; #it{p}/z (GeV/#it{c}); n#sigma_{TPC}(p)", {HistType::kTH2F, {{20, -5.0f, 5.0f}, {200, -5.0f, 5.0f}}}}, + {"h2NsigmaProtonTPC_preselection", "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}}}}, {"h2NsigmaProtonTOF", "NsigmaProton TOF distribution; #it{p}_{T} (GeV/#it{c}); n#sigma_{TOF}(p)", {HistType::kTH2F, {{20, -5.0f, 5.0f}, {200, -5.0f, 5.0f}}}}, }, OutputObjHandlingPolicy::AnalysisObject, @@ -359,10 +365,11 @@ struct lithium4analysis { return false; } if (candidate.itsNCls() < 5 || - candidate.tpcNClsFound() < 90 || // candidate.tpcNClsFound() < 70 || + candidate.tpcNClsFound() < 90 || candidate.tpcNClsCrossedRows() < 70 || candidate.tpcNClsCrossedRows() < 0.8 * candidate.tpcNClsFindable() || candidate.tpcChi2NCl() > 4.f || + candidate.tpcChi2NCl() < setting_cutChi2tpcLow || candidate.itsChi2NCl() > 36.f) { return false; } @@ -374,13 +381,13 @@ struct lithium4analysis { bool selectionPIDProton(const Ttrack& candidate) { m_qaRegistry.fill(HIST("h2NsigmaProtonTPC_preselection"), candidate.tpcInnerParam(), candidate.tpcNSigmaPr()); - if (candidate.hasTOF()) { - if (std::abs(candidate.tofNSigmaPr()) < setting_nsigmaCutTOF && std::abs(candidate.tpcNSigmaPr()) < setting_nsigmaCutTPC) { + if (candidate.hasTOF() && candidate.pt() < setting_cutPtMinTOFPr) { + if (std::abs(candidate.tofNSigmaPr()) < setting_cutNsigmaTOF && std::abs(candidate.tpcNSigmaPr()) < setting_cutNsigmaTPC) { m_qaRegistry.fill(HIST("h2NsigmaProtonTPC"), candidate.tpcInnerParam(), candidate.tpcNSigmaPr()); m_qaRegistry.fill(HIST("h2NsigmaProtonTOF"), candidate.p(), candidate.tofNSigmaPr()); return true; } - } else if (std::abs(candidate.tpcNSigmaPr()) < setting_nsigmaCutTPC) { + } else if (std::abs(candidate.tpcNSigmaPr()) < setting_cutNsigmaTPC) { m_qaRegistry.fill(HIST("h2NsigmaProtonTPC"), candidate.tpcInnerParam(), candidate.tpcNSigmaPr()); return true; } @@ -405,12 +412,33 @@ struct lithium4analysis { float correctedTPCinnerParam = (heliumPID && setting_compensatePIDinTracking) ? candidate.tpcInnerParam() / 2.f : candidate.tpcInnerParam(); m_qaRegistry.fill(HIST("h2dEdxHe3candidates"), correctedTPCinnerParam * 2.f, candidate.tpcSignal()); + if (correctedTPCinnerParam < setting_cutRigidityMinHe3) { + return false; + } + + float cosl = 1. / std::cosh(candidate.eta()); + float meanClsizeIts = 0.f; + int nHitsIts = 0; + for (int ilayer = 0; ilayer < 7; ilayer++) { + float clsizeLayer = (candidate.itsClusterSizes() >> ilayer * 4) & 0b1111; + if (clsizeLayer > 0) { + nHitsIts++; + meanClsizeIts += clsizeLayer; + } + } + float clsizeCoslIts = meanClsizeIts / nHitsIts * cosl; + if (clsizeCoslIts < setting_cutClSizeItsHe3) { + return false; + } + auto nSigmaHe3 = computeNSigmaHe3(candidate); - if (std::abs(nSigmaHe3) < setting_nsigmaCutTPC) { - m_qaRegistry.fill(HIST("h2NsigmaHe3TPC"), candidate.sign() * correctedTPCinnerParam, nSigmaHe3); - return true; + if (std::abs(nSigmaHe3) > setting_cutNsigmaTPC) { + return false; } - return false; + + m_qaRegistry.fill(HIST("h2NsigmaHe3TPC"), candidate.sign() * correctedTPCinnerParam, nSigmaHe3); + m_qaRegistry.fill(HIST("h2ClSizeCosLamHe3"), nSigmaHe3, clsizeCoslIts); + return true; } // ================================================================================================================== @@ -540,6 +568,7 @@ struct lithium4analysis { template void pairTracksSameEvent(const Ttrack& tracks) { + for (auto track0 : tracks) { m_qaRegistry.fill(HIST("hTrackSel"), Selections::kNoCuts); @@ -583,6 +612,7 @@ struct lithium4analysis { void pairTracksEventMixing() { + for (auto& [c1, tracks1, c2, tracks2] : m_pair) { if (!c1.sel8() || !c2.sel8()) { continue; diff --git a/PWGLF/TableProducer/Nuspex/lnnRecoTask.cxx b/PWGLF/TableProducer/Nuspex/lnnRecoTask.cxx index da509a17295..e5ebc7a704a 100644 --- a/PWGLF/TableProducer/Nuspex/lnnRecoTask.cxx +++ b/PWGLF/TableProducer/Nuspex/lnnRecoTask.cxx @@ -76,6 +76,15 @@ std::shared_ptr hIsMatterGen; std::shared_ptr hIsMatterGenTwoBody; std::shared_ptr hDCAxy3H; +float alphaAP(std::array const& momB, std::array const& momC) +{ + std::array momA = {momB[0] + momC[0], momB[1] + momC[1], momB[2] + momC[2]}; + float momTot = std::sqrt(momA[0] * momA[0] + momA[1] * momA[1] + momA[2] * momA[2]); + float lQlPos = (momB[0] * momA[0] + momB[1] * momA[1] + momB[2] * momA[2]) / momTot; + float lQlNeg = (momC[0] * momA[0] + momC[1] * momA[1] + momC[2] * momA[2]) / momTot; + return (lQlPos - lQlNeg) / (lQlPos + lQlNeg); +} + } // namespace struct lnnCandidate { @@ -142,7 +151,6 @@ struct lnnRecoTask { Configurable nSigmaCutMaxTPC{"nSigmaCutMaxTPC", 5, "triton dEdx cut (n sigma)"}; Configurable nTPCClusMin3H{"nTPCClusMin3H", 80, "triton NTPC clusters cut"}; Configurable ptMinTOF{"ptMinTOF", 0.8, "minimum pt for TOF cut"}; - Configurable ptMaxTOF{"ptMaxTOF", 3.5, "minimum pt for TOF cut"}; Configurable TrTOFMass2Cut{"TrTOFMass2Cut", 5.5, "minimum Triton mass square to TOF"}; Configurable mcSignalOnly{"mcSignalOnly", true, "If true, save only signal in MC"}; @@ -339,16 +347,18 @@ struct lnnRecoTask { hdEdxTot->Fill(-negRigidity, negTrack.tpcSignal()); // ITS only tracks do not have TPC information. TPCnSigma: only lower cut to allow for triton reconstruction - bool is3H = posTrack.hasTPC() && nSigmaTPCpos > nSigmaCutMinTPC && nSigmaTPCpos < nSigmaCutMaxTPC; bool isAnti3H = negTrack.hasTPC() && nSigmaTPCneg > nSigmaCutMinTPC && nSigmaTPCneg < nSigmaCutMaxTPC; - if (!is3H && !isAnti3H) + if (!is3H && !isAnti3H) // discard if both tracks are not 3H candidates continue; - // Describing lnn as matter candidate + // if alphaAP is > 0 the candidate is 3H, if < 0 it is anti-3H + std::array momPos = std::array{posTrack.px(), posTrack.py(), posTrack.pz()}; + std::array momNeg = std::array{negTrack.px(), negTrack.py(), negTrack.pz()}; + float alpha = alphaAP(momPos, momNeg); lnnCandidate lnnCand; - lnnCand.isMatter = is3H && isAnti3H ? std::abs(nSigmaTPCpos) < std::abs(nSigmaTPCneg) : is3H; + lnnCand.isMatter = alpha > 0; auto& h3track = lnnCand.isMatter ? posTrack : negTrack; auto& h3Rigidity = lnnCand.isMatter ? posRigidity : negRigidity; @@ -372,29 +382,25 @@ struct lnnRecoTask { lnnCand.flags |= lnnCand.isMatter ? static_cast((posTrack.pidForTracking() & 0xF) << 4) : static_cast((negTrack.pidForTracking() & 0xF) << 4); lnnCand.flags |= lnnCand.isMatter ? static_cast(negTrack.pidForTracking() & 0xF) : static_cast(posTrack.pidForTracking() & 0xF); - auto h3TrackCov = getTrackParCov(posTrack); + auto posTrackCov = getTrackParCov(posTrack); auto negTrackCov = getTrackParCov(negTrack); - int chargeFactor = -1 + 2 * lnnCand.isMatter; - hdEdx3HSel->Fill(chargeFactor * lnnCand.mom3HTPC, h3track.tpcSignal()); - hNsigma3HSel->Fill(chargeFactor * lnnCand.mom3HTPC, lnnCand.nSigma3H); - hDCAxy3H->Fill(h3track.pt(), h3track.dcaXY()); - if (is3H) { - hdEdx3HPosTrack->Fill(lnnCand.mom3HTPC, h3track.tpcSignal()); - } - if (h3track.hasTOF()) { - float beta = h3track.beta(); + + float beta = -1.f; + if (h3track.pt() >= ptMinTOF) { + if (!h3track.hasTOF()) { + continue; + } + beta = h3track.beta(); lnnCand.mass2TrTOF = h3track.mass() * h3track.mass(); - if (h3track.pt() >= ptMinTOF && h3track.pt() <= ptMaxTOF && lnnCand.mass2TrTOF >= TrTOFMass2Cut) { - h3HSignalPtTOF->Fill(chargeFactor * h3track.pt(), beta); - hNsigma3HSelTOF->Fill(chargeFactor * h3track.pt(), h3track.tofNSigmaTr()); - h3HMassPtTOF->Fill(chargeFactor * h3track.pt(), lnnCand.mass2TrTOF); + if (lnnCand.mass2TrTOF < TrTOFMass2Cut) { + continue; } } int nCand = 0; try { - nCand = fitter.process(h3TrackCov, negTrackCov); + nCand = fitter.process(posTrackCov, negTrackCov); } catch (...) { LOG(error) << "Exception caught in DCA fitter process call!"; continue; @@ -459,12 +465,11 @@ struct lnnRecoTask { // if survived all selections, propagate decay daughters to PV gpu::gpustd::array dcaInfo; + o2::base::Propagator::Instance()->propagateToDCABxByBz({collision.posX(), collision.posY(), collision.posZ()}, h3PropTrack, 2.f, fitter.getMatCorrType(), &dcaInfo); + lnnCand.h3DCAXY = dcaInfo[0]; - o2::base::Propagator::Instance()->propagateToDCABxByBz({collision.posX(), collision.posY(), collision.posZ()}, h3TrackCov, 2.f, fitter.getMatCorrType(), &dcaInfo); - lnnCand.isMatter ? lnnCand.h3DCAXY = dcaInfo[0] : lnnCand.piDCAXY = dcaInfo[0]; - - o2::base::Propagator::Instance()->propagateToDCABxByBz({collision.posX(), collision.posY(), collision.posZ()}, negTrackCov, 2.f, fitter.getMatCorrType(), &dcaInfo); - lnnCand.isMatter ? lnnCand.piDCAXY = dcaInfo[0] : lnnCand.h3DCAXY = dcaInfo[0]; + o2::base::Propagator::Instance()->propagateToDCABxByBz({collision.posX(), collision.posY(), collision.posZ()}, piPropTrack, 2.f, fitter.getMatCorrType(), &dcaInfo); + lnnCand.piDCAXY = dcaInfo[0]; // finally, push back the candidate lnnCand.isReco = true; @@ -472,6 +477,16 @@ struct lnnRecoTask { lnnCand.negTrackID = negTrack.globalIndex(); lnnCandidates.push_back(lnnCand); + + // Fill QA histograms + hdEdx3HSel->Fill(chargeFactor * lnnCand.mom3HTPC, h3track.tpcSignal()); + hNsigma3HSel->Fill(chargeFactor * lnnCand.mom3HTPC, lnnCand.nSigma3H); + hDCAxy3H->Fill(h3track.pt(), h3track.dcaXY()); + if (h3track.hasTOF()) { + h3HSignalPtTOF->Fill(chargeFactor * h3track.pt(), beta); + hNsigma3HSelTOF->Fill(chargeFactor * h3track.pt(), h3track.tofNSigmaTr()); + h3HMassPtTOF->Fill(chargeFactor * h3track.pt(), lnnCand.mass2TrTOF); + } } } diff --git a/PWGLF/TableProducer/Nuspex/nucleiSpectra.cxx b/PWGLF/TableProducer/Nuspex/nucleiSpectra.cxx index 97967ac4fbd..7c39c4dad38 100644 --- a/PWGLF/TableProducer/Nuspex/nucleiSpectra.cxx +++ b/PWGLF/TableProducer/Nuspex/nucleiSpectra.cxx @@ -293,6 +293,7 @@ struct nucleiSpectra { // CCDB options Configurable cfgMaterialCorrection{"cfgMaterialCorrection", static_cast(o2::base::Propagator::MatCorrType::USEMatCorrLUT), "Type of material correction"}; Configurable cfgCCDBurl{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; + Configurable cfgZorroCCDBpath{"cfgZorroCCDBpath", "/Users/m/mpuccio/EventFiltering/OTS/", "path to the zorro ccdb objects"}; int mRunNumber = 0; float mBz = 0.f; @@ -374,6 +375,7 @@ struct nucleiSpectra { void init(o2::framework::InitContext&) { zorroSummary.setObject(zorro.getZorroSummary()); + zorro.setBaseCCDBPath(cfgZorroCCDBpath.value); ccdb->setURL(cfgCCDBurl); ccdb->setCaching(true); ccdb->setLocalObjectValidityChecking(); @@ -489,6 +491,9 @@ struct nucleiSpectra { o2::pid::tof::Beta responseBeta; auto bc = collision.template bc_as(); initCCDB(bc); + if (cfgSkimmedProcessing) { + zorro.isSelected(bc.globalBC()); /// Just let Zorro do the accounting + } gRandom->SetSeed(bc.timestamp()); spectra.fill(HIST("hRecVtxZData"), collision.posZ()); @@ -704,9 +709,6 @@ struct nucleiSpectra { if (!eventSelection(collision)) { return; } - if (cfgSkimmedProcessing) { - zorro.isSelected(collision.bc_as().globalBC()); /// Just let Zorro do the accounting - } fillDataInfo(collision, tracks); for (auto& c : nuclei::candidates) { diff --git a/PWGLF/TableProducer/Strangeness/cascadeflow.cxx b/PWGLF/TableProducer/Strangeness/cascadeflow.cxx index abb981fbebe..e027c951c1d 100644 --- a/PWGLF/TableProducer/Strangeness/cascadeflow.cxx +++ b/PWGLF/TableProducer/Strangeness/cascadeflow.cxx @@ -37,8 +37,9 @@ using std::array; using DauTracks = soa::Join; using CollEventPlane = soa::Join::iterator; using CollEventPlaneCentralFW = soa::Join::iterator; +using MCCollisionsStra = soa::Join; using CascCandidates = soa::Join; -using CascMCCandidates = soa::Join; +using CascMCCandidates = soa::Join; namespace cascadev2 { @@ -127,6 +128,7 @@ struct cascadeFlow { ConfigurableAxis axisQVsNorm{"axisQVsNorm", {200, -1.f, 1.f}, "axisQVsNorm"}; // Event selection criteria + Configurable isStoreTrueCascOnly{"isStoreTrueCascOnly", 1, ""}; Configurable cutzvertex{"cutzvertex", 10.0f, "Accepted z-vertex range (cm)"}; Configurable sel8{"sel8", 1, "Apply sel8 event selection"}; Configurable isNoSameBunchPileupCut{"isNoSameBunchPileupCut", 1, "Same found-by-T0 bunch crossing rejection"}; @@ -147,6 +149,7 @@ struct cascadeFlow { Configurable nsigmatpcPi{"nsigmatpcPi", 5, "nsigmatpcPi"}; Configurable mintpccrrows{"mintpccrrows", 70, "mintpccrrows"}; Configurable etaCascMCGen{"etaCascMCGen", 0.8, "etaCascMCGen"}; + Configurable yCascMCGen{"yCascMCGen", 0.5, "yCascMCGen"}; Configurable ccdbUrl{"ccdbUrl", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; Configurable> modelPathsCCDBXi{"modelPathsCCDBXi", std::vector{"Users/c/chdemart/CascadesFlow"}, "Paths of models on CCDB"}; @@ -257,9 +260,9 @@ struct cascadeFlow { return phi; } - HistogramRegistry histos{"histos", {}, OutputObjHandlingPolicy::AnalysisObject}; - HistogramRegistry histosMCGen{"histosMCGen", {}, OutputObjHandlingPolicy::AnalysisObject}; - HistogramRegistry resolution{"resolution", {}, OutputObjHandlingPolicy::AnalysisObject}; + HistogramRegistry histos{"histos", {}, OutputObjHandlingPolicy::AnalysisObject, false, true}; + HistogramRegistry histosMCGen{"histosMCGen", {}, OutputObjHandlingPolicy::AnalysisObject, false, true}; + HistogramRegistry resolution{"resolution", {}, OutputObjHandlingPolicy::AnalysisObject, false, true}; // Tables to produce Produces trainingSample; @@ -352,6 +355,7 @@ struct cascadeFlow { const AxisSpec v2Axis{200, -1., 1., "#it{v}_{2}"}; const AxisSpec CentAxis{18, 0., 90., "FT0C centrality percentile"}; TString hNEventsLabels[8] = {"All", "sel8", "z vrtx", "kNoSameBunchPileup", "kIsGoodZvtxFT0vsPV", "trackOccupancyInTimeRange", "kNoCollInTimeRange", "kIsGoodEventEP"}; + TString hNEventsLabelsMC[5] = {"All", "z vtx", ">=1RecoColl", "1Reco", "2Reco"}; resolution.add("QVectorsT0CTPCA", "QVectorsT0CTPCA", HistType::kTH2F, {axisQVs, CentAxis}); resolution.add("QVectorsT0CTPCC", "QVectorsT0CTPCC", HistType::kTH2F, {axisQVs, CentAxis}); @@ -386,9 +390,16 @@ struct cascadeFlow { histos.add("hv2CEPvsFT0C", "hv2CEPvsFT0C", HistType::kTH2F, {CentAxis, {100, -1, 1}}); histos.add("hv2CEPvsv2CSP", "hv2CEPvsV2CSP", HistType::kTH2F, {{100, -1, 1}, {100, -1, 1}}); - histosMCGen.add("h2DGenXi", "h2DGenXi", HistType::kTH2F, {{100, 0, 00}, {200, 0, 20}}); - histosMCGen.add("h2DGenOmega", "h2DGenOmega", HistType::kTH2F, {{100, 0, 100}, {200, 0, 20}}); - histosMCGen.add("hGenEta", "hGenEta", HistType::kTH1F, {{100, -1, 1}}); + histosMCGen.add("h2DGenXiEta08", "h2DGenXiEta08", HistType::kTH2F, {{100, 0, 00}, {200, 0, 20}}); + histosMCGen.add("h2DGenOmegaEta08", "h2DGenOmegaEta08", HistType::kTH2F, {{100, 0, 100}, {200, 0, 20}}); + histosMCGen.add("h2DGenXiY05", "h2DGenXiY05", HistType::kTH2F, {{100, 0, 00}, {200, 0, 20}}); + histosMCGen.add("h2DGenOmegaY05", "h2DGenOmegaY05", HistType::kTH2F, {{100, 0, 100}, {200, 0, 20}}); + histosMCGen.add("hGenXiY", "hGenXiY", HistType::kTH1F, {{100, -1, 1}}); + histosMCGen.add("hGenOmegaY", "hGenOmegaY", HistType::kTH1F, {{100, -1, 1}}); + histosMCGen.add("hNEventsMC", "hNEventsMC", {HistType::kTH1F, {{5, 0.f, 5.f}}}); + for (Int_t n = 1; n <= histosMCGen.get(HIST("hNEventsMC"))->GetNbinsX(); n++) { + histosMCGen.get(HIST("hNEventsMC"))->GetXaxis()->SetBinLabel(n, hNEventsLabelsMC[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}); @@ -773,6 +784,7 @@ struct cascadeFlow { 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 @@ -848,67 +860,91 @@ struct cascadeFlow { BDTresponse[0] = bdtScore[0][1]; BDTresponse[1] = bdtScore[1][1]; } + if (isStoreTrueCascOnly) { + if (pdgCode == 0) + continue; + } if (isSelectedCasc[0] || isSelectedCasc[1]) fillAnalysedTable(coll, casc, v2CSP, v2CEP, PsiT0C, BDTresponse[0], BDTresponse[1], pdgCode); } } - void processMCGen(soa::Join::iterator const& mcCollision, soa::Join const& collisions, soa::Join const& CascMCCores) - { - // Generated with accepted z vertex - if (TMath::Abs(mcCollision.posZ()) > cutzvertex) { - return; - } - // Check if there is at least one of the reconstructed collisions associated to this MC collision - auto groupedCollisions = collisions.sliceBy(perMcCollision, mcCollision.globalIndex()); - int biggestNContribs = -1; - int bestCollisionIndex = -1; - float centrality = 100.5f; - int nCollisions = 0; - for (auto const& collision : groupedCollisions) { + void processMCGen(MCCollisionsStra const& mcCollisions, soa::Join const& collisions, soa::Join const& CascMCCores) + { - if (!AcceptEvent(collision)) { - continue; - } - if (biggestNContribs < collision.multPVTotalContributors()) { - biggestNContribs = collision.multPVTotalContributors(); - bestCollisionIndex = collision.globalIndex(); - centrality = collision.centFT0C(); + for (auto const& mcCollision : mcCollisions) { + histosMCGen.fill(HIST("hNEventsMC"), 0.5); + // Generated with accepted z vertex + if (TMath::Abs(mcCollision.posZ()) > cutzvertex) { + return; } - nCollisions++; - } - if (nCollisions < 1) { - return; - } - for (auto const& cascMC : CascMCCores) { - if (!cascMC.has_straMCCollision()) - continue; - - if (!cascMC.isPhysicalPrimary()) - continue; - - float ptmc = RecoDecay::sqrtSumOfSquares(cascMC.pxMC(), cascMC.pyMC()); + histosMCGen.fill(HIST("hNEventsMC"), 1.5); + // Check if there is at least one of the reconstructed collisions associated to this MC collision - float theta = std::atan(ptmc / cascMC.pzMC()); //-pi/2 < theta < pi/2 + auto groupedCollisions = collisions.sliceBy(perMcCollision, mcCollision.globalIndex()); - float theta1 = 0; - - // if pz is positive (i.e. positive rapidity): 0 < theta < pi/2 - if (theta > 0) - 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 - - float cascMCeta = -log(std::tan(theta1 / 2)); - if (TMath::Abs(cascMCeta) > etaCascMCGen) - continue; - histosMCGen.fill(HIST("hGenEta"), cascMCeta); + int biggestNContribs = -1; + int bestCollisionIndex = -1; + float centrality = 100.5f; + int nCollisions = 0; + for (auto const& collision : groupedCollisions) { - if (TMath::Abs(cascMC.pdgCode()) == 3312) { - histosMCGen.fill(HIST("h2dGenXi"), centrality, ptmc); - } else if (TMath::Abs(cascMC.pdgCode() == 3334)) { - histosMCGen.fill(HIST("h2dGenOmega"), centrality, ptmc); + if (!AcceptEvent(collision)) { + continue; + } + if (biggestNContribs < collision.multPVTotalContributors()) { + biggestNContribs = collision.multPVTotalContributors(); + bestCollisionIndex = collision.globalIndex(); + centrality = collision.centFT0C(); + } + nCollisions++; + } + if (nCollisions < 1) { + return; + } + histosMCGen.fill(HIST("hNEventsMC"), 2.5); + if (nCollisions == 1) + histosMCGen.fill(HIST("hNEventsMC"), 3.5); + else if (nCollisions == 2) + histosMCGen.fill(HIST("hNEventsMC"), 4.5); + for (auto const& cascMC : CascMCCores) { + if (!cascMC.has_straMCCollision()) + continue; + + if (!cascMC.isPhysicalPrimary()) + continue; + + float ptmc = RecoDecay::sqrtSumOfSquares(cascMC.pxMC(), cascMC.pyMC()); + + float theta = std::atan(ptmc / cascMC.pzMC()); //-pi/2 < theta < pi/2 + + float theta1 = 0; + + // if pz is positive (i.e. positive rapidity): 0 < theta < pi/2 + if (theta > 0) + 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 + + float cascMCeta = -log(std::tan(theta1 / 2)); + float cascMCy = 0; + + if (TMath::Abs(cascMC.pdgCode()) == 3312) { + cascMCy = RecoDecay::y(std::array{cascMC.pxMC(), cascMC.pyMC(), cascMC.pzMC()}, constants::physics::MassXiMinus); + if (TMath::Abs(cascMCeta) < etaCascMCGen) + histosMCGen.fill(HIST("h2DGenXiEta08"), centrality, ptmc); + if (TMath::Abs(cascMCy) < yCascMCGen) + histosMCGen.fill(HIST("h2DGenXiY05"), centrality, ptmc); + histosMCGen.fill(HIST("hGenXiY"), cascMCy); + } else if (TMath::Abs(cascMC.pdgCode() == 3334)) { + cascMCy = RecoDecay::y(std::array{cascMC.pxMC(), cascMC.pyMC(), cascMC.pzMC()}, constants::physics::MassOmegaMinus); + if (TMath::Abs(cascMCeta) < etaCascMCGen) + histosMCGen.fill(HIST("h2DGenOmegaEta08"), centrality, ptmc); + if (TMath::Abs(cascMCy) < yCascMCGen) + histosMCGen.fill(HIST("h2DGenOmegaY05"), centrality, ptmc); + histosMCGen.fill(HIST("hGenOmegaY"), cascMCy); + } } } } diff --git a/PWGLF/TableProducer/Strangeness/strangederivedbuilder.cxx b/PWGLF/TableProducer/Strangeness/strangederivedbuilder.cxx index 098aca4b874..f96c54599b3 100644 --- a/PWGLF/TableProducer/Strangeness/strangederivedbuilder.cxx +++ b/PWGLF/TableProducer/Strangeness/strangederivedbuilder.cxx @@ -129,6 +129,10 @@ struct strangederivedbuilder { Produces v0FoundTags; Produces cascFoundTags; + //__________________________________________________ + // Debug + Produces straOrigin; + // histogram registry for bookkeeping HistogramRegistry histos{"Histos", {}, OutputObjHandlingPolicy::AnalysisObject}; @@ -164,15 +168,17 @@ struct strangederivedbuilder { Configurable roundNSigmaVariables{"roundNSigmaVariables", false, "round NSigma variables"}; Configurable precisionNSigmas{"precisionNSigmas", 0.1f, "precision to keep NSigmas"}; - Configurable fillRawFT0A{"fillRawFT0A", false, "Fill raw FT0A information for debug"}; - Configurable fillRawFT0C{"fillRawFT0C", true, "Fill raw FT0C information for debug"}; - Configurable fillRawFV0A{"fillRawFV0A", false, "Fill raw FV0A information for debug"}; - Configurable fillRawFDDA{"fillRawFDDA", false, "Fill raw FDDA information for debug"}; - Configurable fillRawFDDC{"fillRawFDDC", false, "Fill raw FDDC information for debug"}; - Configurable fillRawZDC{"fillRawZDC", false, "Fill raw ZDC information for debug"}; - Configurable fillRawNTracksEta1{"fillRawNTracksEta1", true, "Fill raw NTracks |eta|<1 information for debug"}; - Configurable fillRawNTracksForCorrelation{"fillRawNTracksForCorrelation", true, "Fill raw NTracks for correlation cuts"}; - Configurable fillTOFInformation{"fillTOFInformation", true, "Fill Daughter Track TOF information"}; + struct : ConfigurableGroup { + Configurable fillRawFT0A{"fillRawFT0A", false, "Fill raw FT0A information for debug"}; + Configurable fillRawFT0C{"fillRawFT0C", true, "Fill raw FT0C information for debug"}; + Configurable fillRawFV0A{"fillRawFV0A", false, "Fill raw FV0A information for debug"}; + Configurable fillRawFDDA{"fillRawFDDA", false, "Fill raw FDDA information for debug"}; + Configurable fillRawFDDC{"fillRawFDDC", false, "Fill raw FDDC information for debug"}; + Configurable fillRawZDC{"fillRawZDC", false, "Fill raw ZDC information for debug"}; + Configurable fillRawNTracksEta1{"fillRawNTracksEta1", true, "Fill raw NTracks |eta|<1 information for debug"}; + Configurable fillRawNTracksForCorrelation{"fillRawNTracksForCorrelation", true, "Fill raw NTracks for correlation cuts"}; + Configurable fillTOFInformation{"fillTOFInformation", true, "Fill Daughter Track TOF information"}; + } fillTruncationOptions; Configurable qaCentrality{"qaCentrality", false, "qa centrality flag: check base raw values"}; struct : ConfigurableGroup { @@ -347,23 +353,23 @@ struct strangederivedbuilder { strangeCents(collision.centFT0M(), collision.centFT0A(), centrality, collision.centFV0A()); strangeEvSels(collision.sel8(), collision.selection_raw(), - collision.multFT0A() * static_cast(fillRawFT0A), - collision.multFT0C() * static_cast(fillRawFT0C), - collision.multFV0A() * static_cast(fillRawFV0A), - collision.multFDDA() * static_cast(fillRawFDDA), - collision.multFDDC() * static_cast(fillRawFDDC), - collision.multNTracksPVeta1() * static_cast(fillRawNTracksEta1), - collision.multPVTotalContributors() * static_cast(fillRawNTracksForCorrelation), - collision.multNTracksGlobal() * static_cast(fillRawNTracksForCorrelation), - collision.multNTracksITSTPC() * static_cast(fillRawNTracksForCorrelation), - collision.multAllTracksTPCOnly() * static_cast(fillRawNTracksForCorrelation), - collision.multAllTracksITSTPC() * static_cast(fillRawNTracksForCorrelation), - collision.multZNA() * static_cast(fillRawZDC), - collision.multZNC() * static_cast(fillRawZDC), - collision.multZEM1() * static_cast(fillRawZDC), - collision.multZEM2() * static_cast(fillRawZDC), - collision.multZPA() * static_cast(fillRawZDC), - collision.multZPC() * static_cast(fillRawZDC), + collision.multFT0A() * static_cast(fillTruncationOptions.fillRawFT0A), + collision.multFT0C() * static_cast(fillTruncationOptions.fillRawFT0C), + collision.multFV0A() * static_cast(fillTruncationOptions.fillRawFV0A), + collision.multFDDA() * static_cast(fillTruncationOptions.fillRawFDDA), + collision.multFDDC() * static_cast(fillTruncationOptions.fillRawFDDC), + collision.multNTracksPVeta1() * static_cast(fillTruncationOptions.fillRawNTracksEta1), + collision.multPVTotalContributors() * static_cast(fillTruncationOptions.fillRawNTracksForCorrelation), + collision.multNTracksGlobal() * static_cast(fillTruncationOptions.fillRawNTracksForCorrelation), + collision.multNTracksITSTPC() * static_cast(fillTruncationOptions.fillRawNTracksForCorrelation), + collision.multAllTracksTPCOnly() * static_cast(fillTruncationOptions.fillRawNTracksForCorrelation), + collision.multAllTracksITSTPC() * static_cast(fillTruncationOptions.fillRawNTracksForCorrelation), + collision.multZNA() * static_cast(fillTruncationOptions.fillRawZDC), + collision.multZNC() * static_cast(fillTruncationOptions.fillRawZDC), + collision.multZEM1() * static_cast(fillTruncationOptions.fillRawZDC), + collision.multZEM2() * static_cast(fillTruncationOptions.fillRawZDC), + collision.multZPA() * static_cast(fillTruncationOptions.fillRawZDC), + collision.multZPC() * static_cast(fillTruncationOptions.fillRawZDC), collision.trackOccupancyInTimeRange(), // UPC info gapSide, @@ -864,6 +870,15 @@ struct strangederivedbuilder { } } + void processDataframeIDs(aod::Origins const& origins) + { + auto origin = origins.begin(); + straOrigin(origin.dataframeID()); + } + + // debug processing + PROCESS_SWITCH(strangederivedbuilder, processDataframeIDs, "Produce data frame ID tags", false); + // collision processing PROCESS_SWITCH(strangederivedbuilder, processCollisions, "Produce collisions", true); PROCESS_SWITCH(strangederivedbuilder, processCollisionsWithUD, "Produce collisions with UD info", true); diff --git a/PWGLF/Tasks/Nuspex/hadronnucleicorrelation.cxx b/PWGLF/Tasks/Nuspex/hadronnucleicorrelation.cxx index bbc28888af0..86c19dd5708 100644 --- a/PWGLF/Tasks/Nuspex/hadronnucleicorrelation.cxx +++ b/PWGLF/Tasks/Nuspex/hadronnucleicorrelation.cxx @@ -15,8 +15,8 @@ #include #include -#include -#include +#include +#include #include #include #include @@ -53,9 +53,9 @@ struct hadronnucleicorrelation { static constexpr int pdgDeuteron = 1000010020; Configurable doQA{"doQA", true, "save QA histograms"}; + Configurable doMCQA{"doMCQA", true, "save MC QA histograms"}; Configurable isMC{"isMC", false, "is MC"}; Configurable mcCorrelation{"mcCorrelation", false, "true: build the correlation function only for SE"}; - Configurable disable_pantip{"disable_pantip", false, "disable_pantip"}; Configurable docorrection{"docorrection", false, "do efficiency correction"}; Configurable fCorrectionPath{"fCorrectionPath", "", "Correction path to file"}; @@ -66,6 +66,8 @@ struct hadronnucleicorrelation { Configurable cutzvertex{"cutzvertex", 10.0, "|vertexZ| value limit"}; // Track selection + Configurable par0{"par0", 0.004, "par 0"}; + Configurable par1{"par1", 0.013, "par 1"}; Configurable min_TPC_nClusters{"min_TPC_nClusters", 80, "minimum number of found TPC clusters"}; Configurable min_TPC_nCrossedRowsOverFindableCls{"min_TPC_nCrossedRowsOverFindableCls", 0.8, "n TPC Crossed Rows Over Findable Cls"}; Configurable max_chi2_TPC{"max_chi2_TPC", 4.0f, "maximum TPC chi^2/Ncls"}; @@ -76,12 +78,9 @@ struct hadronnucleicorrelation { Configurable nsigmaTPC{"nsigmaTPC", 3.0f, "cut nsigma TPC"}; Configurable nsigmaTOF{"nsigmaTOF", 3.5f, "cut nsigma TOF"}; Configurable pTthrpr_TOF{"pTthrpr_TOF", 0.8f, "threshold pT proton to use TOF"}; - Configurable debug_ptthrp{"debug_ptthrp", 2.0f, "threshold pT proton for phi/eta debug"}; - Configurable debug_ptthrd{"debug_ptthrd", 2.0f, "threshold pT deuteron for phi/eta debug"}; + Configurable pTthrde_TOF{"pTthrde_TOF", 1.0f, "threshold pT deuteron to use TOF"}; 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 threta{"threta", 0.1, "threshold for debug DeltaEta"}; - Configurable thrphi{"thrphi", 0.5, "threshold for debug DeltaPhi"}; // Mixing parameters Configurable _vertexNbinsToMix{"vertexNbinsToMix", 10, "Number of vertexZ bins for the mixing"}; @@ -89,14 +88,12 @@ struct hadronnucleicorrelation { // pT/A bins Configurable> pTBins{"pTBins", {0.4f, 0.6f, 0.8f}, "p_{T} bins"}; - Configurable> etaBins{"etaBins", {-0.8f, 0.f, 0.8f}, "#eta bins"}; - Configurable> phiBins{"phiBins", {0.f, TMath::Pi(), 2 * TMath::Pi()}, "#phi bins"}; - ConfigurableAxis AxisNSigma{"AxisNSigma", {50, -10.f, 10.f}, "n#sigma"}; + ConfigurableAxis AxisNSigma{"AxisNSigma", {140, -7.f, 7.f}, "n#sigma"}; using FilteredCollisions = soa::Filtered; - using FilteredTracks = soa::Filtered; - using FilteredTracksMC = soa::Filtered>; + using FilteredTracks = soa::Filtered>; + using FilteredTracksMC = soa::Filtered>; HistogramRegistry registry{"registry"}; HistogramRegistry QA{"QA"}; @@ -107,13 +104,16 @@ struct hadronnucleicorrelation { // key: int64_t - value: vector of trkType objects std::map> selectedtracks_p; + std::map> selectedtracks_d; std::map> selectedtracks_antid; std::map> selectedtracks_antip; // key: int64_t - value: vector of trkType objects + std::map> selectedtracksMC_d; std::map> selectedtracksMC_p; std::map> selectedtracksMC_antid; std::map> selectedtracksMC_antip; + std::map> selectedtracksPIDMC_d; std::map> selectedtracksPIDMC_p; std::map> selectedtracksPIDMC_antid; std::map> selectedtracksPIDMC_antip; @@ -121,16 +121,10 @@ 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_pantip; std::map, std::vector> mixbinsPID_antidantip; - std::map, std::vector> mixbinsPID_pantip; - std::vector> hEtaPhi_PrAntiPr_SE; - std::vector> hEtaPhi_PrAntiPr_ME; std::vector> hEtaPhi_AntiDeAntiPr_SE; std::vector> hEtaPhi_AntiDeAntiPr_ME; - std::vector> hCorrEtaPhi_PrAntiPr_SE; - std::vector> hCorrEtaPhi_PrAntiPr_ME; std::vector> hCorrEtaPhi_AntiDeAntiPr_SE; std::vector> hCorrEtaPhi_AntiDeAntiPr_ME; @@ -138,20 +132,12 @@ struct hadronnucleicorrelation { std::vector> hEtaPhiGen_AntiDeAntiPr_SE; std::vector> hEtaPhiRec_AntiDeAntiPr_ME; std::vector> hEtaPhiGen_AntiDeAntiPr_ME; - std::vector> hEtaPhiRec_PrAntiPr_SE; - std::vector> hEtaPhiGen_PrAntiPr_SE; - std::vector> hEtaPhiRec_PrAntiPr_ME; - std::vector> hEtaPhiGen_PrAntiPr_ME; std::vector> hPIDEtaPhiRec_AntiDeAntiPr_SE; std::vector> hPIDEtaPhiGen_AntiDeAntiPr_SE; std::vector> hPIDEtaPhiRec_AntiDeAntiPr_ME; std::vector> hPIDEtaPhiGen_AntiDeAntiPr_ME; - std::vector> hPIDEtaPhiRec_PrAntiPr_SE; - std::vector> hPIDEtaPhiGen_PrAntiPr_SE; - std::vector> hPIDEtaPhiRec_PrAntiPr_ME; - std::vector> hPIDEtaPhiGen_PrAntiPr_ME; - int nBinspT, nBinseta, nBinsphi; + int nBinspT; TH2F* hEffpTEta_proton; TH2F* hEffpTEta_antiproton; TH2F* hEffpTEta_deuteron; @@ -178,115 +164,61 @@ struct hadronnucleicorrelation { } AxisSpec ptBinnedAxis = {pTBins, "#it{p}_{T} of #bar{p} (GeV/c)"}; - AxisSpec etaBinnedAxis = {etaBins, "#eta"}; - AxisSpec phiBinnedAxis = {phiBins, "#phi"}; - AxisSpec etaAxis = {100, -1.5, 1.5, "#Delta#eta"}; - AxisSpec phiAxis = {60, -TMath::Pi() / 2, 1.5 * TMath::Pi(), "#Delta#phi"}; + AxisSpec etaAxis = {100, -1., 1., "#eta"}; + AxisSpec phiAxis = {157, 0., 2 * TMath::Pi(), "#phi (rad)"}; AxisSpec pTAxis = {200, -10.f, 10.f, "p_{T} GeV/c"}; - registry.add("hNEvents", "hNEvents", {HistType::kTH1I, {{3, 0.f, 3.f}}}); + AxisSpec DeltaEtaAxis = {100, -1.5, 1.5, "#Delta#eta"}; + AxisSpec DeltaPhiAxis = {60, -TMath::Pi() / 2, 1.5 * TMath::Pi(), "#Delta#phi (rad)"}; + + registry.add("hNEvents", "hNEvents", {HistType::kTH1D, {{5, 0.f, 5.f}}}); registry.get(HIST("hNEvents"))->GetXaxis()->SetBinLabel(1, "Selected"); - registry.get(HIST("hNEvents"))->GetXaxis()->SetBinLabel(2, "#bar{d}-#bar{p}"); - registry.get(HIST("hNEvents"))->GetXaxis()->SetBinLabel(3, "p-#bar{p}"); + 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"); nBinspT = pTBins.value.size() - 1; - nBinseta = etaBins.value.size() - 1; - nBinsphi = phiBins.value.size() - 1; if (mcCorrelation) { for (int i = 0; i < nBinspT; i++) { auto htempSERec_AntiDeAntiPr = registry.add(Form("hEtaPhiRec_AntiDeAntiPr_SE_pt%02.0f%02.0f", pTBins.value.at(i) * 10, pTBins.value.at(i + 1) * 10), - Form("Rec #Delta#eta#Delta#phi (%.1f(Form("hEtaPhiGen_AntiDeAntiPr_SE_pt%02.0f%02.0f", pTBins.value.at(i) * 10, pTBins.value.at(i + 1) * 10), - Form("Gen #Delta#eta#Delta#phi (%.1f(Form("hEtaPhiRec_AntiDeAntiPr_ME_pt%02.0f%02.0f", pTBins.value.at(i) * 10, pTBins.value.at(i + 1) * 10), - Form("Rec #Delta#eta#Delta#phi (%.1f(Form("hEtaPhiGen_AntiDeAntiPr_ME_pt%02.0f%02.0f", pTBins.value.at(i) * 10, pTBins.value.at(i + 1) * 10), - Form("Gen #Delta#eta#Delta#phi (%.1f(Form("hEtaPhiRec_PrAntiPr_SE_pt%02.0f%02.0f", pTBins.value.at(i) * 10, pTBins.value.at(i + 1) * 10), - Form("Rec #Delta#eta#Delta#phi (%.1f(Form("hEtaPhiGen_PrAntiPr_SE_pt%02.0f%02.0f", pTBins.value.at(i) * 10, pTBins.value.at(i + 1) * 10), - Form("Gen #Delta#eta#Delta#phi (%.1f(Form("hEtaPhiRec_PrAntiPr_ME_pt%02.0f%02.0f", pTBins.value.at(i) * 10, pTBins.value.at(i + 1) * 10), - Form("Rec #Delta#eta#Delta#phi (%.1f(Form("hEtaPhiGen_PrAntiPr_ME_pt%02.0f%02.0f", pTBins.value.at(i) * 10, pTBins.value.at(i + 1) * 10), - Form("Gen #Delta#eta#Delta#phi (%.1f(Form("hPIDEtaPhiRec_AntiDeAntiPr_SE_pt%02.0f%02.0f", pTBins.value.at(i) * 10, pTBins.value.at(i + 1) * 10), - Form("Rec #Delta#eta#Delta#phi (%.1f(Form("hPIDEtaPhiGen_AntiDeAntiPr_SE_pt%02.0f%02.0f", pTBins.value.at(i) * 10, pTBins.value.at(i + 1) * 10), - Form("Gen #Delta#eta#Delta#phi (%.1f(Form("hPIDEtaPhiRec_AntiDeAntiPr_ME_pt%02.0f%02.0f", pTBins.value.at(i) * 10, pTBins.value.at(i + 1) * 10), - Form("Rec #Delta#eta#Delta#phi (%.1f(Form("hPIDEtaPhiGen_AntiDeAntiPr_ME_pt%02.0f%02.0f", pTBins.value.at(i) * 10, pTBins.value.at(i + 1) * 10), - Form("Gen #Delta#eta#Delta#phi (%.1f(Form("hPIDEtaPhiRec_PrAntiPr_SE_pt%02.0f%02.0f", pTBins.value.at(i) * 10, pTBins.value.at(i + 1) * 10), - Form("Rec #Delta#eta#Delta#phi (%.1f(Form("hPIDEtaPhiGen_PrAntiPr_SE_pt%02.0f%02.0f", pTBins.value.at(i) * 10, pTBins.value.at(i + 1) * 10), - Form("Gen #Delta#eta#Delta#phi (%.1f(Form("hPIDEtaPhiRec_PrAntiPr_ME_pt%02.0f%02.0f", pTBins.value.at(i) * 10, pTBins.value.at(i + 1) * 10), - Form("Rec #Delta#eta#Delta#phi (%.1f(Form("hPIDEtaPhiGen_PrAntiPr_ME_pt%02.0f%02.0f", pTBins.value.at(i) * 10, pTBins.value.at(i + 1) * 10), - Form("Gen #Delta#eta#Delta#phi (%.1f(HIST("hDebug"))->GetXaxis()->SetBinLabel(1, "all"); - registry.get(HIST("hDebug"))->GetXaxis()->SetBinLabel(2, "ev. with #bar{d}"); - registry.get(HIST("hDebug"))->GetXaxis()->SetBinLabel(3, "ev. with #bar{p}"); - registry.get(HIST("hDebug"))->GetXaxis()->SetBinLabel(4, "ev. with p"); - - registry.add("hDebugdp", "hDebugdp", {HistType::kTH1I, {{6, 0.f, 6.f}}}); - registry.get(HIST("hDebugdp"))->GetXaxis()->SetBinLabel(1, "N coll with #bar{d}"); - registry.get(HIST("hDebugdp"))->GetXaxis()->SetBinLabel(2, "N mixing bins"); - registry.get(HIST("hDebugdp"))->GetXaxis()->SetBinLabel(3, "N coll with #bar{d}"); - registry.get(HIST("hDebugdp"))->GetXaxis()->SetBinLabel(4, "#bar{d}-#bar{p} pairs SE"); - registry.get(HIST("hDebugdp"))->GetXaxis()->SetBinLabel(5, "#bar{d}-#bar{p} pairs ME"); - for (int i = 0; i < nBinspT; i++) { - if (!disable_pantip) { - auto htempSE_PrAntiPr = registry.add(Form("hEtaPhi_PrAntiPr_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_PrAntiPr_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("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("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_PrAntiPr_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_PrAntiPr_ME_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_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("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(o2::aod::singletrackselector::storedTpcChi2NCl) <= max_chi2_TPC && o2::aod::singletrackselector::unPack(o2::aod::singletrackselector::storedTpcCrossedRowsOverFindableCls) >= min_TPC_nCrossedRowsOverFindableCls && o2::aod::singletrackselector::unPack(o2::aod::singletrackselector::storedItsChi2NCl) <= max_chi2_ITS && - // nabs(o2::aod::singletrackselector::unPack(o2::aod::singletrackselector::storedDcaXY_v1)) <= max_dcaxy && // For now no filtering on the DCAxy or DCAz (casting not supported) - // nabs(o2::aod::singletrackselector::unPack(o2::aod::singletrackselector::storedDcaXY_v1)) <= max_dcaz && // For now no filtering on the DCAxy or DCAz (casting not supported) + nabs(o2::aod::singletrackselector::unPack(o2::aod::singletrackselector::storedDcaXY_v2)) <= max_dcaxy && // For now no filtering on the DCAxy or DCAz (casting not supported) + nabs(o2::aod::singletrackselector::unPack(o2::aod::singletrackselector::storedDcaXY_v2)) <= max_dcaz && // For now no filtering on the DCAxy or DCAz (casting not supported) nabs(o2::aod::singletrackselector::eta) <= etacut; + template + bool IsProton(Type const& track, int sign) + { + bool isProton = false; + + if (std::abs(track.tpcNSigmaPr()) < nsigmaTPC) { + if (track.pt() < pTthrpr_TOF && track.beta() < -100) { + if (sign > 0) { + if (track.sign() > 0) { + isProton = true; + } else if (track.sign() < 0) { + isProton = false; + } + } else if (sign < 0) { + if (track.sign() > 0) { + isProton = false; + } else if (track.sign() < 0) { + isProton = true; + } + } + } else if (std::abs(track.tofNSigmaPr()) < nsigmaTOF) { + if (sign > 0) { + if (track.sign() > 0) { + isProton = true; + } else if (track.sign() < 0) { + isProton = false; + } + } else if (sign < 0) { + if (track.sign() > 0) { + isProton = false; + } else if (track.sign() < 0) { + isProton = true; + } + } + } + } + return isProton; + } + + template + bool IsDeuteron(Type const& track, int sign) + { + bool isDeuteron = false; + + if (std::abs(track.tpcNSigmaDe()) < nsigmaTPC) { + if (track.pt() < pTthrde_TOF && track.beta() < -100) { + if (sign > 0) { + if (track.sign() > 0) { + isDeuteron = true; + } else if (track.sign() < 0) { + isDeuteron = false; + } + } else if (sign < 0) { + if (track.sign() > 0) { + isDeuteron = false; + } else if (track.sign() < 0) { + isDeuteron = true; + } + } + } else if (std::abs(track.tofNSigmaDe()) < nsigmaTOF) { + if (sign > 0) { + if (track.sign() > 0) { + isDeuteron = true; + } else if (track.sign() < 0) { + isDeuteron = false; + } + } else if (sign < 0) { + if (track.sign() > 0) { + isDeuteron = false; + } else if (track.sign() < 0) { + isDeuteron = true; + } + } + } + } + return isDeuteron; + } + + template + bool applyDCAcut(const T1& track) + { + bool passcut = true; + // pt-dependent selection + if (TMath::Abs(track.dcaXY()) > (par0 + par1 / track.pt())) + passcut = false; + if (TMath::Abs(track.dcaZ()) > (par0 + par1 / track.pt())) + passcut = false; + + return passcut; + } + template - void mixTracks(Type const& tracks1, Type const& tracks2, bool isDe, bool isMCPID) + void mixTracks(Type const& tracks1, Type const& tracks2, bool isMCPID) { // last value: 0 -- SE; 1 -- ME for (auto it1 : tracks1) { for (auto it2 : tracks2) { - // Variables + // Calculate Delta-eta Delta-phi (reco) float deltaEta = it2->eta() - it1->eta(); float deltaPhi = it2->phi() - it1->phi(); deltaPhi = getDeltaPhi(deltaPhi); + // Calculate Delta-eta Delta-phi (gen) float deltaEtaGen = -999.; float deltaPhiGen = -999.; if constexpr (doMC) { @@ -410,114 +459,48 @@ struct hadronnucleicorrelation { deltaPhiGen = getDeltaPhi(deltaPhiGen); } - float pcorr = 1, antipcorr = 1, antidcorr = 1; + float antipcorr = 1, antidcorr = 1; for (int k = 0; k < nBinspT; k++) { - if (!isDe && !disable_pantip) { - if (it1->pt() > pTBins.value.at(k) && it1->pt() <= pTBins.value.at(k + 1)) { - - if (doQA) { - QA.fill(HIST("QA/Pt_Pr"), it1->pt()); - QA.fill(HIST("QA/Pt_AntiPr"), it2->pt()); - } + if (it1->pt() >= pTBins.value.at(k) && it1->pt() < pTBins.value.at(k + 1)) { - if (docorrection) { - pcorr = hEffpTEta_proton->Interpolate(it1->pt(), it1->eta()); - antipcorr = hEffpTEta_antiproton->Interpolate(it2->pt(), it2->eta()); - } - - if (ME) { - if constexpr (!doMC) { - hEtaPhi_PrAntiPr_ME[k]->Fill(deltaEta, deltaPhi, it2->pt()); - hCorrEtaPhi_PrAntiPr_ME[k]->Fill(deltaEta, deltaPhi, it2->pt(), 1. / (pcorr * antipcorr)); - } - if constexpr (doMC) { - if (isMCPID) { - hPIDEtaPhiRec_PrAntiPr_ME[k]->Fill(deltaEta, deltaPhi, it2->pt()); - hPIDEtaPhiGen_PrAntiPr_ME[k]->Fill(deltaEtaGen, deltaPhiGen, it2->pt()); - } else { - hEtaPhiRec_PrAntiPr_ME[k]->Fill(deltaEta, deltaPhi, it2->pt()); - hEtaPhiGen_PrAntiPr_ME[k]->Fill(deltaEtaGen, deltaPhiGen, it2->pt()); - } - } - } else { - if constexpr (!doMC) { - hEtaPhi_PrAntiPr_SE[k]->Fill(deltaEta, deltaPhi, it2->pt()); - hCorrEtaPhi_PrAntiPr_SE[k]->Fill(deltaEta, deltaPhi, it2->pt(), 1. / (pcorr * antipcorr)); - - if (doQA && std::abs(deltaEta) < threta && std::abs(deltaPhi) < thrphi) { - QA.fill(HIST("QA/hnSigmaTPCVsPt_Pr_Debug"), it1->pt(), it1->tpcNSigmaPr()); - QA.fill(HIST("QA/hnSigmaTPCVsPt_Pr_Debug"), -1.f * it2->pt(), it2->tpcNSigmaPr()); - QA.fill(HIST("QA/hnSigmaTOFVsPt_Pr_Debug"), it1->pt(), it1->tofNSigmaPr()); - QA.fill(HIST("QA/hnSigmaTOFVsPt_Pr_Debug"), -1.f * it2->pt(), it2->tofNSigmaPr()); - } - } - if constexpr (doMC) { - if (isMCPID) { - hPIDEtaPhiRec_PrAntiPr_SE[k]->Fill(deltaEta, deltaPhi, it2->pt()); - hPIDEtaPhiGen_PrAntiPr_SE[k]->Fill(deltaEtaGen, deltaPhiGen, it2->pt()); - } else { - hEtaPhiRec_PrAntiPr_SE[k]->Fill(deltaEta, deltaPhi, it2->pt()); - hEtaPhiGen_PrAntiPr_SE[k]->Fill(deltaEtaGen, deltaPhiGen, it2->pt()); - } - } - } + if (docorrection) { // Apply corrections + antipcorr = hEffpTEta_antiproton->Interpolate(it2->pt(), it2->eta()); + antidcorr = hEffpTEta_antideuteron->Interpolate(it1->pt(), it1->eta()); } - } else { - if (it1->pt() > pTBins.value.at(k) && it1->pt() <= pTBins.value.at(k + 1)) { - if (doQA) { - QA.fill(HIST("QA/Pt_AntiDe"), it1->pt()); - QA.fill(HIST("QA/Pt_AntiPr"), it2->pt()); - } - - if (docorrection) { - antipcorr = hEffpTEta_antiproton->Interpolate(it2->pt(), it2->eta()); - antidcorr = hEffpTEta_antideuteron->Interpolate(it1->pt(), it1->eta()); - } - - if (ME) { - if constexpr (!doMC) { - hEtaPhi_AntiDeAntiPr_ME[k]->Fill(deltaEta, deltaPhi, it2->pt()); - hCorrEtaPhi_AntiDeAntiPr_ME[k]->Fill(deltaEta, deltaPhi, it2->pt(), 1. / (antipcorr * antidcorr)); - } - if constexpr (doMC) { - 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) { - hEtaPhi_AntiDeAntiPr_SE[k]->Fill(deltaEta, deltaPhi, it2->pt()); - hCorrEtaPhi_AntiDeAntiPr_SE[k]->Fill(deltaEta, deltaPhi, it2->pt(), 1. / (antipcorr * antidcorr)); - - if (doQA && std::abs(deltaEta) < threta && std::abs(deltaPhi) < thrphi) { - QA.fill(HIST("QA/hnSigmaTPCVsPt_De_Debug"), -1.f * it1->pt(), it1->tpcNSigmaDe()); - QA.fill(HIST("QA/hnSigmaTPCVsPt_APrDe_Debug"), -1.f * it2->pt(), it2->tpcNSigmaPr()); - QA.fill(HIST("QA/hnSigmaTOFVsPt_De_Debug"), -1.f * it1->pt(), it1->tofNSigmaDe()); - QA.fill(HIST("QA/hnSigmaTOFVsPt_APrDe_Debug"), -1.f * it2->pt(), it2->tofNSigmaPr()); - } + 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 constexpr (doMC) { - 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()); - } + } + } 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()); } - } // SE - } - } + } + } // SE + } // pT condition } // nBinspT loop - } - } + } // tracks 2 + } // tracks 1 } float getDeltaPhi(float deltaPhi) @@ -568,10 +551,12 @@ struct hadronnucleicorrelation { for (auto track : tracks) { if (std::abs(track.template singleCollSel_as().posZ()) > cutzvertex) continue; - if (std::abs(track.dcaXY()) > max_dcaxy || std::abs(track.dcaZ()) > max_dcaz) { // For now no filtering on the DCAxy or DCAz (casting not supported) + + if (track.tpcFractionSharedCls() > max_tpcSharedCls) continue; - } - if (track.tpcFractionSharedCls() > max_tpcSharedCls || track.itsNCls() < min_itsNCls) + if (track.itsNCls() < min_itsNCls) + continue; + if (!applyDCAcut(track)) continue; if (doQA) { @@ -579,8 +564,8 @@ struct hadronnucleicorrelation { QA.fill(HIST("QA/hTPCchi2"), track.tpcChi2NCl()); QA.fill(HIST("QA/hTPCcrossedRowsOverFindableCls"), track.tpcCrossedRowsOverFindableCls()); QA.fill(HIST("QA/hITSchi2"), track.itsChi2NCl()); - QA.fill(HIST("QA/hDCAxy"), track.dcaXY()); - QA.fill(HIST("QA/hDCAz"), track.dcaZ()); + QA.fill(HIST("QA/hDCAxy"), track.dcaXY(), track.pt()); + QA.fill(HIST("QA/hDCAz"), track.dcaZ(), track.pt()); QA.fill(HIST("QA/hVtxZ_trk"), track.template singleCollSel_as().posZ()); QA.fill(HIST("QA/hnSigmaTPCVsPt_Pr"), track.pt() * track.sign(), track.tpcNSigmaPr()); QA.fill(HIST("QA/hnSigmaTPCVsPt_De"), track.pt() * track.sign(), track.tpcNSigmaDe()); @@ -588,85 +573,54 @@ struct hadronnucleicorrelation { QA.fill(HIST("QA/hnSigmaTOFVsPt_De"), track.pt() * track.sign(), track.tofNSigmaDe()); } + // Discard candidates outside pT of interest if (track.pt() > pTBins.value.at(nBinspT) || track.pt() < pTBins.value.at(0)) continue; - bool isPr = false; - bool isAntiPr = false; - bool isDeTPCTOF = false; - bool isAntiDeTPCTOF = false; - - if (TMath::Abs(track.tpcNSigmaPr()) < nsigmaTPC && track.sign() > 0) { - if (track.pt() < pTthrpr_TOF) { - isPr = true; - } else if (TMath::Abs(track.tofNSigmaPr()) < nsigmaTOF) { - isPr = true; - } - } - if (TMath::Abs(track.tpcNSigmaPr()) < nsigmaTPC && track.sign() < 0) { - if (track.pt() < pTthrpr_TOF) { - isAntiPr = true; - } else if (TMath::Abs(track.tofNSigmaPr()) < nsigmaTOF) { - isAntiPr = true; - } - } - if (TMath::Abs(track.tpcNSigmaDe()) < nsigmaTPC && TMath::Abs(track.tofNSigmaDe()) < nsigmaTOF && TMath::Abs(track.tofNSigmaPr()) >= nsigmaTOF) { - if (track.sign() > 0) { - isDeTPCTOF = true; - } else if (track.sign() < 0) { - isAntiDeTPCTOF = true; - } - } + bool isPr = IsProton(track, +1); + bool isAntiPr = IsProton(track, -1); + bool isDe = IsDeuteron(track, +1); + bool isAntiDe = IsDeuteron(track, -1); - if (!isPr && !isAntiPr && !isDeTPCTOF && !isAntiDeTPCTOF) + if (!isPr && !isAntiPr && !isDe && !isAntiDe) continue; - if (isPr && isDeTPCTOF) { - isDeTPCTOF = 0; + if (isPr && isDe) { + isDe = 0; } - if (isAntiPr && isAntiDeTPCTOF) { - isAntiDeTPCTOF = 0; + if (isAntiPr && isAntiDe) { + isAntiDe = 0; } - // Deuterons - if (isAntiDeTPCTOF) { + // Deuterons Fill & QA + if (isAntiDe) { selectedtracks_antid[track.singleCollSelId()].push_back(std::make_shared(track)); if (doQA) { QA.fill(HIST("QA/hEtaAntiDe"), track.eta()); QA.fill(HIST("QA/hPhiAntiDe"), track.phi()); - QA.fill(HIST("QA/hnSigmaTPCVsPhi_AntiDe"), track.phi(), track.tpcNSigmaDe()); - QA.fill(HIST("QA/hnSigmaTPCVsEta_AntiDe"), track.eta(), track.tpcNSigmaDe()); - QA.fill(HIST("QA/hnSigmaTOFVsPhi_AntiDe"), track.phi(), track.tofNSigmaDe()); - QA.fill(HIST("QA/hnSigmaTOFVsEta_AntiDe"), track.eta(), track.tofNSigmaDe()); QA.fill(HIST("QA/hnSigmaTOFVsPt_De_AfterSel"), track.pt() * track.sign(), track.tofNSigmaDe()); QA.fill(HIST("QA/hnSigmaTPCVsPt_De_AfterSel"), track.pt() * track.sign(), track.tpcNSigmaDe()); } } - if (isDeTPCTOF) { + if (isDe) { + selectedtracks_d[track.singleCollSelId()].push_back(std::make_shared(track)); + if (doQA) { QA.fill(HIST("QA/hEtaDe"), track.eta()); QA.fill(HIST("QA/hPhiDe"), track.phi()); - QA.fill(HIST("QA/hnSigmaTPCVsPhi_De"), track.phi(), track.tpcNSigmaDe()); - QA.fill(HIST("QA/hnSigmaTPCVsEta_De"), track.eta(), track.tpcNSigmaDe()); - QA.fill(HIST("QA/hnSigmaTOFVsPhi_De"), track.phi(), track.tofNSigmaDe()); - QA.fill(HIST("QA/hnSigmaTOFVsEta_De"), track.eta(), track.tofNSigmaDe()); QA.fill(HIST("QA/hnSigmaTOFVsPt_De_AfterSel"), track.pt() * track.sign(), track.tofNSigmaDe()); QA.fill(HIST("QA/hnSigmaTPCVsPt_De_AfterSel"), track.pt() * track.sign(), track.tpcNSigmaDe()); } } - // Protons + // Protons Fill & QA if (isPr) { selectedtracks_p[track.singleCollSelId()].push_back(std::make_shared(track)); if (doQA) { QA.fill(HIST("QA/hEtaPr"), track.eta()); QA.fill(HIST("QA/hPhiPr"), track.phi()); - QA.fill(HIST("QA/hnSigmaTPCVsPhi_Pr"), track.phi(), track.tpcNSigmaPr()); - QA.fill(HIST("QA/hnSigmaTPCVsEta_Pr"), track.eta(), track.tpcNSigmaPr()); - QA.fill(HIST("QA/hnSigmaTOFVsPhi_Pr"), track.phi(), track.tofNSigmaPr()); - QA.fill(HIST("QA/hnSigmaTOFVsEta_Pr"), track.eta(), track.tofNSigmaPr()); QA.fill(HIST("QA/hnSigmaTPCVsPt_Pr_AfterSel"), track.pt() * track.sign(), track.tpcNSigmaPr()); QA.fill(HIST("QA/hnSigmaTOFVsPt_Pr_AfterSel"), track.pt() * track.sign(), track.tofNSigmaPr()); } @@ -676,10 +630,6 @@ struct hadronnucleicorrelation { if (doQA) { QA.fill(HIST("QA/hEtaAntiPr"), track.eta()); QA.fill(HIST("QA/hPhiAntiPr"), track.phi()); - QA.fill(HIST("QA/hnSigmaTPCVsPhi_AntiPr"), track.phi(), track.tpcNSigmaPr()); - QA.fill(HIST("QA/hnSigmaTPCVsEta_AntiPr"), track.eta(), track.tpcNSigmaPr()); - QA.fill(HIST("QA/hnSigmaTOFVsPhi_AntiPr"), track.phi(), track.tofNSigmaPr()); - QA.fill(HIST("QA/hnSigmaTOFVsEta_AntiPr"), track.eta(), track.tofNSigmaPr()); QA.fill(HIST("QA/hnSigmaTPCVsPt_Pr_AfterSel"), track.pt() * track.sign(), track.tpcNSigmaPr()); QA.fill(HIST("QA/hnSigmaTOFVsPt_Pr_AfterSel"), track.pt() * track.sign(), track.tofNSigmaPr()); } @@ -688,76 +638,28 @@ struct hadronnucleicorrelation { for (auto collision : collisions) { - if (TMath::Abs(collision.posZ()) > cutzvertex) + if (std::abs(collision.posZ()) > cutzvertex) continue; registry.fill(HIST("hNEvents"), 0.5); - registry.fill(HIST("hDebug"), 0.5); - - if (selectedtracks_p.find(collision.globalIndex()) != selectedtracks_p.end() && - selectedtracks_antip.find(collision.globalIndex()) != selectedtracks_antip.end()) { - registry.fill(HIST("hNEvents"), 2.5); - } if (selectedtracks_antid.find(collision.globalIndex()) != selectedtracks_antid.end() && selectedtracks_antip.find(collision.globalIndex()) != selectedtracks_antip.end()) { registry.fill(HIST("hNEvents"), 1.5); } - int vertexBinToMix = std::floor((collision.posZ() + cutzvertex) / (2 * cutzvertex / _vertexNbinsToMix)); - int centBinToMix = std::floor(collision.multPerc() / (100.0 / _multNsubBins)); - - if (selectedtracks_p.find(collision.globalIndex()) != selectedtracks_p.end()) { - registry.fill(HIST("hDebug"), 3.5); - mixbins_pantip[std::pair{vertexBinToMix, centBinToMix}].push_back(std::make_shared(collision)); + if (selectedtracks_d.find(collision.globalIndex()) != selectedtracks_d.end() && + selectedtracks_p.find(collision.globalIndex()) != selectedtracks_p.end()) { + registry.fill(HIST("hNEvents"), 2.5); } - if (selectedtracks_antip.find(collision.globalIndex()) != selectedtracks_antip.end()) { - registry.fill(HIST("hDebug"), 2.5); - } + int vertexBinToMix = std::floor((collision.posZ() + cutzvertex) / (2 * cutzvertex / _vertexNbinsToMix)); + int centBinToMix = std::floor(collision.multPerc() / (100.0 / _multNsubBins)); if (selectedtracks_antid.find(collision.globalIndex()) != selectedtracks_antid.end()) { - registry.fill(HIST("hDebug"), 1.5); - registry.fill(HIST("hDebugdp"), 0.5); // numero tot di collisioni nella mappa mixbins_antidantip - mixbins_antidantip[std::pair{vertexBinToMix, centBinToMix}].push_back(std::make_shared(collision)); - } - } - - registry.get(HIST("hDebugdp"))->SetBinContent(6, mixbins_antidantip.size()); - - if (!disable_pantip) { - if (!mixbins_pantip.empty()) { - for (auto i = mixbins_pantip.begin(); i != mixbins_pantip.end(); i++) { // iterating over all vertex&mult bins - - int EvPerBin = (i->second).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 = (i->second)[indx1]; - - if (selectedtracks_antip.find(col1->index()) != selectedtracks_antip.end()) { - mixTracks<0, 0>(selectedtracks_p[col1->index()], selectedtracks_antip[col1->index()], 0, 0); // mixing SE - } - - int indx3 = EvPerBin; - if (indx1 < (EvPerBin - 11)) { - indx3 = indx1 + 11; - } - - for (int indx2 = indx1 + 1; indx2 < indx3; indx2++) { // nested loop for all the combinations of collisions in a chosen mult/vertex bin - - auto col2 = (i->second)[indx2]; - - if (col1 == col2) { - continue; - } + registry.fill(HIST("hNEvents"), 3.5); - if (selectedtracks_antip.find(col2->index()) != selectedtracks_antip.end()) { - mixTracks<1, 0>(selectedtracks_p[col1->index()], selectedtracks_antip[col2->index()], 0, 0); // mixing ME - } - } - } - } + mixbins_antidantip[std::pair{vertexBinToMix, centBinToMix}].push_back(std::make_shared(collision)); } } @@ -765,20 +667,15 @@ struct hadronnucleicorrelation { for (auto i = mixbins_antidantip.begin(); i != mixbins_antidantip.end(); i++) { // iterating over all vertex&mult bins - registry.fill(HIST("hDebugdp"), 1.5); // numero di keys (vertex&mult bins) nella mappa mixbins_antidantip - 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 - registry.fill(HIST("hDebugdp"), 2.5); - auto col1 = value[indx1]; if (selectedtracks_antip.find(col1->index()) != selectedtracks_antip.end()) { - registry.fill(HIST("hDebugdp"), 3.5); - mixTracks<0, 0>(selectedtracks_antid[col1->index()], selectedtracks_antip[col1->index()], 1, 0); // mixing SE + mixTracks<0, 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 @@ -790,8 +687,7 @@ struct hadronnucleicorrelation { } if (selectedtracks_antip.find(col2->index()) != selectedtracks_antip.end()) { - registry.fill(HIST("hDebugdp"), 4.5); - mixTracks<1, 0>(selectedtracks_antid[col1->index()], selectedtracks_antip[col2->index()], 1, 0); // mixing ME + mixTracks<1, 0>(selectedtracks_antid[col1->index()], selectedtracks_antip[col2->index()], 0); // mixing ME } } } @@ -811,20 +707,14 @@ struct hadronnucleicorrelation { (i->second).clear(); selectedtracks_p.clear(); - for (auto& pair : mixbins_antidantip) { - pair.second.clear(); // Clear the vector associated with the key - } - mixbins_antidantip.clear(); // Then clear the map itself + for (auto i = selectedtracks_d.begin(); i != selectedtracks_d.end(); i++) + (i->second).clear(); + selectedtracks_d.clear(); for (auto& pair : mixbins_antidantip) { pair.second.clear(); // Clear the vector associated with the key } mixbins_antidantip.clear(); // Then clear the map itself - - for (auto& pair : mixbins_pantip) { - pair.second.clear(); // Clear the vector associated with the key - } - mixbins_pantip.clear(); // Then clear the map itself } PROCESS_SWITCH(hadronnucleicorrelation, processData, "processData", true); @@ -834,19 +724,24 @@ struct hadronnucleicorrelation { if (std::abs(track.template singleCollSel_as().posZ()) > cutzvertex) continue; - if (std::abs(track.dcaXY()) > max_dcaxy || std::abs(track.dcaZ()) > max_dcaz) { // For now no filtering on the DCAxy or DCAz (casting not supported) + if (track.tpcFractionSharedCls() > max_tpcSharedCls) continue; - } - if (std::abs(track.pdgCode()) != pdgProton && std::abs(track.pdgCode()) != pdgDeuteron) + if (track.itsNCls() < min_itsNCls) + continue; + if (!applyDCAcut(track)) continue; + // Keep only protons and deuterons + // if (std::abs(track.pdgCode()) != pdgProton && std::abs(track.pdgCode()) != pdgDeuteron) + // continue; + if (doQA) { QA.fill(HIST("QA/hTPCnClusters"), track.tpcNClsFound()); QA.fill(HIST("QA/hTPCchi2"), track.tpcChi2NCl()); QA.fill(HIST("QA/hTPCcrossedRowsOverFindableCls"), track.tpcCrossedRowsOverFindableCls()); QA.fill(HIST("QA/hITSchi2"), track.itsChi2NCl()); - QA.fill(HIST("QA/hDCAxy"), track.dcaXY()); - QA.fill(HIST("QA/hDCAz"), track.dcaZ()); + QA.fill(HIST("QA/hDCAxy"), track.dcaXY(), track.pt()); + QA.fill(HIST("QA/hDCAz"), track.dcaZ(), track.pt()); QA.fill(HIST("QA/hVtxZ_trk"), track.template singleCollSel_as().posZ()); QA.fill(HIST("QA/hnSigmaTPCVsPt_Pr"), track.pt() * track.sign(), track.tpcNSigmaPr()); QA.fill(HIST("QA/hnSigmaTPCVsPt_De"), track.pt() * track.sign(), track.tpcNSigmaDe()); @@ -854,30 +749,22 @@ struct hadronnucleicorrelation { QA.fill(HIST("QA/hnSigmaTOFVsPt_De"), track.pt() * track.sign(), track.tofNSigmaDe()); } - int s = +1; - if (track.pdgCode() == -pdgProton) { - s = -1; - } + bool isPr = (IsProton(track, +1) && track.pdgCode() == pdgProton); + bool isAntiPr = (IsProton(track, -1) && track.pdgCode() == -pdgProton); + bool isDe = (IsDeuteron(track, +1) && track.pdgCode() == pdgDeuteron); + bool isAntiDe = (IsDeuteron(track, -1) && track.pdgCode() == -pdgDeuteron); - if (track.origin() == 1) { // secondaries - if (TMath::Abs(track.pdgCode()) == pdgProton) { - if (TMath::Abs(track.tpcNSigmaPr()) < nsigmaTPC) { - if (track.pt() < pTthrpr_TOF) { - registry.fill(HIST("hSec_EtaPhiPt_Proton"), track.eta(), track.phi(), track.pt() * s); - } else if (TMath::Abs(track.tofNSigmaPr()) < nsigmaTOF) { - registry.fill(HIST("hSec_EtaPhiPt_Proton"), track.eta(), track.phi(), track.pt() * s); - } + if (track.origin() == 1 || track.origin() == 0) { // primaries and secondaries + if (isPr) { + registry.fill(HIST("hPrimSec_EtaPhiPt_Proton"), track.eta(), track.phi(), track.pt() * +1); + if (track.origin() == 1) { // secondaries + registry.fill(HIST("hSec_EtaPhiPt_Proton"), track.eta(), track.phi(), track.pt() * +1); } } - } - if (track.origin() == 1 || track.origin() == 0) { // primaries and secondaries - if (TMath::Abs(track.pdgCode()) == pdgProton) { - if (TMath::Abs(track.tpcNSigmaPr()) < nsigmaTPC) { - if (track.pt() < pTthrpr_TOF) { - registry.fill(HIST("hPrimSec_EtaPhiPt_Proton"), track.eta(), track.phi(), track.pt() * s); - } else if (TMath::Abs(track.tofNSigmaPr()) < nsigmaTOF) { - registry.fill(HIST("hPrimSec_EtaPhiPt_Proton"), track.eta(), track.phi(), track.pt() * s); - } + if (isAntiPr) { + registry.fill(HIST("hPrimSec_EtaPhiPt_Proton"), track.eta(), track.phi(), track.pt() * -1); + if (track.origin() == 1) { + registry.fill(HIST("hSec_EtaPhiPt_Proton"), track.eta(), track.phi(), track.pt() * -1); } } } @@ -885,25 +772,14 @@ struct hadronnucleicorrelation { if (track.origin() != 0) continue; - bool isPr = false; - bool isAntiPr = false; - bool isAntiDeTPCTOF = false; - if (track.pdgCode() == pdgProton) { registry.fill(HIST("hReco_EtaPhiPt_Proton"), track.eta(), track.phi(), track.pt()); registry.fill(HIST("hReco_EtaPhiPtMC_Proton"), track.eta_MC(), track.phi_MC(), track.pt_MC()); registry.fill(HIST("hResPt_Proton"), track.pt_MC(), track.pt() - track.pt_MC()); registry.fill(HIST("hResEta_Proton"), track.eta_MC(), track.eta() - track.eta_MC()); registry.fill(HIST("hResPhi_Proton"), track.phi_MC(), track.phi() - track.phi_MC()); - - if (TMath::Abs(track.tpcNSigmaPr()) < nsigmaTPC) { - if (track.pt() < pTthrpr_TOF) { - isPr = true; - registry.fill(HIST("hReco_PID_EtaPhiPt_Proton"), track.eta(), track.phi(), track.pt()); - } else if (TMath::Abs(track.tofNSigmaPr()) < nsigmaTOF) { - isPr = true; - registry.fill(HIST("hReco_PID_EtaPhiPt_Proton"), track.eta(), track.phi(), track.pt()); - } + if (isPr) { + registry.fill(HIST("hReco_PID_EtaPhiPt_Proton"), track.eta(), track.phi(), track.pt()); } registry.fill(HIST("hnSigmaTPCVsPt_Pr_MC"), track.pt(), track.tpcNSigmaPr()); registry.fill(HIST("hnSigmaTOFVsPt_Pr_MC"), track.pt(), track.tofNSigmaPr()); @@ -914,15 +790,8 @@ struct hadronnucleicorrelation { registry.fill(HIST("hResPt_AntiProton"), track.pt_MC(), track.pt() - track.pt_MC()); registry.fill(HIST("hResEta_AntiProton"), track.eta_MC(), track.eta() - track.eta_MC()); registry.fill(HIST("hResPhi_AntiProton"), track.phi_MC(), track.phi() - track.phi_MC()); - - if (TMath::Abs(track.tpcNSigmaPr()) < nsigmaTPC) { - if (track.pt() < pTthrpr_TOF) { - isAntiPr = true; - registry.fill(HIST("hReco_PID_EtaPhiPt_Proton"), track.eta(), track.phi(), track.pt() * -1); - } else if (TMath::Abs(track.tofNSigmaPr()) < nsigmaTOF) { - isAntiPr = true; - registry.fill(HIST("hReco_PID_EtaPhiPt_Proton"), track.eta(), track.phi(), track.pt() * -1); - } + if (isAntiPr) { + registry.fill(HIST("hReco_PID_EtaPhiPt_Proton"), track.eta(), track.phi(), track.pt() * -1); } registry.fill(HIST("hnSigmaTPCVsPt_Pr_MC"), track.pt() * -1, track.tpcNSigmaPr()); registry.fill(HIST("hnSigmaTOFVsPt_Pr_MC"), track.pt() * -1, track.tofNSigmaPr()); @@ -933,8 +802,7 @@ struct hadronnucleicorrelation { registry.fill(HIST("hResPt_Deuteron"), track.pt_MC(), track.pt() - track.pt_MC()); registry.fill(HIST("hResEta_Deuteron"), track.eta_MC(), track.eta() - track.eta_MC()); registry.fill(HIST("hResPhi_Deuteron"), track.phi_MC(), track.phi() - track.phi_MC()); - - if (TMath::Abs(track.tpcNSigmaDe()) < nsigmaTPC && TMath::Abs(track.tofNSigmaDe()) < nsigmaTOF && TMath::Abs(track.tofNSigmaPr()) >= nsigmaTOF) { + if (isDe) { registry.fill(HIST("hReco_PID_EtaPhiPt_Deuteron"), track.eta(), track.phi(), track.pt()); } registry.fill(HIST("hnSigmaTPCVsPt_De_MC"), track.pt(), track.tpcNSigmaDe()); @@ -946,20 +814,152 @@ struct hadronnucleicorrelation { registry.fill(HIST("hResPt_AntiDeuteron"), track.pt_MC(), track.pt() - track.pt_MC()); registry.fill(HIST("hResEta_AntiDeuteron"), track.eta_MC(), track.eta() - track.eta_MC()); registry.fill(HIST("hResPhi_AntiDeuteron"), track.phi_MC(), track.phi() - track.phi_MC()); - - if (TMath::Abs(track.tpcNSigmaDe()) < nsigmaTPC && TMath::Abs(track.tofNSigmaDe()) < nsigmaTOF && TMath::Abs(track.tofNSigmaPr()) >= nsigmaTOF) { - isAntiDeTPCTOF = true; + if (isAntiDe) { registry.fill(HIST("hReco_PID_EtaPhiPt_Deuteron"), track.eta(), track.phi(), track.pt() * -1); } registry.fill(HIST("hnSigmaTPCVsPt_De_MC"), track.pt() * -1, track.tpcNSigmaDe()); registry.fill(HIST("hnSigmaTOFVsPt_De_MC"), track.pt() * -1, track.tofNSigmaDe()); } + // Purity + // Numerators + if (isPr) { + registry.fill(HIST("hNumeratorPurity_Proton"), track.pt()); + } + if (std::abs(track.tpcNSigmaPr()) < nsigmaTPC && track.pdgCode() == pdgProton) { + registry.fill(HIST("hNumeratorPurity_Proton_TPC"), track.pt()); + registry.fill(HIST("hReco_Pt_Proton_TPC"), track.pt()); + } + if (std::abs(track.tpcNSigmaPr()) < nsigmaTPC && std::abs(track.tofNSigmaPr()) < nsigmaTOF && + track.pdgCode() == pdgProton) { + registry.fill(HIST("hNumeratorPurity_Proton_TPCTOF"), track.pt()); + registry.fill(HIST("hReco_Pt_Proton_TPCTOF"), track.pt()); + } + if (( + (std::abs(track.tpcNSigmaPr()) < nsigmaTPC && track.beta() < -100) || + (track.beta() > -100 && std::abs(track.tpcNSigmaPr()) < nsigmaTPC && std::abs(track.tofNSigmaPr()) < nsigmaTOF)) && + track.pdgCode() == pdgProton) { + registry.fill(HIST("hNumeratorPurity_Proton_TPC_or_TOF"), track.pt()); + registry.fill(HIST("hReco_Pt_Proton_TPC_or_TOF"), track.pt()); + } + + if (isAntiPr) + registry.fill(HIST("hNumeratorPurity_Proton"), track.pt() * -1); + if (std::abs(track.tpcNSigmaPr()) < nsigmaTPC && track.pdgCode() == -pdgProton) { + registry.fill(HIST("hNumeratorPurity_Proton_TPC"), track.pt() * -1); + registry.fill(HIST("hReco_Pt_Proton_TPC"), track.pt() * -1); + } + if (std::abs(track.tpcNSigmaPr()) < nsigmaTPC && std::abs(track.tofNSigmaPr()) < nsigmaTOF && + track.pdgCode() == -pdgProton) { + registry.fill(HIST("hNumeratorPurity_Proton_TPCTOF"), track.pt() * -1); + registry.fill(HIST("hReco_Pt_Proton_TPCTOF"), track.pt() * -1); + } + if (( + (std::abs(track.tpcNSigmaPr()) < nsigmaTPC && track.beta() < -100) || + (track.beta() > -100 && std::abs(track.tpcNSigmaPr()) < nsigmaTPC && std::abs(track.tofNSigmaPr()) < nsigmaTOF)) && + track.pdgCode() == -pdgProton) { + registry.fill(HIST("hNumeratorPurity_Proton_TPC_or_TOF"), track.pt() * -1); + registry.fill(HIST("hReco_Pt_Proton_TPC_or_TOF"), track.pt() * -1); + } + + if (isDe) + registry.fill(HIST("hNumeratorPurity_Deuteron"), track.pt()); + if (std::abs(track.tpcNSigmaDe()) < nsigmaTPC && track.pdgCode() == pdgDeuteron) { + registry.fill(HIST("hNumeratorPurity_Deuteron_TPC"), track.pt()); + registry.fill(HIST("hReco_Pt_Deuteron_TPC"), track.pt()); + } + if (std::abs(track.tpcNSigmaDe()) < nsigmaTPC && std::abs(track.tofNSigmaDe()) < nsigmaTOF && + track.pdgCode() == pdgDeuteron) { + registry.fill(HIST("hNumeratorPurity_Deuteron_TPCTOF"), track.pt()); + registry.fill(HIST("hReco_Pt_Deuteron_TPCTOF"), track.pt()); + } + if (( + (std::abs(track.tpcNSigmaDe()) < nsigmaTPC && track.beta() < -100) || + (track.beta() > -100 && std::abs(track.tpcNSigmaDe()) < nsigmaTPC && std::abs(track.tofNSigmaDe()) < nsigmaTOF)) && + track.pdgCode() == pdgDeuteron) { + registry.fill(HIST("hNumeratorPurity_Deuteron_TPC_or_TOF"), track.pt()); + registry.fill(HIST("hReco_Pt_Deuteron_TPC_or_TOF"), track.pt()); + } + + if (isAntiDe) + registry.fill(HIST("hNumeratorPurity_Deuteron"), track.pt() * -1); + if (std::abs(track.tpcNSigmaDe()) < nsigmaTPC && track.pdgCode() == -pdgDeuteron) { + registry.fill(HIST("hNumeratorPurity_Deuteron_TPC"), track.pt() * -1); + registry.fill(HIST("hReco_Pt_Deuteron_TPC"), track.pt() * -1); + } + if (std::abs(track.tpcNSigmaDe()) < nsigmaTPC && std::abs(track.tofNSigmaDe()) < nsigmaTOF && + track.pdgCode() == -pdgDeuteron) { + registry.fill(HIST("hNumeratorPurity_Deuteron_TPCTOF"), track.pt() * -1); + registry.fill(HIST("hReco_Pt_Deuteron_TPCTOF"), track.pt() * -1); + } + if (( + (std::abs(track.tpcNSigmaDe()) < nsigmaTPC && track.beta() < -100) || + (track.beta() > -100 && std::abs(track.tpcNSigmaDe()) < nsigmaTPC && std::abs(track.tofNSigmaDe()) < nsigmaTOF)) && + track.pdgCode() == -pdgDeuteron) { + registry.fill(HIST("hNumeratorPurity_Deuteron_TPC_or_TOF"), track.pt() * -1); + registry.fill(HIST("hReco_Pt_Deuteron_TPC_or_TOF"), track.pt() * -1); + } + + // Denominators + if (IsProton(track, +1)) + registry.fill(HIST("hDenominatorPurity_Proton"), track.pt()); + if (std::abs(track.tpcNSigmaPr()) < nsigmaTPC && track.sign() > 0) + registry.fill(HIST("hDenominatorPurity_Proton_TPC"), track.pt()); + if (std::abs(track.tpcNSigmaPr()) < nsigmaTPC && std::abs(track.tofNSigmaPr()) < nsigmaTOF && track.sign() > 0) + registry.fill(HIST("hDenominatorPurity_Proton_TPCTOF"), track.pt()); + if (( + (std::abs(track.tpcNSigmaPr()) < nsigmaTPC && track.beta() < -100) || + (track.beta() > -100 && std::abs(track.tpcNSigmaPr()) < nsigmaTPC && std::abs(track.tofNSigmaPr()) < nsigmaTOF)) && + track.sign() > 0) + registry.fill(HIST("hDenominatorPurity_Proton_TPC_or_TOF"), track.pt()); + + if (IsProton(track, -1)) + registry.fill(HIST("hDenominatorPurity_Proton"), track.pt() * -1); + if (std::abs(track.tpcNSigmaPr()) < nsigmaTPC && track.sign() < 0) + registry.fill(HIST("hDenominatorPurity_Proton_TPC"), track.pt() * -1); + if (std::abs(track.tpcNSigmaPr()) < nsigmaTPC && std::abs(track.tofNSigmaPr()) < nsigmaTOF && track.sign() < 0) + registry.fill(HIST("hDenominatorPurity_Proton_TPCTOF"), track.pt() * -1); + if (( + (std::abs(track.tpcNSigmaPr()) < nsigmaTPC && track.beta() < -100) || + (track.beta() > -100 && std::abs(track.tpcNSigmaPr()) < nsigmaTPC && std::abs(track.tofNSigmaPr()) < nsigmaTOF)) && + track.sign() < 0) + registry.fill(HIST("hDenominatorPurity_Proton_TPC_or_TOF"), track.pt() * -1); + + if (IsDeuteron(track, +1)) + registry.fill(HIST("hDenominatorPurity_Deuteron"), track.pt()); + if (std::abs(track.tpcNSigmaDe()) < nsigmaTPC && track.sign() > 0) + registry.fill(HIST("hDenominatorPurity_Deuteron_TPC"), track.pt()); + if (std::abs(track.tpcNSigmaDe()) < nsigmaTPC && std::abs(track.tofNSigmaPr()) < nsigmaTOF && track.sign() > 0) + registry.fill(HIST("hDenominatorPurity_Deuteron_TPCTOF"), track.pt()); + if (( + (std::abs(track.tpcNSigmaDe()) < nsigmaTPC && track.beta() < -100) || + (track.beta() > -100 && std::abs(track.tpcNSigmaDe()) < nsigmaTPC && std::abs(track.tofNSigmaDe()) < nsigmaTOF)) && + track.sign() > 0) + registry.fill(HIST("hDenominatorPurity_Deuteron_TPC_or_TOF"), track.pt()); + + if (IsDeuteron(track, -1)) + registry.fill(HIST("hDenominatorPurity_Deuteron"), track.pt() * -1); + if (std::abs(track.tpcNSigmaDe()) < nsigmaTPC && track.sign() < 0) + registry.fill(HIST("hDenominatorPurity_Deuteron_TPC"), track.pt() * -1); + if (std::abs(track.tpcNSigmaDe()) < nsigmaTPC && std::abs(track.tofNSigmaPr()) < nsigmaTOF && track.sign() < 0) + registry.fill(HIST("hDenominatorPurity_Deuteron_TPCTOF"), track.pt() * -1); + if (( + (std::abs(track.tpcNSigmaDe()) < nsigmaTPC && track.beta() < -100) || + (track.beta() > -100 && std::abs(track.tpcNSigmaDe()) < nsigmaTPC && std::abs(track.tofNSigmaDe()) < nsigmaTOF)) && + track.sign() < 0) + registry.fill(HIST("hDenominatorPurity_Deuteron_TPC_or_TOF"), track.pt() * -1); + if (!mcCorrelation) { continue; } - if (isAntiDeTPCTOF) { + if (isDe) { + selectedtracksPIDMC_d[track.singleCollSelId()].push_back(std::make_shared(track)); + } + if (track.pdgCode() == pdgDeuteron) { + selectedtracksMC_d[track.singleCollSelId()].push_back(std::make_shared(track)); + } + if (isAntiDe) { selectedtracksPIDMC_antid[track.singleCollSelId()].push_back(std::make_shared(track)); } if (track.pdgCode() == -pdgDeuteron) { @@ -984,92 +984,22 @@ struct hadronnucleicorrelation { } for (auto collision : collisions) { - if (TMath::Abs(collision.posZ()) > cutzvertex) + if (std::abs(collision.posZ()) > cutzvertex) continue; registry.fill(HIST("hNEvents"), 0.5); int vertexBinToMix = std::floor((collision.posZ() + cutzvertex) / (2 * cutzvertex / _vertexNbinsToMix)); int centBinToMix = std::floor(collision.multPerc() / (100.0 / _multNsubBins)); - if (selectedtracksMC_p.find(collision.globalIndex()) != selectedtracksMC_p.end()) { - mixbins_pantip[std::pair{vertexBinToMix, centBinToMix}].push_back(std::make_shared(collision)); - } - if (selectedtracksMC_antid.find(collision.globalIndex()) != selectedtracksMC_antid.end()) { mixbins_antidantip[std::pair{vertexBinToMix, centBinToMix}].push_back(std::make_shared(collision)); } - if (selectedtracksPIDMC_p.find(collision.globalIndex()) != selectedtracksPIDMC_p.end()) { - mixbinsPID_pantip[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)); } } // coll - if (!mixbins_pantip.empty()) { - - for (auto i = mixbins_pantip.begin(); i != mixbins_pantip.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 (selectedtracksMC_antip.find(col1->index()) != selectedtracksMC_antip.end()) { - mixTracks<0, 1 /*MC qa*/>(selectedtracksMC_p[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 - - auto col2 = (i->second)[indx2]; - - if (col1 == col2) { - continue; - } - - if (selectedtracksMC_antip.find(col2->index()) != selectedtracksMC_antip.end()) { - mixTracks<1, 1>(selectedtracksMC_p[col1->index()], selectedtracksMC_antip[col2->index()], 0, 0); // mixing ME - } - } - } // event - } - } - - if (!mixbinsPID_pantip.empty()) { - - for (auto i = mixbinsPID_pantip.begin(); i != mixbinsPID_pantip.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 (selectedtracksPIDMC_antip.find(col1->index()) != selectedtracksPIDMC_antip.end()) { - mixTracks<0, 1 /*MC qa*/>(selectedtracksPIDMC_p[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 - - auto col2 = (i->second)[indx2]; - - if (col1 == col2) { - continue; - } - - if (selectedtracksPIDMC_antip.find(col2->index()) != selectedtracksPIDMC_antip.end()) { - mixTracks<1, 1>(selectedtracksPIDMC_p[col1->index()], selectedtracksPIDMC_antip[col2->index()], 0, 1); // mixing ME - } - } - } - } - } - if (!mixbins_antidantip.empty()) { for (auto i = mixbins_antidantip.begin(); i != mixbins_antidantip.end(); i++) { // iterating over all vertex&mult bins @@ -1082,7 +1012,7 @@ struct hadronnucleicorrelation { auto col1 = value[indx1]; if (selectedtracksMC_antip.find(col1->index()) != selectedtracksMC_antip.end()) { - mixTracks<0, 1 /*MC qa*/>(selectedtracksMC_antid[col1->index()], selectedtracksMC_antip[col1->index()], 1, 0); // mixing SE + mixTracks<0, 1>(selectedtracksMC_antid[col1->index()], selectedtracksMC_antip[col1->index()], 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 @@ -1094,7 +1024,7 @@ struct hadronnucleicorrelation { } if (selectedtracksMC_antip.find(col2->index()) != selectedtracksMC_antip.end()) { - mixTracks<1, 1>(selectedtracksMC_antid[col1->index()], selectedtracksMC_antip[col2->index()], 1, 0); // mixing ME + mixTracks<1, 1>(selectedtracksMC_antid[col1->index()], selectedtracksMC_antip[col2->index()], 0); // mixing ME } } } @@ -1113,7 +1043,7 @@ struct hadronnucleicorrelation { auto col1 = value[indx1]; if (selectedtracksPIDMC_antip.find(col1->index()) != selectedtracksPIDMC_antip.end()) { - mixTracks<0, 1 /*MC qa*/>(selectedtracksPIDMC_antid[col1->index()], selectedtracksPIDMC_antip[col1->index()], 1, 1); // mixing SE + mixTracks<0, 1>(selectedtracksPIDMC_antid[col1->index()], selectedtracksPIDMC_antip[col1->index()], 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 @@ -1125,7 +1055,7 @@ struct hadronnucleicorrelation { } if (selectedtracksPIDMC_antip.find(col2->index()) != selectedtracksPIDMC_antip.end()) { - mixTracks<1, 1>(selectedtracksPIDMC_antid[col1->index()], selectedtracksPIDMC_antip[col2->index()], 1, 1); // mixing ME + mixTracks<1, 1>(selectedtracksPIDMC_antid[col1->index()], selectedtracksPIDMC_antip[col2->index()], 1); // mixing ME } } } @@ -1137,6 +1067,10 @@ struct hadronnucleicorrelation { (i->second).clear(); selectedtracksMC_antid.clear(); + for (auto i = selectedtracksMC_d.begin(); i != selectedtracksMC_d.end(); i++) + (i->second).clear(); + selectedtracksMC_d.clear(); + for (auto i = selectedtracksMC_antip.begin(); i != selectedtracksMC_antip.end(); i++) (i->second).clear(); selectedtracksMC_antip.clear(); @@ -1149,6 +1083,10 @@ struct hadronnucleicorrelation { (i->second).clear(); selectedtracksPIDMC_antid.clear(); + for (auto i = selectedtracksPIDMC_d.begin(); i != selectedtracksPIDMC_d.end(); i++) + (i->second).clear(); + selectedtracksPIDMC_d.clear(); + for (auto i = selectedtracksPIDMC_antip.begin(); i != selectedtracksPIDMC_antip.end(); i++) (i->second).clear(); selectedtracksPIDMC_antip.clear(); @@ -1166,16 +1104,6 @@ struct hadronnucleicorrelation { pair.second.clear(); // clear the vector associated with the key } mixbins_antidantip.clear(); // clear the map - - for (auto& pair : mixbinsPID_pantip) { - pair.second.clear(); // clear the vector associated with the key - } - mixbinsPID_pantip.clear(); // clear the map - - for (auto& pair : mixbins_pantip) { - pair.second.clear(); // clear the vector associated with the key - } - mixbins_pantip.clear(); // clear the map } PROCESS_SWITCH(hadronnucleicorrelation, processMC, "processMC", false); }; diff --git a/PWGLF/Tasks/Nuspex/nuclei_in_jets.cxx b/PWGLF/Tasks/Nuspex/nuclei_in_jets.cxx index f14b4fb93bf..ba53f7854b1 100644 --- a/PWGLF/Tasks/Nuspex/nuclei_in_jets.cxx +++ b/PWGLF/Tasks/Nuspex/nuclei_in_jets.cxx @@ -94,6 +94,8 @@ struct nuclei_in_jets { Configurable requireNoOverlap{"requireNoOverlap", false, "require no overlap between jets and UE cones"}; // Track Parameters + Configurable par0{"par0", 0.004, "par 0"}; + Configurable par1{"par1", 0.013, "par 1"}; Configurable min_ITS_nClusters{"min_ITS_nClusters", 5, "minimum number of ITS clusters"}; Configurable min_TPC_nClusters{"min_TPC_nClusters", 80, "minimum number of TPC clusters"}; Configurable min_TPC_nCrossedRows{"min_TPC_nCrossedRows", 80, "minimum number of TPC crossed pad rows"}; @@ -111,7 +113,6 @@ struct nuclei_in_jets { Configurable require_PV_contributor{"require_PV_contributor", true, "require that the track is a PV contributor"}; Configurable setDCAselectionPtDep{"setDCAselectionPtDep", true, "require pt dependent selection"}; Configurable applyReweighting{"applyReweighting", true, "apply reweighting"}; - Configurable runMCefficiency{"runMCefficiency", false, "run MC efficiency"}; Configurable url_to_ccdb{"url_to_ccdb", "http://alice-ccdb.cern.ch", "url of the personal ccdb"}; Configurable path_to_file{"path_to_file", "", "path to file with reweighting"}; @@ -132,7 +133,7 @@ struct nuclei_in_jets { ccdb->setCreatedNotAfter(std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count()); ccdb->setFatalWhenNull(false); - if (runMCefficiency) { + if (applyReweighting) { GetReweightingHistograms(ccdb, TString(path_to_file), TString(histo_name_weight_antip_jet), TString(histo_name_weight_antip_ue)); } else { twod_weights_antip_jet = nullptr; @@ -244,9 +245,9 @@ struct nuclei_in_jets { // pt-dependent selection if (setDCAselectionPtDep) { - if (TMath::Abs(track.dcaXY()) > (0.004f + 0.013f / track.pt())) + if (TMath::Abs(track.dcaXY()) > (par0 + par1 / track.pt())) return false; - if (TMath::Abs(track.dcaZ()) > (0.004f + 0.013f / track.pt())) + if (TMath::Abs(track.dcaZ()) > (par0 + par1 / track.pt())) return false; } @@ -437,7 +438,7 @@ struct nuclei_in_jets { registryData.fill(HIST("number_of_events_data"), 1.5); // Cut on z-vertex - if (std::abs(collision.posZ()) > zVtx) + if (TMath::Abs(collision.posZ()) > zVtx) return; // Event Counter: after z-vertex cut @@ -508,7 +509,7 @@ struct nuclei_in_jets { int n_jets_selected(0); for (int i = 0; i < static_cast(jet.size()); i++) { - if ((std::abs(jet[i].Eta()) + Rjet) > max_eta) + if ((TMath::Abs(jet[i].Eta()) + Rjet) > max_eta) continue; // Perpendicular cones @@ -720,20 +721,21 @@ struct nuclei_in_jets { double w_antip_jet(1.0); double w_antip_ue(1.0); - int ix = twod_weights_antip_jet->GetXaxis()->FindBin(particle.pt()); - int iy = twod_weights_antip_jet->GetYaxis()->FindBin(particle.eta()); if (applyReweighting) { + int ix = twod_weights_antip_jet->GetXaxis()->FindBin(particle.pt()); + int iy = twod_weights_antip_jet->GetYaxis()->FindBin(particle.eta()); w_antip_jet = twod_weights_antip_jet->GetBinContent(ix, iy); w_antip_ue = twod_weights_antip_ue->GetBinContent(ix, iy); - } - // protection - if (ix == 0 || ix > twod_weights_antip_jet->GetNbinsX()) { - w_antip_jet = 1.0; - w_antip_ue = 1.0; - } - if (iy == 0 || iy > twod_weights_antip_jet->GetNbinsY()) { - w_antip_jet = 1.0; - w_antip_ue = 1.0; + + // protections + if (ix == 0 || ix > twod_weights_antip_jet->GetNbinsX()) { + w_antip_jet = 1.0; + w_antip_ue = 1.0; + } + if (iy == 0 || iy > twod_weights_antip_jet->GetNbinsY()) { + w_antip_jet = 1.0; + w_antip_ue = 1.0; + } } if (particle.pdgCode() == -2212) { @@ -760,7 +762,7 @@ struct nuclei_in_jets { if (!collision.sel8()) continue; - if (std::abs(collision.posZ()) > 10) + if (TMath::Abs(collision.posZ()) > 10) continue; // Event Counter (after event sel) @@ -819,20 +821,21 @@ struct nuclei_in_jets { double w_antip_jet(1.0); double w_antip_ue(1.0); - int ix = twod_weights_antip_jet->GetXaxis()->FindBin(particle.pt()); - int iy = twod_weights_antip_jet->GetYaxis()->FindBin(particle.eta()); if (applyReweighting) { + int ix = twod_weights_antip_jet->GetXaxis()->FindBin(particle.pt()); + int iy = twod_weights_antip_jet->GetYaxis()->FindBin(particle.eta()); w_antip_jet = twod_weights_antip_jet->GetBinContent(ix, iy); w_antip_ue = twod_weights_antip_ue->GetBinContent(ix, iy); - } - // protection - if (ix == 0 || ix > twod_weights_antip_jet->GetNbinsX()) { - w_antip_jet = 1.0; - w_antip_ue = 1.0; - } - if (iy == 0 || iy > twod_weights_antip_jet->GetNbinsY()) { - w_antip_jet = 1.0; - w_antip_ue = 1.0; + + // protection + if (ix == 0 || ix > twod_weights_antip_jet->GetNbinsX()) { + w_antip_jet = 1.0; + w_antip_ue = 1.0; + } + if (iy == 0 || iy > twod_weights_antip_jet->GetNbinsY()) { + w_antip_jet = 1.0; + w_antip_ue = 1.0; + } } // Antiproton @@ -882,7 +885,7 @@ struct nuclei_in_jets { continue; registryMC.fill(HIST("number_of_events_mc"), 4.5); - if (std::abs(collision.posZ()) > zVtx) + if (TMath::Abs(collision.posZ()) > zVtx) continue; registryMC.fill(HIST("number_of_events_mc"), 5.5); @@ -949,7 +952,7 @@ struct nuclei_in_jets { int n_jets_selected(0); for (int i = 0; i < static_cast(jet.size()); i++) { - if ((std::abs(jet[i].Eta()) + Rjet) > max_eta) + if ((TMath::Abs(jet[i].Eta()) + Rjet) > max_eta) continue; // Perpendicular cones @@ -1063,7 +1066,7 @@ struct nuclei_in_jets { registryMC.fill(HIST("number_of_events_mc"), 7.5); // Selection on z_{vertex} - if (std::abs(mccollision.posZ()) > 10) + if (TMath::Abs(mccollision.posZ()) > 10) continue; registryMC.fill(HIST("number_of_events_mc"), 8.5); @@ -1083,12 +1086,12 @@ struct nuclei_in_jets { double dy = particle.vy() - mccollision.posY(); double dz = particle.vz() - mccollision.posZ(); double dcaxy = sqrt(dx * dx + dy * dy); - double dcaz = std::abs(dz); + double dcaz = TMath::Abs(dz); if (setDCAselectionPtDep) { - if (dcaxy > (0.004f + 0.013f / particle.pt())) + if (dcaxy > (par0 + par1 / particle.pt())) continue; - if (dcaz > (0.004f + 0.013f / particle.pt())) + if (dcaz > (par0 + par1 / particle.pt())) continue; } if (!setDCAselectionPtDep) { @@ -1098,13 +1101,13 @@ struct nuclei_in_jets { continue; } - if (std::abs(particle.eta()) > 0.8) + if (TMath::Abs(particle.eta()) > 0.8) continue; if (particle.pt() < 0.15) continue; // PDG Selection - int pdg = abs(particle.pdgCode()); + int pdg = TMath::Abs(particle.pdgCode()); if ((pdg != 11) && (pdg != 211) && (pdg != 321) && (pdg != 2212)) continue; @@ -1161,7 +1164,7 @@ struct nuclei_in_jets { int n_jets_selected(0); for (int i = 0; i < static_cast(jet.size()); i++) { - if ((std::abs(jet[i].Eta()) + Rjet) > max_eta) + if ((TMath::Abs(jet[i].Eta()) + Rjet) > max_eta) continue; // Perpendicular cones @@ -1184,12 +1187,12 @@ struct nuclei_in_jets { double dy = particle.vy() - mccollision.posY(); double dz = particle.vz() - mccollision.posZ(); double dcaxy = sqrt(dx * dx + dy * dy); - double dcaz = std::abs(dz); + double dcaz = TMath::Abs(dz); if (setDCAselectionPtDep) { - if (dcaxy > (0.004f + 0.013f / particle.pt())) + if (dcaxy > (par0 + par1 / particle.pt())) continue; - if (dcaz > (0.004f + 0.013f / particle.pt())) + if (dcaz > (par0 + par1 / particle.pt())) continue; } if (!setDCAselectionPtDep) { @@ -1199,13 +1202,13 @@ struct nuclei_in_jets { continue; } - if (std::abs(particle.eta()) > 0.8) + if (TMath::Abs(particle.eta()) > 0.8) continue; if (particle.pt() < 0.15) continue; // PDG Selection - int pdg = abs(particle.pdgCode()); + int pdg = TMath::Abs(particle.pdgCode()); if ((pdg != 11) && (pdg != 211) && (pdg != 321) && (pdg != 2212)) continue; diff --git a/PWGLF/Tasks/Nuspex/spectraTOF.cxx b/PWGLF/Tasks/Nuspex/spectraTOF.cxx index 5523f27efb5..21500de73fb 100644 --- a/PWGLF/Tasks/Nuspex/spectraTOF.cxx +++ b/PWGLF/Tasks/Nuspex/spectraTOF.cxx @@ -122,6 +122,7 @@ struct tofSpectra { Configurable minNCrossedRowsTPC{"minNCrossedRowsTPC", 70.f, "Additional cut on the minimum number of crossed rows in the TPC"}; Configurable minNCrossedRowsOverFindableClustersTPC{"minNCrossedRowsOverFindableClustersTPC", 0.8f, "Additional cut on the minimum value of the ratio between crossed rows and findable clusters in the TPC"}; Configurable maxChi2PerClusterTPC{"maxChi2PerClusterTPC", 4.f, "Additional cut on the maximum value of the chi2 per cluster in the TPC"}; + Configurable minChi2PerClusterTPC{"minChi2PerClusterTPC", 0.5f, "Additional cut on the minimum value of the chi2 per cluster in the TPC"}; Configurable maxChi2PerClusterITS{"maxChi2PerClusterITS", 36.f, "Additional cut on the maximum value of the chi2 per cluster in the ITS"}; Configurable maxDcaXYFactor{"maxDcaXYFactor", 1.f, "Additional cut on the maximum value of the DCA xy (multiplicative factor)"}; Configurable maxDcaZ{"maxDcaZ", 2.f, "Additional cut on the maximum value of the DCA z"}; @@ -203,6 +204,7 @@ struct tofSpectra { LOG(info) << "\trequireTPC=" << requireTPC.value; LOG(info) << "\trequireGoldenChi2=" << requireGoldenChi2.value; LOG(info) << "\tmaxChi2PerClusterTPC=" << maxChi2PerClusterTPC.value; + LOG(info) << "\tminChi2PerClusterTPC=" << minChi2PerClusterTPC.value; LOG(info) << "\tminNCrossedRowsTPC=" << minNCrossedRowsTPC.value; LOG(info) << "\tminTPCNClsFound=" << minTPCNClsFound.value; LOG(info) << "\tmaxChi2PerClusterITS=" << maxChi2PerClusterITS.value; @@ -1153,6 +1155,10 @@ struct tofSpectra { } } + if (track.tpcChi2NCl() < minChi2PerClusterTPC || track.tpcChi2NCl() > maxChi2PerClusterTPC) { + return false; + } + if (!passesCutWoDCA(track)) { return false; } diff --git a/PWGLF/Tasks/QC/CMakeLists.txt b/PWGLF/Tasks/QC/CMakeLists.txt index c640ee82586..20377eb08cb 100644 --- a/PWGLF/Tasks/QC/CMakeLists.txt +++ b/PWGLF/Tasks/QC/CMakeLists.txt @@ -44,6 +44,12 @@ o2physics_add_dpl_workflow(its-tpc-matching-qa PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(strangeness-tracking-qc + SOURCES strangenessTrackingQC.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2::ReconstructionDataFormats O2Physics::AnalysisCore O2::DetectorsBase + COMPONENT_NAME Analysis) + + o2physics_add_dpl_workflow(mc-signal-loss SOURCES mcSignalLoss.cxx PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore @@ -113,3 +119,8 @@ o2physics_add_dpl_workflow(mc-particle-predictions SOURCES mcParticlePrediction.cxx PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(strange-derived-qa + SOURCES strangederivedqa.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore + COMPONENT_NAME Analysis) diff --git a/PWGLF/Tasks/QC/strangederivedqa.cxx b/PWGLF/Tasks/QC/strangederivedqa.cxx new file mode 100644 index 00000000000..2e709e07338 --- /dev/null +++ b/PWGLF/Tasks/QC/strangederivedqa.cxx @@ -0,0 +1,158 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. +// +// V0 analysis task +// ================ +// +// This code does basic QA of strangeness derived data + +#include +#include +#include +#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 "CommonConstants/PhysicsConstants.h" +#include "Common/Core/trackUtilities.h" +#include "PWGLF/DataModel/LFStrangenessTables.h" + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace std; +using std::array; + +struct strangederivedqa { + HistogramRegistry histos{"Histos", {}, OutputObjHandlingPolicy::AnalysisObject}; + + ConfigurableAxis axisNCollisions{"axisNCollisions", {50000, -0.5f, 49999.5f}, "collisions"}; + ConfigurableAxis axisNV0s{"axisNV0s", {50000, -0.5f, 49999.5f}, "V0s"}; + + Configurable verbose{"verbose", false, "do more printouts"}; + + void init(InitContext const&) + { + auto h = histos.add("hDFCounter", "hDFCounter", kTH1D, {{6, -0.5f, 5.5f}}); + h->GetXaxis()->SetBinLabel(1, "All"); + h->GetXaxis()->SetBinLabel(2, "Ordered"); + h->GetXaxis()->SetBinLabel(3, "Unordered"); + + auto h2 = histos.add("hEventCounter", "hEventCounter", kTH2D, {{1, -0.5f, 0.5f}, {3, -0.5f, 2.5f}}); + auto h3 = histos.add("hEventsPerDF", "hEventsPerDF", kTH2D, {axisNCollisions, {3, -0.5f, 2.5f}}); + auto h4 = histos.add("hV0sPerDF", "hV0sPerDF", kTH2D, {axisNV0s, {3, -0.5f, 2.5f}}); + + h2->GetYaxis()->SetBinLabel(1, "All"); + h2->GetYaxis()->SetBinLabel(2, "Ordered"); + h2->GetYaxis()->SetBinLabel(3, "Unordered"); + h3->GetYaxis()->SetBinLabel(1, "All"); + h3->GetYaxis()->SetBinLabel(2, "Ordered"); + h3->GetYaxis()->SetBinLabel(3, "Unordered"); + h4->GetYaxis()->SetBinLabel(1, "All"); + h4->GetYaxis()->SetBinLabel(2, "Ordered"); + h4->GetYaxis()->SetBinLabel(3, "Unordered"); + } + + // Real data processing + void processOriginal(aod::Collisions const& collisions, aod::Origins const& origins, soa::Join const& fullV0s) + { + histos.fill(HIST("hDFCounter"), 0.0f); + histos.fill(HIST("hEventCounter"), 0.0f, 0.0f, collisions.size()); + histos.fill(HIST("hEventsPerDF"), collisions.size(), 0.0f); + histos.fill(HIST("hV0sPerDF"), fullV0s.size(), 0.0f); + bool ordered = true; + int previousIndex = -100; + for (auto const& v0 : fullV0s) { + if (v0.collisionId() < previousIndex) { + ordered = false; + } + previousIndex = v0.collisionId(); + } + if (ordered) { + histos.fill(HIST("hEventCounter"), 0.0f, 1.0f, collisions.size()); + histos.fill(HIST("hEventsPerDF"), collisions.size(), 1.0f); + histos.fill(HIST("hV0sPerDF"), fullV0s.size(), 1.0f); + + if (verbose) { + auto origin = origins.begin(); + LOGF(info, "Sorted DF ID: %lld collisions: %i V0s: %i", origin.dataframeID(), collisions.size(), fullV0s.size()); + } + } else { + histos.fill(HIST("hEventCounter"), 0.0f, 2.0f, collisions.size()); + histos.fill(HIST("hEventsPerDF"), collisions.size(), 2.0f); + histos.fill(HIST("hV0sPerDF"), fullV0s.size(), 2.0f); + + if (verbose) { + auto origin = origins.begin(); + LOGF(info, "Unsorted DF ID: %lld collisions: %i V0s: %i", origin.dataframeID(), collisions.size(), fullV0s.size()); + } + } + } + + // Real data processing + void processDerived(aod::StraCollisions const& collisions, aod::StraOrigins const& origins, soa::Join const& fullV0s) + { + histos.fill(HIST("hDFCounter"), 0.0f); + histos.fill(HIST("hEventCounter"), 0.0f, 0.0f, collisions.size()); + histos.fill(HIST("hEventsPerDF"), collisions.size(), 0.0f); + histos.fill(HIST("hV0sPerDF"), fullV0s.size(), 0.0f); + bool ordered = true; + int previousIndex = -100; + for (auto const& v0 : fullV0s) { + if (v0.straCollisionId() < previousIndex) { + ordered = false; + } + previousIndex = v0.straCollisionId(); + } + if (ordered) { + histos.fill(HIST("hEventCounter"), 0.0f, 1.0f, collisions.size()); + histos.fill(HIST("hEventsPerDF"), collisions.size(), 1.0f); + histos.fill(HIST("hV0sPerDF"), fullV0s.size(), 1.0f); + + if (verbose) { + auto origin = origins.begin(); + LOGF(info, "Sorted DF ID: %lld collisions: %i V0s: %i Origins size: %i", origin.dataframeID(), collisions.size(), fullV0s.size(), origins.size()); + } + } else { + histos.fill(HIST("hEventCounter"), 0.0f, 2.0f, collisions.size()); + histos.fill(HIST("hEventsPerDF"), collisions.size(), 2.0f); + histos.fill(HIST("hV0sPerDF"), fullV0s.size(), 2.0f); + + if (verbose) { + auto origin = origins.begin(); + LOGF(info, "Unsorted DF ID: %lld collisions: %i V0s: %i Origins size: %i", origin.dataframeID(), collisions.size(), fullV0s.size(), origins.size()); + uint64_t directoryName = origin.dataframeID(); + for (auto const& orig : origins) { + LOGF(info, "Unsorted DF ID: %lld separate origin: %lld", directoryName, orig.dataframeID()); + } + } + } + } + + PROCESS_SWITCH(strangederivedqa, processOriginal, "Process original data", false); + PROCESS_SWITCH(strangederivedqa, processDerived, "Process derived data", true); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc)}; +} diff --git a/PWGLF/Tasks/QC/strangenessTrackingQC.cxx b/PWGLF/Tasks/QC/strangenessTrackingQC.cxx new file mode 100644 index 00000000000..09c5698fd92 --- /dev/null +++ b/PWGLF/Tasks/QC/strangenessTrackingQC.cxx @@ -0,0 +1,311 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does 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 "Common/DataModel/Centrality.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/PIDResponse.h" +#include "Common/DataModel/TrackSelectionTables.h" +#include "Common/Core/RecoDecay.h" +#include "Common/Core/trackUtilities.h" +#include "DataFormatsParameters/GRPMagField.h" +#include "DataFormatsParameters/GRPObject.h" +#include "DataFormatsTPC/BetheBlochAleph.h" +#include "DCAFitter/DCAFitterN.h" +#include "DetectorsBase/Propagator.h" +#include "Framework/AnalysisTask.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/ASoA.h" +#include "Framework/ASoAHelpers.h" +#include "Framework/HistogramRegistry.h" +#include "Framework/runDataProcessing.h" +// #include "PWGHF/Core/PDG.h" +#include "PWGLF/DataModel/LFStrangenessTables.h" +#include "ReconstructionDataFormats/DCA.h" +#include "ReconstructionDataFormats/Track.h" +#include "PWGLF/DataModel/LFNonPromptCascadeTables.h" + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; + +namespace +{ + +}; + +struct miniCasc { + bool fillOmega; + float pt; + float eta; + float phi; + float radius; + float massOmega; + float massXi; + float dcaXYCasc; + float dcaXYTracked; +}; + +struct strangenessTrackingQC { + + using TrackCandidates = soa::Join; + using CollisionCandidates = soa::Join; + + Configurable setting_materialCorrection{"cfgMaterialCorrection", static_cast(o2::base::Propagator::MatCorrType::USEMatCorrLUT), "Type of material correction"}; + + Configurable cascsetting_dcaCascDaughters{"casc_setting_dcaV0daughters", 0.1f, "DCA between the V0 daughters"}; + Configurable cascsetting_cosPA{"casc_setting_cosPA", 0.995f, "Cosine of the pointing angle of the V0"}; + Configurable cascsetting_massWindowXi{"casc_setting_massWindowXi", 0.01f, "Mass window for the Xi"}; + + Configurable cfgGRPmagPath{"cfgGRPmagPath", "GLO/Config/GRPMagField", "CCDB path of the GRPMagField object"}; + Configurable cfgGRPpath{"cfgGRPpath", "GLO/GRP/GRP", "Path of the grp file"}; + + Configurable cfgCutNclusTPC{"cfgCutNclusTPC", 70, "Minimum number of TPC clusters"}; + + ConfigurableAxis ptBins{"ptBins", {200, -10.f, 10.f}, "Binning for #it{p}_{T} (GeV/#it{c})"}; + ConfigurableAxis dcaBins{"dcaBins", {1e3, -0.1, 0.1}, "Binning for DCA (cm)"}; + ConfigurableAxis decayRadBins{"decayRadBins", {100, 0.f, 40.f}, "Binning for decay radius (cm)"}; + ConfigurableAxis omegaMassBins{"omegaMassBins", {125, 1.650, 1.700}, "Invariant mass (GeV/#it{c}^{2})"}; + ConfigurableAxis xiMassBins{"xiMassBins", {125, 1.296, 1.346}, "Invariant mass (GeV/#it{c}^{2})"}; + + Service ccdb; + int mRunNumber = 0; + float bz = 0.f; + o2::vertexing::DCAFitterN<2> m_fitter; + + HistogramRegistry registry{ + "registry", + { + {"omegaMass", "; Mass (GeV/#it{c}^{2}); Counts", {HistType::kTH1F, {{125, 1.650, 1.700}}}}, + {"xiMass", "; Mass (GeV/#it{c}^{2}); Counts", {HistType::kTH1F, {{125, 1.296, 1.346}}}}, + {"omegaMassTracked", "; Mass (GeV/#it{c}^{2}); Counts", {HistType::kTH1F, {{125, 1.650, 1.700}}}}, + {"xiMassTracked", "; Mass (GeV/#it{c}^{2}); Counts", {HistType::kTH1F, {{125, 1.296, 1.346}}}}, + + {"omegaHist", "; #it{p}_{T} (GeV/#it{c}); Radius (cm); Mass", {HistType::kTH3F, {{ptBins, decayRadBins, omegaMassBins}}}}, + {"xiHist", "; #it{p}_{T} (GeV/#it{c}); Radius (cm); Mass", {HistType::kTH3F, {{ptBins, decayRadBins, xiMassBins}}}}, + {"xiHistTracked", "; #it{p}_{T} (GeV/#it{c}); Radius (cm); Mass", {HistType::kTH3F, {{ptBins, decayRadBins, xiMassBins}}}}, + {"omegaHistTracked", "; #it{p}_{T} (GeV/#it{c}); Radius (cm); Mass", {HistType::kTH3F, {{ptBins, decayRadBins, omegaMassBins}}}}, + + {"xiDCAvsPt", "; #it{p}_{T} (GeV/#it{c}); DCA (cm)", {HistType::kTH2F, {{ptBins, dcaBins}}}}, + {"omegaDCAvsPt", "; #it{p}_{T} (GeV/#it{c}); DCA (cm)", {HistType::kTH2F, {{ptBins, dcaBins}}}}, + {"xiDCAvsPtTracked", "; #it{p}_{T} (GeV/#it{c}); DCA (cm)", {HistType::kTH2F, {{ptBins, dcaBins}}}}, + {"omegaDCAvsPtTracked", "; #it{p}_{T} (GeV/#it{c}); DCA (cm)", {HistType::kTH2F, {{ptBins, dcaBins}}}}, + }}; + + template + float dcaToPV(o2::dataformats::VertexBase& PV, T& trackParCov) + { + auto matCorr = static_cast(setting_materialCorrection.value); + o2::dataformats::DCA impactParameterTrk; + o2::base::Propagator::Instance()->propagateToDCA(PV, trackParCov, bz, 2.f, matCorr, &impactParameterTrk); + return impactParameterTrk.getY(); + } + + template + bool qualityTrackSelection(const T& track) + { + if (std::abs(track.eta()) > 0.9) { + return false; + } + if (track.tpcNClsFound() < cfgCutNclusTPC) { + return false; + } + return true; + } + + float computeMassMother(const float massA, const float massB, const std::array& momA, const std::array& momB) const + { + float eA = std::hypot(massA, std::hypot(momA[0], momA[1], momA[2])); + float eB = std::hypot(massB, std::hypot(momB[0], momB[1], momB[2])); + float momTot = std::hypot(momA[0] + momB[0], momA[1] + momB[1], momA[2] + momB[2]); + float eMother = eA + eB; + return std::sqrt(eMother * eMother - momTot * momTot); + } + + template + bool buildCascade(TCasc const& casc, CollisionCandidates::iterator const& collision, aod::V0s const&, TrackCandidates const&, miniCasc& miniCasc) + { + const auto& v0 = casc.template v0_as(); + const auto& bachelor = casc.template bachelor_as(); + const auto& ptrack = v0.template posTrack_as(); + const auto& ntrack = v0.template negTrack_as(); + if (!qualityTrackSelection(ptrack) || !qualityTrackSelection(ntrack) || !qualityTrackSelection(bachelor)) { + return false; + } + const auto& protonTrack = bachelor.sign() > 0 ? ntrack : ptrack; + const auto& pionTrack = bachelor.sign() > 0 ? ptrack : ntrack; + if (std::abs(protonTrack.tpcNSigmaPr()) > 3 || std::abs(pionTrack.tpcNSigmaPi()) > 3) { + return false; + } + auto primaryVertex = getPrimaryVertex(collision); + std::array pvPos = {primaryVertex.getX(), primaryVertex.getY(), primaryVertex.getZ()}; + + float cascCpa = -1; + float cascDauDCA = -1; + + std::array cascMom; + std::array v0Mom; + std::array bachelorMom; + + // track propagation + o2::track::TrackParCov trackParCovV0; + o2::track::TrackPar trackParV0; + o2::track::TrackPar trackParBachelor; + o2::track::TrackParCov trackParCovCasc; + if (m_fitter.process(getTrackParCov(pionTrack), getTrackParCov(protonTrack))) { + trackParCovV0 = m_fitter.createParentTrackParCov(0); // V0 track retrieved from p and pi daughters + if (m_fitter.process(trackParCovV0, getTrackParCov(bachelor))) { + trackParV0 = m_fitter.getTrackParamAtPCA(0); + trackParBachelor = m_fitter.getTrackParamAtPCA(1); + trackParV0.getPxPyPzGlo(v0Mom); + trackParBachelor.getPxPyPzGlo(bachelorMom); + trackParCovCasc = m_fitter.createParentTrackParCov(); + trackParCovCasc.getPxPyPzGlo(cascMom); + cascCpa = RecoDecay::cpa(pvPos, m_fitter.getPCACandidate(), cascMom); + cascDauDCA = std::sqrt(std::abs(m_fitter.getChi2AtPCACandidate())); + } else { + return false; + } + } else { + return false; + } + + if (cascCpa < cascsetting_cosPA) { + return false; + } + + if (cascDauDCA > cascsetting_dcaCascDaughters) { + return false; + } + + int chargeFactor = bachelor.sign() > 0 ? 1 : -1; + miniCasc.pt = chargeFactor * std::hypot(cascMom[0], cascMom[1]); + miniCasc.massOmega = computeMassMother(constants::physics::MassLambda0, constants::physics::MassKaonCharged, v0Mom, bachelorMom); + miniCasc.massXi = computeMassMother(constants::physics::MassLambda0, constants::physics::MassPionCharged, v0Mom, bachelorMom); + miniCasc.fillOmega = false; + if (TMath::Abs(miniCasc.massXi - constants::physics::MassXiMinus) > cascsetting_massWindowXi && std::abs(bachelor.tpcNSigmaKa()) < 3) { + miniCasc.fillOmega = true; + } + + miniCasc.dcaXYCasc = dcaToPV(primaryVertex, trackParCovCasc); + auto svPos = m_fitter.getPCACandidate(); + miniCasc.radius = std::hypot(svPos[0], svPos[1]); + + return true; + } + + void initCCDB(aod::BCsWithTimestamps::iterator const& bc) + { + if (mRunNumber == bc.runNumber()) { + return; + } + mRunNumber = bc.runNumber(); + auto timestamp = bc.timestamp(); + + if (o2::parameters::GRPObject* grpo = ccdb->getForTimeStamp(cfgGRPpath, timestamp)) { + o2::base::Propagator::initFieldFromGRP(grpo); + bz = grpo->getNominalL3Field(); + } else if (o2::parameters::GRPMagField* grpmag = ccdb->getForTimeStamp(cfgGRPmagPath, timestamp)) { + o2::base::Propagator::initFieldFromGRP(grpmag); + bz = std::lround(5.f * grpmag->getL3Current() / 30000.f); + LOG(debug) << "bz = " << bz; + } else { + LOG(fatal) << "Got nullptr from CCDB for path " << cfgGRPmagPath << " of object GRPMagField and " << cfgGRPpath << " of object GRPObject for timestamp " << timestamp; + } + } + + void init(InitContext const&) + { + mRunNumber = 0; + bz = 0; + + if (static_cast(setting_materialCorrection.value) == o2::base::Propagator::MatCorrType::USEMatCorrLUT) { + auto* lut = o2::base::MatLayerCylSet::rectifyPtrFromFile(ccdb->get("GLO/Param/MatLUT")); + LOG(info) << "Setting material correction LUT"; + o2::base::Propagator::Instance(true)->setMatLUT(lut); + } + + ccdb->setURL("http://alice-ccdb.cern.ch"); + ccdb->setCaching(true); + ccdb->setLocalObjectValidityChecking(); + ccdb->setFatalWhenNull(false); + m_fitter.setPropagateToPCA(true); + m_fitter.setMaxR(200.); + m_fitter.setMinParamChange(1e-3); + m_fitter.setMinRelChi2Change(0.9); + m_fitter.setMaxDZIni(4); + m_fitter.setMaxDXYIni(4); + m_fitter.setMaxChi2(1e9); + m_fitter.setUseAbsDCA(true); + m_fitter.setWeightedFinalPCA(false); + // int mat{static_cast(setting_materialCorrection)}; + // m_fitter.setMatCorrType(static_cast(mat)); + } + + void process(CollisionCandidates const&, aod::AssignedTrackedCascades const& trackedCascades, aod::Cascades const& cascades, aod::V0s const& v0s, TrackCandidates const& tracks, aod::BCsWithTimestamps const&) + { + + for (const auto& trackedCascade : trackedCascades) { + miniCasc miniCasc; + const auto& casc = trackedCascade.cascade(); + auto collision = trackedCascade.collision_as(); + if (!collision.sel8() || std::abs(collision.posZ()) > 10) { + continue; + } + initCCDB(collision.bc_as()); + m_fitter.setBz(bz); + if (buildCascade(casc, collision, v0s, tracks, miniCasc)) { + + // compute the dca of the tracked cascade + const auto& track = trackedCascade.track_as(); + auto trackCovTrk = getTrackParCov(track); + + auto primaryVertex = getPrimaryVertex(collision); + miniCasc.dcaXYTracked = dcaToPV(primaryVertex, trackCovTrk); + // fill the histograms + if (miniCasc.fillOmega) { + registry.fill(HIST("omegaMassTracked"), miniCasc.massOmega); + registry.fill(HIST("omegaDCAvsPtTracked"), miniCasc.pt, miniCasc.dcaXYTracked); + registry.fill(HIST("omegaHistTracked"), miniCasc.pt, miniCasc.radius, miniCasc.massOmega); + } + registry.fill(HIST("xiMassTracked"), miniCasc.massXi); + registry.fill(HIST("xiDCAvsPtTracked"), miniCasc.pt, miniCasc.dcaXYTracked); + registry.fill(HIST("xiHistTracked"), miniCasc.pt, miniCasc.radius, miniCasc.massXi); + } + } + + for (auto& cascade : cascades) { + miniCasc miniCasc; + auto collision = cascade.collision_as(); + if (!collision.sel8() || std::abs(collision.posZ()) > 10) { + continue; + } + initCCDB(collision.bc_as()); + m_fitter.setBz(bz); + if (buildCascade(cascade, collision, v0s, tracks, miniCasc)) { + if (miniCasc.fillOmega) { + registry.fill(HIST("omegaMass"), miniCasc.massOmega); + registry.fill(HIST("omegaDCAvsPt"), miniCasc.pt, miniCasc.dcaXYCasc); + registry.fill(HIST("omegaHist"), miniCasc.pt, miniCasc.radius, miniCasc.massOmega); + } + registry.fill(HIST("xiMass"), miniCasc.massXi); + registry.fill(HIST("xiDCAvsPt"), miniCasc.pt, miniCasc.dcaXYCasc); + registry.fill(HIST("xiHist"), miniCasc.pt, miniCasc.radius, miniCasc.massXi); + } + } + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc)}; +} diff --git a/PWGLF/Tasks/Resonances/f0980pbpbanalysis.cxx b/PWGLF/Tasks/Resonances/f0980pbpbanalysis.cxx index 4eca3e4f45a..bb27b5f81c7 100644 --- a/PWGLF/Tasks/Resonances/f0980pbpbanalysis.cxx +++ b/PWGLF/Tasks/Resonances/f0980pbpbanalysis.cxx @@ -62,9 +62,6 @@ using namespace o2::soa; using namespace o2::constants::physics; struct f0980pbpbanalysis { - using EventCandidates = soa::Join; - using TrackCandidates = soa::Join; - HistogramRegistry histos{ "histos", {}, @@ -76,6 +73,13 @@ struct f0980pbpbanalysis { 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"}; + Configurable cfgCutVertex{"cfgCutVertex", 10.0, "PV selection"}; + Configurable cfgQvecSel{"cfgQvecSel", true, "Reject events when no QVector"}; + Configurable cfgOccupancySel{"cfgOccupancySe", false, "Occupancy selection"}; + Configurable cfgMaxOccupancy{"cfgMaxOccupancy", 999999, "maximum occupancy of tracks in neighbouring collisions in a given time range"}; + Configurable cfgMinOccupancy{"cfgMinOccupancy", -100, "maximum occupancy of tracks in neighbouring collisions in a given time range"}; + Configurable cfgNCollinTR{"cfgNCollinTR", false, "Additional selection for the number of coll in time range"}; + Configurable cfgCentSel{"cfgCentSel", 80., "Centrality selection"}; Configurable cfgCentEst{"cfgCentEst", 1, "Centrality estimator, 1: FT0C, 2: FT0M"}; @@ -127,6 +131,13 @@ struct f0980pbpbanalysis { double massPi = o2::constants::physics::MassPionCharged; + Filter collisionFilter = nabs(aod::collision::posZ) < cfgCutVertex; + Filter acceptanceFilter = (nabs(aod::track::eta) < cfgMaxEta && nabs(aod::track::pt) > cfgMinPt); + Filter DCAcutFilter = (nabs(aod::track::dcaXY) < cfgMaxDCArToPVcut) && (nabs(aod::track::dcaZ) < cfgMaxDCAzToPVcut); + + using EventCandidates = soa::Filtered>; + using TrackCandidates = soa::Filtered>; + template int GetDetId(const T& name) { @@ -172,7 +183,13 @@ struct f0980pbpbanalysis { if (!collision.selection_bit(aod::evsel::kNoSameBunchPileup)) { return 0; } - if (collision.qvecAmp()[DetId] < 1e-4 || collision.qvecAmp()[RefAId] < 1e-4 || collision.qvecAmp()[RefAId] < 1e-4) { + if (cfgQvecSel && (collision.qvecAmp()[DetId] < 1e-4 || collision.qvecAmp()[RefAId] < 1e-4 || collision.qvecAmp()[RefAId] < 1e-4)) { + return 0; + } + if (cfgOccupancySel && (collision.trackOccupancyInTimeRange() > cfgMaxOccupancy || collision.trackOccupancyInTimeRange() < cfgMinOccupancy)) { + return 0; + } + if (cfgNCollinTR && !collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard)) { return 0; } @@ -247,9 +264,9 @@ struct f0980pbpbanalysis { double eventPlaneRefB = TMath::ATan2(collision.qvecIm()[QvecRefBInd], collision.qvecRe()[QvecRefBInd]) / static_cast(nmode); histos.fill(HIST("QA/EPhist"), centrality, eventPlaneDet); - histos.fill(HIST("QA/QA/EPResAB"), centrality, TMath::Cos(static_cast(nmode) * (eventPlaneDet - eventPlaneRefA))); - histos.fill(HIST("QA/QA/EPResAC"), centrality, TMath::Cos(static_cast(nmode) * (eventPlaneDet - eventPlaneRefB))); - histos.fill(HIST("QA/QA/EPResBC"), centrality, TMath::Cos(static_cast(nmode) * (eventPlaneRefA - eventPlaneRefB))); + histos.fill(HIST("QA/EPResAB"), centrality, TMath::Cos(static_cast(nmode) * (eventPlaneDet - eventPlaneRefA))); + histos.fill(HIST("QA/EPResAC"), centrality, TMath::Cos(static_cast(nmode) * (eventPlaneDet - eventPlaneRefB))); + histos.fill(HIST("QA/EPResBC"), centrality, TMath::Cos(static_cast(nmode) * (eventPlaneRefA - eventPlaneRefB))); TLorentzVector Pion1, Pion2, Reco; for (auto& [trk1, trk2] : diff --git a/PWGLF/Tasks/Resonances/k1analysis.cxx b/PWGLF/Tasks/Resonances/k1analysis.cxx index e3599531046..7d145eff641 100644 --- a/PWGLF/Tasks/Resonances/k1analysis.cxx +++ b/PWGLF/Tasks/Resonances/k1analysis.cxx @@ -27,55 +27,96 @@ #include "Framework/runDataProcessing.h" #include "PWGLF/DataModel/LFResonanceTables.h" #include "DataFormatsParameters/GRPObject.h" +#include "CommonConstants/PhysicsConstants.h" using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; using namespace o2::soa; +using namespace o2::constants::physics; struct k1analysis { + 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 - Configurable cUseOnlyTOFTrackKa{"cUseOnlyTOFTrackKa", false, "Use only TOF track for PID selection"}; // Use only TOF track for Kaon 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 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 cfgPVContributor{"cfgPVContributor", true, "PV contributor track selection"}; // PV Contriuibutor - - // bachelor pion TOF PID? - Configurable cDoTOFPID{"cDoTOFPID", 1, "Do TOF PID"}; - - // K(892)0 selection - Configurable cK892masswindow{"cK892masswindow", 0.1, "K(892)0 inv mass selection window"}; - Configurable cPiPiMin{"cPiPiMin", 0, "Pion pair inv mass selection minimum"}; - Configurable cPiPiMax{"cPiPiMax", 999, "Pion pair inv mass selection maximum"}; - Configurable cPiKaMin{"cPiKaMin", 0, "bPion-Kaon pair inv mass selection minimum"}; - Configurable cPiKaMax{"cPiKaMax", 999, "bPion-Kaon pair inv mass selection maximum"}; + Configurable cfgGlobalTrack{"cfgGlobalTrack", false, "Global track selection"}; // kGoldenChi2 | kDCAxy | kDCAz + Configurable cfgPVContributor{"cfgPVContributor", false, "PV contributor track selection"}; // PV Contriuibutor + Configurable additionalQAplots{"additionalQAplots", true, "Additional QA plots"}; + Configurable tof_at_high_pt{"tof_at_high_pt", false, "Use TOF at high pT"}; + Configurable additionalEvsel{"additionalEvsel", true, "Additional event selcection"}; + Configurable 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 cfgModeK892orRho{"cfgModeK892orRho", true, "Secondary scenario for K892 (true) or Rho (false)"}; + Configurable cSecondaryMasswindow{"cSecondaryMasswindow", 0.1, "Secondary inv mass selection window"}; + Configurable cMinAnotherSecondaryMassCut{"cMinAnotherSecondaryMassCut", 0, "Min inv. mass selection of another secondary scenario"}; + Configurable cMaxAnotherSecondaryMassCut{"cMaxAnotherSecondaryMassCut", 999, "MAx inv. mass selection of another secondary scenario"}; + Configurable cMinPiKaMassCut{"cMinPiKaMassCut", 0, "bPion-Kaon pair inv mass selection minimum"}; + Configurable cMaxPiKaMassCut{"cMaxPiKaMassCut", 999, "bPion-Kaon pair inv mass selection maximum"}; Configurable cMinAngle{"cMinAngle", 0, "Minimum angle between K(892)0 and bachelor pion"}; Configurable cMaxAngle{"cMaxAngle", 4, "Maximum angle between K(892)0 and bachelor pion"}; Configurable cMinPairAsym{"cMinPairAsym", -1, "Minimum pair asymmetry"}; @@ -92,108 +133,174 @@ struct k1analysis { AxisSpec ptAxis = {150, 0, 15, "#it{p}_{T} (GeV/#it{c})"}; AxisSpec dcaxyAxis = {300, 0, 3, "DCA_{#it{xy}} (cm)"}; AxisSpec dcazAxis = {500, 0, 5, "DCA_{#it{xy}} (cm)"}; - AxisSpec invMassAxis = {900, 0.6, 1.5, "Invariant Mass (GeV/#it{c}^2)"}; // K(892)0 - AxisSpec invMassAxisReso = {1600, 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 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"}; - // Mass QA (quick check) - histos.add("k892invmass", "Invariant mass of K(892)0", HistType::kTH1F, {invMassAxis}); - histos.add("k1invmass", "Invariant mass of K1(1270)pm", HistType::kTH1F, {invMassAxisReso}); - histos.add("k1invmass_LS", "Invariant mass of K1(1270)pm", HistType::kTH1F, {invMassAxisReso}); - histos.add("k1invmass_Mix", "Invariant mass of K1(1270)pm", HistType::kTH1F, {invMassAxisReso}); - if (doprocessMC) { - histos.add("k1invmass_MC", "Invariant mass of K1(1270)pm", HistType::kTH1F, {invMassAxisReso}); - } + // 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 - histos.add("QA/trkDCAxy_pi", "DCAxy distribution of pion track candidates", HistType::kTH1F, {dcaxyAxis}); - histos.add("QA/trkDCAxy_ka", "DCAxy distribution of kaon track candidates", HistType::kTH1F, {dcaxyAxis}); - histos.add("QA/trkDCAxy_pi_bach", "DCAxy distribution of bachelor pion track candidates", HistType::kTH1F, {dcaxyAxis}); - histos.add("QA/trkDCAz_pi", "DCAz distribution of pion track candidates", HistType::kTH1F, {dcazAxis}); - histos.add("QA/trkDCAz_ka", "DCAz distribution of kaon track candidates", HistType::kTH1F, {dcazAxis}); - histos.add("QA/trkDCAz_pi_bach", "DCAz distribution of bachelor pion track candidates", HistType::kTH1F, {dcazAxis}); - - // pT QA - histos.add("QA/trkpT_pi", "pT distribution of pion track candidates", HistType::kTH1F, {ptAxis}); - histos.add("QA/trkpT_ka", "pT distribution of kaon track candidates", HistType::kTH1F, {ptAxis}); - histos.add("QA/trkpT_pi_bach", "pT distribution of bachelor pion track candidates", HistType::kTH1F, {ptAxis}); - // PID QA after cuts - histos.add("QA/TOF_TPC_Map_pi", "TOF + TPC Combined PID for Pion;#sigma_{TOF}^{Pion};#sigma_{TPC}^{Pion}", {HistType::kTH2F, {pidQAAxis, pidQAAxis}}); - histos.add("QA/TOF_Nsigma_pi", "TOF NSigma for Pion;#it{p}_{T} (GeV/#it{c});#sigma_{TOF}^{Pion};", {HistType::kTH2F, {ptAxis, pidQAAxis}}); - histos.add("QA/TPC_Nsigma_pi", "TPC NSigma for Pion;#it{p}_{T} (GeV/#it{c});#sigma_{TPC}^{Pion};", {HistType::kTH2F, {ptAxis, pidQAAxis}}); - histos.add("QA/TOF_TPC_Map_ka", "TOF + TPC Combined PID for Pion;#sigma_{TOF}^{Kaon};#sigma_{TPC}^{Kaon}", {HistType::kTH2F, {pidQAAxis, pidQAAxis}}); - histos.add("QA/TOF_Nsigma_ka", "TOF NSigma for Pion;#it{p}_{T} (GeV/#it{c});#sigma_{TOF}^{Kaon};", {HistType::kTH2F, {ptAxis, pidQAAxis}}); - histos.add("QA/TPC_Nsigmaka", "TPC NSigma for Kaon;#it{p}_{T} (GeV/#it{c});#sigma_{TPC}^{Kaon};", {HistType::kTH2F, {ptAxis, pidQAAxis}}); - histos.add("QA/TOF_TPC_Map_pi_bach", "TOF + TPC Combined PID for Pion;#sigma_{TOF}^{Pion};#sigma_{TPC}^{Pion}", {HistType::kTH2F, {pidQAAxis, pidQAAxis}}); - histos.add("QA/TOF_Nsigma_pi_bach", "TOF NSigma for Pion;#it{p}_{T} (GeV/#it{c});#sigma_{TOF}^{Pion};", {HistType::kTH2F, {ptAxis, pidQAAxis}}); - histos.add("QA/TPC_Nsigma_pi_bach", "TPC NSigma for Pion;#it{p}_{T} (GeV/#it{c});#sigma_{TPC}^{Pion};", {HistType::kTH2F, {ptAxis, pidQAAxis}}); - histos.add("QA/InvMass_piK_pipi", "Invariant mass of pion + kaon and pion+pion;Invariant Mass (GeV/#it{c}^{2});Invariant Mass (GeV/#it{c}^{2});", {HistType::kTH2F, {invMassAxisScan, invMassAxisScan}}); - histos.add("QA/InvMass_piK_pika", "Invariant mass of pion + kaon and pion+kaon;Invariant Mass (GeV/#it{c}^{2});Invariant Mass (GeV/#it{c}^{2});", {HistType::kTH2F, {invMassAxisScan, invMassAxisScan}}); - histos.add("QA/K1OA", "Opening angle of K1(1270)pm", HistType::kTH1F, {AxisSpec{100, 0, 3.14, "Opening angle of K1(1270)pm"}}); - histos.add("QA/K1PairAsymm", "Pair asymmetry of K1(1270)pm", HistType::kTH1F, {AxisSpec{100, -1, 1, "Pair asymmetry of K1(1270)pm"}}); - - // Invariant mass histograms - histos.add("hK892invmass_PP", "Invariant mass of K(892)0 (Matter + Matter)", HistType::kTH3F, {centAxis, ptAxis, invMassAxis}); - histos.add("hK892invmass_NP", "Invariant mass of K(892)0 (Matter + Anti-matter)", HistType::kTH3F, {centAxis, ptAxis, invMassAxis}); - histos.add("hK892invmass_PN", "Invariant mass of K(892)0 (Anti-matter + Matter)", HistType::kTH3F, {centAxis, ptAxis, invMassAxis}); - histos.add("hK892invmass_NN", "Invariant mass of K(892)0 (Anti-matter + Anti-matter)", HistType::kTH3F, {centAxis, ptAxis, invMassAxis}); - histos.add("hK1invmass_NPP", "Invariant mass of K(892)0 + pion (Matter + Matter)", HistType::kTH3F, {centAxis, ptAxis, invMassAxisReso}); - histos.add("hK1invmass_NPN", "Invariant mass of K(892)0 + pion (Matter + Anti-matter)", HistType::kTH3F, {centAxis, ptAxis, invMassAxisReso}); - histos.add("hK1invmass_PNP", "Invariant mass of K(892)0 + pion (Anti-matter + Matter)", HistType::kTH3F, {centAxis, ptAxis, invMassAxisReso}); - histos.add("hK1invmass_PNN", "Invariant mass of K(892)0 + pion (Anti-matter + Anti-matter)", HistType::kTH3F, {centAxis, ptAxis, invMassAxisReso}); - // K892-LS bkg - histos.add("hK1invmass_PPP", "Invariant mass of K(892)0 + pion (Matter + Anti-matter)", HistType::kTH3F, {centAxis, ptAxis, invMassAxisReso}); - histos.add("hK1invmass_PPN", "Invariant mass of K(892)0 + pion (Anti-matter + Matter)", HistType::kTH3F, {centAxis, ptAxis, invMassAxisReso}); - histos.add("hK1invmass_NNP", "Invariant mass of K(892)0 + pion (Anti-matter + Anti-matter)", HistType::kTH3F, {centAxis, ptAxis, invMassAxisReso}); - histos.add("hK1invmass_NNN", "Invariant mass of K(892)0 + pion (Anti-matter + Anti-matter)", HistType::kTH3F, {centAxis, ptAxis, invMassAxisReso}); - // Mixed event - histos.add("hK1invmass_NPP_Mix", "Invariant mass of K(892)0 + pion (Matter + Matter)", HistType::kTH3F, {centAxis, ptAxis, invMassAxisReso}); - histos.add("hK1invmass_NPN_Mix", "Invariant mass of K(892)0 + pion (Matter + Anti-matter)", HistType::kTH3F, {centAxis, ptAxis, invMassAxisReso}); - histos.add("hK1invmass_PNP_Mix", "Invariant mass of K(892)0 + pion (Anti-matter + Matter)", HistType::kTH3F, {centAxis, ptAxis, invMassAxisReso}); - histos.add("hK1invmass_PNN_Mix", "Invariant mass of K(892)0 + pion (Anti-matter + Anti-matter)", HistType::kTH3F, {centAxis, ptAxis, invMassAxisReso}); + // Primary pion + histos.add("QA/trkppionDCAxy", "DCAxy distribution of primary pion candidates", HistType::kTH1F, {dcaxyAxis}); + histos.add("QA/trkppionDCAz", "DCAz distribution of primary pion candidates", HistType::kTH1F, {dcaxyAxis}); + histos.add("QA/trkppionpT", "pT distribution of primary pion candidates", HistType::kTH1F, {ptAxis}); + histos.add("QA/trkppionTPCPID", "TPC PID of primary pion candidates", HistType::kTH2F, {ptAxis, pidQAAxis}); + histos.add("QA/trkppionTOFPID", "TOF PID of primary pion candidates", HistType::kTH2F, {ptAxis, pidQAAxis}); + histos.add("QA/trkppionTPCTOFPID", "TPC-TOF PID map of primary pion candidates", HistType::kTH2F, {pidQAAxis, pidQAAxis}); + + histos.add("QAcut/trkppionDCAxy", "DCAxy distribution of primary pion candidates", HistType::kTH1F, {dcaxyAxis}); + histos.add("QAcut/trkppionDCAz", "DCAz distribution of primary pion candidates", HistType::kTH1F, {dcaxyAxis}); + histos.add("QAcut/trkppionpT", "pT distribution of primary pion candidates", HistType::kTH1F, {ptAxis}); + histos.add("QAcut/trkppionTPCPID", "TPC PID of primary pion candidates", HistType::kTH2F, {ptAxis, pidQAAxis}); + histos.add("QAcut/trkppionTOFPID", "TOF PID of primary pion candidates", HistType::kTH2F, {ptAxis, pidQAAxis}); + histos.add("QAcut/trkppionTPCTOFPID", "TPC-TOF PID map of primary pion candidates", HistType::kTH2F, {pidQAAxis, pidQAAxis}); + + // Secondary pion + histos.add("QA/trkspionDCAxy", "DCAxy distribution of secondary pion candidates", HistType::kTH1F, {dcaxyAxis}); + histos.add("QA/trkspionDCAz", "DCAz distribution of secondary pion candidates", HistType::kTH1F, {dcaxyAxis}); + histos.add("QA/trkspionpT", "pT distribution of secondary pion candidates", HistType::kTH1F, {ptAxis}); + histos.add("QA/trkspionTPCPID", "TPC PID of secondary pion candidates", HistType::kTH2F, {ptAxis, pidQAAxis}); + histos.add("QA/trkspionTOFPID", "TOF PID of secondary pion candidates", HistType::kTH2F, {ptAxis, pidQAAxis}); + histos.add("QA/trkspionTPCTOFPID", "TPC-TOF PID map of secondary pion candidates", HistType::kTH2F, {pidQAAxis, pidQAAxis}); + + histos.add("QAcut/trkspionDCAxy", "DCAxy distribution of secondary pion candidates", HistType::kTH1F, {dcaxyAxis}); + histos.add("QAcut/trkspionDCAz", "DCAz distribution of secondary pion candidates", HistType::kTH1F, {dcaxyAxis}); + histos.add("QAcut/trkspionpT", "pT distribution of secondary pion candidates", HistType::kTH1F, {ptAxis}); + histos.add("QAcut/trkspionTPCPID", "TPC PID of secondary pion candidates", HistType::kTH2F, {ptAxis, pidQAAxis}); + histos.add("QAcut/trkspionTOFPID", "TOF PID of secondary pion candidates", HistType::kTH2F, {ptAxis, pidQAAxis}); + histos.add("QAcut/trkspionTPCTOFPID", "TPC-TOF PID map of secondary pion candidates", HistType::kTH2F, {pidQAAxis, pidQAAxis}); + + // Kaon + histos.add("QA/trkkaonDCAxy", "DCAxy distribution of kaon candidates", HistType::kTH1F, {dcaxyAxis}); + histos.add("QA/trkkaonDCAz", "DCAz distribution of kaon candidates", HistType::kTH1F, {dcaxyAxis}); + histos.add("QA/trkkaonpT", "pT distribution of kaon candidates", HistType::kTH1F, {ptAxis}); + histos.add("QA/trkkaonTPCPID", "TPC PID of kaon candidates", HistType::kTH2F, {ptAxis, pidQAAxis}); + histos.add("QA/trkkaonTOFPID", "TOF PID of kaon candidates", HistType::kTH2F, {ptAxis, pidQAAxis}); + histos.add("QA/trkkaonTPCTOFPID", "TPC-TOF PID map of kaon candidates", HistType::kTH2F, {pidQAAxis, pidQAAxis}); + + histos.add("QAcut/trkkaonDCAxy", "DCAxy distribution of kaon candidates", HistType::kTH1F, {dcaxyAxis}); + histos.add("QAcut/trkkaonDCAz", "DCAz distribution of kaon candidates", HistType::kTH1F, {dcaxyAxis}); + histos.add("QAcut/trkkaonpT", "pT distribution of kaon candidates", HistType::kTH1F, {ptAxis}); + histos.add("QAcut/trkkaonTPCPID", "TPC PID of kaon candidates", HistType::kTH2F, {ptAxis, pidQAAxis}); + histos.add("QAcut/trkkaonTOFPID", "TOF PID of kaon candidates", HistType::kTH2F, {ptAxis, pidQAAxis}); + histos.add("QAcut/trkkaonTPCTOFPID", "TPC-TOF PID map of kaon candidates", HistType::kTH2F, {pidQAAxis, pidQAAxis}); + + // K1 + histos.add("QA/K1OA", "Opening angle of K1(1270)", HistType::kTH1F, {AxisSpec{100, 0, 3.14, "Opening angle"}}); + histos.add("QA/K1PairAssym", "Pair asymmetry of K1(1270)", HistType::kTH1F, {AxisSpec{100, -1, 1, "Pair asymmetry"}}); + histos.add("QA/hInvmassK892_Rho", "Invariant mass of K(892)0 vs Rho(770)", HistType::kTH2F, {invMassAxisK892, invMassAxisRho}); + histos.add("QA/hInvmassSecon_PiKa", "Invariant mass of secondary resonance vs pion-kaon", HistType::kTH2F, {invMassAxisK892, invMassAxisK892}); + histos.add("QA/hInvmassSecon", "Invariant mass of secondary resonance", HistType::kTH1F, {invMassAxisRho}); + histos.add("QA/hpT_Secondary", "pT distribution of secondary resonance", HistType::kTH1F, {ptAxis}); + + histos.add("QAcut/K1OA", "Opening angle of K1(1270)", HistType::kTH1F, {AxisSpec{100, 0, 3.14, "Opening angle"}}); + histos.add("QAcut/K1PairAssym", "Pair asymmetry of K1(1270)", HistType::kTH1F, {AxisSpec{100, -1, 1, "Pair asymmetry"}}); + histos.add("QAcut/hInvmassK892_Rho", "Invariant mass of K(892)0 vs Rho(770)", HistType::kTH2F, {invMassAxisK892, invMassAxisRho}); + histos.add("QAcut/hInvmassSecon_PiKa", "Invariant mass of secondary resonance vs pion-kaon", HistType::kTH2F, {invMassAxisK892, invMassAxisK892}); + histos.add("QAcut/hInvmassSecon", "Invariant mass of secondary resonance", HistType::kTH1F, {invMassAxisRho}); + histos.add("QAcut/hpT_Secondary", "pT distribution of secondary resonance", HistType::kTH1F, {ptAxis}); + + // Invariant mass + histos.add("hInvmass_K1", "Invariant mass of K1(1270)", HistType::kTHnSparseD, {axisAnti, axisType, centAxis, ptAxis, invMassAxisReso}); + // Mass QA (quick check) + histos.add("k1invmass", "Invariant mass of K1(1270)", HistType::kTH1F, {invMassAxisReso}); + histos.add("k1invmass_Mix", "Invariant mass of K1(1270)", HistType::kTH1F, {invMassAxisReso}); + // MC if (doprocessMC) { - histos.add("QAMC/InvMass_piK_pipi", "Invariant mass of pion + kaon and pion+pion;Invariant Mass (GeV/#it{c}^{2});Invariant Mass (GeV/#it{c}^{2});", {HistType::kTH2F, {invMassAxisScan, invMassAxisScan}}); - histos.add("QAMC/InvMass_piK_pika", "Invariant mass of pion + kaon and pion+kaon;Invariant Mass (GeV/#it{c}^{2});Invariant Mass (GeV/#it{c}^{2});", {HistType::kTH2F, {invMassAxisScan, invMassAxisScan}}); - histos.add("QAMC/K1OA", "Opening angle of K1(1270)pm", HistType::kTH1F, {AxisSpec{100, 0, 3.14, "Opening angle of K1(1270)pm"}}); - histos.add("QAMC/K1PairAsymm", "Pair asymmetry of K1(1270)pm", HistType::kTH1F, {AxisSpec{100, 0, 1, "Pair asymmetry of K1(1270)pm"}}); - - histos.add("hK1invmass_NPP_MC", "Invariant mass of K(892)0 + pion (Matter + Matter)", HistType::kTH3F, {centAxis, ptAxis, invMassAxisReso}); - histos.add("hK1invmass_PNN_MC", "Invariant mass of K(892)0 + pion (Anti-matter + Anti-matter)", HistType::kTH3F, {centAxis, ptAxis, invMassAxisReso}); - - histos.add("hReconK892pt", "pT distribution of Reconstructed MC K(892)0", HistType::kTH1F, {ptAxis}); - histos.add("hTrueK1pt", "pT distribution of True MC K1", HistType::kTH1F, {ptAxis}); - histos.add("hReconK1pt", "pT distribution of Reconstructed MC K1", HistType::kTH1F, {ptAxis}); - - histos.add("k1invmass_noK1", "Invariant mass of K1(1270)pm", HistType::kTH1F, {invMassAxisReso}); + histos.add("k1invmass_MC", "Invariant mass of K1(1270)", HistType::kTH1F, {invMassAxisReso}); + histos.add("k1invmass_MC_noK1", "Invariant mass of K1(1270)", HistType::kTH1F, {invMassAxisReso}); + + histos.add("QAMC/trkppionDCAxy", "DCAxy distribution of primary pion candidates", HistType::kTH1F, {dcaxyAxis}); + histos.add("QAMC/trkppionDCAz", "DCAz distribution of primary pion candidates", HistType::kTH1F, {dcaxyAxis}); + histos.add("QAMC/trkppionpT", "pT distribution of primary pion candidates", HistType::kTH1F, {ptAxis}); + histos.add("QAMC/trkppionTPCPID", "TPC PID of primary pion candidates", HistType::kTH2F, {ptAxis, pidQAAxis}); + histos.add("QAMC/trkppionTOFPID", "TOF PID of primary pion candidates", HistType::kTH2F, {ptAxis, pidQAAxis}); + histos.add("QAMC/trkppionTPCTOFPID", "TPC-TOF PID map of primary pion candidates", HistType::kTH2F, {pidQAAxis, pidQAAxis}); + + histos.add("QAMC/trkspionDCAxy", "DCAxy distribution of secondary pion candidates", HistType::kTH1F, {dcaxyAxis}); + histos.add("QAMC/trkspionDCAz", "DCAz distribution of secondary pion candidates", HistType::kTH1F, {dcaxyAxis}); + histos.add("QAMC/trkspionpT", "pT distribution of secondary pion candidates", HistType::kTH1F, {ptAxis}); + histos.add("QAMC/trkspionTPCPID", "TPC PID of secondary pion candidates", HistType::kTH2F, {ptAxis, pidQAAxis}); + histos.add("QAMC/trkspionTOFPID", "TOF PID of secondary pion candidates", HistType::kTH2F, {ptAxis, pidQAAxis}); + histos.add("QAMC/trkspionTPCTOFPID", "TPC-TOF PID map of secondary pion candidates", HistType::kTH2F, {pidQAAxis, pidQAAxis}); + + histos.add("QAMC/trkkaonDCAxy", "DCAxy distribution of kaon candidates", HistType::kTH1F, {dcaxyAxis}); + histos.add("QAMC/trkkaonDCAz", "DCAz distribution of kaon candidates", HistType::kTH1F, {dcaxyAxis}); + histos.add("QAMC/trkkaonpT", "pT distribution of kaon candidates", HistType::kTH1F, {ptAxis}); + histos.add("QAMC/trkkaonTPCPID", "TPC PID of kaon candidates", HistType::kTH2F, {ptAxis, pidQAAxis}); + histos.add("QAMC/trkkaonTOFPID", "TOF PID of kaon candidates", HistType::kTH2F, {ptAxis, pidQAAxis}); + histos.add("QAMC/trkkaonTPCTOFPID", "TPC-TOF PID map of kaon candidates", HistType::kTH2F, {pidQAAxis, pidQAAxis}); + + histos.add("QAMC/K1OA", "Opening angle of K1(1270)", HistType::kTH1F, {AxisSpec{100, 0, 3.14, "Opening angle"}}); + histos.add("QAMC/K1PairAssym", "Pair asymmetry of K1(1270)", HistType::kTH1F, {AxisSpec{100, -1, 1, "Pair asymmetry"}}); + histos.add("QAMC/hInvmassK892_Rho", "Invariant mass of K(892)0 vs Rho(770)", HistType::kTH2F, {invMassAxisK892, invMassAxisRho}); + histos.add("QAMC/hInvmassSecon_PiKa", "Invariant mass of secondary resonance vs pion-kaon", HistType::kTH2F, {invMassAxisK892, invMassAxisK892}); + histos.add("QAMC/hInvmassSecon", "Invariant mass of secondary resonance", HistType::kTH1F, {invMassAxisRho}); + histos.add("QAMC/hpT_Secondary", "pT distribution of secondary resonance", HistType::kTH1F, {ptAxis}); } // Print output histograms statistics - LOG(info) << "Size of the histograms in spectraTOF"; + LOG(info) << "Size of the histograms in K1 Analysis Task"; histos.print(); } - double massKa = TDatabasePDG::Instance()->GetParticle(kKPlus)->Mass(); // FIXME: Get from the common header - double massPi = TDatabasePDG::Instance()->GetParticle(kPiPlus)->Mass(); // FIXME: Get from the common header - double massK892 = TDatabasePDG::Instance()->GetParticle(313)->Mass(); // FIXME: Get from the common header + double massKa = MassKaonCharged; + double massPi = MassPionCharged; + // double massRho770 = MassRho770; + // double massK892 = MassKStar892; + double massRho770 = 0.77526; + double massK892 = 0.892; + + // PDG code + int kPDGRho770 = 113; + int kK1Plus = 10323; template bool trackCut(const TrackType track) { // basic track cuts - if (track.pt() < cMinPtcut) + 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.itsNCls() < cfgITScluster) + return false; + if (track.tpcNClsFound() < cfgTPCcluster) + return false; + if (track.tpcCrossedRowsOverFindableCls() < cfgRatioTPCRowsOverFindableCls) + return false; + if (track.itsChi2NCl() >= cfgITSChi2NCl) return false; - if (track.dcaXY() > cMaxDCArToPVcut) + if (track.tpcChi2NCl() >= cfgTPCChi2NCl) return false; - if (track.dcaZ() < cMinDCAzToPVcut || track.dcaZ() > cMaxDCAzToPVcut) + 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 (cfgPrimaryTrack && !track.isPrimaryTrack()) return false; if (cfgGlobalWoDCATrack && !track.isGlobalTrackWoDCA()) return false; - if (cfgPVContributor && !track.isPVContributor()) + if (cfgGlobalTrack && !track.isGlobalTrack()) return false; + return true; } @@ -204,6 +311,8 @@ struct k1analysis { 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) { @@ -213,6 +322,9 @@ struct k1analysis { tofPIDPassed = true; } } else { + if (!cTOFVeto) { + return false; + } tofPIDPassed = true; } if (tpcPIDPassed && tofPIDPassed) { @@ -226,6 +338,8 @@ struct k1analysis { 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) { @@ -235,6 +349,9 @@ struct k1analysis { tofPIDPassed = true; } } else { + if (!cTOFVeto) { + return false; + } tofPIDPassed = true; } if (tpcPIDPassed && tofPIDPassed) { @@ -245,6 +362,42 @@ struct k1analysis { template bool isTrueK1(const T& trk1, const T& trk2, const T2& bTrack) + { + if (abs(trk1.pdgCode()) != kPiPlus || abs(trk2.pdgCode()) != kKPlus) + return false; + if (abs(bTrack.pdgCode()) != kPiPlus) + return false; + if (cfgModeK892orRho) { // K892 mode + auto mother1 = trk1.motherId(); + auto mother2 = trk2.motherId(); + if (mother1 != mother2) + return false; + if (abs(trk1.motherPDG()) != kK0Star892) + return false; + if (abs(bTrack.motherPDG()) != kK1Plus) + return false; + auto siblings = bTrack.siblingIds(); + if (siblings[0] != mother1 && siblings[1] != mother1) + return false; + return true; + } else { // Rho mode + auto mother1 = trk1.motherId(); + auto motherb = bTrack.motherId(); + if (mother1 != motherb) + return false; + if (abs(trk1.motherPDG()) != kPDGRho770) + return false; + if (abs(trk2.motherPDG()) != kK1Plus) + return false; + auto siblings = trk2.siblingIds(); + if (siblings[0] != mother1 && siblings[1] != mother1) + return false; + return true; + } + } + + template + bool isTrueK892(const T& trk1, const T& trk2) { if (abs(trk1.pdgCode()) != kPiPlus || abs(trk2.pdgCode()) != kKPlus) return false; @@ -252,29 +405,21 @@ struct k1analysis { auto mother2 = trk2.motherId(); if (mother1 != mother2) return false; - if (abs(trk1.motherPDG()) != 313) - return false; - if (abs(bTrack.pdgCode()) != kPiPlus) - return false; - if (abs(bTrack.motherPDG()) != 10323) + if (abs(trk1.motherPDG()) != kK0Star892) return false; - auto siblings = bTrack.siblingIds(); - if (siblings[0] != mother1 && siblings[1] != mother1) - return false; - return true; } template - bool isTrueK892(const T& trk1, const T& trk2) + bool isTrueRho(const T& trk1, const T& trk2) { - if (abs(trk1.pdgCode()) != kPiPlus || abs(trk2.pdgCode()) != kKPlus) + if (abs(trk1.pdgCode()) != kPiPlus || abs(trk2.pdgCode()) != kPiPlus) return false; auto mother1 = trk1.motherId(); auto mother2 = trk2.motherId(); if (mother1 != mother2) return false; - if (abs(trk1.motherPDG()) != 313) + if (abs(trk1.motherPDG()) != kPDGRho770) return false; return true; } @@ -283,7 +428,7 @@ struct k1analysis { void fillHistograms(const CollisionType& collision, const TracksType& dTracks1, const TracksType& dTracks2) { auto multiplicity = collision.cent(); - TLorentzVector lDecayDaughter1, lDecayDaughter2, lResonanceK892, lDecayDaughter_bach, lResonanceK1; + TLorentzVector lDecayDaughter1, lDecayDaughter2, lResonanceSecondary, lDecayDaughter_bach, lResonanceK1; for (auto& [trk1, trk2] : combinations(CombinationsFullIndexPolicy(dTracks2, dTracks2))) { // Full index policy is needed to consider all possible combinations if (trk1.index() == trk2.index()) @@ -295,211 +440,217 @@ struct k1analysis { auto isTrk1hasTOF = trk1.hasTOF(); auto isTrk2hasTOF = trk2.hasTOF(); - auto trk1ptPi = trk1.pt(); + auto trk1pt = trk1.pt(); auto trk1NSigmaPiTPC = trk1.tpcNSigmaPi(); auto trk1NSigmaPiTOF = (isTrk1hasTOF) ? trk1.tofNSigmaPi() : -999.; - auto trk2ptKa = trk2.pt(); + auto trk2pt = trk2.pt(); auto trk2NSigmaKaTPC = trk2.tpcNSigmaKa(); auto trk2NSigmaKaTOF = (isTrk2hasTOF) ? trk2.tofNSigmaKa() : -999.; + // for rho mode + auto trk2NSigmaPiTPC = trk2.tpcNSigmaPi(); + auto trk2NSigmaPiTOF = (isTrk2hasTOF) ? trk2.tofNSigmaPi() : -999.; //// PID selections if (cUseOnlyTOFTrackPi && !isTrk1hasTOF) continue; if (cUseOnlyTOFTrackKa && !isTrk2hasTOF) continue; - if (!selectionPIDPion(trk1) || !selectionPIDKaon(trk2)) - continue; + + if (cfgModeK892orRho) { // K892 mode + if (!selectionPIDPion(trk1) || !selectionPIDKaon(trk2)) + continue; + } else { // Rho mode + if (!selectionPIDPion(trk1) || !selectionPIDPion(trk2)) + continue; + } //// QA plots after the selection - // --- PID QA Pion if constexpr (!IsMix) { - histos.fill(HIST("QA/TPC_Nsigma_pi"), trk1ptPi, trk1NSigmaPiTPC); + // --- PID QA Pion + histos.fill(HIST("QA/trkspionTPCPID"), trk1pt, trk1NSigmaPiTPC); if (isTrk1hasTOF) { - histos.fill(HIST("QA/TOF_Nsigma_pi"), trk1ptPi, trk1NSigmaPiTOF); - histos.fill(HIST("QA/TOF_TPC_Map_pi"), trk1NSigmaPiTOF, trk1NSigmaPiTPC); + histos.fill(HIST("QA/trkspionTOFPID"), trk1pt, trk1NSigmaPiTOF); + histos.fill(HIST("QA/trkspionTPCTOFPID"), trk1NSigmaPiTPC, trk1NSigmaPiTOF); } - // --- PID QA Kaon - histos.fill(HIST("QA/TPC_Nsigmaka"), trk2ptKa, trk2NSigmaKaTPC); - if (isTrk1hasTOF) { - histos.fill(HIST("QA/TOF_Nsigma_ka"), trk2ptKa, trk2NSigmaKaTOF); - histos.fill(HIST("QA/TOF_TPC_Map_ka"), trk2NSigmaKaTOF, trk2NSigmaKaTPC); + histos.fill(HIST("QA/trkspionpT"), trk1pt); + histos.fill(HIST("QA/trkspionDCAxy"), trk1.dcaXY()); + histos.fill(HIST("QA/trkspionDCAz"), trk1.dcaZ()); + + if (cfgModeK892orRho) { // K892 mode + // --- PID QA Kaon + histos.fill(HIST("QA/trkkaonTPCPID"), trk2pt, trk2NSigmaKaTPC); + if (isTrk1hasTOF) { + histos.fill(HIST("QA/trkkaonTOFPID"), trk2pt, trk2NSigmaKaTOF); + histos.fill(HIST("QA/trkkaonTPCTOFPID"), trk2NSigmaKaTPC, trk2NSigmaKaTOF); + } + histos.fill(HIST("QA/trkkaonpT"), trk2pt); + histos.fill(HIST("QA/trkkaonDCAxy"), trk2.dcaXY()); + histos.fill(HIST("QA/trkkaonDCAz"), trk2.dcaZ()); + } else { // Rho mode + // --- PID QA Pion + histos.fill(HIST("QA/trkppionTPCPID"), trk2pt, trk2NSigmaPiTPC); + if (isTrk2hasTOF) { + histos.fill(HIST("QA/trkppionTOFPID"), trk2pt, trk2NSigmaPiTOF); + histos.fill(HIST("QA/trkppionTPCTOFPID"), trk2NSigmaPiTPC, trk2NSigmaPiTOF); + } + histos.fill(HIST("QA/trkppionpT"), trk2pt); + histos.fill(HIST("QA/trkppionDCAxy"), trk2.dcaXY()); + histos.fill(HIST("QA/trkppionDCAz"), trk2.dcaZ()); } - histos.fill(HIST("QA/trkpT_pi"), trk1ptPi); - histos.fill(HIST("QA/trkpT_ka"), trk2ptKa); - - histos.fill(HIST("QA/trkDCAxy_pi"), trk1.dcaXY()); - histos.fill(HIST("QA/trkDCAxy_ka"), trk2.dcaXY()); - histos.fill(HIST("QA/trkDCAz_pi"), trk1.dcaZ()); - histos.fill(HIST("QA/trkDCAz_ka"), trk2.dcaZ()); } //// Resonance reconstruction lDecayDaughter1.SetXYZM(trk1.px(), trk1.py(), trk1.pz(), massPi); - lDecayDaughter2.SetXYZM(trk2.px(), trk2.py(), trk2.pz(), massKa); - lResonanceK892 = lDecayDaughter1 + lDecayDaughter2; + lDecayDaughter2.SetXYZM(trk2.px(), trk2.py(), trk2.pz(), (cfgModeK892orRho) ? massKa : massPi); + lResonanceSecondary = lDecayDaughter1 + lDecayDaughter2; if constexpr (!IsMix) { - histos.fill(HIST("k892invmass"), lResonanceK892.M()); // quick check - if (trk1.sign() > 0) { // Positive pion - if (trk2.sign() > 0) // Positive kaon - histos.fill(HIST("hK892invmass_PP"), multiplicity, lResonanceK892.Pt(), lResonanceK892.M()); - else // Negative kaon - histos.fill(HIST("hK892invmass_PN"), multiplicity, lResonanceK892.Pt(), lResonanceK892.M()); // Anti-K(892)0 - } else { // Negative pion - if (trk2.sign() > 0) // Positive kaon - histos.fill(HIST("hK892invmass_NP"), multiplicity, lResonanceK892.Pt(), lResonanceK892.M()); // K(892)0 - else // Negative kaon - histos.fill(HIST("hK892invmass_NN"), multiplicity, lResonanceK892.Pt(), lResonanceK892.M()); - } + histos.fill(HIST("QA/hInvmassSecon"), lResonanceSecondary.M()); } - // Like-sign rejection for K(892)0 - disabled for further LS bkg study - // if (trk1.sign() * trk2.sign() > 0) - // continue; - if constexpr (IsMC) { // MC Check of K(892)0 - if (isTrueK892(trk1, trk2)) - histos.fill(HIST("hReconK892pt"), lResonanceK892.Pt()); + if constexpr (IsMC) { // MC Check + if (cfgModeK892orRho) { + if (isTrueK892(trk1, trk2)) + histos.fill(HIST("QAMC/hpT_Secondary"), lResonanceSecondary.Pt()); + } else { + if (isTrueRho(trk1, trk2)) + histos.fill(HIST("QAMC/hpT_Secondary"), lResonanceSecondary.Pt()); + } } // Mass window cut - if (std::abs(lResonanceK892.M() - massK892) > cK892masswindow) + double massCut = cfgModeK892orRho ? massK892 : massRho770; + if (std::abs(lResonanceSecondary.M() - massCut) > cSecondaryMasswindow) continue; - // Add one more track loop for K1 reconstruction + + // bTrack loop for K1 reconstruction for (auto bTrack : dTracks1) { - // ID cut if (bTrack.index() == trk1.index() || bTrack.index() == trk2.index()) continue; - // Track cut if (!trackCut(bTrack)) continue; - auto bTrkPt = bTrack.pt(); - auto bTrkTPCnSigmaPi = bTrack.tpcNSigmaPi(); - auto isbTrkhasTOF = bTrack.hasTOF(); - auto bTrack_TOFnSigma = (isbTrkhasTOF) ? bTrack.tofNSigmaPi() : -999.; - - // PID selection - if (!selectionPIDPion(bTrack)) + // Kaon or Pion + if (cfgModeK892orRho && !selectionPIDPion(bTrack)) + continue; + if (!cfgModeK892orRho && !selectionPIDKaon(bTrack)) continue; - - if constexpr (!IsMix) { - histos.fill(HIST("QA/trkpT_pi_bach"), bTrkPt); - // --- PID QA Pion - histos.fill(HIST("QA/TPC_Nsigma_pi_bach"), bTrkPt, bTrkTPCnSigmaPi); - if (isbTrkhasTOF) { - histos.fill(HIST("QA/TOF_Nsigma_pi_bach"), bTrkPt, bTrack_TOFnSigma); - histos.fill(HIST("QA/TOF_TPC_Map_pi_bach"), bTrack_TOFnSigma, bTrkTPCnSigmaPi); - } - histos.fill(HIST("QA/trkDCAxy_pi_bach"), bTrack.dcaXY()); - histos.fill(HIST("QA/trkDCAz_pi_bach"), bTrack.dcaZ()); - } // K1 reconstruction - lDecayDaughter_bach.SetXYZM(bTrack.px(), bTrack.py(), bTrack.pz(), massPi); - lResonanceK1 = lResonanceK892 + lDecayDaughter_bach; + lDecayDaughter_bach.SetXYZM(bTrack.px(), bTrack.py(), bTrack.pz(), cfgModeK892orRho ? massPi : massKa); + lResonanceK1 = lResonanceSecondary + lDecayDaughter_bach; - // Rapidity cut + // Cuts if (lResonanceK1.Rapidity() > cK1MaxRap || lResonanceK1.Rapidity() < cK1MinRap) continue; - // Opening angle cut - auto lK1Angle = lResonanceK892.Angle(lDecayDaughter_bach.Vect()); - // Pair asymmetry cut - auto lPairAsym = (lResonanceK892.E() - lDecayDaughter_bach.E()) / (lResonanceK892.E() + lDecayDaughter_bach.E()); - // PiPi, PiKa mass range cut - TLorentzVector tempPiPi = lDecayDaughter1 + lDecayDaughter_bach; - TLorentzVector tempPiKa = lDecayDaughter2 + lDecayDaughter_bach; + + 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 histograms if constexpr (!IsMix) { - histos.fill(HIST("QA/InvMass_piK_pipi"), lResonanceK892.M(), tempPiPi.M()); - histos.fill(HIST("QA/InvMass_piK_pika"), lResonanceK892.M(), tempPiKa.M()); histos.fill(HIST("QA/K1OA"), lK1Angle); - histos.fill(HIST("QA/K1PairAsymm"), lPairAsym); + histos.fill(HIST("QA/K1PairAssym"), lPairAsym); + if (cfgModeK892orRho) { + histos.fill(HIST("QA/hInvmassK892_Rho"), lResonanceSecondary.M(), temp13.M()); + } else { + histos.fill(HIST("QA/hInvmassK892_Rho"), temp13.M(), lResonanceSecondary.M()); + } + histos.fill(HIST("QA/hInvmassSecon_PiKa"), lResonanceSecondary.M(), temp23.M()); + histos.fill(HIST("QA/hpT_Secondary"), lResonanceSecondary.Pt()); } - if (tempPiPi.M() < cPiPiMin || tempPiPi.M() > cPiPiMax) + + // Selection cuts + if (temp13.M() < cMinAnotherSecondaryMassCut || temp13.M() > cMaxAnotherSecondaryMassCut) continue; - if (tempPiKa.M() < cPiKaMin || tempPiKa.M() > cPiKaMax) + if (temp23.M() < cMinPiKaMassCut || temp23.M() > cMaxPiKaMassCut) continue; if (lK1Angle < cMinAngle || lK1Angle > cMaxAngle) continue; if (lPairAsym < cMinPairAsym || lPairAsym > cMaxPairAsym) continue; - if constexpr (!IsMix) { // Same event pair - if (trk1.sign() * trk2.sign() < 0) { // K892 - if (bTrack.sign() > 0) { // bachelor pi+ - if (trk2.sign() > 0) { // kaon + means K(892)0 is matter. - histos.fill(HIST("k1invmass"), lResonanceK1.M()); // quick check - histos.fill(HIST("hK1invmass_NPP"), multiplicity, lResonanceK1.Pt(), lResonanceK1.M()); - } else { - histos.fill(HIST("k1invmass_LS"), lResonanceK1.M()); // quick check - histos.fill(HIST("hK1invmass_PNP"), multiplicity, lResonanceK1.Pt(), lResonanceK1.M()); - } - } else { // bachelor pi- - if (trk2.sign() > 0) { // kaon + means K(892)0 is matter. - histos.fill(HIST("k1invmass_LS"), lResonanceK1.M()); // quick check - histos.fill(HIST("hK1invmass_NPN"), multiplicity, lResonanceK1.Pt(), lResonanceK1.M()); - } else { - histos.fill(HIST("k1invmass"), lResonanceK1.M()); // quick check - histos.fill(HIST("hK1invmass_PNN"), multiplicity, lResonanceK1.Pt(), lResonanceK1.M()); - } - } - } else { // K892-LS (false) - if (bTrack.sign() > 0) { // bachelor pi+ - if (trk2.sign() > 0) { // Kaon+ - histos.fill(HIST("hK1invmass_PPP"), multiplicity, lResonanceK1.Pt(), lResonanceK1.M()); - } else { - histos.fill(HIST("hK1invmass_PPN"), multiplicity, lResonanceK1.Pt(), lResonanceK1.M()); - } - } else { // bachelor pi- - if (trk2.sign() > 0) { // Kaon_ - histos.fill(HIST("hK1invmass_NNN"), multiplicity, lResonanceK1.Pt(), lResonanceK1.M()); - } else { - histos.fill(HIST("hK1invmass_NNP"), multiplicity, lResonanceK1.Pt(), lResonanceK1.M()); - } - } + // QA histograms after the cuts + if constexpr (!IsMix) { + histos.fill(HIST("QAcut/K1OA"), lK1Angle); + histos.fill(HIST("QAcut/K1PairAssym"), lPairAsym); + if (cfgModeK892orRho) { + histos.fill(HIST("QAcut/hInvmassK892_Rho"), lResonanceSecondary.M(), temp13.M()); + } else { + histos.fill(HIST("QAcut/hInvmassK892_Rho"), temp13.M(), lResonanceSecondary.M()); } + histos.fill(HIST("QAcut/hInvmassSecon_PiKa"), lResonanceSecondary.M(), temp23.M()); + histos.fill(HIST("QAcut/hInvmassSecon"), lResonanceSecondary.M()); + histos.fill(HIST("QAcut/hpT_Secondary"), lResonanceSecondary.Pt()); + } + + if constexpr (!IsMix) { + unsigned int typeK1 = bTrack.sign() > 0 ? binType::kK1P : binType::kK1N; + unsigned int typeNormal = cfgModeK892orRho ? (trk1.sign() < 0 ? binAnti::kNormal : binAnti::kAnti) : binAnti::kNormal; + histos.fill(HIST("k1invmass"), lResonanceK1.M()); + histos.fill(HIST("hInvmass_K1"), typeNormal, typeK1, multiplicity, lResonanceK1.Pt(), lResonanceK1.M()); if constexpr (IsMC) { if (isTrueK1(trk1, trk2, bTrack)) { - histos.fill(HIST("hReconK1pt"), lResonanceK1.Pt()); - histos.fill(HIST("QAMC/InvMass_piK_pipi"), lResonanceK892.M(), tempPiPi.M()); - histos.fill(HIST("QAMC/InvMass_piK_pika"), lResonanceK892.M(), tempPiKa.M()); + 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/K1PairAsymm"), lPairAsym); - - if ((bTrack.sign() > 0) && (trk2.sign() > 0)) { // Matter - histos.fill(HIST("hK1invmass_NPP_MC"), multiplicity, lResonanceK1.Pt(), lResonanceK1.M()); - histos.fill(HIST("k1invmass_MC"), lResonanceK1.M()); // quick check - } - if ((bTrack.sign() < 0) && (trk2.sign() < 0)) { // Anti-matter - histos.fill(HIST("hK1invmass_PNN_MC"), multiplicity, lResonanceK1.Pt(), lResonanceK1.M()); - histos.fill(HIST("k1invmass_MC"), lResonanceK1.M()); // quick check - } - histos.fill(HIST("hTrueK1pt"), lResonanceK1.Pt()); - } else { - if (((bTrack.sign() > 0) && (trk2.sign() > 0)) || ((bTrack.sign() < 0) && (trk2.sign() < 0))) - histos.fill(HIST("k1invmass_noK1"), lResonanceK1.M()); // quick check - } - } - } else { // Mixed event pair - if (trk1.sign() * trk2.sign() < 0) { // K892 - if (bTrack.sign() > 0) { // bachelor pi+ - if (trk2.sign() > 0) { // kaon + means K(892)0 is matter. - histos.fill(HIST("k1invmass_Mix"), lResonanceK1.M()); // quick check - histos.fill(HIST("hK1invmass_NPP_Mix"), multiplicity, lResonanceK1.Pt(), lResonanceK1.M()); + histos.fill(HIST("QAMC/K1PairAssym"), lPairAsym); + if (cfgModeK892orRho) { + histos.fill(HIST("QAMC/hInvmassK892_Rho"), lResonanceSecondary.M(), temp13.M()); } else { - histos.fill(HIST("hK1invmass_PNP_Mix"), multiplicity, lResonanceK1.Pt(), lResonanceK1.M()); + histos.fill(HIST("QAMC/hInvmassK892_Rho"), temp13.M(), lResonanceSecondary.M()); } - } else { // bachelor pi- - if (trk2.sign() > 0) { // kaon + means K(892)0 is matter. - histos.fill(HIST("hK1invmass_NPN_Mix"), multiplicity, lResonanceK1.Pt(), lResonanceK1.M()); - } else { - histos.fill(HIST("k1invmass_Mix"), lResonanceK1.M()); // quick check - histos.fill(HIST("hK1invmass_PNN_Mix"), multiplicity, lResonanceK1.Pt(), lResonanceK1.M()); + histos.fill(HIST("QAMC/hInvmassSecon_PiKa"), lResonanceSecondary.M(), temp23.M()); + histos.fill(HIST("QAMC/hInvmassSecon"), lResonanceSecondary.M()); + histos.fill(HIST("QAMC/hpT_Secondary"), lResonanceSecondary.Pt()); + + // --- PID QA Pion + histos.fill(HIST("QAMC/trkspionTPCPID"), trk1pt, trk1NSigmaPiTPC); + if (isTrk1hasTOF) { + histos.fill(HIST("QAMC/trkspionTOFPID"), trk1pt, trk1NSigmaPiTOF); + histos.fill(HIST("QAMC/trkspionTPCTOFPID"), trk1NSigmaPiTPC, trk1NSigmaPiTOF); + } + histos.fill(HIST("QAMC/trkspionpT"), trk1pt); + histos.fill(HIST("QAMC/trkspionDCAxy"), trk1.dcaXY()); + histos.fill(HIST("QAMC/trkspionDCAz"), trk1.dcaZ()); + + if (cfgModeK892orRho) { // K892 mode + // --- PID QA Kaon + histos.fill(HIST("QAMC/trkkaonTPCPID"), trk2pt, trk2NSigmaKaTPC); + if (isTrk1hasTOF) { + histos.fill(HIST("QAMC/trkkaonTOFPID"), trk2pt, trk2NSigmaKaTOF); + histos.fill(HIST("QAMC/trkkaonTPCTOFPID"), trk2NSigmaKaTPC, trk2NSigmaKaTOF); + } + histos.fill(HIST("QAMC/trkkaonpT"), trk2pt); + histos.fill(HIST("QAMC/trkkaonDCAxy"), trk2.dcaXY()); + histos.fill(HIST("QAMC/trkkaonDCAz"), trk2.dcaZ()); + } else { // Rho mode + // --- PID QA Pion + histos.fill(HIST("QAMC/trkppionTPCPID"), trk2pt, trk2NSigmaPiTPC); + if (isTrk2hasTOF) { + histos.fill(HIST("QAMC/trkppionTOFPID"), trk2pt, trk2NSigmaPiTOF); + histos.fill(HIST("QAMC/trkppionTPCTOFPID"), trk2NSigmaPiTPC, trk2NSigmaPiTOF); + } + histos.fill(HIST("QAMC/trkppionpT"), trk2pt); + histos.fill(HIST("QAMC/trkppionDCAxy"), trk2.dcaXY()); + histos.fill(HIST("QAMC/trkppionDCAz"), trk2.dcaZ()); } + } else { + histos.fill(HIST("k1invmass_MC_noK1"), lResonanceK1.M()); } - } + } // MC + } else { // Mixed event handling + unsigned int typeK1 = bTrack.sign() > 0 ? binType::kK1P_Mix : binType::kK1N_Mix; + unsigned int typeNormal = cfgModeK892orRho ? (trk1.sign() < 0 ? binAnti::kNormal : binAnti::kAnti) : binAnti::kNormal; + histos.fill(HIST("hInvmass_K1"), typeNormal, typeK1, multiplicity, lResonanceK1.Pt(), lResonanceK1.M()); + histos.fill(HIST("k1invmass_Mix"), lResonanceK1.M()); } - } + } // bTrack } } @@ -517,25 +668,57 @@ struct k1analysis { } PROCESS_SWITCH(k1analysis, processMC, "Process Event for MC", false); - void processMCTrue(aod::ResoMCParents& resoParents) + void processMCTrue(ResoMCCols::iterator const& collision, aod::ResoMCParents& resoParents) { - for (auto& part : resoParents) { // loop over all pre-filtered MC particles - if (abs(part.pdgCode()) != 10323) // K892(0) + auto multiplicity = collision.cent(); + for (auto& part : resoParents) { // loop over all pre-filtered MC particles + if (abs(part.pdgCode()) != kK1Plus) // K892(0) continue; if (abs(part.y()) > 0.5) { // rapidity cut continue; } bool pass1 = false; bool pass2 = false; - if (abs(part.daughterPDG1()) == 313 || abs(part.daughterPDG2()) == 313) { // At least one decay to Kaon - pass2 = true; + if (cfgModeK892orRho) { + if (abs(part.daughterPDG1()) == 313 || abs(part.daughterPDG2()) == 313) { // At least one decay to K892 + pass2 = true; + } + if (abs(part.daughterPDG1()) == kPiPlus || abs(part.daughterPDG2()) == kPiPlus) { // At least one decay to Pion + pass1 = true; + } + if (!pass1 || !pass2) // If we have both decay products + continue; + } else { + if (abs(part.daughterPDG1()) == kPDGRho770 || abs(part.daughterPDG2()) == kPDGRho770) { // At least one decay to Rho + pass2 = true; + } + if (abs(part.daughterPDG1()) == kKPlus || abs(part.daughterPDG2()) == kKPlus) { // At least one decay to Kaon + pass1 = true; + } + if (!pass1 || !pass2) // If we have both decay products + continue; } - if (abs(part.daughterPDG1()) == kPiPlus || abs(part.daughterPDG2()) == kPiPlus) { // At least one decay to Pion - pass1 = true; + auto typeNormal = part.pdgCode() > 0 ? binAnti::kNormal : binAnti::kAnti; + if (collision.isVtxIn10()) // INEL10 + { + auto typeK1 = part.pdgCode() > 0 ? binType::kK1P_GenINEL10 : binType::kK1N_GenINEL10; + histos.fill(HIST("hInvmass_K1"), typeNormal, typeK1, multiplicity, part.pt(), 1); + } + if (collision.isVtxIn10() && collision.isInSel8()) // INEL>10, vtx10 + { + auto typeK1 = part.pdgCode() > 0 ? binType::kK1P_GenINELgt10 : binType::kK1N_GenINELgt10; + histos.fill(HIST("hInvmass_K1"), typeNormal, typeK1, multiplicity, part.pt(), 1); + } + if (collision.isVtxIn10() && collision.isTriggerTVX()) // vtx10, TriggerTVX + { + auto typeK1 = part.pdgCode() > 0 ? binType::kK1P_GenTrig10 : binType::kK1N_GenTrig10; + histos.fill(HIST("hInvmass_K1"), typeNormal, typeK1, multiplicity, part.pt(), 1); + } + if (collision.isInAfterAllCuts()) // after all event selection + { + auto typeK1 = part.pdgCode() > 0 ? binType::kK1P_GenEvtSel : binType::kK1N_GenEvtSel; + histos.fill(HIST("hInvmass_K1"), typeNormal, typeK1, multiplicity, part.pt(), 1); } - if (!pass1 || !pass2) // If we have both decay products - continue; - histos.fill(HIST("hTrueK1pt"), part.pt()); } } PROCESS_SWITCH(k1analysis, processMCTrue, "Process Event for MC", false); diff --git a/PWGLF/Tasks/Resonances/kstarpbpb.cxx b/PWGLF/Tasks/Resonances/kstarpbpb.cxx index 6dd4a09fafb..f3eff07b363 100644 --- a/PWGLF/Tasks/Resonances/kstarpbpb.cxx +++ b/PWGLF/Tasks/Resonances/kstarpbpb.cxx @@ -8,7 +8,7 @@ // In applying this license CERN does not waive the privileges and immunities // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -// sourav.kundu@cern.ch +// sourav.kundu@cern.ch , sarjeeta.gami@cern.ch #include #include @@ -77,6 +77,7 @@ struct kstarpbpb { // track Configurable cfgCutCharge{"cfgCutCharge", 0.0, "cut on Charge"}; Configurable additionalEvSel2{"additionalEvSel2", true, "Additional evsel2"}; + Configurable additionalEvSel3{"additionalEvSel3", true, "Additional evsel3"}; 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"}; @@ -104,7 +105,7 @@ struct kstarpbpb { Configurable confMaxRot{"confMaxRot", 7.0 * TMath::Pi() / 6.0, "Maximum of rotation"}; Configurable nBkgRotations{"nBkgRotations", 9, "Number of rotated copies (background) per each original candidate"}; Configurable fillRotation{"fillRotation", true, "fill rotation"}; - Configurable fillRotation1{"fillRotation1", true, "fill rotation"}; + Configurable fillRotation1{"fillRotation1", false, "fill rotation"}; Configurable like{"like", true, "fill rotation"}; Configurable fillOccupancy{"fillOccupancy", false, "fill Occupancy"}; Configurable cfgOccupancyCut{"cfgOccupancyCut", 500, "Occupancy cut"}; @@ -132,6 +133,7 @@ struct kstarpbpb { void init(o2::framework::InitContext&) { + std::vector occupancyBinning = {0.0, 500.0, 1000.0, 1500.0, 2000.0, 3000.0, 4000.0, 5000.0, 50000.0}; const AxisSpec thnAxisInvMass{configThnAxisInvMass, "#it{M} (GeV/#it{c}^{2})"}; const AxisSpec thnAxisPt{configThnAxisPt, "#it{p}_{T} (GeV/#it{c})"}; const AxisSpec thnAxisPhiminusPsi{configThnAxisPhiminusPsi, "#phi - #psi"}; @@ -140,25 +142,21 @@ struct kstarpbpb { AxisSpec phiAxis = {500, -6.28, 6.28, "phi"}; AxisSpec resAxis = {400, -2, 2, "Res"}; AxisSpec centAxis = {8, 0, 80, "V0M (%)"}; - AxisSpec occupancyAxis = {1500, 0, 1500, "Occupancy"}; + AxisSpec occupancyAxis = {occupancyBinning, "Occupancy"}; histos.add("hpTvsRapidity", "pT vs Rapidity", kTH2F, {{100, 0.0f, 10.0f}, {300, -1.5f, 1.5f}}); - histos.add("hFTOCvsTPC", "Mult correlation FT0C vs. TPC", kTH2F, {{80, 0.0f, 80.0f}, {100, -0.5f, 5999.5f}}); histos.add("hFTOCvsTPCSelected", "Mult correlation FT0C vs. TPC after selection", kTH2F, {{80, 0.0f, 80.0f}, {100, -0.5f, 5999.5f}}); histos.add("hCentrality", "Centrality distribution", kTH1F, {{200, 0.0, 200.0}}); histos.add("hOccupancy", "Occupancy distribution", kTH1F, {occupancyAxis}); histos.add("hVtxZ", "Vertex distribution in Z;Z (cm)", kTH1F, {{400, -20.0, 20.0}}); - histos.add("hPsiFT0C", "PsiFT0C", kTH3F, {centAxis, occupancyAxis, phiAxis}); - histos.add("hPsiFT0A", "PsiFT0A", kTH3F, {centAxis, occupancyAxis, phiAxis}); - histos.add("hPsiTPC", "PsiTPC", kTH3F, {centAxis, occupancyAxis, phiAxis}); + histos.add("hPsiFT0C", "PsiFT0C", kTH2F, {centAxis, phiAxis}); + histos.add("hPsiFT0A", "PsiFT0A", kTH2F, {centAxis, phiAxis}); + histos.add("hPsiTPC", "PsiTPC", kTH2F, {centAxis, phiAxis}); histos.add("hSparseV2SASameEvent_V2", "hSparseV2SASameEvent_V2", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisV2, thnAxisCentrality}); histos.add("hSparseV2SAlikeEventNN_V2", "hSparseV2SAlikeEventNN_V2", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisV2, thnAxisCentrality}); histos.add("hSparseV2SAlikeEventPP_V2", "hSparseV2SAlikeEventPP_V2", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisV2, thnAxisCentrality}); histos.add("hSparseV2SAMixedEvent_V2", "hSparseV2SAMixedEvent_V2", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisV2, thnAxisCentrality}); - histos.add("hSparseV2SAMixedEvent2_V2", "hSparseV2SAMixedEvent2_V2", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisV2, thnAxisCentrality}); histos.add("hSparseV2SASameEventRotational_V2", "hSparseV2SASameEventRotational_V2", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisV2, thnAxisCentrality}); - histos.add("hSparseV2SASameEventRotational1_V2", "hSparseV2SASameEventRotational1_V2", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisV2, thnAxisCentrality}); - histos.add("hMC", "MC Event statistics", kTH1F, {{6, 0.0f, 6.0f}}); // histogram for resolution histos.add("ResFT0CTPC", "ResFT0CTPC", kTH2F, {centAxis, resAxis}); @@ -292,27 +290,6 @@ struct kstarpbpb { return false; } - template - bool selectionPIDpTdependent(const T& candidate, int PID) - { - if (PID == 0) { - if (candidate.pt() < 0.6 && TMath::Abs(candidate.tpcNSigmaKa()) < 2.0) { - return true; - } - if (candidate.pt() >= 0.6 && candidate.pt() < 3.0 && candidate.hasTOF() && candidate.tpcNSigmaKa() > -2.0 && candidate.tpcNSigmaKa() < 3.0 && TMath::Abs(candidate.tofNSigmaKa()) < 2.0) { - return true; - } - } else if (PID == 1) { - if (candidate.pt() < 1.0 && TMath::Abs(candidate.tpcNSigmaPi()) < 2.0) { - return true; - } - if (candidate.pt() >= 1.0 && candidate.pt() < 3.0 && candidate.hasTOF() && candidate.tpcNSigmaPi() > -2.0 && candidate.tpcNSigmaPi() < 3.0 && TMath::Abs(candidate.tofNSigmaPi()) < 2.0) { - return true; - } - } - return false; - } - double GetPhiInRange(double phi) { double result = phi; @@ -336,10 +313,9 @@ struct kstarpbpb { } ConfigurableAxis axisVertex{"axisVertex", {20, -10, 10}, "vertex axis for bin"}; ConfigurableAxis axisMultiplicityClass{"axisMultiplicityClass", {20, 0, 100}, "multiplicity percentile for bin"}; - ConfigurableAxis axisEPAngle{"axisEPAngle", {6, -TMath::Pi() / 2, TMath::Pi() / 2}, "event plane angle"}; - ConfigurableAxis axisOccup{"axisOccup", {20, 0.0, 40000.0}, "occupancy axis"}; + ConfigurableAxis axisEPAngle{"axisEPAngle", {9, -TMath::Pi() / 2, TMath::Pi() / 2}, "event plane angle"}; - using BinningTypeVertexContributor = ColumnBinningPolicy; + using BinningTypeVertexContributor = ColumnBinningPolicy; ROOT::Math::PxPyPzMVector KstarMother, daughter1, daughter2, kaonrot, kstarrot, pionrot, kstarrot1; void processSameEvent(EventCandidates::iterator const& collision, TrackCandidates const& tracks, aod::BCs const&) @@ -358,24 +334,26 @@ struct kstarpbpb { if (additionalEvSel2 && (!collision.selection_bit(aod::evsel::kNoSameBunchPileup) || !collision.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV))) { return; } + if (additionalEvSel3 && (!collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard))) { + return; + } + int occupancy = collision.trackOccupancyInTimeRange(); auto posThisColl = posTracks->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); auto negThisColl = negTracks->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); auto psiFT0C = collision.psiFT0C(); auto psiFT0A = collision.psiFT0A(); auto psiTPC = collision.psiTPC(); - int occupancy = collision.trackOccupancyInTimeRange(); if (fillOccupancy && occupancy >= cfgOccupancyCut) // occupancy info is available for this collision (*) { return; } - histos.fill(HIST("hFTOCvsTPC"), centrality, multTPC); if (additionalEvsel && !eventSelected(collision, centrality)) { return; } histos.fill(HIST("hFTOCvsTPCSelected"), centrality, multTPC); - histos.fill(HIST("hPsiFT0C"), centrality, occupancy, psiFT0C); - histos.fill(HIST("hPsiFT0A"), centrality, occupancy, psiFT0A); - histos.fill(HIST("hPsiTPC"), centrality, occupancy, psiTPC); + histos.fill(HIST("hPsiFT0C"), centrality, psiFT0C); + histos.fill(HIST("hPsiFT0A"), centrality, psiFT0A); + histos.fill(HIST("hPsiTPC"), centrality, psiTPC); histos.fill(HIST("ResFT0CTPC"), centrality, TMath::Cos(2.0 * (psiFT0C - psiTPC))); histos.fill(HIST("ResFT0CFT0A"), centrality, TMath::Cos(2.0 * (psiFT0C - psiFT0A))); histos.fill(HIST("ResFT0ATPC"), centrality, TMath::Cos(2.0 * (psiTPC - psiFT0A))); @@ -515,6 +493,9 @@ struct kstarpbpb { continue; } kstarrot = kaonrot + daughter2; + if (TMath::Abs(kstarrot.Rapidity()) > confRapidity) { + continue; + } auto phiminuspsiRot = GetPhiInRange(kstarrot.Phi() - psiFT0C); auto v2Rot = TMath::Cos(2.0 * phiminuspsiRot); histos.fill(HIST("hSparseV2SASameEventRotational_V2"), kstarrot.M(), kstarrot.Pt(), v2Rot, centrality); @@ -541,6 +522,9 @@ struct kstarpbpb { continue; } kstarrot1 = pionrot + daughter2; + if (TMath::Abs(kstarrot1.Rapidity()) > confRapidity) { + continue; + } auto phiminuspsiRot1 = GetPhiInRange(kstarrot1.Phi() - psiFT0C); auto v2Rot1 = TMath::Cos(2.0 * phiminuspsiRot1); histos.fill(HIST("hSparseV2SASameEventRotational1_V2"), kstarrot1.M(), kstarrot1.Pt(), v2Rot1, centrality); @@ -566,10 +550,11 @@ struct kstarpbpb { if (additionalEvSel2 && (!collision.selection_bit(aod::evsel::kNoSameBunchPileup) || !collision.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV))) { return; } - auto psiFT0C = collision.psiFT0C(); - auto psiFT0A = collision.psiFT0A(); - auto psiTPC = collision.psiTPC(); + if (additionalEvSel3 && (!collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard))) { + return; + } int occupancy = collision.trackOccupancyInTimeRange(); + auto psiFT0C = collision.psiFT0C(); if (fillOccupancy && occupancy >= cfgOccupancyCut) // occupancy info is available for this collision (*) { return; @@ -672,7 +657,7 @@ struct kstarpbpb { PROCESS_SWITCH(kstarpbpb, processlikeEvent, "Process like event", true); void processMixedEvent(EventCandidates const& collisions, TrackCandidates const& /*tracks*/) { - BinningTypeVertexContributor binningOnPositions{{axisVertex, axisMultiplicityClass, axisOccup}, true}; + BinningTypeVertexContributor binningOnPositions{{axisVertex, axisMultiplicityClass, axisEPAngle}, true}; for (auto const& [collision1, collision2] : o2::soa::selfCombinations(binningOnPositions, cfgNoMixedEvents, -1, collisions, collisions)) { if (!collision1.sel8() || !collision2.sel8()) { // printf("Mix = %d\n", 1); @@ -692,13 +677,19 @@ struct kstarpbpb { if (additionalEvSel2 && (!collision2.selection_bit(aod::evsel::kNoSameBunchPileup) || !collision2.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV))) { continue; } - int occupancy = collision1.trackOccupancyInTimeRange(); + if (additionalEvSel3 && (!collision1.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard))) { + continue; + } + if (additionalEvSel3 && (!collision2.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard))) { + continue; + } + int occupancy1 = collision1.trackOccupancyInTimeRange(); + int occupancy2 = collision2.trackOccupancyInTimeRange(); auto posThisColl = posTracks->sliceByCached(aod::track::collisionId, collision1.globalIndex(), cache); auto negThisColl = negTracks->sliceByCached(aod::track::collisionId, collision2.globalIndex(), cache); auto centrality = collision1.centFT0C(); auto centrality2 = collision2.centFT0C(); auto psiFT0C = collision1.psiFT0C(); - auto QFT0C = collision1.qFT0C(); bool track1pion = false; bool track1kaon = false; bool track2pion = false; @@ -711,6 +702,10 @@ struct kstarpbpb { // printf("Mix = %d\n", 5); continue; } + if (fillOccupancy && occupancy1 >= cfgOccupancyCut && occupancy2 >= cfgOccupancyCut) // occupancy info is available for this collision (*) + { + continue; + } for (auto& [track1, track2] : o2::soa::combinations(o2::soa::CombinationsFullIndexPolicy(posThisColl, negThisColl))) { // track selection if (!selectionTrack(track1) || !selectionTrack(track2)) { @@ -782,129 +777,6 @@ struct kstarpbpb { } } PROCESS_SWITCH(kstarpbpb, processMixedEvent, "Process Mixed event", true); - void processMixedEvent2(EventCandidates const& collisions, TrackCandidates const& tracks) - { - auto tracksTuple = std::make_tuple(tracks); - BinningTypeVertexContributor binningOnPositions{{axisVertex, axisMultiplicityClass, axisOccup}, true}; - SameKindPair pair{binningOnPositions, cfgNoMixedEvents, -1, collisions, tracksTuple, &cache}; - for (auto& [collision1, tracks1, collision2, tracks2] : pair) { - if (!collision1.sel8() || !collision2.sel8()) { - continue; - } - if (!collision1.triggereventep() || !collision2.triggereventep()) { - continue; - } - if (additionalEvSel2 && (!collision1.selection_bit(aod::evsel::kNoSameBunchPileup) || !collision1.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV))) { - continue; - } - if (additionalEvSel2 && (!collision2.selection_bit(aod::evsel::kNoSameBunchPileup) || !collision2.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV))) { - continue; - } - if (timFrameEvsel && (!collision1.selection_bit(aod::evsel::kNoTimeFrameBorder) || !collision2.selection_bit(aod::evsel::kNoTimeFrameBorder) || !collision1.selection_bit(aod::evsel::kNoITSROFrameBorder) || !collision2.selection_bit(aod::evsel::kNoITSROFrameBorder))) { - continue; - } - int occupancy1 = collision1.trackOccupancyInTimeRange(); - int occupancy2 = collision2.trackOccupancyInTimeRange(); - if (fillOccupancy && (occupancy1 >= cfgOccupancyCut || occupancy2 >= cfgOccupancyCut)) { - continue; - } - auto centrality = collision1.centFT0C(); - auto centrality2 = collision2.centFT0C(); - auto psiFT0C = collision1.psiFT0C(); - bool track1pion = false; - bool track1kaon = false; - bool track2pion = false; - bool track2kaon = false; - - if (additionalEvsel && !eventSelected(collision1, centrality)) { - // printf("Mix = %d\n", 4); - continue; - } - if (additionalEvsel && !eventSelected(collision2, centrality2)) { - // printf("Mix = %d\n", 5); - continue; - } - - for (auto& [track1, track2] : o2::soa::combinations(o2::soa::CombinationsFullIndexPolicy(tracks1, tracks2))) { - if (track1.sign() * track2.sign() > 0) { - continue; - } - if (!selectionTrack(track1) || !selectionTrack(track2)) { - continue; - } - if (ispTdepPID && !(selectionPIDNew(track1, 0) || selectionPIDNew(track1, 1))) { - continue; - } - if (ispTdepPID && !(selectionPIDNew(track2, 1) || selectionPIDNew(track2, 0))) { - continue; - } - if (!ispTdepPID && !(selectionPID(track1, 0) || selectionPID(track1, 1))) { - continue; - } - if (!ispTdepPID && !(selectionPID(track2, 1) || selectionPID(track2, 0))) { - continue; - } - - if (ispTdepPID) { - if (selectionPIDNew(track1, 1) && selectionPIDNew(track2, 0)) { - track1pion = true; - track2kaon = true; - if (removefaketrak && isFakeKaon(track2, 0)) { - continue; - } - } - if (selectionPIDNew(track2, 1) && selectionPIDNew(track1, 0)) { - track2pion = true; - track1kaon = true; - if (removefaketrak && isFakeKaon(track1, 0)) { - continue; - } - } - } - if (!ispTdepPID) { - if (selectionPID(track1, 1) && selectionPID(track2, 0)) { - track1pion = true; - track2kaon = true; - if (removefaketrak && isFakeKaon(track2, 0)) { - continue; - } - } - if (selectionPID(track2, 1) && selectionPID(track1, 0)) { - track2pion = true; - track1kaon = true; - if (removefaketrak && isFakeKaon(track1, 0)) { - continue; - } - } - } - if (track1.sign() > 0 && track2.sign() < 0) { - if (track1kaon && track2pion) { - daughter1 = ROOT::Math::PxPyPzMVector(track1.px(), track1.py(), track1.pz(), massKa); - daughter2 = ROOT::Math::PxPyPzMVector(track2.px(), track2.py(), track2.pz(), massPi); - } else if (track1pion && track2kaon) { - daughter1 = ROOT::Math::PxPyPzMVector(track1.px(), track1.py(), track1.pz(), massPi); - daughter2 = ROOT::Math::PxPyPzMVector(track2.px(), track2.py(), track2.pz(), massKa); - } - } else if (track1.sign() < 0 && track2.sign() > 0) { - if (track1kaon && track2pion) { - daughter1 = ROOT::Math::PxPyPzMVector(track1.px(), track1.py(), track1.pz(), massKa); - daughter2 = ROOT::Math::PxPyPzMVector(track2.px(), track2.py(), track2.pz(), massPi); - } else if (track1pion && track2kaon) { - daughter1 = ROOT::Math::PxPyPzMVector(track1.px(), track1.py(), track1.pz(), massPi); - daughter2 = ROOT::Math::PxPyPzMVector(track2.px(), track2.py(), track2.pz(), massKa); - } - } - KstarMother = daughter1 + daughter2; - if (TMath::Abs(KstarMother.Rapidity()) > confRapidity) { - continue; - } - auto phiminuspsi = GetPhiInRange(KstarMother.Phi() - psiFT0C); - auto v2 = TMath::Cos(2.0 * phiminuspsi); - histos.fill(HIST("hSparseV2SAMixedEvent2_V2"), KstarMother.M(), KstarMother.Pt(), v2, centrality); - } - } - } - PROCESS_SWITCH(kstarpbpb, processMixedEvent2, "Process Mixed event", true); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { diff --git a/PWGLF/Tasks/Resonances/phianalysisrun3_PbPb.cxx b/PWGLF/Tasks/Resonances/phianalysisrun3_PbPb.cxx index 69b15309c46..9537b986a04 100644 --- a/PWGLF/Tasks/Resonances/phianalysisrun3_PbPb.cxx +++ b/PWGLF/Tasks/Resonances/phianalysisrun3_PbPb.cxx @@ -80,6 +80,7 @@ struct phianalysisrun3_PbPb { Configurable isNoTOF{"isNoTOF", false, "isNoTOF"}; Configurable isEtaAssym{"isEtaAssym", false, "isEtaAssym"}; Configurable additionalEvSel2{"additionalEvSel2", true, "Additional evsel2"}; + Configurable additionalEvSel3{"additionalEvSel3", true, "Additional evsel3"}; Configurable cfgMultFT0{"cfgMultFT0", true, "cfgMultFT0"}; Configurable iscustomDCAcut{"iscustomDCAcut", false, "iscustomDCAcut"}; Configurable ismanualDCAcut{"ismanualDCAcut", true, "ismanualDCAcut"}; @@ -90,21 +91,19 @@ struct phianalysisrun3_PbPb { Configurable timFrameEvsel{"timFrameEvsel", false, "TPC Time frame boundary cut"}; Configurable isDeepAngle{"isDeepAngle", false, "Deep Angle cut"}; Configurable cfgDeepAngle{"cfgDeepAngle", 0.04, "Deep Angle cut value"}; - Configurable additionalQAplots{"additionalQAplots", true, "Additional QA plots"}; + Configurable genacceptancecut{"genacceptancecut", true, "use acceptance cut for generated"}; // MC Configurable isMC{"isMC", false, "Run MC"}; Configurable avoidsplitrackMC{"avoidsplitrackMC", false, "avoid split track in MC"}; void init(o2::framework::InitContext&) { + std::vector occupancyBinning = {0.0, 500.0, 1000.0, 1500.0, 2000.0, 3000.0, 4000.0, 5000.0, 50000.0}; + AxisSpec occupancyAxis = {occupancyBinning, "Occupancy"}; + 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("hNcontributor", "Number of primary vertex contributor", kTH1F, {{2000, 0.0f, 10000.0f}}); - histos.add("hEta", "Eta distribution", kTH1F, {{200, -1.0f, 1.0f}}); - histos.add("hDcaxy", "Dcaxy distribution", kTH1F, {{200, -1.0f, 1.0f}}); - histos.add("hDcaz", "Dcaz distribution", kTH1F, {{200, -1.0f, 1.0f}}); - histos.add("hNsigmaKaonTPC", "NsigmaKaon TPC distribution", kTH1F, {{200, -10.0f, 10.0f}}); - histos.add("hNsigmaKaonTOF", "NsigmaKaon TOF distribution", kTH1F, {{200, -10.0f, 10.0f}}); + histos.add("hOccupancy", "Occupancy distribution", kTH1F, {occupancyAxis}); if (!isMC) { histos.add("h3PhiInvMassUnlikeSign", "Invariant mass of Phi meson Unlike Sign", kTH3F, {{200, 0.0, 200.0}, {200, 0.0f, 20.0f}, {200, 0.9, 1.1}}); histos.add("h3PhiInvMassLikeSignPP", "Invariant mass of Phi meson Like Sign positive", kTH3F, {{200, 0.0, 200.0}, {200, 0.0f, 20.0f}, {200, 0.9, 1.1}}); @@ -133,21 +132,20 @@ struct phianalysisrun3_PbPb { histos.add("h1Phimassrec", "Phi meson Rec", kTH1F, {{200, 0.9, 1.1}}); histos.add("h1Phipt", "Phi meson Rec", kTH1F, {{200, 0.0f, 20.0f}}); } - if (additionalQAplots) { - // DCA QA - histos.add("QAbefore/trkDCAxy", "DCAxy distribution of kaon track candidates", HistType::kTH1F, {{150, 0.0f, 1.0f}}); - histos.add("QAbefore/trkDCAz", "DCAz distribution of kaon track candidates", HistType::kTH1F, {{150, 0.0f, 1.0f}}); - histos.add("QAafter/trkDCAxy", "DCAxy distribution of kaon track candidates", HistType::kTH1F, {{150, 0.0f, 1.0f}}); - histos.add("QAafter/trkDCAz", "DCAz distribution of kaon track candidates", HistType::kTH1F, {{150, 0.0f, 1.0f}}); - // PID QA before cuts - histos.add("QAbefore/TOF_TPC_Mapka_all", "TOF + TPC Combined PID for Kaon;#sigma_{TOF}^{Kaon};#sigma_{TPC}^{Kaon}", {HistType::kTH2D, {{100, -6, 6}, {100, -6, 6}}}); - histos.add("QAbefore/TOF_Nsigma_all", "TOF NSigma for Kaon;#it{p}_{T} (GeV/#it{c});#sigma_{TOF}^{Kaon};", {HistType::kTH2D, {{200, 0.0, 20.0}, {100, -6, 6}}}); - histos.add("QAbefore/TPC_Nsigma_all", "TPC NSigma for Kaon;#it{p}_{T} (GeV/#it{c});#sigma_{TPC}^{Kaon};", {HistType::kTH2D, {{200, 0.0, 20.0}, {100, -6, 6}}}); - // PID QA after cuts - histos.add("QAafter/TOF_TPC_Mapka_all", "TOF + TPC Combined PID for Kaon;#sigma_{TOF}^{Kaon};#sigma_{TPC}^{Kaon}", {HistType::kTH2D, {{100, -6, 6}, {100, -6, 6}}}); - histos.add("QAafter/TOF_Nsigma_all", "TOF NSigma for Kaon;#it{p}_{T} (GeV/#it{c});#sigma_{TOF}^{Kaon};", {HistType::kTH2D, {{200, 0.0, 20.0}, {100, -6, 6}}}); - histos.add("QAafter/TPC_Nsigma_all", "TPC NSigma for Kaon;#it{p}_{T} (GeV/#it{c});#sigma_{TPC}^{Kaon};", {HistType::kTH2D, {{200, 0.0, 20.0}, {100, -6, 6}}}); - } + + // DCA QA + histos.add("QAbefore/trkDCAxy", "DCAxy distribution of kaon track candidates", HistType::kTH1F, {{150, 0.0f, 1.0f}}); + histos.add("QAbefore/trkDCAz", "DCAz distribution of kaon track candidates", HistType::kTH1F, {{150, 0.0f, 1.0f}}); + histos.add("QAafter/trkDCAxy", "DCAxy distribution of kaon track candidates", HistType::kTH1F, {{150, 0.0f, 1.0f}}); + histos.add("QAafter/trkDCAz", "DCAz distribution of kaon track candidates", HistType::kTH1F, {{150, 0.0f, 1.0f}}); + // PID QA before cuts + histos.add("QAbefore/TOF_TPC_Mapka_all", "TOF + TPC Combined PID for Kaon;#sigma_{TOF}^{Kaon};#sigma_{TPC}^{Kaon}", {HistType::kTH2D, {{100, -6, 6}, {100, -6, 6}}}); + histos.add("QAbefore/TOF_Nsigma_all", "TOF NSigma for Kaon;#it{p}_{T} (GeV/#it{c});#sigma_{TOF}^{Kaon};", {HistType::kTH2D, {{200, 0.0, 20.0}, {100, -6, 6}}}); + histos.add("QAbefore/TPC_Nsigma_all", "TPC NSigma for Kaon;#it{p}_{T} (GeV/#it{c});#sigma_{TPC}^{Kaon};", {HistType::kTH2D, {{200, 0.0, 20.0}, {100, -6, 6}}}); + // PID QA after cuts + histos.add("QAafter/TOF_TPC_Mapka_all", "TOF + TPC Combined PID for Kaon;#sigma_{TOF}^{Kaon};#sigma_{TPC}^{Kaon}", {HistType::kTH2D, {{100, -6, 6}, {100, -6, 6}}}); + histos.add("QAafter/TOF_Nsigma_all", "TOF NSigma for Kaon;#it{p}_{T} (GeV/#it{c});#sigma_{TOF}^{Kaon};", {HistType::kTH2D, {{200, 0.0, 20.0}, {100, -6, 6}}}); + histos.add("QAafter/TPC_Nsigma_all", "TPC NSigma for Kaon;#it{p}_{T} (GeV/#it{c});#sigma_{TPC}^{Kaon};", {HistType::kTH2D, {{200, 0.0, 20.0}, {100, -6, 6}}}); } double massKa = o2::constants::physics::MassKPlus; @@ -318,6 +316,9 @@ struct phianalysisrun3_PbPb { if (additionalEvSel2 && (!collision.selection_bit(aod::evsel::kNoSameBunchPileup) || !collision.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV))) { return; } + if (additionalEvSel3 && (!collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard))) { + return; + } int occupancy = collision.trackOccupancyInTimeRange(); if (fillOccupancy && occupancy < cfgOccupancyCut) // occupancy info is available for this collision (*) { @@ -326,11 +327,9 @@ struct phianalysisrun3_PbPb { float multiplicity; if (cfgMultFT0) multiplicity = collision.centFT0C(); - if (!cfgMultFT0) - multiplicity = collision.numContrib(); histos.fill(HIST("hCentrality"), multiplicity); - histos.fill(HIST("hNcontributor"), collision.numContrib()); histos.fill(HIST("hVtxZ"), collision.posZ()); + histos.fill(HIST("hOccupancy"), occupancy); for (auto track1 : tracks) { if (!selectionTrack(track1)) { continue; @@ -341,11 +340,6 @@ struct phianalysisrun3_PbPb { histos.fill(HIST("QAbefore/trkDCAz"), track1.dcaZ()); histos.fill(HIST("QAbefore/TOF_TPC_Mapka_all"), track1.tofNSigmaKa(), track1.tpcNSigmaKa()); - histos.fill(HIST("hEta"), track1.eta()); - histos.fill(HIST("hDcaxy"), track1.dcaXY()); - histos.fill(HIST("hDcaz"), track1.dcaZ()); - histos.fill(HIST("hNsigmaKaonTPC"), track1.tpcNSigmaKa()); - histos.fill(HIST("hNsigmaKaonTOF"), track1.tofNSigmaKa()); auto track1ID = track1.globalIndex(); for (auto track2 : tracks) { if (!selectionTrack(track2)) { @@ -410,8 +404,15 @@ struct phianalysisrun3_PbPb { if (additionalEvSel2 && (!c2.selection_bit(aod::evsel::kNoSameBunchPileup) || !c2.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV))) { continue; } - int occupancy = c1.trackOccupancyInTimeRange(); - if (fillOccupancy && occupancy < cfgOccupancyCut) // occupancy info is available for this collision (*) + if (additionalEvSel3 && (!c1.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard))) { + continue; + } + if (additionalEvSel3 && (!c2.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard))) { + continue; + } + int occupancy1 = c1.trackOccupancyInTimeRange(); + int occupancy2 = c2.trackOccupancyInTimeRange(); + if (fillOccupancy && occupancy1 < cfgOccupancyCut && occupancy2 < cfgOccupancyCut) // occupancy info is available for this collision (*) { return; } diff --git a/PWGLF/Tasks/Strangeness/derivedcascadeanalysis.cxx b/PWGLF/Tasks/Strangeness/derivedcascadeanalysis.cxx index 861f820e157..cbd0a25b906 100644 --- a/PWGLF/Tasks/Strangeness/derivedcascadeanalysis.cxx +++ b/PWGLF/Tasks/Strangeness/derivedcascadeanalysis.cxx @@ -45,6 +45,9 @@ using namespace o2::framework; using namespace o2::framework::expressions; using std::array; +using dauTracks = soa::Join; +using cascMCCandidates = soa::Join; + struct derivedCascadeAnalysis { HistogramRegistry histos{"Histos", {}, OutputObjHandlingPolicy::AnalysisObject}; @@ -54,13 +57,13 @@ struct derivedCascadeAnalysis { ConfigurableAxis axisOccupancy{"axisOccupancy", {VARIABLE_WIDTH, 0.0f, 250.0f, 500.0f, 750.0f, 1000.0f, 1500.0f, 2000.0f, 3000.0f, 4500.0f, 6000.0f, 8000.0f, 10000.0f, 50000.0f}, "occupancy axis"}; ConfigurableAxis vertexZ{"vertexZ", {30, -15.0f, 15.0f}, ""}; - ConfigurableAxis axisXiMass{"axisXiMass", {200, 1.222f, 1.422f}, ""}; - ConfigurableAxis axisOmegaMass{"axisOmegaMass", {200, 1.572f, 1.772f}, ""}; + ConfigurableAxis axisMass{"axisMass", {200, 1.222f, 1.422f}, "range of invariant mass, in case of omega take 1.572f, 1.772f"}; Configurable isXi{"isXi", 1, "Apply cuts for Xi identification"}; - Configurable isMC{"isMC", false, "MC data are processed"}; Configurable doBefSelCheck{"doBefSelCheck", false, "Fill mass histograms of all candidates before selections"}; Configurable doPtDepCutStudy{"doPtDepCutStudy", false, "Fill histogram with a cutting paramer"}; + Configurable doTriggerTVXEventCut{"doTriggerTVXEventCut", false, "Minimal MB event selection, for MC"}; + Configurable doTriggerSel8EventCut{"doTriggerSel8EventCut", true, "Standard MB event selection"}; Configurable doGoodPVFT0EventCut{"doGoodPVFT0EventCut", true, "check for the PV position diffrence when estimated from tracks and FT0"}; Configurable doITSTPCvertexEventCut{"doITSTPCvertexEventCut", true, "checks the presence of at least one ITS-TPC track"}; Configurable doSameBunchPileUpEventCut{"doSameBunchPileUpEventCut", true, "removes events associated with the same \"found-by-T0\" bunch crossing"}; @@ -72,6 +75,9 @@ struct derivedCascadeAnalysis { Configurable doMultiplicityCorrCut{"doMultiplicityCorrCut", false, "Enable multiplicity vs centrality correlation cut"}; Configurable doOccupancyCheck{"doOccupancyCheck", true, ""}; Configurable doTimeRangeStandardCut{"doTimeRangeStandardCut", true, "It rejects a given collision if there are other events nearby in |dt|< 10 μs"}; + Configurable doTimeRangeNarrowCut{"doTimeRangeNarrowCut", false, "It rejects a given collision if there are other events nearby in |dt|< 4 μs"}; + Configurable minOccupancy{"minOccupancy", -1, "Minimal occupancy"}; + Configurable maxOccupancy{"maxOccupancy", -1, "Maximal occupancy"}; Configurable centMin{"centMin", 0, "Minimal accepted centrality"}; Configurable centMax{"centMax", 100, "Maximal accepted centrality"}; @@ -146,16 +152,24 @@ struct derivedCascadeAnalysis { Configurable dcaCacsDauPar1{"dcaCacsDauPar1", 0.5, " par for pt dep DCA cascade daughter cut, 1< p_T < 4 GeV/c"}; Configurable dcaCacsDauPar2{"dcaCacsDauPar2", 0.2, " par for pt dep DCA cascade daughter cut, p_T > 4 GeV/c"}; + ConfigurableAxis axisNch{"axisNch", {500, 0.0f, +5000.0f}, "Number of charged particles in |y| < 0.5"}; + Service pdgDB; static constexpr std::string_view Index[] = {"1", "2", "3", "4", "5", "6", "7", "8", "9", "10"}; static constexpr float centralityIntervals[11] = {0., 5., 10., 20., 30., 40., 50., 60., 70., 80., 90.}; + static constexpr std::string_view charge[] = {"Positive", "Negative"}; + static constexpr std::string_view selectionNames[] = {"BachelorBaryonDCA", "DCAV0ToPV", "V0Radius", "CascadeRadius", "DCAV0Daughters", "DCACascDaughters", "V0pa", "CascPA", "DCABachelorToPV", "DCAMesonToPV", "DCABaryonToPV", "CascadeProperLifeTime"}; + + // For manual sliceBy + // Preslice> perMcCollision = aod::v0data::straMCCollisionId; + PresliceUnsorted> perMcCollision = aod::v0data::straMCCollisionId; void init(InitContext const&) { histos.add("hEventVertexZ", "hEventVertexZ", kTH1F, {vertexZ}); histos.add("hEventCentrality", "hEventCentrality", kTH1F, {{101, 0, 101}}); - histos.add("hEventSelection", "hEventSelection", kTH1F, {{13, 0, 13}}); + histos.add("hEventSelection", "hEventSelection", kTH1F, {{17, 0, 17}}); histos.add("hOccupancyVsCentrality", "", kTH2F, {axisOccupancy, {100, 0, 100}}); histos.add("hEventNchCorrelationAfCuts", "hEventNchCorrelationAfCuts", kTH2F, {{5000, 0, 5000}, {5000, 0, 2500}}); @@ -202,12 +216,12 @@ struct derivedCascadeAnalysis { histos.get(HIST("hCutValue"))->GetXaxis()->SetBinLabel(i, CutLabel[i - 1]); } - histos.add("InvMassAfterSel/hNegativeCascade", "hNegativeCascade", HistType::kTH3F, {axisPt, axisXiMass, {101, 0, 101}}); - histos.add("InvMassAfterSel/hPositiveCascade", "hPositiveCascade", {HistType::kTH3F, {axisPt, axisXiMass, {101, 0, 101}}}); + histos.add("InvMassAfterSel/hNegativeCascade", "hNegativeCascade", HistType::kTH3F, {axisPt, axisMass, {101, 0, 101}}); + histos.add("InvMassAfterSel/hPositiveCascade", "hPositiveCascade", {HistType::kTH3F, {axisPt, axisMass, {101, 0, 101}}}); if (doOccupancyCheck) { - histos.add("InvMassAfterSelCent1/hNegativeCascade", "hNegativeCascade", HistType::kTH3F, {axisPt, axisXiMass, axisOccupancy}); - histos.add("InvMassAfterSelCent1/hPositiveCascade", "hPositiveCascade", HistType::kTH3F, {axisPt, axisXiMass, axisOccupancy}); + histos.add("InvMassAfterSelCent1/hNegativeCascade", "hNegativeCascade", HistType::kTH3F, {axisPt, axisMass, axisOccupancy}); + histos.add("InvMassAfterSelCent1/hPositiveCascade", "hPositiveCascade", HistType::kTH3F, {axisPt, axisMass, axisOccupancy}); histos.addClone("InvMassAfterSelCent1/", "InvMassAfterSelCent2/"); histos.addClone("InvMassAfterSelCent1/", "InvMassAfterSelCent3/"); histos.addClone("InvMassAfterSelCent1/", "InvMassAfterSelCent4/"); @@ -219,118 +233,83 @@ struct derivedCascadeAnalysis { histos.addClone("InvMassAfterSelCent1/", "InvMassAfterSelCent10/"); } - if (!isXi) { - histos.get(HIST("InvMassAfterSel/hNegativeCascade"))->GetYaxis()->Set(200, 1.572f, 1.772f); - histos.get(HIST("InvMassAfterSel/hPositiveCascade"))->GetYaxis()->Set(200, 1.572f, 1.772f); - } - if (doBefSelCheck) histos.addClone("InvMassAfterSel/", "InvMassBefSel/"); - if (isMC) + if (doprocessCascadesMCrec) histos.addClone("InvMassAfterSel/", "InvMassAfterSelMCrecTruth/"); if (doPtDepCutStudy && !doProperLifeTimeCut) { - histos.add("PtDepCutStudy/hNegativeCascadeProperLifeTime", "hNegativeCascadeProperLifeTime", HistType::kTH3F, {axisPt, axisXiMass, {100, 0, 10}}); - histos.add("PtDepCutStudy/hPositiveCascadeProperLifeTime", "hPositiveCascadeProperLifeTime", {HistType::kTH3F, {axisPt, axisXiMass, {100, 0, 10}}}); - if (!isXi) { - histos.get(HIST("PtDepCutStudy/hNegativeCascadeProperLifeTime"))->GetYaxis()->Set(200, 1.572f, 1.772f); - histos.get(HIST("PtDepCutStudy/hPositiveCascadeProperLifeTime"))->GetYaxis()->Set(200, 1.572f, 1.772f); - } + histos.add("PtDepCutStudy/hNegativeCascadeProperLifeTime", "hNegativeCascadeProperLifeTime", HistType::kTH3F, {axisPt, axisMass, {100, 0, 10}}); + histos.add("PtDepCutStudy/hPositiveCascadeProperLifeTime", "hPositiveCascadeProperLifeTime", {HistType::kTH3F, {axisPt, axisMass, {100, 0, 10}}}); } if (doPtDepCutStudy && !doBachelorBaryonCut) { - histos.add("PtDepCutStudy/hNegativeBachelorBaryonDCA", "hNegativeBachelorBaryonDCA", HistType::kTH3F, {axisPt, axisXiMass, {40, 0, 1}}); - histos.add("PtDepCutStudy/hPositiveBachelorBaryonDCA", "hPositiveBachelorBaryonDCA", {HistType::kTH3F, {axisPt, axisXiMass, {40, 0, 1}}}); - if (!isXi) { - histos.get(HIST("PtDepCutStudy/hNegativeBachelorBaryonDCA"))->GetYaxis()->Set(200, 1.572f, 1.772f); - histos.get(HIST("PtDepCutStudy/hPositiveBachelorBaryonDCA"))->GetYaxis()->Set(200, 1.572f, 1.772f); - } + histos.add("PtDepCutStudy/hNegativeBachelorBaryonDCA", "hNegativeBachelorBaryonDCA", HistType::kTH3F, {axisPt, axisMass, {40, 0, 1}}); + histos.add("PtDepCutStudy/hPositiveBachelorBaryonDCA", "hPositiveBachelorBaryonDCA", {HistType::kTH3F, {axisPt, axisMass, {40, 0, 1}}}); } if (doPtDepCutStudy && !doDCAV0ToPVCut) { - histos.add("PtDepCutStudy/hNegativeDCAV0ToPV", "hNegativeDCAV0ToPV", HistType::kTH3F, {axisPt, axisXiMass, {40, 0, 1}}); - histos.add("PtDepCutStudy/hPositiveDCAV0ToPV", "hPositiveDCAV0ToPV", {HistType::kTH3F, {axisPt, axisXiMass, {40, 0, 1}}}); - if (!isXi) { - histos.get(HIST("PtDepCutStudy/hNegativeDCAV0ToPV"))->GetYaxis()->Set(200, 1.572f, 1.772f); - histos.get(HIST("PtDepCutStudy/hPositiveDCAV0ToPV"))->GetYaxis()->Set(200, 1.572f, 1.772f); - } + histos.add("PtDepCutStudy/hNegativeDCAV0ToPV", "hNegativeDCAV0ToPV", HistType::kTH3F, {axisPt, axisMass, {40, 0, 1}}); + histos.add("PtDepCutStudy/hPositiveDCAV0ToPV", "hPositiveDCAV0ToPV", {HistType::kTH3F, {axisPt, axisMass, {40, 0, 1}}}); } if (doPtDepCutStudy && !doV0RadiusCut) { - histos.add("PtDepCutStudy/hNegativeV0Radius", "hNegativeV0Radius", HistType::kTH3F, {axisPt, axisXiMass, {20, 0, 10}}); - histos.add("PtDepCutStudy/hPositiveV0Radius", "hPositiveV0Radius", {HistType::kTH3F, {axisPt, axisXiMass, {20, 0, 10}}}); - if (!isXi) { - histos.get(HIST("PtDepCutStudy/hNegativeV0Radius"))->GetYaxis()->Set(200, 1.572f, 1.772f); - histos.get(HIST("PtDepCutStudy/hPositiveV0Radius"))->GetYaxis()->Set(200, 1.572f, 1.772f); - } + histos.add("PtDepCutStudy/hNegativeV0Radius", "hNegativeV0Radius", HistType::kTH3F, {axisPt, axisMass, {20, 0, 10}}); + histos.add("PtDepCutStudy/hPositiveV0Radius", "hPositiveV0Radius", {HistType::kTH3F, {axisPt, axisMass, {20, 0, 10}}}); } if (doPtDepCutStudy && !doCascadeRadiusCut) { - histos.add("PtDepCutStudy/hNegativeCascadeRadius", "hNegativeCascadeRadius", HistType::kTH3F, {axisPt, axisXiMass, {50, 0, 5}}); - histos.add("PtDepCutStudy/hPositiveCascadeRadius", "hPositiveCascadeRadius", {HistType::kTH3F, {axisPt, axisXiMass, {50, 0, 5}}}); - if (!isXi) { - histos.get(HIST("PtDepCutStudy/hNegativeCascadeRadius"))->GetYaxis()->Set(200, 1.572f, 1.772f); - histos.get(HIST("PtDepCutStudy/hPositiveCascadeRadius"))->GetYaxis()->Set(200, 1.572f, 1.772f); - } + histos.add("PtDepCutStudy/hNegativeCascadeRadius", "hNegativeCascadeRadius", HistType::kTH3F, {axisPt, axisMass, {50, 0, 5}}); + histos.add("PtDepCutStudy/hPositiveCascadeRadius", "hPositiveCascadeRadius", {HistType::kTH3F, {axisPt, axisMass, {50, 0, 5}}}); } if (doPtDepCutStudy && !doDCAV0DauCut) { - histos.add("PtDepCutStudy/hNegativeDCAV0Daughters", "hNegativeDCAV0Daughters", HistType::kTH3F, {axisPt, axisXiMass, {50, 0, 5}}); - histos.add("PtDepCutStudy/hPositiveDCAV0Daughters", "hPositiveDCAV0Daughters", {HistType::kTH3F, {axisPt, axisXiMass, {50, 0, 5}}}); - if (!isXi) { - histos.get(HIST("PtDepCutStudy/hNegativeDCAV0Daughters"))->GetYaxis()->Set(200, 1.572f, 1.772f); - histos.get(HIST("PtDepCutStudy/hPositiveDCAV0Daughters"))->GetYaxis()->Set(200, 1.572f, 1.772f); - } + histos.add("PtDepCutStudy/hNegativeDCAV0Daughters", "hNegativeDCAV0Daughters", HistType::kTH3F, {axisPt, axisMass, {50, 0, 5}}); + histos.add("PtDepCutStudy/hPositiveDCAV0Daughters", "hPositiveDCAV0Daughters", {HistType::kTH3F, {axisPt, axisMass, {50, 0, 5}}}); } if (doPtDepCutStudy && !doDCACascadeDauCut) { - histos.add("PtDepCutStudy/hNegativeDCACascDaughters", "hNegativeDCACascDaughters", {HistType::kTH3F, {axisPt, axisXiMass, {20, 0, 1}}}); - histos.add("PtDepCutStudy/hPositiveDCACascDaughters", "hPositiveDCACascDaughters", {HistType::kTH3F, {axisPt, axisXiMass, {20, 0, 1}}}); - if (!isXi) { - histos.get(HIST("PtDepCutStudy/hPositiveDCACascDaughters"))->GetYaxis()->Set(200, 1.572f, 1.772f); - histos.get(HIST("PtDepCutStudy/hNegativeDCACascDaughters"))->GetYaxis()->Set(200, 1.572f, 1.772f); - } + histos.add("PtDepCutStudy/hNegativeDCACascDaughters", "hNegativeDCACascDaughters", {HistType::kTH3F, {axisPt, axisMass, {20, 0, 1}}}); + histos.add("PtDepCutStudy/hPositiveDCACascDaughters", "hPositiveDCACascDaughters", {HistType::kTH3F, {axisPt, axisMass, {20, 0, 1}}}); } if (doPtDepCutStudy && !doV0CosPaCut) { - histos.add("PtDepCutStudy/hNegativeV0pa", "hNegativeV0pa", HistType::kTH3F, {axisPt, axisXiMass, {40, 0, 0.4}}); - histos.add("PtDepCutStudy/hPositiveV0pa", "hPositiveV0pa", {HistType::kTH3F, {axisPt, axisXiMass, {40, 0, 0.4}}}); - if (!isXi) { - histos.get(HIST("PtDepCutStudy/hNegativeV0pa"))->GetYaxis()->Set(200, 1.572f, 1.772f); - histos.get(HIST("PtDepCutStudy/hPositiveV0pa"))->GetYaxis()->Set(200, 1.572f, 1.772f); - } + histos.add("PtDepCutStudy/hNegativeV0pa", "hNegativeV0pa", HistType::kTH3F, {axisPt, axisMass, {40, 0, 0.4}}); + histos.add("PtDepCutStudy/hPositiveV0pa", "hPositiveV0pa", {HistType::kTH3F, {axisPt, axisMass, {40, 0, 0.4}}}); } if (doPtDepCutStudy && !doDCAdauToPVCut) { - histos.add("PtDepCutStudy/hNegativeDCABachelorToPV", "hNegativeDCABachelorToPV", HistType::kTH3F, {axisPt, axisXiMass, {50, 0, 0.5}}); - histos.add("PtDepCutStudy/hNegativeDCABaryonToPV", "hNegativeDCABaryonToPV", HistType::kTH3F, {axisPt, axisXiMass, {50, 0, 0.5}}); - histos.add("PtDepCutStudy/hNegativeDCAMesonToPV", "hNegativeDCAMesonToPV", HistType::kTH3F, {axisPt, axisXiMass, {50, 0, 0.5}}); - histos.add("PtDepCutStudy/hPositiveDCABachelorToPV", "hPositiveDCABachelorToPV", {HistType::kTH3F, {axisPt, axisXiMass, {50, 0, 0.5}}}); - histos.add("PtDepCutStudy/hPositiveDCABaryonToPV", "hPositiveDCABaryonToPV", HistType::kTH3F, {axisPt, axisXiMass, {50, 0, 0.5}}); - histos.add("PtDepCutStudy/hPositiveDCAMesonToPV", "hPositiveDCAMesonToPV", HistType::kTH3F, {axisPt, axisXiMass, {50, 0, 0.5}}); - if (!isXi) { - histos.get(HIST("PtDepCutStudy/hNegativeDCABachelorToPV"))->GetYaxis()->Set(200, 1.572f, 1.772f); - histos.get(HIST("PtDepCutStudy/hNegativeDCABaryonToPV"))->GetYaxis()->Set(200, 1.572f, 1.772f); - histos.get(HIST("PtDepCutStudy/hNegativeDCAMesonToPV"))->GetYaxis()->Set(200, 1.572f, 1.772f); - histos.get(HIST("PtDepCutStudy/hPositiveDCABachelorToPV"))->GetYaxis()->Set(200, 1.572f, 1.772f); - histos.get(HIST("PtDepCutStudy/hPositiveDCABaryonToPV"))->GetYaxis()->Set(200, 1.572f, 1.772f); - histos.get(HIST("PtDepCutStudy/hPositiveDCAMesonToPV"))->GetYaxis()->Set(200, 1.572f, 1.772f); - } + histos.add("PtDepCutStudy/hNegativeDCABachelorToPV", "hNegativeDCABachelorToPV", HistType::kTH3F, {axisPt, axisMass, {50, 0, 0.5}}); + histos.add("PtDepCutStudy/hNegativeDCABaryonToPV", "hNegativeDCABaryonToPV", HistType::kTH3F, {axisPt, axisMass, {50, 0, 0.5}}); + histos.add("PtDepCutStudy/hNegativeDCAMesonToPV", "hNegativeDCAMesonToPV", HistType::kTH3F, {axisPt, axisMass, {50, 0, 0.5}}); + histos.add("PtDepCutStudy/hPositiveDCABachelorToPV", "hPositiveDCABachelorToPV", {HistType::kTH3F, {axisPt, axisMass, {50, 0, 0.5}}}); + histos.add("PtDepCutStudy/hPositiveDCABaryonToPV", "hPositiveDCABaryonToPV", HistType::kTH3F, {axisPt, axisMass, {50, 0, 0.5}}); + histos.add("PtDepCutStudy/hPositiveDCAMesonToPV", "hPositiveDCAMesonToPV", HistType::kTH3F, {axisPt, axisMass, {50, 0, 0.5}}); } if (doPtDepCutStudy && !doCascadeCosPaCut) { - histos.add("PtDepCutStudy/hNegativeCascPA", "hNegativeCascPA", HistType::kTH3F, {axisPt, axisXiMass, {40, 0, 0.4}}); - histos.add("PtDepCutStudy/hPositiveCascPA", "hPositiveCascPA", {HistType::kTH3F, {axisPt, axisXiMass, {40, 0, 0.4}}}); - if (!isXi) { - histos.get(HIST("PtDepCutStudy/hNegativeCascPA"))->GetYaxis()->Set(200, 1.572f, 1.772f); - histos.get(HIST("PtDepCutStudy/hPositiveCascPA"))->GetYaxis()->Set(200, 1.572f, 1.772f); - } + histos.add("PtDepCutStudy/hNegativeCascPA", "hNegativeCascPA", HistType::kTH3F, {axisPt, axisMass, {40, 0, 0.4}}); + histos.add("PtDepCutStudy/hPositiveCascPA", "hPositiveCascPA", {HistType::kTH3F, {axisPt, axisMass, {40, 0, 0.4}}}); } - if (isMC) { + if (doprocessCascadesMCrec) { histos.addClone("PtDepCutStudy/", "PtDepCutStudyMCTruth/"); - histos.add("hNegativeCascadePtForEfficiency", "hNegativeCascadePtForEfficiency", HistType::kTH3F, {axisPt, axisXiMass, {101, 0, 101}}); - histos.add("hPositiveCascadePtForEfficiency", "hPositiveCascadePtForEfficiency", {HistType::kTH3F, {axisPt, axisXiMass, {101, 0, 101}}}); - if (!isXi) { - histos.get(HIST("hNegativeCascadePtForEfficiency"))->GetYaxis()->Set(200, 1.572f, 1.772f); - histos.get(HIST("hPositiveCascadePtForEfficiency"))->GetYaxis()->Set(200, 1.572f, 1.772f); - } + histos.add("hNegativeCascadePtForEfficiency", "hNegativeCascadePtForEfficiency", HistType::kTH3F, {axisPt, axisMass, {101, 0, 101}}); + histos.add("hPositiveCascadePtForEfficiency", "hPositiveCascadePtForEfficiency", {HistType::kTH3F, {axisPt, axisMass, {101, 0, 101}}}); + } + + if (doprocessCascadesMCforEff) { + histos.add("hGenEvents", "", HistType::kTH2F, {{axisNch}, {2, 0, 2}}); + histos.add("hCentralityVsMultMC", "", kTH2F, {{101, 0.0f, 101.0f}, axisNch}); + + histos.add("hCentralityVsNcoll_beforeEvSel", "", kTH2F, {{101, 0.0f, 101.0f}, {50, 0.f, 50.f}}); + histos.add("hCentralityVsNcoll_afterEvSel", "", kTH2F, {{101, 0.0f, 101.0f}, {50, 0.f, 50.f}}); + + histos.add("h2dGenXiMinus", "h2dGenXiMinus", kTH2D, {{101, 0.0f, 101.0f}, axisPt}); + histos.add("h2dGenXiPlus", "h2dGenXiPlus", kTH2D, {{101, 0.0f, 101.0f}, axisPt}); + histos.add("h2dGenOmegaMinus", "h2dGenOmegaMinus", kTH2D, {{101, 0.0f, 101.0f}, axisPt}); + histos.add("h2dGenOmegaPlus", "h2dGenOmegaPlus", kTH2D, {{101, 0.0f, 101.0f}, axisPt}); + + histos.add("h2dGenXiMinusVsMultMC", "h2dGenXiMinusVsMultMC", kTH2D, {axisNch, axisPt}); + histos.add("h2dGenXiPlusVsMultMC", "h2dGenXiPlusVsMultMC", kTH2D, {axisNch, axisPt}); + histos.add("h2dGenOmegaMinusVsMultMC", "h2dGenOmegaMinusVsMultMC", kTH2D, {axisNch, axisPt}); + histos.add("h2dGenOmegaPlusVsMultMC", "h2dGenOmegaPlusVsMultMC", kTH2D, {axisNch, axisPt}); } } template @@ -370,111 +349,128 @@ struct derivedCascadeAnalysis { return true; } + template - bool IsEventAccepted(TCollision coll, bool sel) + bool IsEventAccepted(TCollision coll, bool fillHists) { - histos.fill(HIST("hEventSelection"), 0.5 /* all collisions */); + if (fillHists) + histos.fill(HIST("hEventSelection"), 0.5 /* all collisions */); if (doBefSelEventMultCorr) { histos.fill(HIST("hEventNchCorrelationBefCuts"), coll.multNTracksPVeta1(), coll.multNTracksGlobal()); histos.fill(HIST("hEventPVcontributorsVsCentralityBefCuts"), coll.centFT0C(), coll.multNTracksPVeta1()); histos.fill(HIST("hEventGlobalTracksVsCentralityBefCuts"), coll.centFT0C(), coll.multNTracksGlobal()); } - if (isMC) { - if (!coll.selection_bit(aod::evsel::kIsTriggerTVX)) { - return false; - } - histos.fill(HIST("hEventSelection"), 1.5 /* MB trigger*/); - if (TMath::Abs(coll.posZ()) > zVertexCut) { - return false; - } + if (doTriggerTVXEventCut && !coll.selection_bit(aod::evsel::kIsTriggerTVX)) { + return false; + } + if (fillHists) + histos.fill(HIST("hEventSelection"), 1.5 /* collisions after sel*/); - histos.fill(HIST("hEventSelection"), 2.5 /* collisions after sel pvz sel*/); + if (doTriggerSel8EventCut && !coll.sel8()) { + return false; + } + if (fillHists) + histos.fill(HIST("hEventSelection"), 2.5 /* collisions after sel*/); - if (doTFeventCut && !coll.selection_bit(o2::aod::evsel::kNoTimeFrameBorder)) { - return false; - } - histos.fill(HIST("hEventSelection"), 3.5 /* Not at TF border */); - if (doITSFrameBorderCut && !coll.selection_bit(o2::aod::evsel::kNoITSROFrameBorder)) { - return false; - } - histos.fill(HIST("hEventSelection"), 4.5 /* Not at ITS ROF border */); - } else { - if (!sel) { - return false; - } - histos.fill(HIST("hEventSelection"), 1.5 /* collisions after sel*/); - if (TMath::Abs(coll.posZ()) > zVertexCut) { - return false; - } + if (TMath::Abs(coll.posZ()) > zVertexCut) { + return false; + } + if (fillHists) + histos.fill(HIST("hEventSelection"), 3.5 /* collisions after sel pvz sel*/); - histos.fill(HIST("hEventSelection"), 2.5 /* collisions after sel pvz sel*/); + if (coll.centFT0C() > centMax || coll.centFT0C() < centMin) { + return false; + } + if (fillHists) + histos.fill(HIST("hEventSelection"), 4.5 /* collisions after centrality sel*/); - if (coll.centFT0C() > centMax || coll.centFT0C() < centMin) { - return false; - } + if (doSameBunchPileUpEventCut && !coll.selection_bit(o2::aod::evsel::kNoSameBunchPileup)) { + return false; + } + if (fillHists) + histos.fill(HIST("hEventSelection"), 5.5 /* Not same Bunch pile up */); - histos.fill(HIST("hEventSelection"), 3.5 /* collisions after centrality sel*/); + if (doGoodPVFT0EventCut && !coll.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV)) { + return false; + } + if (fillHists) + histos.fill(HIST("hEventSelection"), 6.5 /* No large vertexZ difference from tracks and FT0*/); - if (doSameBunchPileUpEventCut && !coll.selection_bit(o2::aod::evsel::kNoSameBunchPileup)) { - return false; - } - histos.fill(HIST("hEventSelection"), 4.5 /* Not same Bunch pile up */); + if (doITSTPCvertexEventCut && !coll.selection_bit(o2::aod::evsel::kIsVertexITSTPC)) { + return false; + } + if (fillHists) + histos.fill(HIST("hEventSelection"), 7.5 /* At least one ITS-TPC track in the event*/); - if (doGoodPVFT0EventCut && !coll.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV)) { - return false; - } - histos.fill(HIST("hEventSelection"), 5.5 /* No large vertexZ difference from tracks and FT0*/); + if (doVertexTOFmatch && !coll.selection_bit(o2::aod::evsel::kIsVertexTOFmatched)) { + return false; + } + if (fillHists) + histos.fill(HIST("hEventSelection"), 8.5 /* At least one of vertex contributors is matched to TOF*/); - if (doITSTPCvertexEventCut && !coll.selection_bit(o2::aod::evsel::kIsVertexITSTPC)) { - return false; - } - histos.fill(HIST("hEventSelection"), 6.5 /* At least one ITS-TPC track in the event*/); + if (doVertexTRDmatch && !coll.selection_bit(o2::aod::evsel::kIsVertexTRDmatched)) { + return false; + } + if (fillHists) + histos.fill(HIST("hEventSelection"), 9.5 /* At least one of vertex contributors is matched to TRD*/); - if (doVertexTOFmatch && !coll.selection_bit(o2::aod::evsel::kIsVertexTOFmatched)) { - return false; - } - histos.fill(HIST("hEventSelection"), 7.5 /* At least one of vertex contributors is matched to TOF*/); + if (doITSFrameBorderCut && !coll.selection_bit(o2::aod::evsel::kNoITSROFrameBorder)) { + return false; + } + if (fillHists) + histos.fill(HIST("hEventSelection"), 10.5 /* Not at ITS ROF border */); - if (doVertexTRDmatch && !coll.selection_bit(o2::aod::evsel::kIsVertexTRDmatched)) { - return false; - } - histos.fill(HIST("hEventSelection"), 8.5 /* At least one of vertex contributors is matched to TRD*/); + if (doTFeventCut && !coll.selection_bit(o2::aod::evsel::kNoTimeFrameBorder)) { + return false; + } + if (fillHists) + histos.fill(HIST("hEventSelection"), 11.5 /* Not at TF border */); - if (doITSFrameBorderCut && !coll.selection_bit(o2::aod::evsel::kNoITSROFrameBorder)) { + if (doMultiplicityCorrCut) { + if (coll.multNTracksGlobal() < (1343.3 * TMath::Exp(-0.0443259 * coll.centFT0C()) - 50) || coll.multNTracksGlobal() > (2098.9 * TMath::Exp(-0.0332444 * coll.centFT0C()))) return false; - } - histos.fill(HIST("hEventSelection"), 9.5 /* Not at ITS ROF border */); - - if (doTFeventCut && !coll.selection_bit(o2::aod::evsel::kNoTimeFrameBorder)) { + if (coll.multNTracksPVeta1() < (3703 * TMath::Exp(-0.0455483 * coll.centFT0C()) - 150) || coll.multNTracksPVeta1() > (4937.33 * TMath::Exp(-0.0372668 * coll.centFT0C()) + 20)) return false; - } - histos.fill(HIST("hEventSelection"), 10.5 /* Not at TF border */); - - if (doMultiplicityCorrCut) { - if (coll.multNTracksGlobal() < (1343.3 * TMath::Exp(-0.0443259 * coll.centFT0C()) - 50) || coll.multNTracksGlobal() > (2098.9 * TMath::Exp(-0.0332444 * coll.centFT0C()))) - return false; - if (coll.multNTracksPVeta1() < (3703 * TMath::Exp(-0.0455483 * coll.centFT0C()) - 150) || coll.multNTracksPVeta1() > (4937.33 * TMath::Exp(-0.0372668 * coll.centFT0C()) + 20)) - return false; - } - histos.fill(HIST("hEventSelection"), 11.5 /* Remove outlyers */); } + if (fillHists) + histos.fill(HIST("hEventSelection"), 12.5 /* Remove outlyers */); if (doTimeRangeStandardCut && !coll.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard)) { return false; } + if (fillHists) + histos.fill(HIST("hEventSelection"), 13.5 /* Rejection of events too close in time */); - histos.fill(HIST("hEventSelection"), 12.5 /* Rejection of events too close in time */); + if (doTimeRangeNarrowCut && !coll.selection_bit(o2::aod::evsel::kNoCollInTimeRangeNarrow)) { + return false; + } + if (fillHists) + histos.fill(HIST("hEventSelection"), 14.5 /* No other collision within +/- 4 microseconds */); int occupancy = coll.trackOccupancyInTimeRange(); - histos.fill(HIST("hOccupancyVsCentrality"), occupancy, coll.centFT0C()); - histos.fill(HIST("hEventCentrality"), coll.centFT0C()); - histos.fill(HIST("hEventVertexZ"), coll.posZ()); - histos.fill(HIST("hEventNchCorrelationAfCuts"), coll.multNTracksPVeta1(), coll.multNTracksGlobal()); - histos.fill(HIST("hEventPVcontributorsVsCentrality"), coll.centFT0C(), coll.multNTracksPVeta1()); - histos.fill(HIST("hEventGlobalTracksVsCentrality"), coll.centFT0C(), coll.multNTracksGlobal()); + if (minOccupancy > 0 && occupancy < minOccupancy) { + return false; + } + if (fillHists) + histos.fill(HIST("hEventSelection"), 15.5 /* Below min occupancy */); + if (maxOccupancy > 0 && occupancy > maxOccupancy) { + return false; + } + if (fillHists) + histos.fill(HIST("hEventSelection"), 16.5 /* Above max occupancy */); + + if (fillHists) { + histos.fill(HIST("hOccupancyVsCentrality"), occupancy, coll.centFT0C()); + histos.fill(HIST("hEventCentrality"), coll.centFT0C()); + histos.fill(HIST("hEventVertexZ"), coll.posZ()); + histos.fill(HIST("hEventNchCorrelationAfCuts"), coll.multNTracksPVeta1(), coll.multNTracksGlobal()); + histos.fill(HIST("hEventPVcontributorsVsCentrality"), coll.centFT0C(), coll.multNTracksPVeta1()); + histos.fill(HIST("hEventGlobalTracksVsCentrality"), coll.centFT0C(), coll.multNTracksGlobal()); + } + return true; } @@ -636,7 +632,7 @@ struct derivedCascadeAnalysis { void processCascades(soa::Join::iterator const& coll, soa::Join const& Cascades, soa::Join const&) { - if (!IsEventAccepted(coll, coll.sel8())) + if (!IsEventAccepted(coll, true)) return; for (auto& casc : Cascades) { @@ -644,17 +640,27 @@ struct derivedCascadeAnalysis { int counter = -1; histos.fill(HIST("hCandidate"), ++counter); + bool isNegative = false; + bool isPositive = false; + if (casc.sign() > 0) + isPositive = true; + if (casc.sign() < 0) + isNegative = true; + if (!isNegative && !isPositive) + continue; + double invmass; if (isXi) invmass = casc.mXi(); else invmass = casc.mOmega(); // To have trace of how it was before selections - if (casc.sign() < 0 && doBefSelCheck) { - histos.fill(HIST("InvMassBefSel/hNegativeCascade"), casc.pt(), invmass, coll.centFT0C()); - } - if (casc.sign() > 0 && doBefSelCheck) { - histos.fill(HIST("InvMassBefSel/hPositiveCascade"), casc.pt(), invmass, coll.centFT0C()); + + if (doBefSelCheck) { + if (isPositive) + histos.fill(HIST("InvMassBefSel/h") + HIST(charge[0]) + HIST("Cascade"), casc.pt(), invmass, coll.centFT0C()); + if (isNegative) + histos.fill(HIST("InvMassBefSel/h") + HIST(charge[1]) + HIST("Cascade"), casc.pt(), invmass, coll.centFT0C()); } if (!IsCascadeCandidateAccepted(casc, counter, coll.centFT0C())) @@ -837,100 +843,101 @@ struct derivedCascadeAnalysis { ++counter; } } + if (isPositive) + histos.fill(HIST("InvMassAfterSel/h") + HIST(charge[0]) + HIST("Cascade"), casc.pt(), invmass, coll.centFT0C()); + if (isNegative) + histos.fill(HIST("InvMassAfterSel/h") + HIST(charge[1]) + HIST("Cascade"), casc.pt(), invmass, coll.centFT0C()); + + if (doOccupancyCheck) { + static_for<0, 9>([&](auto i) { + constexpr int index = i.value; + if (coll.centFT0C() < centralityIntervals[index + 1] && coll.centFT0C() > centralityIntervals[index]) { + if (isPositive) + histos.fill(HIST("InvMassAfterSelCent") + HIST(Index[index]) + HIST("/h") + HIST(charge[0]) + HIST("Cascade"), casc.pt(), invmass, coll.trackOccupancyInTimeRange()); + if (isNegative) + histos.fill(HIST("InvMassAfterSelCent") + HIST(Index[index]) + HIST("/h") + HIST(charge[1]) + HIST("Cascade"), casc.pt(), invmass, coll.trackOccupancyInTimeRange()); + } + }); + } - if (casc.sign() < 0) { - histos.fill(HIST("InvMassAfterSel/hNegativeCascade"), casc.pt(), invmass, coll.centFT0C()); - if (doOccupancyCheck) { - static_for<0, 9>([&](auto i) { - constexpr int index = i.value; - if (coll.centFT0C() < centralityIntervals[index + 1] && coll.centFT0C() > centralityIntervals[index]) { - histos.fill(HIST("InvMassAfterSelCent") + HIST(Index[index]) + HIST("/hNegativeCascade"), casc.pt(), invmass, coll.trackOccupancyInTimeRange()); - } - }); - } - if (!doBachelorBaryonCut && doPtDepCutStudy) - histos.fill(HIST("PtDepCutStudy/hNegativeBachelorBaryonDCA"), casc.pt(), invmass, casc.bachBaryonDCAxyToPV()); - if (!doDCAV0ToPVCut && doPtDepCutStudy) - histos.fill(HIST("PtDepCutStudy/hNegativeDCAV0ToPV"), casc.pt(), invmass, TMath::Abs(casc.dcav0topv(casc.x(), casc.y(), casc.z()))); - if (!doV0RadiusCut && doPtDepCutStudy) - histos.fill(HIST("PtDepCutStudy/hNegativeV0Radius"), casc.pt(), invmass, casc.v0radius()); - if (!doCascadeRadiusCut && doPtDepCutStudy) - histos.fill(HIST("PtDepCutStudy/hNegativeCascadeRadius"), casc.pt(), invmass, casc.cascradius()); - if (!doDCAV0DauCut && doPtDepCutStudy) - histos.fill(HIST("PtDepCutStudy/hNegativeDCAV0Daughters"), casc.pt(), invmass, casc.dcaV0daughters()); - if (!doDCACascadeDauCut && doPtDepCutStudy) - histos.fill(HIST("PtDepCutStudy/hNegativeDCACascDaughters"), casc.pt(), invmass, casc.dcacascdaughters()); - if (!doV0CosPaCut && doPtDepCutStudy) - histos.fill(HIST("PtDepCutStudy/hNegativeV0pa"), casc.pt(), invmass, TMath::ACos(casc.v0cosPA(casc.x(), casc.y(), casc.z()))); - if (!doCascadeCosPaCut && doPtDepCutStudy) - histos.fill(HIST("PtDepCutStudy/hNegativeCascPA"), casc.pt(), invmass, TMath::ACos(casc.casccosPA(coll.posX(), coll.posY(), coll.posZ()))); - if (!doDCAdauToPVCut && doPtDepCutStudy) { - histos.fill(HIST("PtDepCutStudy/hNegativeDCABachelorToPV"), casc.pt(), invmass, casc.dcabachtopv()); - histos.fill(HIST("PtDepCutStudy/hNegativeDCAMesonToPV"), casc.pt(), invmass, casc.dcanegtopv()); - histos.fill(HIST("PtDepCutStudy/hNegativeDCABaryonToPV"), casc.pt(), invmass, casc.dcapostopv()); - } - if (!doProperLifeTimeCut && doPtDepCutStudy) - histos.fill(HIST("PtDepCutStudy/hNegativeCascadeProperLifeTime"), casc.pt(), invmass, ctau); - } else { - histos.fill(HIST("InvMassAfterSel/hPositiveCascade"), casc.pt(), invmass, coll.centFT0C()); - if (doOccupancyCheck) { - static_for<0, 9>([&](auto i) { - constexpr int index = i.value; - if (coll.centFT0C() < centralityIntervals[index + 1] && coll.centFT0C() > centralityIntervals[index]) { - histos.fill(HIST("InvMassAfterSelCent") + HIST(Index[index]) + HIST("/hPositiveCascade"), casc.pt(), invmass, coll.trackOccupancyInTimeRange()); - } - }); - } - if (!doBachelorBaryonCut && doPtDepCutStudy) - histos.fill(HIST("PtDepCutStudy/hPositiveBachelorBaryonDCA"), casc.pt(), invmass, casc.bachBaryonDCAxyToPV()); - if (!doDCAV0ToPVCut && doPtDepCutStudy) - histos.fill(HIST("PtDepCutStudy/hPositiveDCAV0ToPV"), casc.pt(), invmass, TMath::Abs(casc.dcav0topv(casc.x(), casc.y(), casc.z()))); - if (!doV0RadiusCut && doPtDepCutStudy) - histos.fill(HIST("PtDepCutStudy/hPositiveV0Radius"), casc.pt(), invmass, casc.v0radius()); - if (!doCascadeRadiusCut && doPtDepCutStudy) - histos.fill(HIST("PtDepCutStudy/hPositiveCascadeRadius"), casc.pt(), invmass, casc.cascradius()); - if (!doDCAV0DauCut && doPtDepCutStudy) - histos.fill(HIST("PtDepCutStudy/hPositiveDCAV0Daughters"), casc.pt(), invmass, casc.dcaV0daughters()); - if (!doDCACascadeDauCut && doPtDepCutStudy) - histos.fill(HIST("PtDepCutStudy/hPositiveDCACascDaughters"), casc.pt(), invmass, casc.dcacascdaughters()); - if (!doV0CosPaCut && doPtDepCutStudy) - histos.fill(HIST("PtDepCutStudy/hPositiveV0pa"), casc.pt(), invmass, TMath::ACos(casc.v0cosPA(casc.x(), casc.y(), casc.z()))); - if (!doCascadeCosPaCut && doPtDepCutStudy) - histos.fill(HIST("PtDepCutStudy/hPositiveCascPA"), casc.pt(), invmass, TMath::ACos(casc.casccosPA(coll.posX(), coll.posY(), coll.posZ()))); - if (!doDCAdauToPVCut && doPtDepCutStudy) { - histos.fill(HIST("PtDepCutStudy/hPositiveDCABachelorToPV"), casc.pt(), invmass, casc.dcabachtopv()); - histos.fill(HIST("PtDepCutStudy/hPositiveDCAMesonToPV"), casc.pt(), invmass, casc.dcapostopv()); - histos.fill(HIST("PtDepCutStudy/hPositiveDCABaryonToPV"), casc.pt(), invmass, casc.dcanegtopv()); - } - if (!doProperLifeTimeCut && doPtDepCutStudy) - histos.fill(HIST("PtDepCutStudy/hPositiveCascadeProperLifeTime"), casc.pt(), invmass, ctau); + float dcaMesonToPV = -10; + float dcaBaryonToPV = -10; + if (isPositive) { + dcaMesonToPV = casc.dcanegtopv(); + dcaBaryonToPV = casc.dcapostopv(); + } + if (isNegative) { + dcaBaryonToPV = casc.dcanegtopv(); + dcaMesonToPV = casc.dcapostopv(); + } + double selections[] = {casc.bachBaryonDCAxyToPV(), + TMath::Abs(casc.dcav0topv(casc.x(), casc.y(), casc.z())), + casc.v0radius(), + casc.cascradius(), + casc.dcaV0daughters(), + casc.dcacascdaughters(), + TMath::ACos(casc.v0cosPA(casc.x(), casc.y(), casc.z())), + casc.dcabachtopv(), + dcaMesonToPV, + dcaBaryonToPV, + ctau}; + bool selectionToBeTested[] = {doBachelorBaryonCut, doDCAV0ToPVCut, doV0RadiusCut, doCascadeRadiusCut, doDCAV0DauCut, doDCACascadeDauCut, doV0CosPaCut, doCascadeCosPaCut, doDCAdauToPVCut, doDCAdauToPVCut, doDCAdauToPVCut, doProperLifeTimeCut}; + + if (doPtDepCutStudy) { + static_for<0, 10>([&](auto i) { + constexpr int index = i.value; + if (!selectionToBeTested[index]) { + if (isPositive) + histos.fill(HIST("PtDepCutStudy/h") + HIST(charge[0]) + HIST(selectionNames[index]), casc.pt(), invmass, selections[index]); + if (isNegative) + histos.fill(HIST("PtDepCutStudy/h") + HIST(charge[1]) + HIST(selectionNames[index]), casc.pt(), invmass, selections[index]); + } + }); } } } - void processCascadesMCrec(soa::Join::iterator const& coll, soa::Join const& Cascades, soa::Join const&) + void processCascadesMCrec(soa::Join::iterator const& coll, cascMCCandidates const& Cascades, dauTracks const&, soa::Join const&) //, , , soa::Join const& /*mccollisions*/, soa::Join const&) + // soa::Join const& Cascades, soa::Join const&) { - if (!IsEventAccepted(coll, coll.sel8())) + if (!IsEventAccepted(coll, true)) return; for (auto& casc : Cascades) { + float mass = -1; + if (isXi) + mass = casc.mXi(); + else + mass = casc.mOmega(); int counter = -1; histos.fill(HIST("hCandidate"), ++counter); + bool isNegative = false; + bool isPositive = false; + if (casc.sign() > 0) + isPositive = true; + if (casc.sign() < 0) + isNegative = true; + if (!isNegative && !isPositive) + continue; // To have trace of how it was before selections - if (casc.sign() < 0 && doBefSelCheck) { - if (isXi) - histos.fill(HIST("InvMassBefSel/hNegativeCascade"), casc.pt(), casc.mXi(), coll.centFT0C()); - else - histos.fill(HIST("InvMassBefSel/hNegativeCascade"), casc.pt(), casc.mOmega(), coll.centFT0C()); - } - if (casc.sign() > 0 && doBefSelCheck) { - if (isXi) - histos.fill(HIST("InvMassBefSel/hPositiveCascade"), casc.pt(), casc.mXi(), coll.centFT0C()); - else - histos.fill(HIST("InvMassBefSel/hPositiveCascade"), casc.pt(), casc.mOmega(), coll.centFT0C()); + if (doBefSelCheck) { + if (isPositive) + histos.fill(HIST("InvMassBefSel/h") + HIST(charge[0]) + HIST("Cascade"), casc.pt(), mass, coll.centFT0C()); + if (isNegative) + histos.fill(HIST("InvMassBefSel/h") + HIST(charge[1]) + HIST("Cascade"), casc.pt(), mass, coll.centFT0C()); } + if (!casc.has_cascMCCore()) + continue; + auto cascMC = casc.cascMCCore_as>(); + + bool isTrueMCCascade = false; + if (cascMC.isPhysicalPrimary() && ((isXi && std::abs(cascMC.pdgCode()) == 3312) || (!isXi && std::abs(cascMC.pdgCode()) == 3334))) + isTrueMCCascade = true; + + float ptmc = RecoDecay::sqrtSumOfSquares(cascMC.pxMC(), cascMC.pyMC()); + if (!IsCascadeCandidateAccepted(casc, counter, coll.centFT0C())) continue; counter += 13; @@ -967,7 +974,7 @@ struct derivedCascadeAnalysis { ++counter; } - if (casc.sign() < 0) { + if (isNegative) { if (doFillNsigmaTPCHistProton) histos.fill(HIST("hNsigmaProton"), posExtra.tpcNSigmaPr(), fullMomentumPosDaugh, coll.centFT0C()); if (doFillNsigmaTPCHistV0Pion) @@ -977,7 +984,15 @@ struct derivedCascadeAnalysis { if (doFillNsigmaTPCHistPionBach && !isXi) histos.fill(HIST("hNsigmaKaon"), bachExtra.tpcNSigmaPi(), fullmomentumBachelor, coll.centFT0C()); - } else if (casc.sign() > 0) { + if (doNTPCSigmaCut) { + if (TMath::Abs(posExtra.tpcNSigmaPr()) > nsigmatpcPr || TMath::Abs(negExtra.tpcNSigmaPi()) > nsigmatpcPi) + continue; + histos.fill(HIST("hCandidate"), ++counter); + } else { + ++counter; + } + } + if (isPositive) { if (doFillNsigmaTPCHistV0Pion) histos.fill(HIST("hNsigmaPionPos"), posExtra.tpcNSigmaPi(), fullMomentumPosDaugh, coll.centFT0C()); if (doFillNsigmaTPCHistProton) @@ -986,18 +1001,7 @@ struct derivedCascadeAnalysis { histos.fill(HIST("hNsigmaPionPosBach"), bachExtra.tpcNSigmaPi(), fullmomentumBachelor, coll.centFT0C()); if (doFillNsigmaTPCHistPionBach && !isXi) histos.fill(HIST("hNsigmaKaon"), bachExtra.tpcNSigmaPi(), fullmomentumBachelor, coll.centFT0C()); - } - if (casc.sign() < 0) { - if (doNTPCSigmaCut) { - if (TMath::Abs(posExtra.tpcNSigmaPr()) > nsigmatpcPr || TMath::Abs(negExtra.tpcNSigmaPi()) > nsigmatpcPi) - continue; - histos.fill(HIST("hCandidate"), ++counter); - } else { - ++counter; - } - - } else if (casc.sign() > 0) { if (doNTPCSigmaCut) { if (TMath::Abs(posExtra.tpcNSigmaPi()) > nsigmatpcPi || TMath::Abs(negExtra.tpcNSigmaPr()) > nsigmatpcPr) continue; @@ -1025,18 +1029,17 @@ struct derivedCascadeAnalysis { ++counter; } - double invmass; float cascpos = std::hypot(casc.x() - coll.posX(), casc.y() - coll.posY(), casc.z() - coll.posZ()); float cascptotmom = std::hypot(casc.px(), casc.py(), casc.pz()); float ctau = -10; if (posExtra.hasTOF()) { - if (doNTOFSigmaProtonCut && casc.sign() < 0) { + if (doNTOFSigmaProtonCut && isNegative) { histos.fill(HIST("hNsigmaTOFProton"), casc.tofNSigmaXiLaPr(), fullMomentumPosDaugh, coll.centFT0C()); if (TMath::Abs(casc.tofNSigmaXiLaPr()) > nsigmatofPr && fullMomentumPosDaugh > 0.6) continue; } - if (doNTOFSigmaV0PionCut && casc.sign() > 0) { + if (doNTOFSigmaV0PionCut && isPositive) { histos.fill(HIST("hNsigmaTOFV0Pion"), casc.tofNSigmaXiLaPi(), fullMomentumPosDaugh, coll.centFT0C()); if (TMath::Abs(casc.tofNSigmaXiLaPi()) > nsigmatofPion) continue; @@ -1044,12 +1047,12 @@ struct derivedCascadeAnalysis { } if (negExtra.hasTOF()) { - if (doNTOFSigmaProtonCut && casc.sign() > 0) { + if (doNTOFSigmaProtonCut && isPositive) { histos.fill(HIST("hNsigmaTOFProton"), casc.tofNSigmaXiLaPr(), fullmomentumNegDaugh, coll.centFT0C()); if (TMath::Abs(casc.tofNSigmaXiLaPr()) > nsigmatofPr && fullmomentumNegDaugh > 0.6) continue; } - if (doNTOFSigmaV0PionCut && casc.sign() < 0) { + if (doNTOFSigmaV0PionCut && isNegative) { histos.fill(HIST("hNsigmaTOFV0Pion"), casc.tofNSigmaXiLaPi(), fullmomentumNegDaugh, coll.centFT0C()); if (TMath::Abs(casc.tofNSigmaXiLaPi()) > nsigmatofPion) continue; @@ -1072,15 +1075,6 @@ struct derivedCascadeAnalysis { } ctau = pdgDB->Mass(3312) * cascpos / ((cascptotmom + 1e-13) * ctauxiPDG); - if (doProperLifeTimeCut) { - if (ctau > proplifetime) - continue; - histos.fill(HIST("hCandidate"), ++counter); - } else { - ++counter; - } - - invmass = casc.mXi(); } else { if (doNTPCSigmaCut) { if (TMath::Abs(bachExtra.tpcNSigmaKa()) > nsigmatpcKa) @@ -1097,147 +1091,173 @@ struct derivedCascadeAnalysis { } ctau = pdgDB->Mass(3334) * cascpos / ((cascptotmom + 1e-13) * ctauomegaPDG); - if (doProperLifeTimeCut) { - if (ctau > proplifetime) - continue; - histos.fill(HIST("hCandidate"), ++counter); - } else { - ++counter; - } - invmass = casc.mOmega(); } - if (casc.sign() < 0) { - histos.fill(HIST("InvMassAfterSel/hNegativeCascade"), casc.pt(), invmass, coll.centFT0C()); - if (doOccupancyCheck) { - static_for<0, 9>([&](auto i) { - constexpr int index = i.value; - if (coll.centFT0C() < centralityIntervals[index + 1] && coll.centFT0C() > centralityIntervals[index]) { - histos.fill(HIST("InvMassAfterSelCent") + HIST(Index[index]) + HIST("/hNegativeCascade"), casc.pt(), invmass, coll.trackOccupancyInTimeRange()); - } - }); - } - if (!doBachelorBaryonCut && doPtDepCutStudy) - histos.fill(HIST("PtDepCutStudy/hNegativeBachelorBaryonDCA"), casc.pt(), invmass, casc.bachBaryonDCAxyToPV()); - if (!doDCAV0ToPVCut && doPtDepCutStudy) - histos.fill(HIST("PtDepCutStudy/hNegativeDCAV0ToPV"), casc.pt(), invmass, TMath::Abs(casc.dcav0topv(casc.x(), casc.y(), casc.z()))); - if (!doV0RadiusCut && doPtDepCutStudy) - histos.fill(HIST("PtDepCutStudy/hNegativeV0Radius"), casc.pt(), invmass, casc.v0radius()); - if (!doCascadeRadiusCut && doPtDepCutStudy) - histos.fill(HIST("PtDepCutStudy/hNegativeCascadeRadius"), casc.pt(), invmass, casc.cascradius()); - if (!doDCAV0DauCut && doPtDepCutStudy) - histos.fill(HIST("PtDepCutStudy/hNegativeDCAV0Daughters"), casc.pt(), invmass, casc.dcaV0daughters()); - if (!doDCACascadeDauCut && doPtDepCutStudy) - histos.fill(HIST("PtDepCutStudy/hNegativeDCACascDaughters"), casc.pt(), invmass, casc.dcacascdaughters()); - if (!doV0CosPaCut && doPtDepCutStudy) - histos.fill(HIST("PtDepCutStudy/hNegativeV0pa"), casc.pt(), invmass, TMath::ACos(casc.v0cosPA(casc.x(), casc.y(), casc.z()))); - if (!doCascadeCosPaCut && doPtDepCutStudy) - histos.fill(HIST("PtDepCutStudy/hNegativeCascPA"), casc.pt(), invmass, TMath::ACos(casc.casccosPA(coll.posX(), coll.posY(), coll.posZ()))); - if (!doDCAdauToPVCut && doPtDepCutStudy) { - histos.fill(HIST("PtDepCutStudy/hNegativeDCABachelorToPV"), casc.pt(), invmass, casc.dcabachtopv()); - histos.fill(HIST("PtDepCutStudy/hNegativeDCAMesonToPV"), casc.pt(), invmass, casc.dcanegtopv()); - histos.fill(HIST("PtDepCutStudy/hNegativeDCABaryonToPV"), casc.pt(), invmass, casc.dcapostopv()); - } - if (!doProperLifeTimeCut && doPtDepCutStudy) - histos.fill(HIST("PtDepCutStudy/hNegativeCascadeProperLifeTime"), casc.pt(), invmass, ctau); - if (casc.isPhysicalPrimary()) { - if ((isXi && casc.pdgCode() == 3312) || (!isXi && casc.pdgCode() == 3334)) { - histos.fill(HIST("InvMassAfterSelMCrecTruth/hNegativeCascade"), casc.pt(), invmass, coll.centFT0C()); - if (!doBachelorBaryonCut && doPtDepCutStudy) - histos.fill(HIST("PtDepCutStudyMCTruth/hNegativeBachelorBaryonDCA"), casc.pt(), invmass, casc.bachBaryonDCAxyToPV()); - if (!doDCAV0ToPVCut && doPtDepCutStudy) - histos.fill(HIST("PtDepCutStudyMCTruth/hNegativeDCAV0ToPV"), casc.pt(), invmass, TMath::Abs(casc.dcav0topv(casc.x(), casc.y(), casc.z()))); - if (!doV0RadiusCut && doPtDepCutStudy) - histos.fill(HIST("PtDepCutStudyMCTruth/hNegativeV0Radius"), casc.pt(), invmass, casc.v0radius()); - if (!doCascadeRadiusCut && doPtDepCutStudy) - histos.fill(HIST("PtDepCutStudyMCTruth/hNegativeCascadeRadius"), casc.pt(), invmass, casc.cascradius()); - if (!doDCAV0DauCut && doPtDepCutStudy) - histos.fill(HIST("PtDepCutStudyMCTruth/hNegativeDCAV0Daughters"), casc.pt(), invmass, casc.dcaV0daughters()); - if (!doDCACascadeDauCut && doPtDepCutStudy) - histos.fill(HIST("PtDepCutStudyMCTruth/hNegativeDCACascDaughters"), casc.pt(), invmass, casc.dcacascdaughters()); - if (!doV0CosPaCut && doPtDepCutStudy) - histos.fill(HIST("PtDepCutStudyMCTruth/hNegativeV0pa"), casc.pt(), invmass, TMath::ACos(casc.v0cosPA(casc.x(), casc.y(), casc.z()))); - if (!doCascadeCosPaCut && doPtDepCutStudy) - histos.fill(HIST("PtDepCutStudyMCTruth/hNegativeCascPA"), casc.pt(), invmass, TMath::ACos(casc.casccosPA(coll.posX(), coll.posY(), coll.posZ()))); - if (!doDCAdauToPVCut && doPtDepCutStudy) { - histos.fill(HIST("PtDepCutStudyMCTruth/hNegativeDCABachelorToPV"), casc.pt(), invmass, casc.dcabachtopv()); - histos.fill(HIST("PtDepCutStudyMCTruth/hNegativeDCAMesonToPV"), casc.pt(), invmass, casc.dcanegtopv()); - histos.fill(HIST("PtDepCutStudyMCTruth/hNegativeDCABaryonToPV"), casc.pt(), invmass, casc.dcapostopv()); - } - if (!doProperLifeTimeCut && doPtDepCutStudy) - histos.fill(HIST("PtDepCutStudyMCTruth/hNegativeCascadeProperLifeTime"), casc.pt(), invmass, ctau); - if ((isXi && casc.pdgCodeV0() == 3122 && casc.pdgCodePositive() == 2212 && casc.pdgCodeNegative() == -211 && casc.pdgCodeBachelor() == -211) || (!isXi && casc.pdgCodeV0() == 3122 && casc.pdgCodePositive() == 2212 && casc.pdgCodeNegative() == -211 && casc.pdgCodeBachelor() == -321)) - histos.fill(HIST("hNegativeCascadePtForEfficiency"), casc.pt(), invmass, coll.centFT0C()); - } - } + if (doProperLifeTimeCut) { + if (ctau > proplifetime) + continue; + histos.fill(HIST("hCandidate"), ++counter); } else { - histos.fill(HIST("InvMassAfterSel/hPositiveCascade"), casc.pt(), invmass, coll.centFT0C()); - if (doOccupancyCheck) { - static_for<0, 9>([&](auto i) { - constexpr int index = i.value; - if (coll.centFT0C() < centralityIntervals[index + 1] && coll.centFT0C() > centralityIntervals[index]) { - histos.fill(HIST("InvMassAfterSelCent") + HIST(Index[index]) + HIST("/hPositiveCascade"), casc.pt(), invmass, coll.trackOccupancyInTimeRange()); - } - }); - } - if (!doBachelorBaryonCut && doPtDepCutStudy) - histos.fill(HIST("PtDepCutStudy/hPositiveBachelorBaryonDCA"), casc.pt(), invmass, casc.bachBaryonDCAxyToPV()); - if (!doDCAV0ToPVCut && doPtDepCutStudy) - histos.fill(HIST("PtDepCutStudy/hPositiveDCAV0ToPV"), casc.pt(), invmass, TMath::Abs(casc.dcav0topv(casc.x(), casc.y(), casc.z()))); - if (!doV0RadiusCut && doPtDepCutStudy) - histos.fill(HIST("PtDepCutStudy/hPositiveV0Radius"), casc.pt(), invmass, casc.v0radius()); - if (!doCascadeRadiusCut && doPtDepCutStudy) - histos.fill(HIST("PtDepCutStudy/hPositiveCascadeRadius"), casc.pt(), invmass, casc.cascradius()); - if (!doDCAV0DauCut && doPtDepCutStudy) - histos.fill(HIST("PtDepCutStudy/hPositiveDCAV0Daughters"), casc.pt(), invmass, casc.dcaV0daughters()); - if (!doDCACascadeDauCut && doPtDepCutStudy) - histos.fill(HIST("PtDepCutStudy/hPositiveDCACascDaughters"), casc.pt(), invmass, casc.dcacascdaughters()); - if (!doV0CosPaCut && doPtDepCutStudy) - histos.fill(HIST("PtDepCutStudy/hPositiveV0pa"), casc.pt(), invmass, TMath::ACos(casc.v0cosPA(casc.x(), casc.y(), casc.z()))); - if (!doCascadeCosPaCut && doPtDepCutStudy) - histos.fill(HIST("PtDepCutStudy/hPositiveCascPA"), casc.pt(), invmass, TMath::ACos(casc.casccosPA(coll.posX(), coll.posY(), coll.posZ()))); - if (!doDCAdauToPVCut && doPtDepCutStudy) { - histos.fill(HIST("PtDepCutStudy/hPositiveDCABachelorToPV"), casc.pt(), invmass, casc.dcabachtopv()); - histos.fill(HIST("PtDepCutStudy/hPositiveDCAMesonToPV"), casc.pt(), invmass, casc.dcapostopv()); - histos.fill(HIST("PtDepCutStudy/hPositiveDCABaryonToPV"), casc.pt(), invmass, casc.dcanegtopv()); - } - if (!doProperLifeTimeCut && doPtDepCutStudy) - histos.fill(HIST("PtDepCutStudy/hPositiveCascadeProperLifeTime"), casc.pt(), invmass, ctau); - if (casc.isPhysicalPrimary()) { - if ((isXi && casc.pdgCode() == -3312) || (!isXi && casc.pdgCode() == -3334)) { - histos.fill(HIST("InvMassAfterSelMCrecTruth/hPositiveCascade"), casc.pt(), invmass, coll.centFT0C()); - if (!doBachelorBaryonCut && doPtDepCutStudy) - histos.fill(HIST("PtDepCutStudyMCTruth/hPositiveBachelorBaryonDCA"), casc.pt(), invmass, casc.bachBaryonDCAxyToPV()); - if (!doDCAV0ToPVCut && doPtDepCutStudy) - histos.fill(HIST("PtDepCutStudyMCTruth/hPositiveDCAV0ToPV"), casc.pt(), invmass, TMath::Abs(casc.dcav0topv(casc.x(), casc.y(), casc.z()))); - if (!doV0RadiusCut && doPtDepCutStudy) - histos.fill(HIST("PtDepCutStudyMCTruth/hPositiveV0Radius"), casc.pt(), invmass, casc.v0radius()); - if (!doCascadeRadiusCut && doPtDepCutStudy) - histos.fill(HIST("PtDepCutStudyMCTruth/hPositiveCascadeRadius"), casc.pt(), invmass, casc.cascradius()); - if (!doDCAV0DauCut && doPtDepCutStudy) - histos.fill(HIST("PtDepCutStudyMCTruth/hPositiveDCAV0Daughters"), casc.pt(), invmass, casc.dcaV0daughters()); - if (!doDCACascadeDauCut && doPtDepCutStudy) - histos.fill(HIST("PtDepCutStudyMCTruth/hPositiveDCACascDaughters"), casc.pt(), invmass, casc.dcacascdaughters()); - if (!doV0CosPaCut && doPtDepCutStudy) - histos.fill(HIST("PtDepCutStudyMCTruth/hPositiveV0pa"), casc.pt(), invmass, TMath::ACos(casc.v0cosPA(casc.x(), casc.y(), casc.z()))); - if (!doCascadeCosPaCut && doPtDepCutStudy) - histos.fill(HIST("PtDepCutStudyMCTruth/hPositiveCascPA"), casc.pt(), invmass, TMath::ACos(casc.casccosPA(coll.posX(), coll.posY(), coll.posZ()))); - if (!doDCAdauToPVCut && doPtDepCutStudy) { - histos.fill(HIST("PtDepCutStudyMCTruth/hPositiveDCABachelorToPV"), casc.pt(), invmass, casc.dcabachtopv()); - histos.fill(HIST("PtDepCutStudyMCTruth/hPositiveDCAMesonToPV"), casc.pt(), invmass, casc.dcapostopv()); - histos.fill(HIST("PtDepCutStudyMCTruth/hPositiveDCABaryonToPV"), casc.pt(), invmass, casc.dcanegtopv()); + ++counter; + } + + if (isPositive) + histos.fill(HIST("InvMassAfterSel/h") + HIST(charge[0]) + HIST("Cascade"), casc.pt(), mass, coll.centFT0C()); + if (isNegative) + histos.fill(HIST("InvMassAfterSel/h") + HIST(charge[1]) + HIST("Cascade"), casc.pt(), mass, coll.centFT0C()); + if (isTrueMCCascade) { + if (isPositive) + histos.fill(HIST("InvMassAfterSelMCrecTruth/h") + HIST(charge[0]) + HIST("Cascade"), ptmc, mass, coll.centFT0C()); + if (isNegative) + histos.fill(HIST("InvMassAfterSelMCrecTruth/h") + HIST(charge[1]) + HIST("Cascade"), ptmc, mass, coll.centFT0C()); + } + if (doOccupancyCheck) { + static_for<0, 9>([&](auto i) { + constexpr int index = i.value; + if (coll.centFT0C() < centralityIntervals[index + 1] && coll.centFT0C() > centralityIntervals[index]) { + if (isPositive) + histos.fill(HIST("InvMassAfterSelCent") + HIST(Index[index]) + HIST("/h") + HIST(charge[0]) + HIST("Cascade"), casc.pt(), mass, coll.trackOccupancyInTimeRange()); + if (isNegative) + histos.fill(HIST("InvMassAfterSelCent") + HIST(Index[index]) + HIST("/h") + HIST(charge[1]) + HIST("Cascade"), casc.pt(), mass, coll.trackOccupancyInTimeRange()); + } + }); + } + float dcaMesonToPV = -10; + float dcaBaryonToPV = -10; + if (isPositive) { + dcaMesonToPV = casc.dcanegtopv(); + dcaBaryonToPV = casc.dcapostopv(); + } + if (isNegative) { + dcaBaryonToPV = casc.dcanegtopv(); + dcaMesonToPV = casc.dcapostopv(); + } + double selections[] = {casc.bachBaryonDCAxyToPV(), + TMath::Abs(casc.dcav0topv(casc.x(), casc.y(), casc.z())), + casc.v0radius(), + casc.cascradius(), + casc.dcaV0daughters(), + casc.dcacascdaughters(), + TMath::ACos(casc.v0cosPA(casc.x(), casc.y(), casc.z())), + casc.dcabachtopv(), + dcaMesonToPV, + dcaBaryonToPV, + ctau}; + bool selectionToBeTested[] = {doBachelorBaryonCut, doDCAV0ToPVCut, doV0RadiusCut, doCascadeRadiusCut, doDCAV0DauCut, doDCACascadeDauCut, doV0CosPaCut, doCascadeCosPaCut, doDCAdauToPVCut, doDCAdauToPVCut, doDCAdauToPVCut, doProperLifeTimeCut}; + + if (doPtDepCutStudy) { + static_for<0, 10>([&](auto i) { + constexpr int index = i.value; + if (!selectionToBeTested[index]) { + if (isPositive) + histos.fill(HIST("PtDepCutStudy/h") + HIST(charge[0]) + HIST(selectionNames[index]), casc.pt(), mass, selections[index]); + if (isNegative) + histos.fill(HIST("PtDepCutStudy/h") + HIST(charge[1]) + HIST(selectionNames[index]), casc.pt(), mass, selections[index]); + if (isTrueMCCascade) { + if (isPositive) + histos.fill(HIST("PtDepCutStudyMCTruth/h") + HIST(charge[0]) + HIST(selectionNames[index]), ptmc, mass, selections[index]); + if (isNegative) + histos.fill(HIST("PtDepCutStudyMCTruth/h") + HIST(charge[1]) + HIST(selectionNames[index]), ptmc, mass, selections[index]); } - if (!doProperLifeTimeCut && doPtDepCutStudy) - histos.fill(HIST("PtDepCutStudyMCTruth/hPositiveCascadeProperLifeTime"), casc.pt(), invmass, ctau); - if ((isXi && casc.pdgCodeV0() == -3122 && casc.pdgCodePositive() == 211 && casc.pdgCodeNegative() == -2212 && casc.pdgCodeBachelor() == 211) || (!isXi && casc.pdgCodeV0() == -3122 && casc.pdgCodePositive() == 211 && casc.pdgCodeNegative() == -2212 && casc.pdgCodeBachelor() == 321)) - histos.fill(HIST("hPositiveCascadePtForEfficiency"), casc.pt(), invmass, coll.centFT0C()); } + }); + } + } + } + void processCascadesMCforEff(soa::Join const& mcCollisions, soa::Join const& Cascades, soa::Join const& collisions) + { + + std::vector listBestCollisionIdx = fillGenEventHist(mcCollisions, collisions); + + for (auto const& cascMC : Cascades) { + if (!cascMC.has_straMCCollision()) + continue; + + if (!cascMC.isPhysicalPrimary()) + continue; + + float ptmc = RecoDecay::sqrtSumOfSquares(cascMC.pxMC(), cascMC.pyMC()); + float ymc = 1e3; + if (TMath::Abs(cascMC.pdgCode()) == 3312) + ymc = RecoDecay::y(std::array{cascMC.pxMC(), cascMC.pyMC(), cascMC.pzMC()}, o2::constants::physics::MassXiMinus); + else if (TMath::Abs(cascMC.pdgCode()) == 3334) + ymc = RecoDecay::y(std::array{cascMC.pxMC(), cascMC.pyMC(), cascMC.pzMC()}, o2::constants::physics::MassOmegaMinus); + + if (TMath::Abs(ymc) > rapCut) + continue; + + auto mcCollision = cascMC.straMCCollision_as>(); + float centrality = 100.5f; + if (listBestCollisionIdx[mcCollision.globalIndex()] > -1) { + auto collision = collisions.iteratorAt(listBestCollisionIdx[mcCollision.globalIndex()]); + centrality = collision.centFT0C(); + } + + if (cascMC.pdgCode() == 3312) { + histos.fill(HIST("h2dGenXiMinus"), centrality, ptmc); + histos.fill(HIST("h2dGenXiMinusVsMultMC"), mcCollision.multMCNParticlesEta05(), ptmc); + } + if (cascMC.pdgCode() == -3312) { + histos.fill(HIST("h2dGenXiPlus"), centrality, ptmc); + histos.fill(HIST("h2dGenXiPlusVsMultMC"), mcCollision.multMCNParticlesEta05(), ptmc); + } + if (cascMC.pdgCode() == 3334) { + histos.fill(HIST("h2dGenOmegaMinus"), centrality, ptmc); + histos.fill(HIST("h2dGenOmegaMinusVsMultMC"), mcCollision.multMCNParticlesEta05(), ptmc); + } + if (cascMC.pdgCode() == -3334) { + histos.fill(HIST("h2dGenOmegaPlus"), centrality, ptmc); + histos.fill(HIST("h2dGenOmegaPlusVsMultMC"), mcCollision.multMCNParticlesEta05(), ptmc); + } + } + } + // ______________________________________________________ + // Simulated processing + // Fill event information (for event loss estimation) and return the index to the recoed collision associated to a given MC collision. + std::vector fillGenEventHist(soa::Join const& mcCollisions, soa::Join const& collisions) + { + std::vector listBestCollisionIdx(mcCollisions.size()); + for (auto const& mcCollision : mcCollisions) { + histos.fill(HIST("hGenEvents"), mcCollision.multMCNParticlesEta05(), 0.5 /* all gen. events*/); + + auto groupedCollisions = collisions.sliceBy(perMcCollision, mcCollision.globalIndex()); + // Check if there is at least one of the reconstructed collisions associated to this MC collision + // If so, we consider it + bool atLeastOne = false; + int biggestNContribs = -1; + int bestCollisionIndex = -1; + float centrality = 100.5f; + int nCollisions = 0; + for (auto const& collision : groupedCollisions) { + if (!IsEventAccepted(collision, false)) { + continue; + } + + if (biggestNContribs < collision.multPVTotalContributors()) { + biggestNContribs = collision.multPVTotalContributors(); + bestCollisionIndex = collision.globalIndex(); + centrality = collision.centFT0C(); } + nCollisions++; + + atLeastOne = true; + } + listBestCollisionIdx[mcCollision.globalIndex()] = bestCollisionIndex; + + histos.fill(HIST("hCentralityVsNcoll_beforeEvSel"), centrality, groupedCollisions.size() + 0.5); + histos.fill(HIST("hCentralityVsNcoll_afterEvSel"), centrality, nCollisions + 0.5); + + histos.fill(HIST("hCentralityVsMultMC"), centrality, mcCollision.multMCNParticlesEta05()); + + if (atLeastOne) { + histos.fill(HIST("hGenEvents"), mcCollision.multMCNParticlesEta05(), 1.5 /* at least 1 rec. event*/); } } + return listBestCollisionIdx; } PROCESS_SWITCH(derivedCascadeAnalysis, processCascades, "cascade analysis, run3 data ", true); PROCESS_SWITCH(derivedCascadeAnalysis, processCascadesMCrec, "cascade analysis, run3 rec MC", false); + PROCESS_SWITCH(derivedCascadeAnalysis, processCascadesMCforEff, "cascade analysis, run3 rec MC", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGLF/Tasks/Strangeness/hStrangeCorrelation.cxx b/PWGLF/Tasks/Strangeness/hStrangeCorrelation.cxx index 815de438b9a..894934e1243 100644 --- a/PWGLF/Tasks/Strangeness/hStrangeCorrelation.cxx +++ b/PWGLF/Tasks/Strangeness/hStrangeCorrelation.cxx @@ -694,6 +694,7 @@ struct correlateStrangeness { histos.add("hTriggerPtResolution", ";p_{T}^{reconstructed} (GeV/c); p_{T}^{generated} (GeV/c)", kTH2F, {axisPtQA, axisPtQA}); histos.add("hTriggerPrimaryEtaVsPt", "hTriggerPrimaryEtaVsPt", kTH3F, {axisPtQA, axisEta, axisMult}); histos.add("hTrackEtaVsPtVsPhi", "hTrackEtaVsPtVsPhi", kTH3F, {axisPtQA, axisEta, axisPhi}); + bool hStrange = false; for (int i = 0; i < 8; i++) { histos.add(fmt::format("h{}EtaVsPtVsPhi", particlenames[i]).c_str(), "", kTH3F, {axisPtQA, axisEta, axisPhi}); histos.add(fmt::format("h{}EtaVsPtVsPhiBg", particlenames[i]).c_str(), "", kTH3F, {axisPtQA, axisEta, axisPhi}); @@ -701,12 +702,14 @@ struct correlateStrangeness { histos.add(fmt::format("h3d{}Spectrum", particlenames[i]).c_str(), fmt::format("h3d{}Spectrum", particlenames[i]).c_str(), kTH3F, {axisPtQA, axisMult, axisMassNSigma}); histos.add(fmt::format("h3d{}SpectrumY", particlenames[i]).c_str(), fmt::format("h3d{}SpectrumY", particlenames[i]).c_str(), kTH3F, {axisPtQA, axisMult, axisMassNSigma}); histos.add(fmt::format("sameEvent/Signal/{}", particlenames[i]).c_str(), "", kTHnF, {axisDeltaPhiNDim, axisDeltaEtaNDim, axisPtAssocNDim, axisPtTriggerNDim, axisVtxZNDim, axisMultNDim}); - if (i < 7) { - histos.addClone("sameEvent/Signal/", "sameEvent/LeftBg/"); - histos.addClone("sameEvent/Signal/", "sameEvent/RightBg/"); - } + if (i < 7) + hStrange = true; } } + if (hStrange) { + histos.addClone("sameEvent/Signal/", "sameEvent/LeftBg/"); + histos.addClone("sameEvent/Signal/", "sameEvent/RightBg/"); + } LOGF(info, "Init THnFs done"); // mixed-event correlation functions diff --git a/PWGLF/Tasks/Strangeness/lambdapolsp.cxx b/PWGLF/Tasks/Strangeness/lambdapolsp.cxx index d9aed1db736..7dc64e6102c 100644 --- a/PWGLF/Tasks/Strangeness/lambdapolsp.cxx +++ b/PWGLF/Tasks/Strangeness/lambdapolsp.cxx @@ -80,12 +80,14 @@ struct lambdapolsp { Configurable cfgCutCentralityMin{"cfgCutCentralityMin", 30.0f, "Accepted minimum Centrality"}; // proton track cut Configurable confRapidity{"confRapidity", 0.8, "cut on Rapidity"}; - Configurable cfgCutPT{"cfgCutPT", 0.3, "PT cut on daughter track"}; + Configurable cfgCutPT{"cfgCutPT", 0.15, "PT cut on daughter track"}; Configurable cfgCutEta{"cfgCutEta", 0.8, "Eta cut on daughter track"}; Configurable cfgCutDCAxy{"cfgCutDCAxy", 0.1f, "DCAxy range for tracks"}; - Configurable cfgCutDCAz{"cfgCutDCAz", 1.0f, "DCAz range for tracks"}; + Configurable cfgCutDCAz{"cfgCutDCAz", 0.1f, "DCAz range for tracks"}; Configurable cfgITScluster{"cfgITScluster", 5, "Number of ITS cluster"}; Configurable cfgTPCcluster{"cfgTPCcluster", 70, "Number of TPC cluster"}; + Configurable isPVContributor{"isPVContributor", true, "is PV contributor"}; + Configurable checkwithpub{"checkwithpub", true, "checking results with published"}; // Configs for V0 Configurable ConfV0PtMin{"ConfV0PtMin", 0.f, "Minimum transverse momentum of V0"}; Configurable ConfV0Rap{"ConfV0Rap", 0.8f, "Rapidity range of V0"}; @@ -131,6 +133,23 @@ struct lambdapolsp { AxisSpec thnAxisPol{PolNbins, lbinPol, hbinPol, "Sin(#phi - #psi)"}; AxisSpec thnAxisCosThetaStar{SANbins, lbinSA, hbinSA, "SA"}; AxisSpec centAxis = {CentNbins, lbinCent, hbinCent, "V0M (%)"}; + AxisSpec etaAxis = {8, -0.8, 0.8, "Eta"}; + + if (checkwithpub) { + histos.add("hpuxQxpvscent", "hpuxQxpvscent", kTProfile, {centAxis}); + histos.add("hpuyQypvscent", "hpuyQypvscent", kTProfile, {centAxis}); + histos.add("hpuxQxtvscent", "hpuxQxtvscent", kTProfile, {centAxis}); + histos.add("hpuyQytvscent", "hpuyQytvscent", kTProfile, {centAxis}); + histos.add("hpQxtQxpvscent", "hpQxtQxpvscent", kTProfile, {centAxis}); + histos.add("hpQytQypvscent", "hpQytQypvscent", kTProfile, {centAxis}); + + histos.add("hpposuxyQxytvseta", "hpposuxyQxytvseta", kTProfile, {etaAxis}); + histos.add("hpposuxyQxypvseta", "hpposuxyQxypvseta", kTProfile, {etaAxis}); + histos.add("hpposQxytpvseta", "hpposQxytpvseta", kTProfile, {etaAxis}); + histos.add("hpneguxyQxytvseta", "hpneguxyQxytvseta", kTProfile, {etaAxis}); + histos.add("hpneguxyQxypvseta", "hpneguxyQxypvseta", kTProfile, {etaAxis}); + histos.add("hpnegQxytpvseta", "hpnegQxytpvseta", kTProfile, {etaAxis}); + } histos.add("hCentrality", "Centrality distribution", kTH1F, {{centAxis}}); histos.add("hVtxZ", "Vertex distribution in Z;Z (cm)", kTH1F, {{20, -10.0, 10.0}}); @@ -153,6 +172,15 @@ struct lambdapolsp { } } + template + bool selectionTrack(const T& candidate) + { + if (!isPVContributor || !candidate.isGlobalTrackWoDCA() || !(candidate.itsNCls() > cfgITScluster) || !(candidate.tpcNClsFound() > cfgTPCcluster)) { + return false; + } + return true; + } + template bool SelectionV0(Collision const& collision, V0 const& candidate) { @@ -262,14 +290,16 @@ struct lambdapolsp { Filter collisionFilter = nabs(aod::collision::posZ) < cfgCutVertex; Filter centralityFilter = (nabs(aod::cent::centFT0C) < cfgCutCentralityMax && nabs(aod::cent::centFT0C) > cfgCutCentralityMin); - // Filter acceptanceFilter = (nabs(aod::track::eta) < cfgCutEta && nabs(aod::track::pt) > cfgCutPT); - // Filter dcaCutFilter = (nabs(aod::track::dcaXY) < cfgCutDCAxy) && (nabs(aod::track::dcaZ) < cfgCutDCAz); + Filter acceptanceFilter = (nabs(aod::track::eta) < cfgCutEta && nabs(aod::track::pt) > cfgCutPT); + Filter dcaCutFilter = (nabs(aod::track::dcaXY) < cfgCutDCAxy) && (nabs(aod::track::dcaZ) < cfgCutDCAz); using EventCandidates = soa::Filtered>; - using AllTrackCandidates = soa::Join; + // using AllTrackCandidates = soa::Join; + using AllTrackCandidates = soa::Filtered>; using ResoV0s = aod::V0Datas; - void processData(EventCandidates::iterator const& collision, AllTrackCandidates const&, ResoV0s const& V0s, aod::BCs const&) + // void processData(EventCandidates::iterator const& collision, AllTrackCandidates const&, ResoV0s const& V0s, aod::BCs const&) + void processData(EventCandidates::iterator const& collision, AllTrackCandidates const& tracks, ResoV0s const& V0s, aod::BCs const&) { if (!collision.sel8()) { @@ -304,6 +334,61 @@ struct lambdapolsp { histos.fill(HIST("hpSinPsiA"), centrality, (TMath::Sin(psiZDCA))); histos.fill(HIST("hpSinPsiC"), centrality, (TMath::Sin(psiZDCC))); + ///////////checking v1 and v2//////////////////////////////// + + if (checkwithpub) { + auto qxZDCA = collision.qxZDCA(); + auto qxZDCC = collision.qxZDCC(); + auto qyZDCA = collision.qyZDCA(); + auto qyZDCC = collision.qyZDCC(); + + for (auto track : tracks) { + if (!selectionTrack(track)) { + continue; + } + + float sign = track.sign(); + if (sign == 0.0) // removing neutral particles + continue; + + auto ux = GetPhiInRange(TMath::Cos(track.phi())); + auto uy = GetPhiInRange(TMath::Sin(track.phi())); + + auto uxQxp = ux * qxZDCA; + auto uyQyp = uy * qyZDCA; + auto uxyQxyp = uxQxp + uyQyp; + auto uxQxt = ux * qxZDCC; + auto uyQyt = uy * qyZDCC; + auto uxyQxyt = uxQxt + uyQyt; + + auto QxtQxp = qxZDCA * qxZDCC; + auto QytQyp = qyZDCA * qyZDCC; + auto Qxytp = QxtQxp + QytQyp; + histos.fill(HIST("hpuxQxpvscent"), centrality, uxQxp); + histos.fill(HIST("hpuyQypvscent"), centrality, uyQyp); + histos.fill(HIST("hpuxQxtvscent"), centrality, uxQxt); + histos.fill(HIST("hpuyQytvscent"), centrality, uyQyt); + histos.fill(HIST("hpQxtQxpvscent"), centrality, QxtQxp); + histos.fill(HIST("hpQytQypvscent"), centrality, QytQyp); + + if (centrality > 5.0 && centrality < 40.0) { + if (track.pt() > 0.2) { + if (sign > 0.0) { + histos.fill(HIST("hpposuxyQxytvseta"), track.eta(), uxyQxyt); + histos.fill(HIST("hpposuxyQxypvseta"), track.eta(), uxyQxyp); + histos.fill(HIST("hpposQxytpvseta"), track.eta(), Qxytp); + } else if (sign < 0.0) { + histos.fill(HIST("hpneguxyQxytvseta"), track.eta(), uxyQxyt); + histos.fill(HIST("hpneguxyQxypvseta"), track.eta(), uxyQxyp); + histos.fill(HIST("hpnegQxytpvseta"), track.eta(), Qxytp); + } + } + } + } + } + + ////////////////////////////////////////////////////////////////////////// + for (auto v0 : V0s) { auto postrack = v0.template posTrack_as(); diff --git a/PWGLF/Tasks/Strangeness/strangeness_in_jets.cxx b/PWGLF/Tasks/Strangeness/strangeness_in_jets.cxx index bebddc16a72..db2c7c01d83 100644 --- a/PWGLF/Tasks/Strangeness/strangeness_in_jets.cxx +++ b/PWGLF/Tasks/Strangeness/strangeness_in_jets.cxx @@ -44,8 +44,8 @@ using std::array; using SelCollisions = soa::Join; using SimCollisions = soa::Join; -using FullTracks = soa::Join; -using MCTracks = soa::Join; +using StrHadronDaughterTracks = soa::Join; +using MCTracks = soa::Join; struct strangeness_in_jets { @@ -111,7 +111,7 @@ struct strangeness_in_jets { void init(InitContext const&) { // Event Counters - registryData.add("number_of_events_data", "number of events in data", HistType::kTH1F, {{10, 0, 10, "Event Cuts"}}); + registryData.add("number_of_events_data", "number of events in data", HistType::kTH1F, {{20, 0, 20, "Event Cuts"}}); registryMC.add("number_of_events_mc", "number of events in mc", HistType::kTH1F, {{10, 0, 10, "Event Cuts"}}); // QC Histograms @@ -128,6 +128,7 @@ struct strangeness_in_jets { registryQC.add("dcaxy_vs_pt", "dcaxy_vs_pt", HistType::kTH2F, {{100, 0.0, 5.0, "#it{p}_{T} (GeV/#it{c})"}, {2000, -0.05, 0.05, "DCA_{xy} (cm)"}}); registryQC.add("dcaz_vs_pt", "dcaz_vs_pt", HistType::kTH2F, {{100, 0.0, 5.0, "#it{p}_{T} (GeV/#it{c})"}, {2000, -0.05, 0.05, "DCA_{z} (cm)"}}); registryQC.add("jet_ue_overlaps", "jet_ue_overlaps", HistType::kTH2F, {{20, 0.0, 20.0, "#it{n}_{jet}"}, {200, 0.0, 200.0, "#it{n}_{overlaps}"}}); + registryQC.add("survivedK0", "survivedK0", HistType::kTH1F, {{20, 0, 20, "step"}}); // Multiplicity Binning std::vector multBinning = {0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100}; @@ -312,9 +313,9 @@ struct strangeness_in_jets { return false; if (v0.dcaV0daughters() > dcaV0DaughtersMax) return false; - if (v0.dcapostopv() < dcapostoPVmin) + if (TMath::Abs(v0.dcapostopv()) < dcapostoPVmin) return false; - if (v0.dcanegtopv() < dcanegtoPVmin) + if (TMath::Abs(v0.dcanegtopv()) < dcanegtoPVmin) return false; // PID Selections (TPC) @@ -363,9 +364,9 @@ struct strangeness_in_jets { return false; if (v0.dcaV0daughters() > dcaV0DaughtersMax) return false; - if (v0.dcapostopv() < dcapostoPVmin) + if (TMath::Abs(v0.dcapostopv()) < dcapostoPVmin) return false; - if (v0.dcanegtopv() < dcanegtoPVmin) + if (TMath::Abs(v0.dcanegtopv()) < dcanegtoPVmin) return false; // PID Selections (TPC) @@ -414,9 +415,9 @@ struct strangeness_in_jets { return false; if (v0.dcaV0daughters() > dcaV0DaughtersMax) return false; - if (v0.dcapostopv() < dcapostoPVmin) + if (TMath::Abs(v0.dcapostopv()) < dcapostoPVmin) return false; - if (v0.dcanegtopv() < dcanegtoPVmin) + if (TMath::Abs(v0.dcanegtopv()) < dcanegtoPVmin) return false; // PID Selections (TPC) @@ -660,10 +661,9 @@ struct strangeness_in_jets { template bool isHighPurityPion(const pionTrack& track) { - if (track.p() < 0.6 && std::abs(track.tpcNSigmaPi()) < 3.0) + if (track.p() < 0.6 && TMath::Abs(track.tpcNSigmaPi()) < 3.0) return true; - if (track.p() > 0.6 && std::abs(track.tpcNSigmaPi()) < 3.0 && - std::abs(track.tofNSigmaPi()) < 3.0) + if (track.p() > 0.6 && TMath::Abs(track.tpcNSigmaPi()) < 3.0 && TMath::Abs(track.tofNSigmaPi()) < 3.0) return true; return false; } @@ -765,7 +765,7 @@ struct strangeness_in_jets { return false; } - void processData(SelCollisions::iterator const& collision, aod::V0Datas const& fullV0s, aod::CascDataExt const& Cascades, FullTracks const& tracks) + void processData(SelCollisions::iterator const& collision, aod::V0Datas const& fullV0s, aod::CascDataExt const& Cascades, StrHadronDaughterTracks const& tracks) { // Event Counter: before event selection @@ -779,7 +779,7 @@ struct strangeness_in_jets { registryData.fill(HIST("number_of_events_data"), 1.5); // Cut on z-vertex - if (std::abs(collision.posZ()) > zVtx) + if (TMath::Abs(collision.posZ()) > zVtx) return; // Event Counter: after z-vertex cut @@ -847,7 +847,7 @@ struct strangeness_in_jets { int n_jets_selected(0); for (int i = 0; i < static_cast(jet.size()); i++) { - if ((std::abs(jet[i].Eta()) + Rjet) > etaMax) + if ((TMath::Abs(jet[i].Eta()) + Rjet) > etaMax) continue; // Perpendicular cones @@ -954,8 +954,8 @@ struct strangeness_in_jets { if (particle_of_interest == option::vzeros) { for (auto& v0 : fullV0s) { - const auto& pos = v0.posTrack_as(); - const auto& neg = v0.negTrack_as(); + const auto& pos = v0.posTrack_as(); + const auto& neg = v0.negTrack_as(); TVector3 v0dir(v0.px(), v0.py(), v0.pz()); float deltaEta_jet = v0dir.Eta() - jet[i].Eta(); @@ -1002,9 +1002,9 @@ struct strangeness_in_jets { if (particle_of_interest == option::cascades) { for (auto& casc : Cascades) { - auto bach = casc.bachelor_as(); - auto pos = casc.posTrack_as(); - auto neg = casc.negTrack_as(); + auto bach = casc.bachelor_as(); + auto pos = casc.posTrack_as(); + auto neg = casc.negTrack_as(); TVector3 cascade_dir(casc.px(), casc.py(), casc.pz()); float deltaEta_jet = cascade_dir.Eta() - jet[i].Eta(); @@ -1139,6 +1139,103 @@ struct strangeness_in_jets { } PROCESS_SWITCH(strangeness_in_jets, 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 (TMath::Abs(collision.posZ()) > zVtx) + return; + registryData.fill(HIST("number_of_events_data"), 12.5); + + for (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 pion_pos(v0.pxpos(), v0.pypos(), v0.pzpos()); + TVector3 pion_neg(v0.pxneg(), v0.pyneg(), v0.pzneg()); + + if (pion_pos.Pt() < ptMin_K0_pion) + continue; + registryQC.fill(HIST("survivedK0"), 3.5); + + if (pion_pos.Pt() > ptMax_K0_pion) + continue; + registryQC.fill(HIST("survivedK0"), 4.5); + + if (pion_neg.Pt() < ptMin_K0_pion) + continue; + registryQC.fill(HIST("survivedK0"), 5.5); + + if (pion_neg.Pt() > ptMax_K0_pion) + continue; + registryQC.fill(HIST("survivedK0"), 6.5); + + // V0 Selections + if (v0.v0cosPA() < v0cospaMin) + continue; + registryQC.fill(HIST("survivedK0"), 7.5); + + if (v0.v0radius() < minimumV0Radius || v0.v0radius() > maximumV0Radius) + continue; + registryQC.fill(HIST("survivedK0"), 8.5); + + if (v0.dcaV0daughters() > dcaV0DaughtersMax) + continue; + registryQC.fill(HIST("survivedK0"), 9.5); + + if (TMath::Abs(v0.dcapostopv()) < dcapostoPVmin) + continue; + registryQC.fill(HIST("survivedK0"), 10.5); + + if (TMath::Abs(v0.dcanegtopv()) < dcanegtoPVmin) + continue; + registryQC.fill(HIST("survivedK0"), 11.5); + + // PID Selections (TPC) + if (ptrack.tpcNSigmaPi() < nsigmaTPCmin || ptrack.tpcNSigmaPi() > nsigmaTPCmax) + continue; + registryQC.fill(HIST("survivedK0"), 12.5); + + if (ntrack.tpcNSigmaPi() < nsigmaTPCmin || ntrack.tpcNSigmaPi() > nsigmaTPCmax) + continue; + registryQC.fill(HIST("survivedK0"), 13.5); + + // PID Selections (TOF) + if (requireTOF) { + if (ptrack.tofNSigmaPi() < nsigmaTOFmin || ptrack.tofNSigmaPi() > nsigmaTOFmax) + continue; + registryQC.fill(HIST("survivedK0"), 14.5); + + if (ntrack.tofNSigmaPi() < nsigmaTOFmin || ntrack.tofNSigmaPi() > nsigmaTOFmax) + continue; + registryQC.fill(HIST("survivedK0"), 15.5); + } + } + + for (auto& v0 : fullV0s) { + const auto& ptrack = v0.posTrack_as(); + const auto& ntrack = v0.negTrack_as(); + if (!passedK0ShortSelection(v0, ptrack, ntrack)) + continue; + registryQC.fill(HIST("survivedK0"), 16.5); + } + } + PROCESS_SWITCH(strangeness_in_jets, processK0s, "Process K0s", false); + Preslice perCollisionV0 = o2::aod::v0data::collisionId; Preslice perCollisionCasc = o2::aod::cascade::collisionId; Preslice perMCCollision = o2::aod::mcparticle::mcCollisionId; @@ -1152,7 +1249,7 @@ struct strangeness_in_jets { continue; registryMC.fill(HIST("number_of_events_mc"), 1.5); - if (std::abs(collision.posZ()) > 10.0) + if (TMath::Abs(collision.posZ()) > 10.0) continue; registryMC.fill(HIST("number_of_events_mc"), 2.5); @@ -1244,7 +1341,7 @@ struct strangeness_in_jets { for (auto& particleMotherOfBach : bachParticle.mothers_as()) { if (particleMotherOfNeg != particleMotherOfPos) continue; - if (abs(particleMotherOfNeg.pdgCode()) != 3122) + if (TMath::Abs(particleMotherOfNeg.pdgCode()) != 3122) continue; if (!particleMotherOfBach.isPhysicalPrimary()) continue; @@ -1284,7 +1381,7 @@ struct strangeness_in_jets { continue; const auto particle = track.mcParticle(); - if (abs(particle.pdgCode()) != 211) + if (TMath::Abs(particle.pdgCode()) != 211) continue; if (particle.isPhysicalPrimary()) { @@ -1387,7 +1484,7 @@ struct strangeness_in_jets { registryMC.fill(HIST("number_of_events_mc"), 3.5); // Selection on z_{vertex} - if (std::abs(mccollision.posZ()) > 10) + if (TMath::Abs(mccollision.posZ()) > 10) continue; registryMC.fill(HIST("number_of_events_mc"), 4.5); @@ -1399,7 +1496,7 @@ struct strangeness_in_jets { for (auto& particle : mcParticles_per_coll) { - int pdg = abs(particle.pdgCode()); + int pdg = TMath::Abs(particle.pdgCode()); if (particle.isPhysicalPrimary() && pdg == 211) { registryMC.fill(HIST("Pion_eta_pt_pythia"), particle.pt(), particle.eta()); @@ -1422,14 +1519,14 @@ struct strangeness_in_jets { double dy = particle.vy() - mccollision.posY(); double dz = particle.vz() - mccollision.posZ(); double dcaxy = sqrt(dx * dx + dy * dy); - double dcaz = std::abs(dz); + double dcaz = TMath::Abs(dz); + if (particle.pt() < 0.15) + continue; if (dcaxy > (par0 + par1 / particle.pt())) continue; if (dcaz > (par0 + par1 / particle.pt())) continue; - if (std::abs(particle.eta()) > 0.8) - continue; - if (particle.pt() < 0.15) + if (TMath::Abs(particle.eta()) > 0.8) continue; // PDG Selection @@ -1489,7 +1586,7 @@ struct strangeness_in_jets { int n_jets_selected(0); for (int i = 0; i < static_cast(jet.size()); i++) { - if ((std::abs(jet[i].Eta()) + Rjet) > etaMax) + if ((TMath::Abs(jet[i].Eta()) + Rjet) > etaMax) continue; // Perpendicular cones @@ -1512,19 +1609,18 @@ struct strangeness_in_jets { double dy = particle.vy() - mccollision.posY(); double dz = particle.vz() - mccollision.posZ(); double dcaxy = sqrt(dx * dx + dy * dy); - double dcaz = std::abs(dz); - + double dcaz = TMath::Abs(dz); + if (particle.pt() < 0.15) + continue; if (dcaxy > (par0 + par1 / particle.pt())) continue; if (dcaz > (par0 + par1 / particle.pt())) continue; - if (std::abs(particle.eta()) > 0.8) - continue; - if (particle.pt() < 0.15) + if (TMath::Abs(particle.eta()) > 0.8) continue; // PDG Selection - int pdg = abs(particle.pdgCode()); + int pdg = TMath::Abs(particle.pdgCode()); if ((pdg != 11) && (pdg != 211) && (pdg != 321) && (pdg != 2212)) continue; @@ -1585,7 +1681,7 @@ struct strangeness_in_jets { double deltaPhi_ue2 = GetDeltaPhi(particle_dir.Phi(), ue2[i].Phi()); double deltaR_ue2 = sqrt(deltaEta_ue2 * deltaEta_ue2 + deltaPhi_ue2 * deltaPhi_ue2); - int pdg = abs(particle.pdgCode()); + int pdg = TMath::Abs(particle.pdgCode()); if (pdg == 211) { if (deltaR_jet < Rjet) { diff --git a/PWGMM/Lumi/Tasks/lumiStability.cxx b/PWGMM/Lumi/Tasks/lumiStability.cxx index 0a6c62f35b9..af7bf889948 100644 --- a/PWGMM/Lumi/Tasks/lumiStability.cxx +++ b/PWGMM/Lumi/Tasks/lumiStability.cxx @@ -44,6 +44,7 @@ struct lumiStabilityTask { Configurable myMaxDeltaBCFV0{"myMaxDeltaBCFV0", 5, {"My BC cut"}}; Configurable nOrbitsConf{"nOrbits", 10000, "number of orbits"}; Configurable minOrbitConf{"minOrbit", 0, "minimum orbit"}; + Configurable is2022Data{"is2022Data", true, "To 2022 data"}; Service ccdb; int nBCsPerOrbit = 3564; @@ -68,12 +69,25 @@ struct lumiStabilityTask { const AxisSpec axisCounts{6, -0.5, 5.5}; const AxisSpec axisV0Counts{5, -0.5, 4.5}; const AxisSpec axisTriggger{nBCsPerOrbit, -0.5f, nBCsPerOrbit - 0.5f}; + const AxisSpec axisPos{1000, -1, 1}; + const AxisSpec axisPosZ{1000, -25, 25}; + const AxisSpec axisNumContrib{1001, -0.5, 1000}; + const AxisSpec axisColisionTime{1000, -50, 50}; + const AxisSpec axisTime{1000, -10, 40}; + const AxisSpec axisTimeFDD{1000, -20, 100}; + const AxisSpec axisCountsTime{2, -0.5, 1.5}; histos.add("hBcA", "BC pattern A; BC ; It is present", kTH1F, {axisTriggger}); histos.add("hBcC", "BC pattern C; BC ; It is present", kTH1F, {axisTriggger}); histos.add("hBcB", "BC pattern B; BC ; It is present", kTH1F, {axisTriggger}); histos.add("hBcE", "BC pattern Empty; BC ; It is present", kTH1F, {axisTriggger}); - + histos.add("hvertexX", "Pos X vertex trigger; Pos x; Count ", kTH1F, {axisPos}); + histos.add("hvertexXvsTime", "Pos X vertex vs Collision Time; vertex X (cm) ; time (ns)", {HistType::kTH2F, {{axisPos}, {axisColisionTime}}}); + histos.add("hvertexY", "Pos Y vertex trigger; Pos y; Count ", kTH1F, {axisPos}); + histos.add("hvertexZ", "Pos Z vertex trigger; Pos z; Count ", kTH1F, {axisPosZ}); + histos.add("hnumContrib", "Num of contributors; Num of contributors; Count ", kTH1I, {axisNumContrib}); + histos.add("hcollisinTime", "Collision Time; ns; Count ", kTH1F, {axisColisionTime}); + // time 32.766 is dummy time // histo about triggers histos.add("FDD/hCounts", "0 FDDCount - 1 FDDVertexCount - 2 FDDPPVertexCount - 3 FDDCoincidencesVertexCount - 4 FDDPPCoincidencesVertexCount - 5 FDDPPBotSidesCount; Number; counts", kTH1F, {axisCounts}); histos.add("FDD/bcVertexTrigger", "vertex trigger per BC (FDD);BC in FDD; counts", kTH1F, {axisTriggger}); @@ -105,6 +119,28 @@ struct lumiStabilityTask { histos.add("FDD/timeACbcA", "time bcA ; A (ns); C (ns)", {HistType::kTH2F, {{300, -15, 15}, {300, -15, 15}}}); histos.add("FDD/timeACbcC", "time bcC ; A (ns); C (ns)", {HistType::kTH2F, {{300, -15, 15}, {300, -15, 15}}}); histos.add("FDD/timeACbcE", "time bcE ; A (ns); C (ns)", {HistType::kTH2F, {{300, -15, 15}, {300, -15, 15}}}); + histos.add("FDD/hTimeAVertex", "FDD time A; ns ; count", kTH1F, {axisTimeFDD}); + histos.add("FDD/hTimeCVertex", "FDD time C; ns ; count", kTH1F, {axisTimeFDD}); + histos.add("FDD/hTimeACoinc", "FDD time A; ns ; count", kTH1F, {axisTimeFDD}); + histos.add("FDD/hTimeCCoinc", "FDD time C; ns ; count", kTH1F, {axisTimeFDD}); + histos.add("FDD/hCountsTimeA2022", "0 Dummy Time - 1 Valid Time ; Kind of Time; counts", kTH1F, {axisCounts}); + histos.add("FDD/hCountsTimeC2022", "0 Dummy Time - 1 Valid Time ; Kind of Time; counts", kTH1F, {axisCounts}); + histos.add("FDD/hCountsTime2022", "0 Dummy Time - 1 Valid Time ; Kind of Time; counts", kTH1F, {axisCounts}); + histos.add("FDD/hValidTimeAvsBC2022", "Valid Time A vs BC id;BC in FT0;valid time counts", kTH1F, {axisTriggger}); + histos.add("FDD/hInvTimeAvsBC2022", "Invalid Time A vs BC id;BC in FT0;invalid time counts", kTH1F, {axisTriggger}); + histos.add("FDD/hValidTimeCvsBC2022", "Valid Time C vs BC id;BC in FT0;valid time counts", kTH1F, {axisTriggger}); + histos.add("FDD/hInvTimeCvsBC2022", "Invalid Time C vs BC id;BC in FT0;invalid time counts", kTH1F, {axisTriggger}); + histos.add("FDD/hValidTimevsBC2022", "Valid Time vs BC id;BC in FT0;valid time counts", kTH1F, {axisTriggger}); + histos.add("FDD/hInvTimevsBC2022", "Invalid Time vs BC id;BC in FT0;invalid time counts", kTH1F, {axisTriggger}); + histos.add("FDD/hCountsTimeA", "0 Dummy Time - 1 Valid Time ; Kind of Time; counts", kTH1F, {axisCounts}); + histos.add("FDD/hCountsTimeC", "0 Dummy Time - 1 Valid Time ; Kind of Time; counts", kTH1F, {axisCounts}); + histos.add("FDD/hCountsTime", "0 Dummy Time - 1 Valid Time ; Kind of Time; counts", kTH1F, {axisCounts}); + histos.add("FDD/hValidTimeAvsBC", "Valid Time A vs BC id;BC in FT0;valid time counts", kTH1F, {axisTriggger}); + histos.add("FDD/hInvTimeAvsBC", "Invalid Time A vs BC id;BC in FT0;invalid time counts", kTH1F, {axisTriggger}); + histos.add("FDD/hValidTimeCvsBC", "Valid Time C vs BC id;BC in FT0;valid time counts", kTH1F, {axisTriggger}); + histos.add("FDD/hInvTimeCvsBC", "Invalid Time C vs BC id;BC in FT0;invalid time counts", kTH1F, {axisTriggger}); + histos.add("FDD/hValidTimevsBC", "Valid Time vs BC id;BC in FT0;valid time counts", kTH1F, {axisTriggger}); + histos.add("FDD/hInvTimevsBC", "Invalid Time vs BC id;BC in FT0;invalid time counts", kTH1F, {axisTriggger}); histos.add("FT0/hCounts", "0 FT0Count - 1 FT0VertexCount - 2 FT0PPVertexCount - 3 FT0PPBothSidesCount; Number; counts", kTH1F, {axisCounts}); histos.add("FT0/bcVertexTrigger", "vertex trigger per BC (FT0);BC in FT0; counts", kTH1F, {axisTriggger}); @@ -122,6 +158,17 @@ struct lumiStabilityTask { histos.add("FT0/timeACbcA", "time bcA ; A (ns); C (ns)", {HistType::kTH2F, {{300, -15, 15}, {300, -15, 15}}}); histos.add("FT0/timeACbcC", "time bcC ; A (ns); C (ns)", {HistType::kTH2F, {{300, -15, 15}, {300, -15, 15}}}); histos.add("FT0/timeACbcE", "time bcE ; A (ns); C (ns)", {HistType::kTH2F, {{300, -15, 15}, {300, -15, 15}}}); + histos.add("FT0/hTimeA", "FT0 time A; ns ; count", kTH1F, {axisTime}); + histos.add("FT0/hTimeC", "FT0 time C; ns ; count", kTH1F, {axisTime}); + histos.add("FT0/hCountsTimeA", "0 Dummy Time - 1 Valid Time ; Kind of Time; counts", kTH1F, {axisCounts}); + histos.add("FT0/hCountsTimeC", "0 Dummy Time - 1 Valid Time ; Kind of Time; counts", kTH1F, {axisCounts}); + histos.add("FT0/hCountsTime", "0 Dummy Time - 1 Valid Time ; Kind of Time; counts", kTH1F, {axisCounts}); + histos.add("FT0/hValidTimeAvsBC", "Valid Time A vs BC id;BC in FT0;valid time counts", kTH1F, {axisTriggger}); + histos.add("FT0/hInvTimeAvsBC", "Invalid Time A vs BC id;BC in FT0;invalid time counts", kTH1F, {axisTriggger}); + histos.add("FT0/hValidTimeCvsBC", "Valid Time C vs BC id;BC in FT0;valid time counts", kTH1F, {axisTriggger}); + histos.add("FT0/hInvTimeCvsBC", "Invalid Time C vs BC id;BC in FT0;invalid time counts", kTH1F, {axisTriggger}); + histos.add("FT0/hValidTimevsBC", "Valid Time vs BC id;BC in FT0;valid time counts", kTH1F, {axisTriggger}); + histos.add("FT0/hInvTimevsBC", "Invalid Time vs BC id;BC in FT0;invalid time counts", kTH1F, {axisTriggger}); histos.add("FV0/hCounts", "0 CountCentralFV0 - 1 CountPFPCentralFV0 - 2 CountPFPOutInFV0 - 3 CountPPCentralFV0 - 4 CountPPOutInFV0; Number; counts", kTH1F, {axisV0Counts}); histos.add("FV0/bcOutTrigger", "Out trigger per BC (FV0);BC in V0; counts", kTH1F, {axisTriggger}); @@ -132,6 +179,14 @@ struct lumiStabilityTask { histos.add("FV0/bcCenTriggerPPCentral", "Central trigger per BC (FV0) with PP in central trigger;BC in V0; counts", kTH1F, {axisTriggger}); histos.add("FV0/bcCenTriggerPFPOutIn", "Central trigger per BC (FV0) with PFP in Out and In trigger;BC in V0; counts", kTH1F, {axisTriggger}); histos.add("FV0/bcCenTriggerPPOutIn", "Central trigger per BC (FV0) with PP in Out and In trigger;BC in V0; counts", kTH1F, {axisTriggger}); + histos.add("FV0/hBcA", "BC pattern A in FV0; BC in FV0 ; It is present", kTH1F, {axisTriggger}); + histos.add("FV0/hBcC", "BC pattern C in FV0; BC in FV0 ; It is present", kTH1F, {axisTriggger}); + histos.add("FV0/hBcB", "BC pattern B in FV0; BC in FV0 ; It is present", kTH1F, {axisTriggger}); + histos.add("FV0/hBcE", "BC pattern Empty in FV0; BC in FV0 ; It is present", kTH1F, {axisTriggger}); + histos.add("FV0/timeAbcB", "time bcB ; A (ns)", kTH1F, {{300, -15, 15}}); + histos.add("FV0/timeAbcA", "time bcA ; A (ns)", kTH1F, {{300, -15, 15}}); + histos.add("FV0/timeAbcC", "time bcC ; A (ns)", kTH1F, {{300, -15, 15}}); + histos.add("FV0/timeAbcE", "time bcE ; A (ns)", kTH1F, {{300, -15, 15}}); } bool checkAnyCoincidence(const std::vector& channels) @@ -217,10 +272,10 @@ struct lumiStabilityTask { // create orbit-axis histograms on the fly with binning based on info from GRP if GRP is available // otherwise default minOrbit and nOrbits will be used const AxisSpec axisOrbits{static_cast(nOrbits / nOrbitsPerTF), 0., static_cast(nOrbits), ""}; - histos.add("hOrbitFDD", "FDD Orbits; Orbit; Entries", kTH1F, {axisOrbits}); + histos.add("hOrbitFDDVertexCoinc", "FDD Orbits; Orbit; Entries", kTH1F, {axisOrbits}); histos.add("hOrbitFDDVertex", "FDD Orbits; Orbit; Entries", kTH1F, {axisOrbits}); - histos.add("hOrbitFT0", "FT0 Orbits; Orbit; Entries", kTH1F, {axisOrbits}); - histos.add("hOrbitFV0", "FV0 Orbits; Orbit; Entries", kTH1F, {axisOrbits}); + histos.add("hOrbitFT0vertex", "FT0 Orbits; Orbit; Entries", kTH1F, {axisOrbits}); + histos.add("hOrbitFV0Central", "FV0 Orbits; Orbit; Entries", kTH1F, {axisOrbits}); } for (auto const& fdd : fdds) { @@ -260,23 +315,6 @@ struct lumiStabilityTask { histos.fill(HIST("FDD/hCounts"), 1); histos.fill(HIST("hOrbitFDDVertex"), orbit - minOrbit); - if (bcPatternA[localBC]) { - histos.fill(HIST("FDD/timeACbcAVertex"), fdd.timeA(), fdd.timeC()); - histos.fill(HIST("FDD/hBcAVertex"), localBC); - } - if (bcPatternC[localBC]) { - histos.fill(HIST("FDD/timeACbcCVertex"), fdd.timeA(), fdd.timeC()); - histos.fill(HIST("FDD/hBcCVertex"), localBC); - } - if (bcPatternB[localBC]) { - histos.fill(HIST("FDD/timeACbcBVertex"), fdd.timeA(), fdd.timeC()); - histos.fill(HIST("FDD/hBcBVertex"), localBC); - } - if (bcPatternE[localBC]) { - histos.fill(HIST("FDD/timeACbcEVertex"), fdd.timeA(), fdd.timeC()); - histos.fill(HIST("FDD/hBcEVertex"), localBC); - } - int deltaIndex = 0; // backward move counts int deltaBC = 0; // current difference wrt globalBC bool pastActivityFDDVertex = false; @@ -301,12 +339,56 @@ struct lumiStabilityTask { if (pastActivityFDDVertex == false) { histos.fill(HIST("FDD/hCounts"), 2); histos.fill(HIST("FDD/bcVertexTriggerPP"), localBC); + if (bcPatternA[localBC]) { + histos.fill(HIST("FDD/timeACbcAVertex"), fdd.timeA(), fdd.timeC()); + histos.fill(HIST("FDD/hBcAVertex"), localBC); + } + if (bcPatternC[localBC]) { + histos.fill(HIST("FDD/timeACbcCVertex"), fdd.timeA(), fdd.timeC()); + histos.fill(HIST("FDD/hBcCVertex"), localBC); + } + if (bcPatternB[localBC]) { + histos.fill(HIST("FDD/timeACbcBVertex"), fdd.timeA(), fdd.timeC()); + histos.fill(HIST("FDD/hBcBVertex"), localBC); + histos.fill(HIST("FDD/hTimeAVertex"), fdd.timeA()); + histos.fill(HIST("FDD/hTimeCVertex"), fdd.timeC()); + if (is2022Data) { + if (fdd.timeA() > 30) { + histos.fill(HIST("FDD/hCountsTimeA2022"), 0); + histos.fill(HIST("FDD/hInvTimeAvsBC2022"), localBC); + } else { + histos.fill(HIST("FDD/hCountsTimeA2022"), 1); + histos.fill(HIST("FDD/hValidTimeAvsBC2022"), localBC); + } + + if (fdd.timeC() > 30) { + histos.fill(HIST("FDD/hCountsTimeC2022"), 0); + histos.fill(HIST("FDD/hInvTimeCvsBC2022"), localBC); + } else { + histos.fill(HIST("FDD/hCountsTimeC2022"), 1); + histos.fill(HIST("FDD/hValidTimeCvsBC2022"), localBC); + } + + if (fdd.timeA() > 30 || fdd.timeC() > 30) { + histos.fill(HIST("FDD/hCountsTime2022"), 0); + histos.fill(HIST("FDD/hInvTimevsBC2022"), localBC); + } + if (fdd.timeA() < 30 && fdd.timeC() < 30) { + histos.fill(HIST("FDD/hCountsTime2022"), 1); + histos.fill(HIST("FDD/hValidTimevsBC2022"), localBC); + } + } + } + if (bcPatternE[localBC]) { + histos.fill(HIST("FDD/timeACbcEVertex"), fdd.timeA(), fdd.timeC()); + histos.fill(HIST("FDD/hBcEVertex"), localBC); + } } if (isCoinA && isCoinC) { histos.fill(HIST("FDD/bcVertexTriggerCoincidence"), localBC); - histos.fill(HIST("FDD/hCounts"), 1); - histos.fill(HIST("hOrbitFDD"), orbit - minOrbit); + histos.fill(HIST("FDD/hCounts"), 3); + histos.fill(HIST("hOrbitFDDVertexCoinc"), orbit - minOrbit); if (bcPatternA[localBC]) { histos.fill(HIST("FDD/timeACbcA"), fdd.timeA(), fdd.timeC()); @@ -319,6 +401,34 @@ struct lumiStabilityTask { if (bcPatternB[localBC]) { histos.fill(HIST("FDD/timeACbcB"), fdd.timeA(), fdd.timeC()); histos.fill(HIST("FDD/hBcB"), localBC); + histos.fill(HIST("FDD/hTimeACoinc"), fdd.timeA()); + histos.fill(HIST("FDD/hTimeCCoinc"), fdd.timeC()); + if (!is2022Data) { + if (fdd.timeA() > 30) { + histos.fill(HIST("FDD/hCountsTimeA"), 0); + histos.fill(HIST("FDD/hInvTimeAvsBC"), localBC); + } else { + histos.fill(HIST("FDD/hCountsTimeA"), 1); + histos.fill(HIST("FDD/hValidTimeAvsBC"), localBC); + } + + if (fdd.timeC() > 30) { + histos.fill(HIST("FDD/hCountsTimeC"), 0); + histos.fill(HIST("FDD/hInvTimeCvsBC"), localBC); + } else { + histos.fill(HIST("FDD/hCountsTimeC"), 1); + histos.fill(HIST("FDD/hValidTimeCvsBC"), localBC); + } + + if (fdd.timeA() > 30 || fdd.timeC() > 30) { + histos.fill(HIST("FDD/hCountsTime"), 0); + histos.fill(HIST("FDD/hInvTimevsBC"), localBC); + } + if (fdd.timeA() < 30 && fdd.timeC() < 30) { + histos.fill(HIST("FDD/hCountsTime"), 1); + histos.fill(HIST("FDD/hValidTimevsBC"), localBC); + } + } } if (bcPatternE[localBC]) { histos.fill(HIST("FDD/timeACbcE"), fdd.timeA(), fdd.timeC()); @@ -368,15 +478,16 @@ struct lumiStabilityTask { deltaBC = 0; if (pastActivityFDDVertexCoincidences == false) { - histos.fill(HIST("FDD/hCounts"), 2); + histos.fill(HIST("FDD/hCounts"), 4); histos.fill(HIST("FDD/bcVertexTriggerCoincidencePP"), localBC); } if (pastActivityFDDTriggerACoincidenceA == false || pastActivityFDDTriggerCCoincidenceC == false) { - histos.fill(HIST("FDD/hCounts"), 3); + histos.fill(HIST("FDD/hCounts"), 5); histos.fill(HIST("FDD/bcVertexTriggerBothSidesCoincidencePP"), localBC); } } // coincidences - } // vertex true + + } // vertex true if (scentral) { histos.fill(HIST("FDD/bcSCentralTrigger"), localBC); @@ -405,7 +516,7 @@ struct lumiStabilityTask { histos.fill(HIST("FDD/bcVCTriggerCoincidence"), localBC); } } // vertex and scentral true - } // loop over FDD events + } // loop over FDD events for (auto const& ft0 : ft0s) { auto bc = ft0.bc_as(); @@ -425,7 +536,7 @@ struct lumiStabilityTask { histos.fill(HIST("FT0/hCounts"), 0); if (vertex) { histos.fill(HIST("FT0/bcVertexTrigger"), localBC); - histos.fill(HIST("hOrbitFT0"), orbit - minOrbit); + histos.fill(HIST("hOrbitFT0vertex"), orbit - minOrbit); if (bcPatternA[localBC]) { histos.fill(HIST("FT0/timeACbcA"), ft0.timeA(), ft0.timeC()); @@ -438,6 +549,33 @@ struct lumiStabilityTask { if (bcPatternB[localBC]) { histos.fill(HIST("FT0/timeACbcB"), ft0.timeA(), ft0.timeC()); histos.fill(HIST("FT0/hBcB"), localBC); + histos.fill(HIST("FT0/hTimeA"), ft0.timeA()); + histos.fill(HIST("FT0/hTimeC"), ft0.timeC()); + + if (ft0.timeA() > 30) { + histos.fill(HIST("FT0/hCountsTimeA"), 0); + histos.fill(HIST("FT0/hInvTimeAvsBC"), localBC); + } else { + histos.fill(HIST("FT0/hCountsTimeA"), 1); + histos.fill(HIST("FT0/hValidTimeAvsBC"), localBC); + } + + if (ft0.timeC() > 30) { + histos.fill(HIST("FT0/hCountsTimeC"), 0); + histos.fill(HIST("FT0/hInvTimeCvsBC"), localBC); + } else { + histos.fill(HIST("FT0/hCountsTimeC"), 1); + histos.fill(HIST("FT0/hValidTimeCvsBC"), localBC); + } + + if (ft0.timeA() > 30 || ft0.timeC() > 30) { + histos.fill(HIST("FT0/hCountsTime"), 0); + histos.fill(HIST("FT0/hInvTimevsBC"), localBC); + } + if (ft0.timeA() < 30 && ft0.timeC() < 30) { + histos.fill(HIST("FT0/hCountsTime"), 1); + histos.fill(HIST("FT0/hValidTimevsBC"), localBC); + } } if (bcPatternE[localBC]) { histos.fill(HIST("FT0/timeACbcE"), ft0.timeA(), ft0.timeC()); @@ -530,9 +668,26 @@ struct lumiStabilityTask { } if (aCen) { - histos.fill(HIST("hOrbitFV0"), orbit - minOrbit); + histos.fill(HIST("hOrbitFV0Central"), orbit - minOrbit); histos.fill(HIST("FV0/bcCenTrigger"), localBC); + if (bcPatternA[localBC]) { + histos.fill(HIST("FV0/timeAbcA"), fv0.time()); + histos.fill(HIST("FV0/hBcA"), localBC); + } + if (bcPatternC[localBC]) { + histos.fill(HIST("FV0/timeAbcC"), fv0.time()); + histos.fill(HIST("FV0/hBcC"), localBC); + } + if (bcPatternB[localBC]) { + histos.fill(HIST("FV0/timeAbcB"), fv0.time()); + histos.fill(HIST("FV0/hBcB"), localBC); + } + if (bcPatternE[localBC]) { + histos.fill(HIST("FV0/timeAbcE"), fv0.time()); + histos.fill(HIST("FV0/hBcE"), localBC); + } + int deltaIndex = 0; // backward move counts int deltaBC = 0; // current difference wrt globalBC bool pastActivityFV0Cen = false; @@ -607,9 +762,21 @@ struct lumiStabilityTask { } } } // loop over V0 events - } // end processMain + } // end processMain PROCESS_SWITCH(lumiStabilityTask, processMain, "Process FDD and FT0 to lumi stability analysis", true); + + void processCollisions(aod::Collision const& collision) + { + histos.fill(HIST("hvertexX"), collision.posX()); + histos.fill(HIST("hvertexY"), collision.posY()); + histos.fill(HIST("hvertexZ"), collision.posZ()); + histos.fill(HIST("hnumContrib"), collision.numContrib()); + histos.fill(HIST("hcollisinTime"), collision.collisionTime()); + histos.fill(HIST("hvertexXvsTime"), collision.posX(), collision.collisionTime()); + } + + PROCESS_SWITCH(lumiStabilityTask, processCollisions, "Process collision to get vertex position", true); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGUD/DataModel/UDTables.h b/PWGUD/DataModel/UDTables.h index 46f379c24d5..e83f3c5daa2 100644 --- a/PWGUD/DataModel/UDTables.h +++ b/PWGUD/DataModel/UDTables.h @@ -151,7 +151,7 @@ DECLARE_SOA_INDEX_COLUMN(UDMcCollision, udMcCollision); } // namespace udcollision -DECLARE_SOA_TABLE(UDCollisions, "AOD", "UDCOLLISION", +DECLARE_SOA_TABLE(UDCollisions_000, "AOD", "UDCOLLISION", o2::soa::Index<>, udcollision::GlobalBC, udcollision::RunNumber, @@ -161,6 +161,18 @@ DECLARE_SOA_TABLE(UDCollisions, "AOD", "UDCOLLISION", collision::NumContrib, udcollision::NetCharge, udcollision::RgtrwTOF); +// Version with UPC Reco Flag +DECLARE_SOA_TABLE_VERSIONED(UDCollisions_001, "AOD", "UDCOLLISION", 1, + o2::soa::Index<>, + udcollision::GlobalBC, + udcollision::RunNumber, + collision::PosX, + collision::PosY, + collision::PosZ, + collision::Flags, + collision::NumContrib, + udcollision::NetCharge, + udcollision::RgtrwTOF); DECLARE_SOA_TABLE(SGCollisions, "AOD", "SGCOLLISION", udcollision::GapSide); @@ -208,6 +220,8 @@ DECLARE_SOA_TABLE(UDCollsLabels, "AOD", "UDCOLLSLABEL", DECLARE_SOA_TABLE(UDMcCollsLabels, "AOD", "UDMCCOLLSLABEL", udcollision::UDMcCollisionId); +using UDCollisions = UDCollisions_001; + using UDCollision = UDCollisions::iterator; using SGCollision = SGCollisions::iterator; using UDCollisionsSel = UDCollisionsSels::iterator; diff --git a/PWGUD/TableProducer/Converters/CMakeLists.txt b/PWGUD/TableProducer/Converters/CMakeLists.txt index b8d13cc587e..3bcb34f6ac2 100644 --- a/PWGUD/TableProducer/Converters/CMakeLists.txt +++ b/PWGUD/TableProducer/Converters/CMakeLists.txt @@ -14,3 +14,9 @@ o2physics_add_dpl_workflow(fwd-tracks-extra-converter PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(collisions-converter + SOURCES UDCollisionsConverter.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + diff --git a/PWGUD/TableProducer/Converters/UDCollisionsConverter.cxx b/PWGUD/TableProducer/Converters/UDCollisionsConverter.cxx new file mode 100644 index 00000000000..8be7bce717b --- /dev/null +++ b/PWGUD/TableProducer/Converters/UDCollisionsConverter.cxx @@ -0,0 +1,58 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// \file UDCollisionsConverter.cxx +/// \brief Converts UDCollisions table from version 000 to 001 + +/// This task allows for the conversion of the UDCollisions table from the version 000, +/// that is before the introduction of Flags for UPC reconstruction +/// to the version 001, that includes it + +/// executable name o2-analysis-ud-collisions-converter + +/// \author Sasha Bylinkin + +#include "Framework/runDataProcessing.h" +#include "Framework/AnalysisTask.h" +#include "Framework/AnalysisDataModel.h" +#include "PWGUD/DataModel/UDTables.h" + +using namespace o2; +using namespace o2::framework; + +// Converts UDCollisions for version 000 to 001 +struct UDCollisionsConverter { + Produces udCollisions_001; + + void process(o2::aod::UDCollisions_000 const& collisions) + { + + for (const auto& collision : collisions) { + + udCollisions_001(collision.globalBC(), + collision.runNumber(), + collision.posX(), + collision.posY(), + collision.posZ(), + 0.0f, // dummy UPC reco flag, not available in version 000 + collision.numContrib(), + collision.netCharge(), + collision.rgtrwTOF()); + } + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc), + }; +} diff --git a/PWGUD/TableProducer/DGBCCandProducer.cxx b/PWGUD/TableProducer/DGBCCandProducer.cxx index ab3ecf6aeaa..97b60c42c9e 100644 --- a/PWGUD/TableProducer/DGBCCandProducer.cxx +++ b/PWGUD/TableProducer/DGBCCandProducer.cxx @@ -17,6 +17,7 @@ #include #include "Framework/runDataProcessing.h" #include "Framework/AnalysisTask.h" +#include "ReconstructionDataFormats/Vertex.h" #include "PWGUD/DataModel/UDTables.h" #include "PWGUD/Core/UDHelpers.h" #include "PWGUD/Core/UPCHelpers.h" @@ -279,11 +280,11 @@ struct DGBCCandProducer { // update UDTables template - void updateUDTables(bool onlyPV, int64_t colID, uint64_t bcnum, int rnum, float vx, float vy, float vz, + void updateUDTables(bool onlyPV, int64_t colID, uint64_t bcnum, int rnum, float vx, float vy, float vz, int flag, uint16_t const& ntrks, int8_t const& ncharge, float const& rtrwTOF, TTracks const& tracks, upchelpers::FITInfo const& fitInfo) { - outputCollisions(bcnum, rnum, vx, vy, vz, ntrks, ncharge, rtrwTOF); + outputCollisions(bcnum, rnum, vx, vy, vz, flag, ntrks, ncharge, rtrwTOF); outputCollisionsSels(fitInfo.ampFT0A, fitInfo.ampFT0C, fitInfo.timeFT0A, fitInfo.timeFT0C, fitInfo.triggerMaskFT0, fitInfo.ampFDDA, fitInfo.ampFDDC, fitInfo.timeFDDA, fitInfo.timeFDDC, @@ -383,7 +384,7 @@ struct DGBCCandProducer { // check if DG event // distinguish between cases with and without associated BC - // 1. candidate has associated BC and associated collision -> vertex position: col.[posX(), posY(), posZ()] + // 1. candidate has associated BC and associated collision -> position: col.[posX(), posY(), posZ()] // 2. candidate has associated BC but no associated collision -> [-2., 2., -2.] // 3. candidate has no associated BC -> [-3., 3., -3.] int isDG = -1; @@ -415,8 +416,11 @@ struct DGBCCandProducer { registry.get(HIST("table/candCase"))->Fill(1, 1.); rtrwTOF = udhelpers::rPVtrwTOF(colTracks, col.numContrib()); nCharge = udhelpers::netCharge(colTracks); - - updateUDTables(false, col.globalIndex(), bc.globalBC(), bc.runNumber(), col.posX(), col.posY(), col.posZ(), + int upc_flag = 0; + ushort flags = col.flags(); + if (flags & dataformats::Vertex>::Flags::UPCMode) + upc_flag = 1; + updateUDTables(false, col.globalIndex(), bc.globalBC(), bc.runNumber(), col.posX(), col.posY(), col.posZ(), upc_flag, col.numContrib(), nCharge, rtrwTOF, colTracks, fitInfo); } } else { @@ -448,7 +452,7 @@ struct DGBCCandProducer { rtrwTOF = udhelpers::rPVtrwTOF(tracksArray, tracksArray.size()); nCharge = udhelpers::netCharge(tracksArray); - updateUDTables(false, -1, bc.globalBC(), bc.runNumber(), -2., 2., -2, + updateUDTables(false, -1, bc.globalBC(), bc.runNumber(), -2., 2., -2, 0, tracksArray.size(), nCharge, rtrwTOF, tracksArray, fitInfo); } } @@ -494,7 +498,7 @@ struct DGBCCandProducer { rtrwTOF = udhelpers::rPVtrwTOF(tracksArray, tracksArray.size()); nCharge = udhelpers::netCharge(tracksArray); - updateUDTables(false, -1, bcnum, tibc.runNumber(), -3., 3., -3, + updateUDTables(false, -1, bcnum, tibc.runNumber(), -3., 3., -3, 0, tracksArray.size(), nCharge, rtrwTOF, tracksArray, fitInfo); } } @@ -612,7 +616,11 @@ struct DGBCCandProducer { auto rtrwTOF = udhelpers::rPVtrwTOF(colTracks, col.numContrib()); auto nCharge = udhelpers::netCharge(colTracks); udhelpers::getFITinfo(fitInfo, bc, bcs, ft0s, fv0as, fdds); - updateUDTables(false, col.globalIndex(), bcnum, bc.runNumber(), col.posX(), col.posY(), col.posZ(), + int upc_flag = 0; + ushort flags = col.flags(); + if (flags & dataformats::Vertex>::Flags::UPCMode) + upc_flag = 1; + updateUDTables(false, col.globalIndex(), bcnum, bc.runNumber(), col.posX(), col.posY(), col.posZ(), upc_flag, col.numContrib(), nCharge, rtrwTOF, colTracks, fitInfo); // fill UDZdcs if (bc.has_zdc()) { @@ -681,7 +689,11 @@ struct DGBCCandProducer { } int64_t colID = withCollision ? col.globalIndex() : -1; - updateUDTables(false, colID, bcnum, tibc.runNumber(), vpos[0], vpos[1], vpos[2], + int upc_flag = 0; + ushort flags = col.flags(); + if (flags & dataformats::Vertex>::Flags::UPCMode) + upc_flag = 1; + updateUDTables(false, colID, bcnum, tibc.runNumber(), vpos[0], vpos[1], vpos[2], upc_flag, tracksArray.size(), nCharge, rtrwTOF, tracksArray, fitInfo); // fill UDZdcs if (bc.globalBC() == bcnum) { diff --git a/PWGUD/TableProducer/DGCandProducer.cxx b/PWGUD/TableProducer/DGCandProducer.cxx index 5add359ac1d..65fe9c3173c 100644 --- a/PWGUD/TableProducer/DGCandProducer.cxx +++ b/PWGUD/TableProducer/DGCandProducer.cxx @@ -14,6 +14,7 @@ #include "Framework/runDataProcessing.h" #include "Framework/AnalysisTask.h" +#include "ReconstructionDataFormats/Vertex.h" #include "PWGUD/DataModel/UDTables.h" #include "PWGUD/Core/UPCHelpers.h" #include "PWGUD/Core/DGSelector.h" @@ -269,8 +270,12 @@ struct DGCandProducer { // update DG candidates tables auto rtrwTOF = udhelpers::rPVtrwTOF(tracks, collision.numContrib()); + int upc_flag = 0; + ushort flags = collision.flags(); + if (flags & dataformats::Vertex>::Flags::UPCMode) + upc_flag = 1; outputCollisions(bc.globalBC(), bc.runNumber(), - collision.posX(), collision.posY(), collision.posZ(), + collision.posX(), collision.posY(), collision.posZ(), upc_flag, collision.numContrib(), udhelpers::netCharge(tracks), rtrwTOF); outputCollisionsSels(fitInfo.ampFT0A, fitInfo.ampFT0C, fitInfo.timeFT0A, fitInfo.timeFT0C, diff --git a/PWGUD/TableProducer/SGCandProducer.cxx b/PWGUD/TableProducer/SGCandProducer.cxx index c6a927114b9..feb0e93f2f0 100644 --- a/PWGUD/TableProducer/SGCandProducer.cxx +++ b/PWGUD/TableProducer/SGCandProducer.cxx @@ -12,6 +12,7 @@ #include #include "Framework/ASoA.h" #include "Framework/AnalysisDataModel.h" +#include "ReconstructionDataFormats/Vertex.h" #include "Common/CCDB/EventSelectionParams.h" #include "Common/DataModel/EventSelection.h" #include "CommonConstants/LHCConstants.h" @@ -213,10 +214,15 @@ struct SGCandProducer { upchelpers::FITInfo fitInfo{}; udhelpers::getFITinfo(fitInfo, newbc, bcs, ft0s, fv0as, fdds); // update SG candidates tables + int upc_flag = 0; + ushort flags = collision.flags(); + if (flags & dataformats::Vertex>::Flags::UPCMode) + upc_flag = 1; outputCollisions(bc.globalBC(), bc.runNumber(), - collision.posX(), collision.posY(), collision.posZ(), + collision.posX(), collision.posY(), collision.posZ(), upc_flag, collision.numContrib(), udhelpers::netCharge(tracks), 1.); // rtrwTOF); //omit the calculation to speed up the things while skimming + outputSGCollisions(issgevent); outputCollisionsSels(fitInfo.ampFT0A, fitInfo.ampFT0C, fitInfo.timeFT0A, fitInfo.timeFT0C, fitInfo.triggerMaskFT0, diff --git a/PWGUD/TableProducer/UPCCandidateProducer.cxx b/PWGUD/TableProducer/UPCCandidateProducer.cxx index 47da6d3ffbd..58a8af75524 100644 --- a/PWGUD/TableProducer/UPCCandidateProducer.cxx +++ b/PWGUD/TableProducer/UPCCandidateProducer.cxx @@ -22,6 +22,7 @@ #include "PWGUD/Core/UPCCutparHolder.h" #include "PWGUD/Core/UPCHelpers.h" #include "PWGUD/DataModel/UDTables.h" +#include "DataFormatsITSMFT/ROFRecord.h" using namespace o2::framework; using namespace o2::framework::expressions; @@ -89,7 +90,7 @@ struct UpcCandProducer { // QA histograms HistogramRegistry histRegistry{"HistRegistry", {}, OutputObjHandlingPolicy::AnalysisObject}; - using BCsWithBcSels = o2::soa::Join; + using BCsWithBcSels = o2::soa::Join; using ForwardTracks = o2::soa::Join; @@ -722,7 +723,7 @@ struct UpcCandProducer { void createCandidatesCentral(BarrelTracks const& barrelTracks, o2::aod::AmbiguousTracks const& ambBarrelTracks, - o2::aod::BCs const& bcs, + BCsWithBcSels const& bcs, o2::aod::Collisions const& collisions, o2::aod::FT0s const& ft0s, o2::aod::FDDs const& /*fdds*/, @@ -916,8 +917,12 @@ struct UpcCandProducer { } RgtrwTOF = RgtrwTOF / static_cast(numContrib); // store used tracks + int upc_flag = 0; + // TODO: introduce better check on association of collision and reconstruction mode + if (bcs.iteratorAt(0).flags() == o2::itsmft::ROFRecord::VtxUPCMode) + upc_flag = 1; fillBarrelTracks(barrelTracks, barrelTrackIDs, candID, globalBC, closestBcITSTPC, mcBarrelTrackLabels, ambBarrelTrBCs); - eventCandidates(globalBC, runNumber, dummyX, dummyY, dummyZ, numContrib, netCharge, RgtrwTOF); + eventCandidates(globalBC, runNumber, dummyX, dummyY, dummyZ, upc_flag, numContrib, netCharge, RgtrwTOF); eventCandidatesSels(fitInfo.ampFT0A, fitInfo.ampFT0C, fitInfo.timeFT0A, fitInfo.timeFT0C, fitInfo.triggerMaskFT0, fitInfo.ampFDDA, fitInfo.ampFDDC, fitInfo.timeFDDA, fitInfo.timeFDDC, fitInfo.triggerMaskFDD, fitInfo.ampFV0A, fitInfo.timeFV0A, fitInfo.triggerMaskFV0A, @@ -981,8 +986,12 @@ struct UpcCandProducer { } RgtrwTOF = RgtrwTOF / static_cast(numContrib); // store used tracks + int upc_flag = 0; + // TODO: introduce better check on association of collision and reconstruction mode + if (bcs.iteratorAt(0).flags() == o2::itsmft::ROFRecord::VtxUPCMode) + upc_flag = 1; fillBarrelTracks(barrelTracks, barrelTrackIDs, candID, globalBC, closestBcITSTPC, mcBarrelTrackLabels, ambBarrelTrBCs); - eventCandidates(globalBC, runNumber, dummyX, dummyY, dummyZ, numContrib, netCharge, RgtrwTOF); + eventCandidates(globalBC, runNumber, dummyX, dummyY, dummyZ, upc_flag, numContrib, netCharge, RgtrwTOF); eventCandidatesSels(fitInfo.ampFT0A, fitInfo.ampFT0C, fitInfo.timeFT0A, fitInfo.timeFT0C, fitInfo.triggerMaskFT0, fitInfo.ampFDDA, fitInfo.ampFDDC, fitInfo.timeFDDA, fitInfo.timeFDDC, fitInfo.triggerMaskFDD, fitInfo.ampFV0A, fitInfo.timeFV0A, fitInfo.triggerMaskFV0A, @@ -1157,9 +1166,13 @@ struct UpcCandProducer { } RgtrwTOF = RgtrwTOF / static_cast(numContrib); // store used tracks + int upc_flag = 0; + // TODO: introduce better check on association of collision and reconstruction mode + if (bcs.iteratorAt(0).flags() == o2::itsmft::ROFRecord::VtxUPCMode) + upc_flag = 1; fillFwdTracks(fwdTracks, fwdTrackIDs, candID, bc, bc, mcFwdTrackLabels); fillBarrelTracks(barrelTracks, barrelTrackIDs, candID, bc, bc, mcBarrelTrackLabels, ambBarrelTrBCs); - eventCandidates(bc, runNumber, dummyX, dummyY, dummyZ, numContrib, netCharge, RgtrwTOF); + eventCandidates(bc, runNumber, dummyX, dummyY, dummyZ, upc_flag, numContrib, netCharge, RgtrwTOF); eventCandidatesSels(fitInfo.ampFT0A, fitInfo.ampFT0C, fitInfo.timeFT0A, fitInfo.timeFT0C, fitInfo.triggerMaskFT0, fitInfo.ampFDDA, fitInfo.ampFDDC, fitInfo.timeFDDA, fitInfo.timeFDDC, fitInfo.triggerMaskFDD, fitInfo.ampFV0A, fitInfo.timeFV0A, fitInfo.triggerMaskFV0A, @@ -1210,7 +1223,7 @@ struct UpcCandProducer { void createCandidatesFwd(ForwardTracks const& fwdTracks, o2::aod::FwdTrkCls const& fwdTrkClusters, o2::aod::AmbiguousFwdTracks const& ambFwdTracks, - o2::aod::BCs const& bcs, + BCsWithBcSels const& bcs, o2::aod::Collisions const& collisions, o2::aod::FT0s const& ft0s, o2::aod::FDDs const& /*fdds*/, @@ -1378,8 +1391,12 @@ struct UpcCandProducer { selTrackIds.push_back(id); } // store used tracks + int upc_flag = 0; + // TODO: introduce better check on association of collision and reconstruction mode + if (bcs.iteratorAt(0).flags() == o2::itsmft::ROFRecord::VtxUPCMode) + upc_flag = 1; fillFwdTracks(fwdTracks, trkCandIDs, candID, globalBC, closestBcMCH, mcFwdTrackLabels); - eventCandidates(globalBC, runNumber, dummyX, dummyY, dummyZ, numContrib, netCharge, RgtrwTOF); + eventCandidates(globalBC, runNumber, dummyX, dummyY, dummyZ, upc_flag, numContrib, netCharge, RgtrwTOF); eventCandidatesSels(fitInfo.ampFT0A, fitInfo.ampFT0C, fitInfo.timeFT0A, fitInfo.timeFT0C, fitInfo.triggerMaskFT0, fitInfo.ampFDDA, fitInfo.ampFDDC, fitInfo.timeFDDA, fitInfo.timeFDDC, fitInfo.triggerMaskFDD, fitInfo.ampFV0A, fitInfo.timeFV0A, fitInfo.triggerMaskFV0A, @@ -1409,7 +1426,7 @@ struct UpcCandProducer { void createCandidatesFwdGlobal(ForwardTracks const& fwdTracks, o2::aod::FwdTrkCls const& /*fwdTrkClusters*/, o2::aod::AmbiguousFwdTracks const& ambFwdTracks, - o2::aod::BCs const& bcs, + BCsWithBcSels const& bcs, o2::aod::Collisions const& collisions, o2::aod::FT0s const& ft0s, o2::aod::FDDs const& /*fdds*/, @@ -1573,8 +1590,12 @@ struct UpcCandProducer { selTrackIdsGlobal.push_back(id); } // store used tracks + int upc_flag = 0; + // TODO: introduce better check on association of collision and reconstruction mode + if (bcs.iteratorAt(0).flags() == o2::itsmft::ROFRecord::VtxUPCMode) + upc_flag = 1; fillFwdTracks(fwdTracks, trkCandIDs, candID, globalBC, closestBcMCH, mcFwdTrackLabels); - eventCandidates(globalBC, runNumber, dummyX, dummyY, dummyZ, numContrib, netCharge, RgtrwTOF); + eventCandidates(globalBC, runNumber, dummyX, dummyY, dummyZ, upc_flag, numContrib, netCharge, RgtrwTOF); eventCandidatesSels(fitInfo.ampFT0A, fitInfo.ampFT0C, fitInfo.timeFT0A, fitInfo.timeFT0C, fitInfo.triggerMaskFT0, fitInfo.ampFDDA, fitInfo.ampFDDC, fitInfo.timeFDDA, fitInfo.timeFDDC, fitInfo.triggerMaskFDD, fitInfo.ampFV0A, fitInfo.timeFV0A, fitInfo.triggerMaskFV0A, @@ -1628,7 +1649,7 @@ struct UpcCandProducer { // create candidates for central region void processCentral(BarrelTracks const& barrelTracks, o2::aod::AmbiguousTracks const& ambBarrelTracks, - o2::aod::BCs const& bcs, + BCsWithBcSels const& bcs, o2::aod::Collisions const& collisions, o2::aod::FT0s const& ft0s, o2::aod::FDDs const& fdds, @@ -1674,7 +1695,7 @@ struct UpcCandProducer { // create candidates for central region void processCentralMC(BarrelTracks const& barrelTracks, o2::aod::AmbiguousTracks const& ambBarrelTracks, - o2::aod::BCs const& bcs, + BCsWithBcSels const& bcs, o2::aod::Collisions const& collisions, o2::aod::FT0s const& ft0s, o2::aod::FDDs const& fdds, @@ -1697,7 +1718,7 @@ struct UpcCandProducer { void processForward(ForwardTracks const& fwdTracks, o2::aod::FwdTrkCls const& fwdTrkClusters, o2::aod::AmbiguousFwdTracks const& ambFwdTracks, - o2::aod::BCs const& bcs, + BCsWithBcSels const& bcs, o2::aod::Collisions const& collisions, o2::aod::FT0s const& ft0s, o2::aod::FDDs const& fdds, @@ -1714,7 +1735,7 @@ struct UpcCandProducer { void processForwardMC(ForwardTracks const& fwdTracks, o2::aod::FwdTrkCls const& fwdTrkClusters, o2::aod::AmbiguousFwdTracks const& ambFwdTracks, - o2::aod::BCs const& bcs, + BCsWithBcSels const& bcs, o2::aod::Collisions const& collisions, o2::aod::FT0s const& ft0s, o2::aod::FDDs const& fdds, @@ -1737,7 +1758,7 @@ struct UpcCandProducer { void processForwardGlobal(ForwardTracks const& fwdTracks, o2::aod::FwdTrkCls const& fwdTrkClusters, o2::aod::AmbiguousFwdTracks const& ambFwdTracks, - o2::aod::BCs const& bcs, + BCsWithBcSels const& bcs, o2::aod::Collisions const& collisions, o2::aod::FT0s const& ft0s, o2::aod::FDDs const& fdds, diff --git a/PWGUD/Tasks/upcTauCentralBarrelRL.cxx b/PWGUD/Tasks/upcTauCentralBarrelRL.cxx index 965bfb6f327..f0b6d6c6c82 100644 --- a/PWGUD/Tasks/upcTauCentralBarrelRL.cxx +++ b/PWGUD/Tasks/upcTauCentralBarrelRL.cxx @@ -19,6 +19,7 @@ // O2 headers #include "Framework/AnalysisTask.h" #include "Framework/AnalysisDataModel.h" +#include "Framework/HistogramRegistry.h" #include "Framework/O2DatabasePDGPlugin.h" #include "Framework/runDataProcessing.h" @@ -97,6 +98,30 @@ struct UpcTauCentralBarrelRL { Configurable doFourTrackPsi2S{"doFourTrackPsi2S", true, {"Define histos for Psi2S into four charged tracks (pi/mu) and allow to fill them"}}; Configurable doSixTracks{"doSixTracks", false, {"Define histos for six tracks and allow to fill them"}}; + ConfigurableAxis axisNtracks{"axisNtracks", {30, -0.5, 29.5}, "Number of tracks in collision"}; + ConfigurableAxis axisZvtx{"axisZvtx", {40, -20., 20.}, "Z-vertex position (cm)"}; + ConfigurableAxis axisInvMass{"axisInvMass", {400, 1., 5.}, "Invariant mass (GeV/c^{2})"}; + ConfigurableAxis axisInvMassWide{"axisInvMassWide", {1000, 0., 10.}, "Invariant mass (GeV/c^{2}), wider range"}; + ConfigurableAxis axisMom{"axisMom", {400, 0., 2.}, "Momentum (GeV/c)"}; + ConfigurableAxis axisMomWide{"axisMomWide", {1000, 0., 10.}, "Momentum (GeV/c), wider range"}; + ConfigurableAxis axisMomSigned{"axisMomSigned", {800, -2., 2.}, "Signed momentum (GeV/c)"}; + ConfigurableAxis axisPt{"axisPt", {400, 0., 2.}, "Transversal momentum (GeV/c)"}; + ConfigurableAxis axisPhi{"axisPhi", {64, -2 * o2::constants::math::PI, 2 * o2::constants::math::PI}, "Azimuthal angle (a.y.)"}; + ConfigurableAxis axisModPhi{"axisModPhi", {400, 0., .4}, "Track fmod(#phi,#pi/9)"}; + ConfigurableAxis axisEta{"axisEta", {50, -1.2, 1.2}, "Pseudorapidity (a.u.)"}; + ConfigurableAxis axisRap{"axisRap", {50, -1.2, 1.2}, "Rapidity (a.u.)"}; + ConfigurableAxis axisAcoplanarity{"axisAcoplanarity", {32, 0.0, o2::constants::math::PI}, "Acoplanarity (rad)"}; + ConfigurableAxis axisTPCdEdx{"axisTPCdEdx", {2000, 0., 200.}, "TPC dE/dx (a.u.)"}; + ConfigurableAxis axisTOFsignal{"axisTOFsignal", {2500, -10000., 40000.}, "TOF signal (a.u.)"}; + ConfigurableAxis axisNsigma{"axisNsigma", {200, -10., 10.}, "n sigma"}; + ConfigurableAxis axisDCA{"axisDCA", {100, -0.5, 0.5}, "DCA (cm)"}; + ConfigurableAxis axisAvgITSclsSizes{"axisAvgITSclsSizes", {500, 0., 10.}, "ITS average cluster size"}; + ConfigurableAxis axisITSnCls{"axisITSnCls", {8, -0.5, 7.5}, "ITS n clusters"}; + ConfigurableAxis axisITSchi2{"axisITSchi2", {100, 0, 50}, "UTS chi2"}; + ConfigurableAxis axisTPCnCls{"axisTPCnCls", {165, -0.5, 164.5}, "TPC n clusters"}; + ConfigurableAxis axisTPCxRwsFrac{"axisTPCxRwsFrac", {200, 0.0, 2.0}, "TPC fraction of crossed raws"}; + ConfigurableAxis axisTPCchi2{"axisTPCchi2", {100, 0, 10}, "TPC chi2"}; + using FullUDTracks = soa::Join; using FullUDCollision = soa::Join::iterator; using FullSGUDCollision = soa::Join::iterator; @@ -114,30 +139,6 @@ struct UpcTauCentralBarrelRL { countCollisions = 0; isFirstReconstructedCollisions = true; - const AxisSpec axisNtracks{30, -0.5, 29.5}; - const AxisSpec axisZvtx{40, -20., 20.}; - const AxisSpec axisInvMass{400, 1., 5.}; - const AxisSpec axisInvMassWide{1000, 0., 10.}; - const AxisSpec axisMom{400, 0., 2.}; - const AxisSpec axisMomSigned{800, -2., 2.}; - const AxisSpec axisMomWide{1000, 0., 10.}; - const AxisSpec axisPt{400, 0., 2.}; - const AxisSpec axisPhi{64, -2 * o2::constants::math::PI, 2 * o2::constants::math::PI}; - const AxisSpec axisModPhi{400, 0., .4}; - const AxisSpec axisEta{50, -1.2, 1.2}; - const AxisSpec axisRap{50, -1.2, 1.2}; - const AxisSpec axisAcoplanarity{32, 0.0, o2::constants::math::PI}; - const AxisSpec axisDCA{100, -0.5, 0.5}; - const AxisSpec axisAvgITSclsSizes{500, 0., 10.}; - const AxisSpec axisTPCdEdx{2000, 0., 200.}; - const AxisSpec axisTOFsignal{2500, -10000., 40000.}; - const AxisSpec axisNsigma{200, -10., 10.}; - const AxisSpec axisITSnCls{8, -0.5, 7.5}; - const AxisSpec axisITSchi2{100, 0, 50}; - const AxisSpec axisTPCnCls{165, -0.5, 164.5}; - const AxisSpec axisTPCxRwsFrac{200, 0.0, 2.0}; - const AxisSpec axisTPCchi2{100, 0, 10}; - histos.add("Events/hCountCollisions", ";;Number of analysed collision (-)", HistType::kTH1D, {{1, 0.5, 1.5}}); histos.add("Events/UDtableGapSide", ";GapSide value from UD table (-);Number of events (-)", HistType::kTH1D, {{4, -1.5, 2.5}}); histos.add("Events/TrueGapSideDiffToTableValue", ";Difference trueGapSide from SGselector and gapSide from UD table (-);Number of events (-)", HistType::kTH1D, {{7, -3.5, 3.5}}); diff --git a/Tutorials/ML/applyMlSelection.cxx b/Tutorials/ML/applyMlSelection.cxx index d33427e3c2a..bf2e69fc5ce 100644 --- a/Tutorials/ML/applyMlSelection.cxx +++ b/Tutorials/ML/applyMlSelection.cxx @@ -11,7 +11,7 @@ /// \file applyMlSelection.cxx /// \brief Showcase usage of trained ML model exported to ONNX format for candidate selection in analysis -/// \brief This is only the starting point for the tutorial. The complete task is available at https://github.com/AliceO2Group/analysis-tutorials/tree/master/o2at-3/machineLearning/MlInference +/// \brief This is only the starting point for the tutorial. The complete task is available at https://github.com/AliceO2Group/analysis-tutorials/tree/master/o2at-4/machineLearning/MlInference /// /// \author Fabio Catalano , CERN @@ -45,7 +45,7 @@ struct applyMlSelection { // Bonus: CCDB configuration (needed for ML application on the GRID) Configurable loadModelsFromCCDB{"loadModelsFromCCDB", false, "Flag to enable or disable the loading of models from CCDB"}; Configurable ccdbUrl{"ccdbUrl", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; - Configurable modelPathsCCDB{"modelPathsCCDB", "Users/f/fcatalan/O2AT3/MlInference", "Path on CCDB"}; + Configurable> modelPathsCCDB{"modelPathsCCDB", std::vector{"Users/c/ciacco/O2AT4/MlInference"}, "Path on CCDB"}; Configurable timestampCCDB{"timestampCCDB", -1, "timestamp of the ONNX file for ML model used to query in CCDB"}; Filter filterDsFlag = (o2::aod::hf_track_index::hfflag & static_cast(BIT(aod::hf_cand_3prong::DecayType::DsToKKPi))) != static_cast(0); diff --git a/Tutorials/ML/dpl-config_applyMlSelection.json b/Tutorials/ML/dpl-config_applyMlSelection.json index ddb5a42d329..592d2973bf0 100644 --- a/Tutorials/ML/dpl-config_applyMlSelection.json +++ b/Tutorials/ML/dpl-config_applyMlSelection.json @@ -41,124 +41,37 @@ }, "loadModelsFromCCDB": "false", "ccdbUrl": "http://alice-ccdb.cern.ch", - "modelPathsCCDB": "Users/f/fcatalan/O2AT3/MlInference", + "modelPathsCCDB": { + "values": [ + "Users\/c\/ciacco\/O2AT4\/MlInference" + ] + }, "timestampCCDB": "-1" }, - "internal-dpl-aod-reader": { + "aod-file-private": "AO2D_MC_Ds.root", "time-limit": "0", "orbit-offset-enumeration": "0", "orbit-multiplier-enumeration": "0", "start-value-enumeration": "0", "end-value-enumeration": "-1", "step-value-enumeration": "1", - "aod-file": "AO2D.root" - }, - "hf-track-index-skim-creator-cascades": { - "maxDZIni": "4", - "tpcRefitV0Daugh": "1", - "ccdbPathGrpMag": "GLO/Config/GRPMagField", - "processCascades": "0", - "propagateToPCA": "1", - "cutInvMassCascLc": "1", - "ccdbPathGrp": "GLO/GRP/GRP", - "processNoCascades": "1", - "ccdbUrl": "http://alice-ccdb.cern.ch", - "doCutQuality": "1", - "nCrossedRowsMinBach": "50", - "etaMaxV0Daugh": "1.1", - "dcaXYNegToPvMin": "0.1", - "maxR": "200", - "nCrossedRowsMinV0Daugh": "50", - "useAbsDCA": "1", - "minRelChi2Change": "0.9", - "cpaV0Min": "0.995", - "useWeightedFinalPCA": "1", - "cutInvMassV0": "0.05", - "dcaXYPosToPvMin": "0.1", - "minParamChange": "0.001", - "etaMinV0Daugh": "-99999", - "fillHistograms": "1", - "isRun2": "0", - "ptCascCandMin": "-1", - "ccdbPathLut": "GLO/Param/MatLUT", - "tpcRefitBach": "1", - "ptMinV0Daugh": "0.05" - }, - "track-to-collision-association": { - "timeMargin": "500", - "bcWindowForOneSigma": "60", - "usePVAssociation": "1", - "processStandardAssoc": "0", - "processAssocWithTime": "1", - "nSigmaForTimeCompat": "4", - "includeUnassigned": "1", - "fillTableOfCollIdsPerTrack": "0", - "setTrackSelections": "1" - }, - "hf-track-index-skim-creator-lf-cascades": { - "maxDZIni": "4", - "dcaBachToPv": "0.05", - "dcaV0ToPv": "0.05", - "ccdbPathGrpMag": "GLO/Config/GRPMagField", - "v0Radius": "0.9", - "tpcNsigmaBachelor": "4", - "dcaV0Dau": "2", - "processNoLfCascades": "1", - "propagateToPCA": "1", - "ccdbPathGrp": "GLO/GRP/GRP", - "do3Prong": "0", - "v0MassWindow": "0.008", - "ccdbUrl": "http://alice-ccdb.cern.ch", - "rejDiffCollTrack": "1", - "doCutQuality": "1", - "tpcNsigmaPion": "4", - "cascRadius": "0.5", - "tpcNsigmaProton": "4", - "maxR": "200", - "useAbsDCA": "1", - "minRelChi2Change": "0.9", - "dcaPosToPv": "0.05", - "cascCosPA": "0.95", - "dcaNegToPv": "0.05", - "useWeightedFinalPCA": "1", - "dcaCascDau": "1", - "processLfCascades": "0", - "minParamChange": "0.001", - "v0CosPA": "0.95", - "fillHistograms": "1", - "isRun2": "0", - "ccdbPathLut": "GLO/Param/MatLUT" + "aod-parent-access-level": "1" }, "hf-track-index-skim-creator": { - "maxDZIni": "4", - "cutsDplusToPiKPi": { + "thresholdMlScoreDsToPiKK": { "values": [ [ - 1.75, - 2.05, - 0.7, - 0.02 - ], - [ - 1.75, - 2.05, + 0.1, 0.5, - 0.02 + 0.5 ] ] }, - "ccdbPathGrpMag": "GLO/Config/GRPMagField", - "axisNumTracks": { - "values": [ - 250, - -0.5, - 249.5 - ] - }, + "applyProtonPidForXicToPKPi": "1", "binsPtDsToKKPi": { "values": [ - 1, + 0, 5, 1000 ] @@ -167,23 +80,23 @@ "binsPtJpsiToEE": { "values": [ 0, - 0, - 0 + 5, + 1000 ] }, "cutsLcToPKPi": { "values": [ [ - 1.75, - 2.05, + 2.1, + 2.55, 0.7, - 0.02 + 0 ], [ - 1.75, - 2.05, - 0.5, - 0.02 + 2, + 2.6, + 0.85, + 0.01 ] ] }, @@ -191,11 +104,11 @@ "binsPtLcToPKPi": { "values": [ 0, - 0, - 0 + 5, + 1000 ] }, - "process2And3ProngsWithPvRefit": "0", + "minTwoTrackDecayLengthFor3Prongs": "0", "axisPvRefitDeltaY": { "values": [ 1000, @@ -207,16 +120,16 @@ "cutsJpsiToEE": { "values": [ [ - 1.65, - 2.15, - 0.5, - 100 + 0, + 0, + 2, + 0 ], [ - 1.65, - 2.15, - 0.5, - 100 + 0, + 0, + 2, + 0 ] ] }, @@ -227,25 +140,27 @@ 0.5 ] }, - "cutsD0ToPiK": { + "ccdbUrl": "http://alice-ccdb.cern.ch", + "onnxFileNames": { "values": [ [ - 1.65, - 2.15, - 0.5, - 100 + "ModelHandler_onnx_D0ToKPi.onnx" ], [ - 1.65, - 2.15, - 0.5, - 100 + "ModelHandler_onnx_DplusToPiKPi.onnx" + ], + [ + "ModelHandler_onnx_LcToPKPi.onnx" + ], + [ + "ModelHandler_onnx_DsToKKPi.onnx" + ], + [ + "" ] ] }, - "ccdbUrl": "http://alice-ccdb.cern.ch", - "debugPvRefit": "0", - "maxR": "200", + "maxTwoTrackChi2PcaFor3Prongs": "1e+10", "axisPvRefitDeltaX": { "values": [ 1000, @@ -259,372 +174,254 @@ "cutsJpsiToMuMu": { "values": [ [ - 1.65, - 2.15, - 0.5, - 100 + 0, + 0, + 2, + 0 ], [ - 1.65, - 2.15, - 0.5, - 100 + 0, + 0, + 2, + 0 ] ] }, - "debug": "0", "binsPtXicToPKPi": { "values": [ 0, - 0, - 0 - ] - }, - "cutsDsToKKPi": { - "values": [ - [ - 1.78, - 2.18, - 0.95, - 0.01 - ], - [ - 1.78, - 2.18, - 0.98, - 0.02 - ] + 5, + 1000 ] }, - "doDstar": "0", + "doDstar": "1", "binsPtDstarToD0Pi": { "values": [ 0, - 0, - 0 + 5, + 1000 ] }, "binsPtDplusToPiKPi": { "values": [ 0, - 0, - 0 + 5, + 1000 ] }, "useWeightedFinalPCA": "0", - "axisNumCands": { - "values": [ - 200, - -0.5, - 199.5 - ] - }, "cutsDstarToD0Pi": { "values": [ [ 0.17, - 0.05 + 0.12 ], [ 0.17, - 0.08 + 0.4 ] ] }, "binsPtJpsiToMuMu": { "values": [ 0, - 0, - 0 - ] - }, - "binsPtD0ToPiK": { - "values": [ - 0, - 0, - 0 + 5, + 1000 ] }, - "cutsXicToPKPi": { + "loadMlModelsFromCCDB": "1", + "minParamChange": "0.001", + "ptTolerance": "0.1", + "ccdbPathLut": "GLO/Param/MatLUT", + "applyMlForHfFilters": "0", + "maxDZIni": "4", + "cutsDplusToPiKPi": { "values": [ [ - 1.75, + 1.7, 2.05, - 0.7, - 0.02 + 0.85, + 0.01 ], [ - 1.75, - 2.05, - 0.5, + 1.6, + 2.5, + 0.9, 0.02 ] ] }, - "minParamChange": "0.001", - "processNo2And3Prongs": "0", - "ptTolerance": "0.1", - "fillHistograms": "1", - "isRun2": "0", - "ccdbPathLut": "GLO/Param/MatLUT" - }, - "ft0-corrected-table": {}, - "hf-candidate-creator-3prong-expressions": { - "processMc": "1" - }, - "hf-track-index-skim-creator-tag-sel-collisions": { - "zVertexMin": "-10", - "xVertexMax": "1", - "useSel8Trigger": "1", - "axisNumContributors": { + "ccdbPathGrpMag": "GLO/Config/GRPMagField", + "thresholdMlScoreLcToPiKP": { "values": [ - 200, - -0.5, - 199.5 + [ + 0.1, + 0.5, + 0.5 + ] ] }, - "triggerClassName": "kINT7", - "processTrigSel": "1", - "yVertexMax": "1", - "fillHistograms": "1", - "zVertexMax": "10", - "xVertexMin": "-1", - "chi2Max": "0", - "processNoTrigSel": "0", - "nContribMin": "0", - "yVertexMin": "-1" - }, - "hf-track-index-skim-creator-tag-sel-tracks": { - "etaMaxTrack2Prong": "0.8", - "useIsGlobalTrackForSoftPion": "0", - "ccdbPathGrpMag": "GLO/Config/GRPMagField", - "useIsGlobalTrackWoDCAForSoftPion": "0", - "ptMaxSoftPionForDstar": "2", - "ptMinSoftPionForDstar": "0.05", - "cutsTrack3Prong": { + "process2And3ProngsWithPvRefit": "0", + "cutsD0ToPiK": { "values": [ [ - 0, - 10 - ], - [ - 0, - 10 - ], - [ - 0, - 10 + 1.65, + 2.1, + 0.8, + 0.01 ], [ - 0, - 10 - ], + 1.6, + 5, + 0.85, + 0.01 + ] + ] + }, + "debugPvRefit": "0", + "maxR": "200", + "debug": "0", + "cutsDsToKKPi": { + "values": [ [ - 0, - 10 + 1.7, + 2.15, + 0.8, + 0.01, + 0.02 ], [ - 0, - 10 + 1.7, + 2.25, + 0.85, + 0.01, + 0.02 ] ] }, - "binsPtTrack": { + "applyProtonPidForLcToPKPi": "1", + "applyKaonPidIn3Prongs": "0", + "binsPtD0ToPiK": { "values": [ 0, - 0.5, - 1, - 1.5, - 2, - 3, + 5, 1000 ] }, - "ccdbPathGrp": "GLO/GRP/GRP", - "doPvRefit": "0", - "useIsGlobalTrackWoDCA": "1", - "axisPvRefitDeltaY": { - "values": [ - 1000, - -0.5, - 0.5 - ] - }, - "axisPvRefitDeltaZ": { - "values": [ - 1000, - -0.5, - 0.5 - ] - }, - "ptMinTrack3Prong": "0.3", - "etaMinTrack3Prong": "-99999", - "useIsQualityTrackITSForSoftPion": "1", - "ccdbUrl": "http://alice-ccdb.cern.ch", - "doCutQuality": "1", - "debugPvRefit": "0", - "ptMinTrackBach": "0.3", - "useIsGlobalTrack": "0", - "axisPvRefitDeltaX": { - "values": [ - 1000, - -0.5, - 0.5 - ] - }, - "etaMaxTrackBach": "0.8", - "cutsTrack2Prong": { + "mlModelPathCCDB": "EventFiltering/PWGHF/BDTSmeared", + "cutsXicToPKPi": { "values": [ [ - 0, - 10 - ], - [ - 0, - 10 - ], - [ - 0, - 10 - ], - [ - 0, - 10 - ], - [ - 0, - 10 + 2.1, + 2.65, + 0.8, + 0.01 ], [ - 0, - 10 + 2, + 2.7, + 0.85, + 0.01 ] ] }, - "ptMinTrack2Prong": "0.3", - "etaMinTrackBach": "-99999", - "cutsTrackDstar": { + "processNo2And3Prongs": "0", + "fillHistograms": "1", + "isRun2": "0", + "thresholdMlScoreXicToPiKP": { "values": [ [ - 0, - 0 - ], - [ - 0, - 0 - ], - [ - 0, - 0 - ], - [ - 0, - 0 - ], - [ - 0, - 0 - ], - [ - 0, - 0 + 0.1, + 0.5, + 0.5 ] ] }, - "etaMaxSoftPionForDstar": "0.8", - "etaMinTrack2Prong": "-99999", - "tpcNClsFoundMin": "70", - "etaMaxTrack3Prong": "0.8", - "fillHistograms": "1", - "isRun2": "0", - "cutsTrackBach": { + "timestampCcdbForHfFilters": "1657032422771", + "thresholdMlScoreDplusToPiKPi": { "values": [ [ - 10, - 10 - ], - [ - 10, - 10 - ], - [ - 10, - 10 - ], - [ - 10, - 10 - ], - [ - 10, - 10 - ], - [ - 10, - 10 + 0.1, + 0.5, + 0.5 ] ] }, - "etaMinSoftPionForDstar": "-99999", - "ccdbPathLut": "GLO/Param/MatLUT" + "thresholdMlScoreD0ToKPi": { + "values": [ + [ + 0.1, + 0.5, + 0.5 + ] + ] + } }, - "track-selection": { - "ptMax": "1e+10", - "produceTable": "1", - "etaMin": "-0.8", - "isRun3": "1", - "itsMatching": "1", - "etaMax": "0.8", - "compatibilityIU": "0", - "dcaSetup": "0", - "ptMin": "0.1", - "produceFBextendedTable": "-1" + "timestamp-task": { + "fatalOnInvalidTimestamp": "false", + "verbose": "false", + "rct-path": "RCT\/Info\/RunInformation", + "orbit-reset-path": "CTP\/Calib\/OrbitReset", + "ccdb-url": "http:\/\/alice-ccdb.cern.ch", + "isRun2MC": "-1" + }, + "track-propagation": { + "ccdb-url": "http:\/\/alice-ccdb.cern.ch", + "lutPath": "GLO\/Param\/MatLUT", + "geoPath": "GLO\/Config\/GeometryAligned", + "grpmagPath": "GLO\/Config\/GRPMagField", + "mVtxPath": "GLO\/Calib\/MeanVertex", + "minPropagationDistance": "5", + "trackTunerParams": "debugInfo=0|updateTrackDCAs=1|updateTrackCovMat=1|updateCurvature=0|updateCurvatureIU=1|updatePulls=1|isInputFileFromCCDB=1|pathInputFile=Users\/m\/mfaggin\/test\/inputsTrackTuner\/pp2023\/smoothHighPtMC|nameInputFile=trackTuner_DataLHC23fPass1_McLHC23k4b_run535085.root|pathFileQoverPt=Users\/h\/hsharma\/qOverPtGraphs|nameFileQoverPt=D0sigma_Data_removal_itstps_MC_LHC22b1b.root|usePvRefitCorrections=0|qOverPtMC=1|qOverPtData=1.5", + "processStandard": "false", + "processStandardWithPID": "false", + "processCovarianceMc": "false", + "processCovariance": "true", + "processCovarianceWithPID": "false" }, "bc-selection-task": { "triggerBcShift": "999", - "processRun3": "1", - "processRun2": "0" + "processRun2": "false", + "processRun3": "true" }, "event-selection-task": { "syst": "pp", - "isMC": "1", - "processRun3": "1", - "processRun2": "0", "muonSelection": "0", - "customDeltaBC": "-1" + "maxDiffZvtxFT0vsPV": "1", + "isMC": "1", + "processRun2": "false", + "processRun3": "true" }, "hf-candidate-creator-3prong": { + "propagateToPCA": "true", + "useAbsDCA": "false", + "useWeightedFinalPCA": "false", + "maxR": "200", "maxDZIni": "4", - "minRelChi2Change": "0.9", - "processNoPvRefit": "1", - "ccdbPathGrpMag": "GLO/Config/GRPMagField", - "useWeightedFinalPCA": "0", - "propagateToPCA": "1", "minParamChange": "0.001", - "ccdbPathGrp": "GLO/GRP/GRP", - "processPvRefit": "0", - "fillHistograms": "1", - "ccdbUrl": "http://alice-ccdb.cern.ch", - "isRun2": "0", - "ccdbPathLut": "GLO/Param/MatLUT", - "maxR": "200", - "useAbsDCA": "0" - }, - "track-propagation": { - "lutPath": "GLO/Param/MatLUT", - "mVtxPath": "GLO/Calib/MeanVertex", - "geoPath": "GLO/Config/GeometryAligned", - "grpmagPath": "GLO/Config/GRPMagField", - "ccdb-url": "http://alice-ccdb.cern.ch", - "minPropagationDistance": "5", - "processStandard": "0", - "processCovariance": "1" + "minRelChi2Change": "0.9", + "fillHistograms": "true", + "isRun2": "false", + "ccdbUrl": "http:\/\/alice-ccdb.cern.ch", + "ccdbPathLut": "GLO\/Param\/MatLUT", + "ccdbPathGrp": "GLO\/GRP\/GRP", + "ccdbPathGrpMag": "GLO\/Config\/GRPMagField", + "createDplus": "true", + "createDs": "true", + "createLc": "false", + "createXic": "false", + "processNoPvRefit": "true" }, - "timestamp-task": { - "rct-path": "RCT/Info/RunInformation", - "orbit-reset-path": "CTP/Calib/OrbitReset", - "ccdb-url": "http://alice-ccdb.cern.ch", - "verbose": "0", - "isRun2MC": "0" + "track-selection": { + "ptMax": "1e+10", + "produceTable": "1", + "etaMin": "-0.8", + "isRun3": "1", + "itsMatching": "1", + "etaMax": "0.8", + "compatibilityIU": "0", + "dcaSetup": "0", + "ptMin": "0.1", + "produceFBextendedTable": "-1" } -} \ No newline at end of file +} diff --git a/Tutorials/PWGCF/CMakeLists.txt b/Tutorials/PWGCF/CMakeLists.txt index 9bf7685cfeb..ad718c5289f 100644 --- a/Tutorials/PWGCF/CMakeLists.txt +++ b/Tutorials/PWGCF/CMakeLists.txt @@ -9,6 +9,7 @@ # granted to it by virtue of its status as an Intergovernmental Organization # or submit itself to any jurisdiction. +add_subdirectory(EventPlane) add_subdirectory(FemtoFramework) add_subdirectory(FlowGenericFramework) add_subdirectory(TwoParticleCorrelations) diff --git a/Tutorials/PWGCF/EventPlane/CMakeLists.txt b/Tutorials/PWGCF/EventPlane/CMakeLists.txt new file mode 100644 index 00000000000..4e0a34d9971 --- /dev/null +++ b/Tutorials/PWGCF/EventPlane/CMakeLists.txt @@ -0,0 +1,12 @@ +# Copyright 2019-2020 CERN and copyright holders of ALICE O2. +# See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +# All rights not expressly granted are reserved. +# +# This software is distributed under the terms of the GNU General Public +# License v3 (GPL Version 3), copied verbatim in the file "COPYING". +# +# In applying this license CERN does not waive the privileges and immunities +# granted to it by virtue of its status as an Intergovernmental Organization +# or submit itself to any jurisdiction. + +add_subdirectory(src) diff --git a/Tutorials/PWGCF/EventPlane/README.md b/Tutorials/PWGCF/EventPlane/README.md new file mode 100644 index 00000000000..c9610b0b45c --- /dev/null +++ b/Tutorials/PWGCF/EventPlane/README.md @@ -0,0 +1,3 @@ +# O2AT - Second edition - PWG-CF + +## Event Plane hands-on session diff --git a/Tutorials/PWGCF/EventPlane/doc/README.md b/Tutorials/PWGCF/EventPlane/doc/README.md new file mode 100644 index 00000000000..c9610b0b45c --- /dev/null +++ b/Tutorials/PWGCF/EventPlane/doc/README.md @@ -0,0 +1,3 @@ +# O2AT - Second edition - PWG-CF + +## Event Plane hands-on session diff --git a/Tutorials/PWGCF/EventPlane/src/CMakeLists.txt b/Tutorials/PWGCF/EventPlane/src/CMakeLists.txt new file mode 100644 index 00000000000..86e39d138cf --- /dev/null +++ b/Tutorials/PWGCF/EventPlane/src/CMakeLists.txt @@ -0,0 +1,15 @@ +# Copyright 2019-2020 CERN and copyright holders of ALICE O2. +# See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +# All rights not expressly granted are reserved. +# +# This software is distributed under the terms of the GNU General Public +# License v3 (GPL Version 3), copied verbatim in the file "COPYING". +# +# In applying this license CERN does not waive the privileges and immunities +# granted to it by virtue of its status as an Intergovernmental Organization +# or submit itself to any jurisdiction. + +o2physics_add_dpl_workflow(qvectors-tutorial + SOURCES qVectorstutorial.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + COMPONENT_NAME Analysis) diff --git a/Tutorials/PWGCF/EventPlane/src/qVectorstutorial.cxx b/Tutorials/PWGCF/EventPlane/src/qVectorstutorial.cxx new file mode 100644 index 00000000000..db754fb8c88 --- /dev/null +++ b/Tutorials/PWGCF/EventPlane/src/qVectorstutorial.cxx @@ -0,0 +1,175 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +// C++/ROOT includes. +#include +#include +#include +#include +#include +#include +#include +#include + +// o2Physics includes. +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/ASoAHelpers.h" +#include "Framework/HistogramRegistry.h" +#include "Framework/runDataProcessing.h" +#include "Framework/RunningWorkflowInfo.h" +#include "Framework/StaticFor.h" + +#include "Common/DataModel/Qvectors.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/TrackSelectionTables.h" +#include "Common/DataModel/Centrality.h" +#include "Common/Core/EventPlaneHelper.h" +#include "Common/Core/TrackSelection.h" + +#include "CommonConstants/PhysicsConstants.h" + +// o2 includes. + +using namespace o2; +using namespace o2::framework; + +using MyCollisions = soa::Join; +using MyTracks = soa::Join; + +struct qVectorstutorial { + 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.15, "Minimum transverse momentum for charged track"}; + Configurable cfgMaxEta{"cfgMaxEta", 0.8, "Maximum pseudorapidiy for charged track"}; + Configurable cfgMaxDCArToPVcut{"cfgMaxDCArToPVcut", 0.1, "Maximum transverse DCA"}; + Configurable cfgMaxDCAzToPVcut{"cfgMaxDCAzToPVcut", 1.0, "Maximum longitudinal DCA"}; + + 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}, ""}; + + 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"}; + + histosQA.add(Form("histQvecV2"), "", {HistType::kTH3F, {axisQvecF, axisQvecF, 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}}); + } + + template + bool SelEvent(const CollType& collision) + { + if (!collision.sel8()) { + return 0; + } + if (!collision.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV)) { + return 0; + } + if (!collision.selection_bit(aod::evsel::kNoSameBunchPileup)) { + return 0; + } + if (!collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard)) { + return 0; + } + + return 1; + } + + template + bool SelTrack(const TrackType 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(const CollType& collision, int nmode) + { + if (nmode == 2) { + histosQA.fill(HIST("histQvecV2"), collision.qvecFT0CReVec()[0], collision.qvecFT0CImVec()[0], 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()); + } + } + + template + void fillHistosFlow(const CollType& collision, const TrackType& track, int nmode) + { + if (collision.sumAmplFT0C() < 1e-4) { + return; + } + for (auto& trk : track) { + if (!SelTrack(trk)) { + continue; + } + if (nmode == 2) { + histosQA.fill(HIST("histCosDetV2"), collision.centFT0C(), 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 (!SelEvent(collision)) { + return; + } + for (auto 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/Tutorials/PWGCF/FemtoFramework/src/CFTutorialTask1.cxx b/Tutorials/PWGCF/FemtoFramework/src/CFTutorialTask1.cxx index acb7f799a7c..369e63cbdf6 100644 --- a/Tutorials/PWGCF/FemtoFramework/src/CFTutorialTask1.cxx +++ b/Tutorials/PWGCF/FemtoFramework/src/CFTutorialTask1.cxx @@ -37,7 +37,7 @@ struct CFTutorialTask1 { // TODO : // Defining filters for analysis level selections on events and tracks - // on Femto tables defined FemtoDerived.h + // on Femto tables defined in FemtoDerived.h // Filter collisionFilter = ... // Filter trackFilter = ... @@ -50,7 +50,6 @@ struct CFTutorialTask1 { // create analysis objects like histograms void init(o2::framework::InitContext&) { - // Add histograms to histogram registry HistRegistry.add("Event/hZvtx", ";Z (cm)", kTH1F, {{240, -12, 12}}); diff --git a/Tutorials/PWGCF/FemtoFramework/src/CFTutorialTask2.cxx b/Tutorials/PWGCF/FemtoFramework/src/CFTutorialTask2.cxx index 8c3adcfd542..ff5fa93aa5b 100644 --- a/Tutorials/PWGCF/FemtoFramework/src/CFTutorialTask2.cxx +++ b/Tutorials/PWGCF/FemtoFramework/src/CFTutorialTask2.cxx @@ -92,7 +92,7 @@ struct CFTutorialTask2 { HistRegistry.fill(HIST("Event/hZvtx"), col.posZ()); // TODO - // generate partition of particles 1&2 with sliceByCached method + // generate partition of particles 1 & 2 with sliceByCached method /// TODO: /// loop over particle group 1 diff --git a/Tutorials/PWGCF/FemtoFramework/src/CFTutorialTask3.cxx b/Tutorials/PWGCF/FemtoFramework/src/CFTutorialTask3.cxx index 02e7b9d9e14..ca200fd3937 100644 --- a/Tutorials/PWGCF/FemtoFramework/src/CFTutorialTask3.cxx +++ b/Tutorials/PWGCF/FemtoFramework/src/CFTutorialTask3.cxx @@ -57,13 +57,11 @@ struct CFTutorialTask3 { // ... Configurable ConfCutPartTwo{"ConfCutPartTwo", 3191978, "Particle 2 - Selection bit"}; - // additional configurables for particle 1 - // ... - - // more configurables for PID selection + // additional configurables for particle 2 // ... - /// Partitions for particle 1 and particle 2 + // Partitions for particle 1 and particle 2 + // add PID selection to partition definition Partition PartsOne = (aod::femtodreamparticle::partType == uint8_t(aod::femtodreamparticle::ParticleType::kTrack)) && ((aod::femtodreamparticle::cut & ConfCutPartOne) == ConfCutPartOne); Partition PartsTwo = (aod::femtodreamparticle::partType == uint8_t(aod::femtodreamparticle::ParticleType::kTrack)) && ((aod::femtodreamparticle::cut & ConfCutPartTwo) == ConfCutPartTwo); @@ -96,40 +94,27 @@ struct CFTutorialTask3 { void process(FilteredFDCollision const& col, FilteredFDParts const& /*parts*/) { - /// event QA + // event QA HistRegistry.fill(HIST("Event/hZvtx"), col.posZ()); // generate partition of particels auto GroupPartsOne = PartsOne->sliceByCached(aod::femtodreamparticle::fdCollisionId, col.globalIndex(), cache); auto GroupPartsTwo = PartsTwo->sliceByCached(aod::femtodreamparticle::fdCollisionId, col.globalIndex(), cache); - /// QA for particle 1 + // QA for particle 1 for (auto& part : GroupPartsOne) { - - // TODO: - // add function for PID selection from FemtoUtils - // if (PID cut) { - HistRegistry.fill(HIST("Particle1/hPt"), part.pt()); HistRegistry.fill(HIST("Particle1/hEta"), part.eta()); HistRegistry.fill(HIST("Particle1/hPhi"), part.phi()); - - // } } - /// QA for particle 2 - /// skip QA if particle 1 & 2 are the same + // QA for particle 2 + // skip QA if particle 1 & 2 are the same if (ConfIsSame.value == false) { for (auto& part : GroupPartsTwo) { - // TODO: - // add function for PID selection from FemtoUtils - // if (PID cut) { - HistRegistry.fill(HIST("Particle2/hPt"), part.pt()); HistRegistry.fill(HIST("Particle2/hEta"), part.eta()); HistRegistry.fill(HIST("Particle2/hPhi"), part.phi()); - - // } } } } diff --git a/Tutorials/PWGCF/FemtoFramework/src/CFTutorialTask4.cxx b/Tutorials/PWGCF/FemtoFramework/src/CFTutorialTask4.cxx index 943f1e5bc12..90ae5168a78 100644 --- a/Tutorials/PWGCF/FemtoFramework/src/CFTutorialTask4.cxx +++ b/Tutorials/PWGCF/FemtoFramework/src/CFTutorialTask4.cxx @@ -50,18 +50,16 @@ struct CFTutorialTask4 { Configurable ConfIsSame{"ConfIsSame", false, "Pairs of the same particle"}; Configurable ConfPDGCodePartOne{"ConfPDGCodePartOne", 2212, "Particle 1 - PDG code"}; - Configurable ConfCutPartOne{"ConfCutPartOne", 3191978, "Particle 1 - Selection bit from cutCulator"}; - Configurable ConfPIDPartOne{"ConfPIDPartOne", 0, "Particle 1 - Index in ConfTrkPIDspecies of producer task"}; - Configurable ConfPIDValuePartOne{"ConfPIDValuePartOne", 3, "Particle 1 - Read from cutCulator"}; + Configurable ConfCutPartOne{"ConfCutPartOne", 3191978, "Particle 1 - Selection bit"}; + Configurable ConfPIDTPCPartOne{"ConfPIDTPCPartOne", 2, "Particle 1 - TPC PID Selection bit"}; + Configurable ConfPIDTPCTOFPartOne{"ConfPIDTPCTOFPartOne", 4, "Particle 1 - TPCTOF PID Selection bit"}; + Configurable ConfPIDThresholdPartOne{"ConfPIDThresholdPartOne", 0.75, "Particle 1 - Momentum threshold for TPC to TPCTOF PID"}; Configurable ConfPDGCodePartTwo{"ConfPDGCodePartTwo", 2212, "Particle 2 - PDG code"}; Configurable ConfCutPartTwo{"ConfCutPartTwo", 3191978, "Particle 2 - Selection bit"}; - Configurable ConfPIDPartTwo{"ConfPIDPartTwo", 0, "Particle 2 - Index in ConfTrkPIDspecies of producer task"}; - Configurable ConfPIDValuePartTwo{"ConfPIDValuePartTwo", 3, "Particle 1 - Read from cutCulator"}; - - Configurable ConfPIDThreshold{"ConfPIDThreshold", 0.75, "Momentum threshold for TPC to TPCTOF PID"}; - Configurable ConfNspecies{"ConfNspecies", 2, "Number of particle spieces with PID info"}; - Configurable> ConfTrkPIDnSigmaMax{"ConfTrkPIDnSigmaMax", std::vector{3.f, 3.5f, 2.5f}, "This configurable needs to be the same as the one used in the producer task"}; + Configurable ConfPIDTPCPartTwo{"ConfPIDTPCPartTwo", 0, "Particle 2 - TPC PID Selection bit"}; + Configurable ConfPIDTPCTOFPartTwo{"ConfPIDTPCTOFPartTwo", 0, "Particle 2 - TPCTOF PID Selection bit"}; + Configurable ConfPIDThresholdPartTwo{"ConfPIDThresholdPartTwo", 0.75, "Particle 2 - Momentum threshold for TPC to TPCTOF PID"}; /// Partitions for particle 1 and particle 2 Partition PartsOne = (aod::femtodreamparticle::partType == uint8_t(aod::femtodreamparticle::ParticleType::kTrack)) && ((aod::femtodreamparticle::cut & ConfCutPartOne) == ConfCutPartOne); @@ -105,38 +103,18 @@ struct CFTutorialTask4 { /// QA for particle 1 for (auto& part : GroupPartsOne) { - /// check PID of particle 1 using function from FemtoUtils using PID bit - if (isFullPIDSelected(part.pidcut(), - part.p(), - ConfPIDThreshold.value, - ConfPIDPartOne.value, - ConfNspecies.value, - ConfTrkPIDnSigmaMax.value, - ConfPIDValuePartOne.value, - ConfPIDValuePartOne.value)) { - HistRegistry.fill(HIST("Particle1/hPt"), part.pt()); - HistRegistry.fill(HIST("Particle1/hEta"), part.eta()); - HistRegistry.fill(HIST("Particle1/hPhi"), part.phi()); - } + HistRegistry.fill(HIST("Particle1/hPt"), part.pt()); + HistRegistry.fill(HIST("Particle1/hEta"), part.eta()); + HistRegistry.fill(HIST("Particle1/hPhi"), part.phi()); } /// QA for particle 2 /// skip QA if particle 1 & 2 are the same if (ConfIsSame.value == false) { for (auto& part : GroupPartsTwo) { - /// check PID of particle 1 using function from FemtoUtils using PID bit - if (isFullPIDSelected(part.pidcut(), - part.p(), - ConfPIDThreshold.value, - ConfPIDPartTwo.value, - ConfNspecies.value, - ConfTrkPIDnSigmaMax.value, - ConfPIDValuePartTwo.value, - ConfPIDValuePartTwo.value)) { - HistRegistry.fill(HIST("Particle2/hPt"), part.pt()); - HistRegistry.fill(HIST("Particle2/hEta"), part.eta()); - HistRegistry.fill(HIST("Particle2/hPhi"), part.phi()); - } + HistRegistry.fill(HIST("Particle2/hPt"), part.pt()); + HistRegistry.fill(HIST("Particle2/hEta"), part.eta()); + HistRegistry.fill(HIST("Particle2/hPhi"), part.phi()); } } diff --git a/Tutorials/PWGCF/FemtoFramework/src/CFTutorialTask5.cxx b/Tutorials/PWGCF/FemtoFramework/src/CFTutorialTask5.cxx index f7c0c4a815a..d9159c2e3cc 100644 --- a/Tutorials/PWGCF/FemtoFramework/src/CFTutorialTask5.cxx +++ b/Tutorials/PWGCF/FemtoFramework/src/CFTutorialTask5.cxx @@ -51,22 +51,21 @@ struct CFTutorialTask5 { Configurable ConfIsSame{"ConfIsSame", false, "Pairs of the same particle"}; Configurable ConfPDGCodePartOne{"ConfPDGCodePartOne", 2212, "Particle 1 - PDG code"}; - Configurable ConfCutPartOne{"ConfCutPartOne", 3191978, "Particle 1 - Selection bit from cutCulator"}; - Configurable ConfPIDPartOne{"ConfPIDPartOne", 0, "Particle 1 - Index in ConfTrkPIDspecies of producer task"}; - Configurable ConfPIDValuePartOne{"ConfPIDValuePartOne", 3, "Particle 1 - Read from cutCulator"}; + Configurable ConfCutPartOne{"ConfCutPartOne", 3191978, "Particle 1 - Selection bit"}; + Configurable ConfPIDTPCPartOne{"ConfPIDTPCPartOne", 2, "Particle 1 - TPC PID Selection bit"}; + Configurable ConfPIDTPCTOFPartOne{"ConfPIDTPCTOFPartOne", 4, "Particle 1 - TPCTOF PID Selection bit"}; + Configurable ConfPIDThresholdPartOne{"ConfPIDThresholdPartOne", 0.75, "Particle 1 - Momentum threshold for TPC to TPCTOF PID"}; Configurable ConfPDGCodePartTwo{"ConfPDGCodePartTwo", 2212, "Particle 2 - PDG code"}; Configurable ConfCutPartTwo{"ConfCutPartTwo", 3191978, "Particle 2 - Selection bit"}; - Configurable ConfPIDPartTwo{"ConfPIDPartTwo", 0, "Particle 2 - Index in ConfTrkPIDspecies of producer task"}; - Configurable ConfPIDValuePartTwo{"ConfPIDValuePartTwo", 3, "Particle 1 - Read from cutCulator"}; - - Configurable ConfPIDThreshold{"ConfPIDThreshold", 0.75, "Momentum threshold for TPC to TPCTOF PID"}; - Configurable ConfNspecies{"ConfNspecies", 2, "Number of particle spieces with PID info"}; - Configurable> ConfTrkPIDnSigmaMax{"ConfTrkPIDnSigmaMax", std::vector{3.f, 3.5f, 2.5f}, "This configurable needs to be the same as the one used in the producer task"}; + Configurable ConfPIDTPCPartTwo{"ConfPIDTPCPartTwo", 0, "Particle 2 - TPC PID Selection bit"}; + Configurable ConfPIDTPCTOFPartTwo{"ConfPIDTPCTOFPartTwo", 0, "Particle 2 - TPCTOF PID Selection bit"}; + Configurable ConfPIDThresholdPartTwo{"ConfPIDThresholdPartTwo", 0.75, "Particle 2 - Momentum threshold for TPC to TPCTOF PID"}; /// Partitions for particle 1 and particle 2 - Partition PartsOne = (aod::femtodreamparticle::partType == uint8_t(aod::femtodreamparticle::ParticleType::kTrack)) && ((aod::femtodreamparticle::cut & ConfCutPartOne) == ConfCutPartOne); - Partition PartsTwo = (aod::femtodreamparticle::partType == uint8_t(aod::femtodreamparticle::ParticleType::kTrack)) && ((aod::femtodreamparticle::cut & ConfCutPartTwo) == ConfCutPartTwo); + Partition PartsOne = (aod::femtodreamparticle::partType == uint8_t(aod::femtodreamparticle::ParticleType::kTrack)) && ((aod::femtodreamparticle::cut & ConfCutPartOne) == ConfCutPartOne) && ifnode(aod::femtodreamparticle::pt < ConfPIDThresholdPartOne, ncheckbit(aod::femtodreamparticle::pidcut, ConfPIDTPCPartOne), ncheckbit(aod::femtodreamparticle::pidcut, ConfPIDTPCTOFPartOne)); + + Partition PartsTwo = (aod::femtodreamparticle::partType == uint8_t(aod::femtodreamparticle::ParticleType::kTrack)) && ((aod::femtodreamparticle::cut & ConfCutPartTwo) == ConfCutPartTwo) && ifnode(aod::femtodreamparticle::pt < ConfPIDThresholdPartTwo, ncheckbit(aod::femtodreamparticle::pidcut, ConfPIDTPCPartTwo), ncheckbit(aod::femtodreamparticle::pidcut, ConfPIDTPCTOFPartTwo)); HistogramRegistry HistRegistry{"FemtoTutorial", {}, OutputObjHandlingPolicy::AnalysisObject}; @@ -104,7 +103,6 @@ struct CFTutorialTask5 { // process same event void process(FilteredFDCollision const& col, FilteredFDParts const& /*parts*/) { - /// event QA HistRegistry.fill(HIST("Event/hZvtx"), col.posZ()); @@ -114,94 +112,36 @@ struct CFTutorialTask5 { /// QA for particle 1 for (auto& part : GroupPartsOne) { - /// check PID of particle 1 using function from FemtoUtils using PID bit - if (isFullPIDSelected(part.pidcut(), - part.p(), - ConfPIDThreshold.value, - ConfPIDPartOne.value, - ConfNspecies.value, - ConfTrkPIDnSigmaMax.value, - ConfPIDValuePartOne.value, - ConfPIDValuePartOne.value)) { - HistRegistry.fill(HIST("Particle1/hPt"), part.pt()); - HistRegistry.fill(HIST("Particle1/hEta"), part.eta()); - HistRegistry.fill(HIST("Particle1/hPhi"), part.phi()); - } + HistRegistry.fill(HIST("Particle1/hPt"), part.pt()); + HistRegistry.fill(HIST("Particle1/hEta"), part.eta()); + HistRegistry.fill(HIST("Particle1/hPhi"), part.phi()); } /// QA for particle 2 /// skip QA if particle 1 & 2 are the same if (ConfIsSame.value == false) { for (auto& part : GroupPartsTwo) { - /// check PID of particle 1 using function from FemtoUtils using PID bit - if (isFullPIDSelected(part.pidcut(), - part.p(), - ConfPIDThreshold.value, - ConfPIDPartTwo.value, - ConfNspecies.value, - ConfTrkPIDnSigmaMax.value, - ConfPIDValuePartTwo.value, - ConfPIDValuePartTwo.value)) { - HistRegistry.fill(HIST("Particle2/hPt"), part.pt()); - HistRegistry.fill(HIST("Particle2/hEta"), part.eta()); - HistRegistry.fill(HIST("Particle2/hPhi"), part.phi()); - } + HistRegistry.fill(HIST("Particle2/hPt"), part.pt()); + HistRegistry.fill(HIST("Particle2/hEta"), part.eta()); + HistRegistry.fill(HIST("Particle2/hPhi"), part.phi()); } } float kstar = 0.; - float m0 = TDatabasePDG::Instance()->GetParticle(ConfPDGCodePartOne.value)->Mass(); - float m1 = TDatabasePDG::Instance()->GetParticle(ConfPDGCodePartTwo.value)->Mass(); + float m0 = o2::analysis::femtoDream::getMass(ConfPDGCodePartOne); + float m1 = o2::analysis::femtoDream::getMass(ConfPDGCodePartTwo); /// particle combinations /// if particles are the same or not determines the combination stratety if (ConfIsSame) { for (auto& [p0, p1] : combinations(soa::CombinationsStrictlyUpperIndexPolicy(GroupPartsOne, GroupPartsTwo))) { - if (isFullPIDSelected(p0.pidcut(), - p0.p(), - ConfPIDThreshold.value, - ConfPIDPartOne.value, - ConfNspecies.value, - ConfTrkPIDnSigmaMax.value, - ConfPIDValuePartOne.value, - ConfPIDValuePartOne.value) && - isFullPIDSelected(p1.pidcut(), - p1.p(), - ConfPIDThreshold.value, - ConfPIDPartOne.value, - ConfNspecies.value, - ConfTrkPIDnSigmaMax.value, - ConfPIDValuePartOne.value, - ConfPIDValuePartOne.value) - - ) { - kstar = FemtoDreamMath::getkstar(p0, m0, p1, m1); - HistRegistry.fill(HIST("Pair/hSE"), kstar); - } + kstar = FemtoDreamMath::getkstar(p0, m0, p1, m1); + HistRegistry.fill(HIST("Pair/hSE"), kstar); } } else { for (auto& [p0, p1] : combinations(soa::CombinationsFullIndexPolicy(GroupPartsOne, GroupPartsTwo))) { - if (isFullPIDSelected(p0.pidcut(), - p0.p(), - ConfPIDThreshold.value, - ConfPIDPartOne.value, - ConfNspecies.value, - ConfTrkPIDnSigmaMax.value, - ConfPIDValuePartOne.value, - ConfPIDValuePartOne.value) && - isFullPIDSelected(p1.pidcut(), - p1.p(), - ConfPIDThreshold.value, - ConfPIDPartOne.value, - ConfNspecies.value, - ConfTrkPIDnSigmaMax.value, - ConfPIDValuePartOne.value, - ConfPIDValuePartOne.value) - - ) { - kstar = FemtoDreamMath::getkstar(p0, m0, p1, m1); - HistRegistry.fill(HIST("Pair/hSE"), kstar); - } + kstar = FemtoDreamMath::getkstar(p0, m0, p1, m1); + HistRegistry.fill(HIST("Pair/hSE"), kstar); } } } diff --git a/Tutorials/PWGHF/run_task.sh b/Tutorials/PWGHF/run_task.sh index 529ef5de7f0..73c1c014930 100644 --- a/Tutorials/PWGHF/run_task.sh +++ b/Tutorials/PWGHF/run_task.sh @@ -43,7 +43,7 @@ o2-analysis-pid-tof-full $OPTIONS | \ o2-analysis-ft0-corrected-table $OPTIONS | \ o2-analysis-bc-converter $OPTIONS | \ o2-analysis-tracks-extra-converter $OPTIONS | \ -o2-analysis-multiplicity-table $OPTIONS \ +o2-analysis-zdc-converter $OPTIONS \ > "$LOGFILE" 2>&1 # report status diff --git a/Tutorials/PWGLF/Resonance/CMakeLists.txt b/Tutorials/PWGLF/Resonance/CMakeLists.txt index 36c4b84bf28..6adf9fb3247 100644 --- a/Tutorials/PWGLF/Resonance/CMakeLists.txt +++ b/Tutorials/PWGLF/Resonance/CMakeLists.txt @@ -24,3 +24,23 @@ o2physics_add_dpl_workflow(resonances-step2 SOURCES resonances_step2.cxx PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME AnalysisTutorial) + +o2physics_add_dpl_workflow(resonances-step3 + SOURCES resonances_step3.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore + COMPONENT_NAME AnalysisTutorial) + +o2physics_add_dpl_workflow(resonances-step4 + SOURCES resonances_step4.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore + COMPONENT_NAME AnalysisTutorial) + +o2physics_add_dpl_workflow(resonances-step5 + SOURCES resonances_step5.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore + COMPONENT_NAME AnalysisTutorial) + +o2physics_add_dpl_workflow(resonances-step6 + SOURCES resonances_step6.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore + COMPONENT_NAME AnalysisTutorial) diff --git a/Tutorials/PWGLF/Resonance/README.md b/Tutorials/PWGLF/Resonance/README.md index 7e1433bb8bb..19d51c0eced 100644 --- a/Tutorials/PWGLF/Resonance/README.md +++ b/Tutorials/PWGLF/Resonance/README.md @@ -1,6 +1,6 @@ # This is the base for the PWGLF tutorials for the O2AT -The tutorial (6-10 Nov 2023) can be still used and is a reference for the LF analyses. +The tutorial can be still used and is a reference for the LF Resonance analyses. It is built as a set of steps. Each step adds a level of complexity and is built in a separate executable. The executables are defined in the `CMakeLists.txt`. @@ -8,3 +8,9 @@ The executables are defined in the `CMakeLists.txt`. * `README.md` this readme * `CMakeLists.txt` here are defined the source files to compile * `resonance_step0.cxx` Read the resonance table and run basic track loop +* `resonance_step1.cxx` Producing same event invariant mass distribution +* `resonance_step2.cxx` Producing Mixed event invariant mass distribution +* `resonance_step3.cxx` Starting point for MC: loop over all Generated MC particles +* `resonance_step4.cxx` Producing histograms (pt distributions etc.) for Generated MCs +* `resonance_step5.cxx` Loop over all MC Tracks and produce basic QA histograms +* `resonance_step6.cxx` Resonance reconstruction diff --git a/Tutorials/PWGLF/Resonance/resonances_step3.cxx b/Tutorials/PWGLF/Resonance/resonances_step3.cxx new file mode 100644 index 00000000000..f2ef8dbbe67 --- /dev/null +++ b/Tutorials/PWGLF/Resonance/resonances_step3.cxx @@ -0,0 +1,77 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. +/// +/// \brief this is a starting point for the Resonances tutorial for MC part +/// \author Hirak Kumar Koley +/// \since 11/10/2024 + +#include "CommonConstants/PhysicsConstants.h" +#include "Framework/AnalysisTask.h" +#include "Framework/ASoAHelpers.h" +#include "Framework/runDataProcessing.h" +#include "PWGLF/DataModel/LFResonanceTables.h" + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; + +// STEP 3 +// Starting point for MC: loop over all Generated MC particles +struct resonances_tutorial { + HistogramRegistry histos{"histos", {}, OutputObjHandlingPolicy::AnalysisObject}; + + // Configurable for number of bins + Configurable nBins{"nBins", 100, "N bins in all histos"}; + // Configurable for min pT cut + Configurable cMinPtcut{"cMinPtcut", 0.15, "Track minimum pt cut"}; + + // Initialize the ananlysis task + void init(o2::framework::InitContext&) + { + // register histograms + histos.add("hVertexZ", "hVertexZ", HistType::kTH1F, {{nBins, -15., 15.}}); + histos.add("hEta", "Eta distribution", kTH1F, {{200, -1.0f, 1.0f}}); + } + + // MC particle selection + template + bool ptCut(const ParticleType resoParents) + { + // basic pt cuts + if (std::abs(resoParents.pt()) < cMinPtcut) + return false; + + return true; + } + + // Fill histograms (main function) + template + void fillHistograms(const CollisionType& /*collision*/, const ParticleType& resoParents) + { + for (auto part : resoParents) { // loop over all resoParents + if (!ptCut(part)) + continue; // pt selection + + // QA plots + histos.fill(HIST("hEta"), part.eta()); + } + } + + // Process the MC + void process(aod::ResoCollision& collision, aod::ResoMCParents& resoParents) + { + // Fill the event counter + histos.fill(HIST("hVertexZ"), collision.posZ()); + fillHistograms(collision, resoParents); // Fill histograms, MC + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { return WorkflowSpec{adaptAnalysisTask(cfgc)}; } diff --git a/Tutorials/PWGLF/Resonance/resonances_step4.cxx b/Tutorials/PWGLF/Resonance/resonances_step4.cxx new file mode 100644 index 00000000000..05f7b35f7cf --- /dev/null +++ b/Tutorials/PWGLF/Resonance/resonances_step4.cxx @@ -0,0 +1,109 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. +/// +/// \brief this is a starting point for the Resonances tutorial for MC +/// \author Hirak Kumar Koley +/// \since 11/10/2024 + +#include "CommonConstants/PhysicsConstants.h" +#include "Framework/AnalysisTask.h" +#include "Framework/ASoAHelpers.h" +#include "Framework/runDataProcessing.h" +#include "PWGLF/DataModel/LFResonanceTables.h" + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; + +// STEP 4 +// Producing histograms for Generated MCs +struct resonances_tutorial { + HistogramRegistry histos{"histos", {}, OutputObjHandlingPolicy::AnalysisObject}; + + // Configurable for number of bins + Configurable nBins{"nBins", 100, "N bins in all histos"}; + // Configurable for min pT cut + Configurable cMinPtcut{"cMinPtcut", 0.15, "Track minium pt cut"}; + + /// Histograms + ConfigurableAxis binsPt{"binsPt", {VARIABLE_WIDTH, 0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 2.0, 2.1, 2.2, 2.3, 2.4, 2.5, 2.6, 2.7, 2.8, 2.9, 3.0, 3.1, 3.2, 3.3, 3.4, 3.5, 3.6, 3.7, 3.8, 3.9, 4.0, 4.1, 4.2, 4.3, 4.4, 4.5, 4.6, 4.7, 4.8, 4.9, 5.0, 5.1, 5.2, 5.3, 5.4, 5.5, 5.6, 5.7, 5.8, 5.9, 6.0, 6.1, 6.2, 6.3, 6.4, 6.5, 6.6, 6.7, 6.8, 6.9, 7.0, 7.1, 7.2, 7.3, 7.4, 7.5, 7.6, 7.7, 7.8, 7.9, 8.0, 8.1, 8.2, 8.3, 8.4, 8.5, 8.6, 8.7, 8.8, 8.9, 9.0, 9.1, 9.2, 9.3, 9.4, 9.5, 9.6, 9.7, 9.8, 9.9, 10.0, 10.1, 10.2, 10.3, 10.4, 10.5, 10.6, 10.7, 10.8, 10.9, 11.0, 11.1, 11.2, 11.3, 11.4, 11.5, 11.6, 11.7, 11.8, 11.9, 12.0, 12.1, 12.2, 12.3, 12.4, 12.5, 12.6, 12.7, 12.8, 12.9, 13.0, 13.1, 13.2, 13.3, 13.4, 13.5, 13.6, 13.7, 13.8, 13.9, 14.0, 14.1, 14.2, 14.3, 14.4, 14.5, 14.6, 14.7, 14.8, 14.9, 15.0}, "Binning of the pT axis"}; + ConfigurableAxis binsCent{"binsCent", {VARIABLE_WIDTH, 0., 1., 5., 10., 30., 50., 70., 100., 110.}, "Binning of the centrality axis"}; + + // Initialize the ananlysis task + void init(o2::framework::InitContext&) + { + AxisSpec centAxis = {binsCent, "V0M (%)"}; + AxisSpec ptAxis = {binsPt, "#it{p}_{T} (GeV/#it{c})"}; + + // register histograms + histos.add("hVertexZ", "hVertexZ", HistType::kTH1F, {{nBins, -15., 15.}}); + histos.add("hEta", "Eta distribution", kTH1F, {{200, -1.0f, 1.0f}}); + histos.add("hMultiplicityPercent", "Multiplicity Percentile", kTH1F, {{120, 0.0f, 120.0f}}); + + // MC QA + histos.add("hphipt", "pT distribution of True MC phi", kTH1F, {ptAxis}); + histos.add("phiGen", "pT distribution of True MC phi", kTH2F, {ptAxis, centAxis}); + + // Print output histograms statistics + LOG(info) << "Size of the histograms in resonance tutorial step1:"; + histos.print(); + } + + // MC particle selection + template + bool ptCut(const ParticleType resoParents) + { + // basic pt cuts + if (std::abs(resoParents.pt()) < cMinPtcut) + return false; + + return true; + } + + // Fill histograms (main function) + template + void fillHistograms(const CollisionType& collision, const ParticleType& resoParents) + { + auto multiplicity = collision.cent(); + for (auto& part : resoParents) { // loop over all pre-filtered MC particles + if (!ptCut(part)) + continue; // pt selection + + // QA plots + histos.fill(HIST("hEta"), part.eta()); + + if (abs(part.pdgCode()) != 333) // phi(0) + continue; + if (abs(part.y()) > 0.5) { // rapidity cut + continue; + } + if (abs(part.daughterPDG1()) != 321 || abs(part.daughterPDG2()) != 321) { // At least one decay to Kaon + continue; + } + histos.fill(HIST("phiGen"), part.pt(), multiplicity); + histos.fill(HIST("hphipt"), part.pt()); + } + } + + // Process the MC + void process(aod::ResoCollision& collision, aod::ResoMCParents& resoParents) + { + auto multiplicity = collision.cent(); + + // Fill the event counter + histos.fill(HIST("hVertexZ"), collision.posZ()); + histos.fill(HIST("hMultiplicityPercent"), multiplicity); + + fillHistograms(collision, resoParents); // Fill histograms, MC + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { return WorkflowSpec{adaptAnalysisTask(cfgc)}; } diff --git a/Tutorials/PWGLF/Resonance/resonances_step5.cxx b/Tutorials/PWGLF/Resonance/resonances_step5.cxx new file mode 100644 index 00000000000..7d8463b9236 --- /dev/null +++ b/Tutorials/PWGLF/Resonance/resonances_step5.cxx @@ -0,0 +1,136 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. +/// +/// \brief this is a starting point for the Resonances tutorial +/// \author Hirak Kumar Koley +/// \since 11/10/2024 + +#include "CommonConstants/PhysicsConstants.h" +#include "Framework/AnalysisTask.h" +#include "Framework/ASoAHelpers.h" +#include "Framework/runDataProcessing.h" +#include "PWGLF/DataModel/LFResonanceTables.h" + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; + +// STEP 5 +// loop over all MC Tracks and produce basic QA histograms +struct resonances_tutorial { + // Define slice per Resocollision + SliceCache cache; + Preslice perResoCollision = aod::resodaughter::resoCollisionId; + Preslice perCollision = aod::track::collisionId; + + HistogramRegistry histos{"histos", {}, OutputObjHandlingPolicy::AnalysisObject}; + + // Configurable for number of bins + Configurable nBins{"nBins", 100, "N bins in all histos"}; + // Configurable for min pT cut + Configurable cMinPtcut{"cMinPtcut", 0.15, "Track minium pt cut"}; + + // Track selection + // primary track condition + 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 + + // DCA Selections + // DCAr to PV + Configurable cMaxDCArToPVcut{"cMaxDCArToPVcut", 0.5, "Track DCAr cut to PV Maximum"}; + // DCAz to PV + Configurable cMaxDCAzToPVcut{"cMaxDCAzToPVcut", 2.0, "Track DCAz cut to PV Maximum"}; + + // PID selection + Configurable nsigmaCutTPC{"nsigmacutTPC", 3.0, "Value of the TPC Nsigma cut"}; + Configurable nsigmacutTOF{"nsigmacutTOF", 3.0, "Value /home/hirak/Desktop/LstarTaskTest/run/dpl-config.jsonof the TOF Nsigma cut"}; + + // Initialize the ananlysis task + void init(o2::framework::InitContext&) + { + // register histograms + histos.add("hVertexZ", "hVertexZ", HistType::kTH1F, {{nBins, -15., 15.}}); + histos.add("hEta", "Eta distribution", kTH1F, {{200, -1.0f, 1.0f}}); + histos.add("hMultiplicityPercent", "Multiplicity Percentile", kTH1F, {{120, 0.0f, 120.0f}}); + histos.add("hDcaxy", "Dcaxy distribution", kTH1F, {{100, -0.5f, 0.5f}}); + histos.add("hDcaz", "Dcaz distribution", kTH1F, {{100, -0.5f, 0.5f}}); + histos.add("hNsigmaKaonTPC", "NsigmaKaon TPC distribution", kTH1F, {{100, -10.0f, 10.0f}}); + histos.add("hNsigmaKaonTOF", "NsigmaKaon TOF distribution", kTH1F, {{100, -10.0f, 10.0f}}); + + // Print output histograms statistics + LOG(info) << "Size of the histograms in resonance tutorial step2:"; + histos.print(); + } + + // Track selection + template + bool trackCut(const TrackType track) + { + // 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 (cfgPrimaryTrack && !track.isPrimaryTrack()) + return false; + if (cfgGlobalWoDCATrack && !track.isGlobalTrackWoDCA()) + return false; + if (cfgPVContributor && !track.isPVContributor()) + return false; + return true; + } + + // PID selection TPC +TOF Veto + template + bool selectionPID(const T& candidate) + { + bool tpcPass = std::abs(candidate.tpcNSigmaKa()) < nsigmaCutTPC; + bool tofPass = (candidate.hasTOF()) ? std::abs(candidate.tofNSigmaKa()) < nsigmacutTOF : true; + if (tpcPass && tofPass) { + return true; + } + return false; + } + + template + void fillHistograms(const CollisionType& /* collision */, const TracksType& dTracks) + { + for (auto track : dTracks) { // loop over all dTracks + if (!trackCut(track) || !selectionPID(track)) { + continue; // track selection and PID selection + } + // QA plots + histos.fill(HIST("hEta"), track.eta()); + histos.fill(HIST("hDcaxy"), track.dcaXY()); + histos.fill(HIST("hDcaz"), track.dcaZ()); + histos.fill(HIST("hNsigmaKaonTPC"), track.tpcNSigmaKa()); + if (track.hasTOF()) { + histos.fill(HIST("hNsigmaKaonTOF"), track.tofNSigmaKa()); + } + } + } + + // Process the data + void process(aod::ResoCollision& collision, + soa::Join const& resotracks) + { + // Fill the event counter + histos.fill(HIST("hVertexZ"), collision.posZ()); + histos.fill(HIST("hMultiplicityPercent"), collision.cent()); + + fillHistograms(collision, resotracks); + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { return WorkflowSpec{adaptAnalysisTask(cfgc)}; } diff --git a/Tutorials/PWGLF/Resonance/resonances_step6.cxx b/Tutorials/PWGLF/Resonance/resonances_step6.cxx new file mode 100644 index 00000000000..23ccac6dfd2 --- /dev/null +++ b/Tutorials/PWGLF/Resonance/resonances_step6.cxx @@ -0,0 +1,188 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. +/// +/// \brief this is a starting point for the Resonances tutorial +/// \author Hirak Kumar Koley +/// \since 11/10/2024 + +#include + +#include "CommonConstants/PhysicsConstants.h" +#include "Framework/AnalysisTask.h" +#include "Framework/ASoAHelpers.h" +#include "Framework/runDataProcessing.h" +#include "PWGLF/DataModel/LFResonanceTables.h" + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; + +// STEP 6 +// Resonance reconstruction +struct resonances_tutorial { + // Define slice per Resocollision + SliceCache cache; + Preslice perResoCollision = aod::resodaughter::resoCollisionId; + Preslice perCollision = aod::track::collisionId; + + HistogramRegistry histos{"histos", {}, OutputObjHandlingPolicy::AnalysisObject}; + + ///// Configurables + /// Histograms + ConfigurableAxis binsPt{"binsPt", {VARIABLE_WIDTH, 0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 2.0, 2.1, 2.2, 2.3, 2.4, 2.5, 2.6, 2.7, 2.8, 2.9, 3.0, 3.1, 3.2, 3.3, 3.4, 3.5, 3.6, 3.7, 3.8, 3.9, 4.0, 4.1, 4.2, 4.3, 4.4, 4.5, 4.6, 4.7, 4.8, 4.9, 5.0, 5.1, 5.2, 5.3, 5.4, 5.5, 5.6, 5.7, 5.8, 5.9, 6.0, 6.1, 6.2, 6.3, 6.4, 6.5, 6.6, 6.7, 6.8, 6.9, 7.0, 7.1, 7.2, 7.3, 7.4, 7.5, 7.6, 7.7, 7.8, 7.9, 8.0, 8.1, 8.2, 8.3, 8.4, 8.5, 8.6, 8.7, 8.8, 8.9, 9.0, 9.1, 9.2, 9.3, 9.4, 9.5, 9.6, 9.7, 9.8, 9.9, 10.0, 10.1, 10.2, 10.3, 10.4, 10.5, 10.6, 10.7, 10.8, 10.9, 11.0, 11.1, 11.2, 11.3, 11.4, 11.5, 11.6, 11.7, 11.8, 11.9, 12.0, 12.1, 12.2, 12.3, 12.4, 12.5, 12.6, 12.7, 12.8, 12.9, 13.0, 13.1, 13.2, 13.3, 13.4, 13.5, 13.6, 13.7, 13.8, 13.9, 14.0, 14.1, 14.2, 14.3, 14.4, 14.5, 14.6, 14.7, 14.8, 14.9, 15.0}, "Binning of the pT axis"}; + ConfigurableAxis binsCent{"binsCent", {VARIABLE_WIDTH, 0., 1., 5., 10., 30., 50., 70., 100., 110.}, "Binning of the centrality axis"}; + Configurable cInvMassStart{"cInvMassStart", 0.6, "Invariant mass start"}; + Configurable cInvMassEnd{"cInvMassEnd", 1.5, "Invariant mass end"}; + Configurable cInvMassBins{"cInvMassBins", 900, "Invariant mass binning"}; + + // Configurable for number of bins + Configurable nBins{"nBins", 100, "N bins in all histos"}; + // Configurable for min pT cut + Configurable cMinPtcut{"cMinPtcut", 0.15, "Track minium pt cut"}; + + // Track selection + // primary track condition + 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 + + // DCA Selections + // DCAr to PV + Configurable cMaxDCArToPVcut{"cMaxDCArToPVcut", 0.5, "Track DCAr cut to PV Maximum"}; + // DCAz to PV + Configurable cMaxDCAzToPVcut{"cMaxDCAzToPVcut", 2.0, "Track DCAz cut to PV Maximum"}; + + // PID selection + Configurable nsigmaCutTPC{"nsigmacutTPC", 3.0, "Value of the TPC Nsigma cut"}; + Configurable nsigmacutTOF{"nsigmacutTOF", 3.0, "Value of the TOF Nsigma cut"}; + + // variables + double massKa = o2::constants::physics::MassKPlus; + + // Initialize the ananlysis task + void init(o2::framework::InitContext&) + { + AxisSpec centAxis = {binsCent, "V0M (%)"}; + AxisSpec ptAxis = {binsPt, "#it{p}_{T} (GeV/#it{c})"}; + AxisSpec invMassAxis = {cInvMassBins, cInvMassStart, cInvMassEnd, "Invariant Mass (GeV/#it{c}^2)"}; + + // register histograms + histos.add("hVertexZ", "hVertexZ", HistType::kTH1F, {{nBins, -15., 15.}}); + histos.add("hEta", "Eta distribution", kTH1F, {{200, -1.0f, 1.0f}}); + histos.add("hMultiplicityPercent", "Multiplicity Percentile", kTH1F, {{120, 0.0f, 120.0f}}); + histos.add("hDcaxy", "Dcaxy distribution", kTH1F, {{100, -0.5f, 0.5f}}); + histos.add("hDcaz", "Dcaz distribution", kTH1F, {{100, -0.5f, 0.5f}}); + histos.add("hNsigmaKaonTPC", "NsigmaKaon TPC distribution", kTH1F, {{100, -10.0f, 10.0f}}); + histos.add("hNsigmaKaonTOF", "NsigmaKaon TOF distribution", kTH1F, {{100, -10.0f, 10.0f}}); + + // MC QA + histos.add("h3Recphiinvmass", "Invariant mass of Reconstructed MC phi", kTH3F, {centAxis, ptAxis, invMassAxis}); + histos.add("phiRec", "pT distribution of Reconstructed MC phi", kTH2F, {ptAxis, centAxis}); + histos.add("phiRecinvmass", "Inv mass distribution of Reconstructed MC Phi", kTH1F, {invMassAxis}); + + // Print output histograms statistics + LOG(info) << "Size of the histograms in resonance tutorial step2:"; + histos.print(); + } + + // Track selection + template + bool trackCut(const TrackType track) + { + // 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 (cfgPrimaryTrack && !track.isPrimaryTrack()) + return false; + if (cfgGlobalWoDCATrack && !track.isGlobalTrackWoDCA()) + return false; + if (cfgPVContributor && !track.isPVContributor()) + return false; + return true; + } + + // PID selection TPC +TOF Veto + template + bool selectionPID(const T& candidate) + { + bool tpcPass = std::abs(candidate.tpcNSigmaKa()) < nsigmaCutTPC; + bool tofPass = (candidate.hasTOF()) ? std::abs(candidate.tofNSigmaKa()) < nsigmacutTOF : true; + if (tpcPass && tofPass) { + return true; + } + return false; + } + + // Fill histograms (main function) + double rapidity, mass, pT, paircharge; + TLorentzVector daughter1, daughter2, lResonance; + template + void fillHistograms(const CollisionType& collision, const TracksType& dTracks1, const TracksType& dTracks2) + { + auto multiplicity = collision.cent(); + for (auto track1 : dTracks1) { // loop over all dTracks1 + if (!trackCut(track1) || !selectionPID(track1)) { + continue; // track selection and PID selection + } + // QA plots + histos.fill(HIST("hEta"), track1.eta()); + histos.fill(HIST("hDcaxy"), track1.dcaXY()); + histos.fill(HIST("hDcaz"), track1.dcaZ()); + histos.fill(HIST("hNsigmaKaonTPC"), track1.tpcNSigmaKa()); + if (track1.hasTOF()) { + histos.fill(HIST("hNsigmaKaonTOF"), track1.tofNSigmaKa()); + } + for (auto track2 : dTracks2) { // loop over all dTracks2 + if (!trackCut(track2) || !selectionPID(track2)) { + continue; // track selection and PID selection + } + if (track2.index() <= track1.index()) { + continue; // condition to avoid double counting of pair + } + daughter1.SetXYZM(track1.px(), track1.py(), track1.pz(), massKa); // set the daughter1 4-momentum + daughter2.SetXYZM(track2.px(), track2.py(), track2.pz(), massKa); // set the daughter2 4-momentum + lResonance = daughter1 + daughter2; // calculate the lResonance 4-momentum + mass = lResonance.M(); + pT = lResonance.Pt(); + rapidity = lResonance.Rapidity(); + + if (abs(track1.pdgCode()) != 321 || abs(track2.pdgCode()) != 321) + continue; + if (track1.motherId() != track2.motherId()) // Same mother + continue; + if (abs(track1.motherPDG()) != 333) + continue; + + // MC histograms + histos.fill(HIST("phiRec"), lResonance.Pt(), multiplicity); + histos.fill(HIST("phiRecinvmass"), lResonance.M()); + histos.fill(HIST("h3Recphiinvmass"), multiplicity, lResonance.Pt(), lResonance.M()); + } + } + } + + // Process the data + void process(aod::ResoCollision& collision, + soa::Join const& resotracks) + { + // Fill the event counter + histos.fill(HIST("hVertexZ"), collision.posZ()); + histos.fill(HIST("hMultiplicityPercent"), collision.cent()); + + fillHistograms(collision, resotracks, resotracks); + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { return WorkflowSpec{adaptAnalysisTask(cfgc)}; } diff --git a/Tutorials/PWGLF/Strangeness/CMakeLists.txt b/Tutorials/PWGLF/Strangeness/CMakeLists.txt index ede23b4c734..39734cb836a 100644 --- a/Tutorials/PWGLF/Strangeness/CMakeLists.txt +++ b/Tutorials/PWGLF/Strangeness/CMakeLists.txt @@ -9,28 +9,6 @@ # granted to it by virtue of its status as an Intergovernmental Organization # or submit itself to any jurisdiction. -# Strangeness analysis tutorial -o2physics_add_dpl_workflow(strangeness-step0 - SOURCES strangeness_step0.cxx - PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore - COMPONENT_NAME AnalysisTutorial) +add_subdirectory(pp) +add_subdirectory(PbPb) -o2physics_add_dpl_workflow(strangeness-step1 - SOURCES strangeness_step1.cxx - PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore - COMPONENT_NAME AnalysisTutorial) - -o2physics_add_dpl_workflow(strangeness-step2 - SOURCES strangeness_step2.cxx - PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore - COMPONENT_NAME AnalysisTutorial) - -o2physics_add_dpl_workflow(strangeness-step3 - SOURCES strangeness_step3.cxx - PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore - COMPONENT_NAME AnalysisTutorial) - -o2physics_add_dpl_workflow(strangeness-step4 - SOURCES strangeness_step4.cxx - PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore - COMPONENT_NAME AnalysisTutorial) diff --git a/Tutorials/PWGLF/Strangeness/PbPb/Analysis/CMakeLists.txt b/Tutorials/PWGLF/Strangeness/PbPb/Analysis/CMakeLists.txt new file mode 100644 index 00000000000..d050dc59b47 --- /dev/null +++ b/Tutorials/PWGLF/Strangeness/PbPb/Analysis/CMakeLists.txt @@ -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. + +o2physics_add_dpl_workflow(strangeness-pbpb-skeleton + SOURCES strangeness_pbpb_skeleton.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore + COMPONENT_NAME AnalysisTutorial) + +o2physics_add_dpl_workflow(strangeness-pbpb-step0 + SOURCES strangeness_pbpb_step0.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore + COMPONENT_NAME AnalysisTutorial) + +o2physics_add_dpl_workflow(strangeness-pbpb-step1 + SOURCES strangeness_pbpb_step1.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore + COMPONENT_NAME AnalysisTutorial) + +o2physics_add_dpl_workflow(strangeness-pbpb-step2 + SOURCES strangeness_pbpb_step2.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore + COMPONENT_NAME AnalysisTutorial) + +o2physics_add_dpl_workflow(strangeness-pbpb-step3 + SOURCES strangeness_pbpb_step3.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore + COMPONENT_NAME AnalysisTutorial) + +o2physics_add_dpl_workflow(strangeness-pbpb-step4 + SOURCES strangeness_pbpb_step4.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore + COMPONENT_NAME AnalysisTutorial) + diff --git a/Tutorials/PWGLF/Strangeness/PbPb/Analysis/run_skeleton.sh b/Tutorials/PWGLF/Strangeness/PbPb/Analysis/run_skeleton.sh new file mode 100644 index 00000000000..9327402771f --- /dev/null +++ b/Tutorials/PWGLF/Strangeness/PbPb/Analysis/run_skeleton.sh @@ -0,0 +1,24 @@ +#!/bin/bash +# log file where the terminal output will be saved +STEP="skeleton" +LOGFILE="log-${STEP}.txt" + +#directory of this script +DIR_THIS=$PWD + +OPTION="-b --configuration json://configuration_skeleton.json" + +o2-analysistutorial-lf-strangeness-pbpb-skeleton "${OPTION}" --aod-file @input_data.txt > "$LOGFILE" 2>&1 + +# report status +rc=$? +if [ $rc -eq 0 ]; then + echo "No problems!" + mkdir -p "${DIR_THIS}/results/${STEP}" + mv AnalysisResults.root "${DIR_THIS}/results/${STEP}/AnalysisResults.root" + mv dpl-config.json "${DIR_THIS}/results/${STEP}/${STEP}.json" +else + echo "Error: Exit code ${rc}" + echo "Check the log file ${LOGFILE}" + exit ${rc} +fi \ No newline at end of file diff --git a/Tutorials/PWGLF/Strangeness/PbPb/Analysis/run_step0.sh b/Tutorials/PWGLF/Strangeness/PbPb/Analysis/run_step0.sh new file mode 100644 index 00000000000..bcfeb9ab890 --- /dev/null +++ b/Tutorials/PWGLF/Strangeness/PbPb/Analysis/run_step0.sh @@ -0,0 +1,24 @@ +#!/bin/bash +# log file where the terminal output will be saved +STEP="0" +LOGFILE="log-${STEP}.txt" + +#directory of this script +DIR_THIS=$PWD + +OPTION="-b --configuration json://configuration_step0.json" + +o2-analysis-lf-cascadespawner "${OPTION}" | o2-analysistutorial-lf-strangeness-pbpb-step0 "${OPTION}" --aod-file @input_data.txt > "$LOGFILE" 2>&1 + +# report status +rc=$? +if [ $rc -eq 0 ]; then + echo "No problems!" + mkdir -p "${DIR_THIS}/results/step${STEP}" + mv AnalysisResults.root "${DIR_THIS}/results/step${STEP}/AnalysisResults.root" + mv dpl-config.json "${DIR_THIS}/results/step${STEP}/step${STEP}.json" +else + echo "Error: Exit code ${rc}" + echo "Check the log file ${LOGFILE}" + exit ${rc} +fi \ No newline at end of file diff --git a/Tutorials/PWGLF/Strangeness/PbPb/Analysis/run_step1.sh b/Tutorials/PWGLF/Strangeness/PbPb/Analysis/run_step1.sh new file mode 100644 index 00000000000..826f0ea1421 --- /dev/null +++ b/Tutorials/PWGLF/Strangeness/PbPb/Analysis/run_step1.sh @@ -0,0 +1,24 @@ +#!/bin/bash +# log file where the terminal output will be saved +STEP="1" +LOGFILE="log-${STEP}.txt" + +#directory of this script +DIR_THIS=$PWD + +OPTION="-b --configuration json://configuration_step1.json" + +o2-analysis-lf-cascadespawner "${OPTION}" | o2-analysistutorial-lf-strangeness-pbpb-step1 "${OPTION}" --aod-file @input_data.txt > "$LOGFILE" 2>&1 + +# report status +rc=$? +if [ $rc -eq 0 ]; then + echo "No problems!" + mkdir -p "${DIR_THIS}/results/step${STEP}" + mv AnalysisResults.root "${DIR_THIS}/results/step${STEP}/AnalysisResults.root" + mv dpl-config.json "${DIR_THIS}/results/step${STEP}/step${STEP}.json" +else + echo "Error: Exit code ${rc}" + echo "Check the log file ${LOGFILE}" + exit ${rc} +fi \ No newline at end of file diff --git a/Tutorials/PWGLF/Strangeness/PbPb/Analysis/run_step2.sh b/Tutorials/PWGLF/Strangeness/PbPb/Analysis/run_step2.sh new file mode 100644 index 00000000000..aca62bad45e --- /dev/null +++ b/Tutorials/PWGLF/Strangeness/PbPb/Analysis/run_step2.sh @@ -0,0 +1,24 @@ +#!/bin/bash +# log file where the terminal output will be saved +STEP="2" +LOGFILE="log-${STEP}.txt" + +#directory of this script +DIR_THIS=$PWD + +OPTION="-b --configuration json://configuration_step2.json" + +o2-analysis-lf-cascadespawner "${OPTION}" | o2-analysistutorial-lf-strangeness-pbpb-step2 "${OPTION}" --aod-file @input_data.txt > "$LOGFILE" 2>&1 + +# report status +rc=$? +if [ $rc -eq 0 ]; then + echo "No problems!" + mkdir -p "${DIR_THIS}/results/step${STEP}" + mv AnalysisResults.root "${DIR_THIS}/results/step${STEP}/AnalysisResults.root" + mv dpl-config.json "${DIR_THIS}/results/step${STEP}/step${STEP}.json" +else + echo "Error: Exit code ${rc}" + echo "Check the log file ${LOGFILE}" + exit ${rc} +fi \ No newline at end of file diff --git a/Tutorials/PWGLF/Strangeness/PbPb/Analysis/run_step3.sh b/Tutorials/PWGLF/Strangeness/PbPb/Analysis/run_step3.sh new file mode 100644 index 00000000000..580b3c0c17f --- /dev/null +++ b/Tutorials/PWGLF/Strangeness/PbPb/Analysis/run_step3.sh @@ -0,0 +1,24 @@ +#!/bin/bash +# log file where the terminal output will be saved +STEP="3" +LOGFILE="log-${STEP}.txt" + +#directory of this script +DIR_THIS=$PWD + +OPTION="-b --configuration json://configuration_step3.json" + +o2-analysis-lf-cascadepid "${OPTION}" | o2-analysis-lf-cascadespawner "${OPTION}" | o2-analysistutorial-lf-strangeness-pbpb-step3 "${OPTION}" --aod-file @input_data.txt > "$LOGFILE" 2>&1 + +# report status +rc=$? +if [ $rc -eq 0 ]; then + echo "No problems!" + mkdir -p "${DIR_THIS}/results/step${STEP}" + mv AnalysisResults.root "${DIR_THIS}/results/step${STEP}/AnalysisResults.root" + mv dpl-config.json "${DIR_THIS}/results/step${STEP}/step${STEP}.json" +else + echo "Error: Exit code ${rc}" + echo "Check the log file ${LOGFILE}" + exit ${rc} +fi diff --git a/Tutorials/PWGLF/Strangeness/PbPb/Analysis/run_step4.sh b/Tutorials/PWGLF/Strangeness/PbPb/Analysis/run_step4.sh new file mode 100644 index 00000000000..08f929b3fa8 --- /dev/null +++ b/Tutorials/PWGLF/Strangeness/PbPb/Analysis/run_step4.sh @@ -0,0 +1,24 @@ +#!/bin/bash +# log file where the terminal output will be saved +STEP="4" +LOGFILE="log-${STEP}.txt" + +#directory of this script +DIR_THIS=$PWD + +OPTION="-b --configuration json://configuration_step4.json" + +o2-analysis-lf-cascadepid "${OPTION}" | o2-analysis-lf-cascadespawner "${OPTION}" | o2-analysistutorial-lf-strangeness-pbpb-step4 "${OPTION}" --aod-file @input_data.txt > "$LOGFILE" 2>&1 + +# report status +rc=$? +if [ $rc -eq 0 ]; then + echo "No problems!" + mkdir -p "${DIR_THIS}/results/step${STEP}" + mv AnalysisResults.root "${DIR_THIS}/results/step${STEP}/AnalysisResults.root" + mv dpl-config.json "${DIR_THIS}/results/step${STEP}/step${STEP}.json" +else + echo "Error: Exit code ${rc}" + echo "Check the log file ${LOGFILE}" + exit ${rc} +fi \ No newline at end of file diff --git a/Tutorials/PWGLF/Strangeness/PbPb/Analysis/strangeness_pbpb_skeleton.cxx b/Tutorials/PWGLF/Strangeness/PbPb/Analysis/strangeness_pbpb_skeleton.cxx new file mode 100644 index 00000000000..788aaead7ae --- /dev/null +++ b/Tutorials/PWGLF/Strangeness/PbPb/Analysis/strangeness_pbpb_skeleton.cxx @@ -0,0 +1,67 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does 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 Step4 of the Strangeness tutorial +/// \author Romain Schotter +/// based on the original codes from: +/// \author Nepeivoda Roman (roman.nepeivoda@cern.ch) +/// \author Chiara De Martin (chiara.de.martin@cern.ch) + +#include "Framework/runDataProcessing.h" +#include "Framework/AnalysisTask.h" +#include "Common/DataModel/EventSelection.h" +#include "PWGLF/DataModel/LFStrangenessTables.h" +#include "Framework/O2DatabasePDGPlugin.h" + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; + +struct strangeness_pbpb_tutorial { + // Histograms are defined with HistogramRegistry + HistogramRegistry rEventSelection{"eventSelection", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + + // Configurable for histograms + Configurable nBins{"nBins", 100, "N bins in all histos"}; + + // Configurable for event selection + Configurable cutzvertex{"cutzvertex", 10.0f, "Accepted z-vertex range (cm)"}; + + // PDG data base + Service pdgDB; + + void init(InitContext const&) + { + // Axes + AxisSpec vertexZAxis = {nBins, -15., 15., "vrtx_{Z} [cm]"}; + + // Histograms + // Event selection + rEventSelection.add("hVertexZRec", "hVertexZRec", {HistType::kTH1F, {vertexZAxis}}); + } + + // Defining filters for events (event selection) + // Processed events will be already fulfilling the event selection requirements + Filter eventFilter = (o2::aod::evsel::sel8 == true); + Filter posZFilter = (nabs(o2::aod::collision::posZ) < cutzvertex); + + void process(soa::Filtered>::iterator const& collision) + { + // Fill the event counter + rEventSelection.fill(HIST("hVertexZRec"), collision.posZ()); + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc)}; +} diff --git a/Tutorials/PWGLF/Strangeness/PbPb/Analysis/strangeness_pbpb_step0.cxx b/Tutorials/PWGLF/Strangeness/PbPb/Analysis/strangeness_pbpb_step0.cxx new file mode 100644 index 00000000000..b0e595246d7 --- /dev/null +++ b/Tutorials/PWGLF/Strangeness/PbPb/Analysis/strangeness_pbpb_step0.cxx @@ -0,0 +1,86 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does 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 Step4 of the Strangeness tutorial +/// \author Romain Schotter +/// based on the original codes from: +/// \author Nepeivoda Roman (roman.nepeivoda@cern.ch) +/// \author Chiara De Martin (chiara.de.martin@cern.ch) + +#include "Framework/runDataProcessing.h" +#include "Framework/AnalysisTask.h" +#include "Common/DataModel/EventSelection.h" +#include "PWGLF/DataModel/LFStrangenessTables.h" +#include "Framework/O2DatabasePDGPlugin.h" + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; + +// STEP 0 +// Starting point: loop over all cascades and fill invariant mass histogram + +struct strangeness_pbpb_tutorial { + // Histograms are defined with HistogramRegistry + HistogramRegistry rEventSelection{"eventSelection", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + HistogramRegistry rXi{"xi", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + HistogramRegistry rOmega{"omega", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + + // Configurable for histograms + Configurable nBins{"nBins", 100, "N bins in all histos"}; + + // Configurable for event selection + Configurable cutzvertex{"cutzvertex", 10.0f, "Accepted z-vertex range (cm)"}; + + // PDG data base + Service pdgDB; + + void init(InitContext const&) + { + // Axes + AxisSpec XiMassAxis = {100, 1.28f, 1.36f, "#it{M}_{inv} [GeV/#it{c}^{2}]"}; + AxisSpec OmegaMassAxis = {100, 1.63f, 1.7f, "#it{M}_{inv} [GeV/#it{c}^{2}]"}; + AxisSpec vertexZAxis = {nBins, -15., 15., "vrtx_{Z} [cm]"}; + + // Histograms + // Event selection + rEventSelection.add("hVertexZRec", "hVertexZRec", {HistType::kTH1F, {vertexZAxis}}); + + // Xi/Omega reconstruction + rXi.add("hMassXi", "hMassXi", {HistType::kTH1F, {XiMassAxis}}); + + rOmega.add("hMassOmega", "hMassOmega", {HistType::kTH1F, {OmegaMassAxis}}); + } + + // Defining filters for events (event selection) + // Processed events will be already fulfilling the event selection requirements + Filter eventFilter = (o2::aod::evsel::sel8 == true); + Filter posZFilter = (nabs(o2::aod::collision::posZ) < cutzvertex); + + void process(soa::Filtered>::iterator const& collision, + aod::CascCores const& Cascades) + { + // Fill the event counter + rEventSelection.fill(HIST("hVertexZRec"), collision.posZ()); + + // Cascades + for (const auto& casc : Cascades) { + rXi.fill(HIST("hMassXi"), casc.mXi()); + rOmega.fill(HIST("hMassOmega"), casc.mOmega()); + } + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc)}; +} diff --git a/Tutorials/PWGLF/Strangeness/PbPb/Analysis/strangeness_pbpb_step1.cxx b/Tutorials/PWGLF/Strangeness/PbPb/Analysis/strangeness_pbpb_step1.cxx new file mode 100644 index 00000000000..836be98b240 --- /dev/null +++ b/Tutorials/PWGLF/Strangeness/PbPb/Analysis/strangeness_pbpb_step1.cxx @@ -0,0 +1,146 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does 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 Step4 of the Strangeness tutorial +/// \author Romain Schotter +/// based on the original codes from: +/// \author Nepeivoda Roman (roman.nepeivoda@cern.ch) +/// \author Chiara De Martin (chiara.de.martin@cern.ch) + +#include "Framework/runDataProcessing.h" +#include "Framework/AnalysisTask.h" +#include "Common/DataModel/EventSelection.h" +#include "PWGLF/DataModel/LFStrangenessTables.h" +#include "Framework/O2DatabasePDGPlugin.h" + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; + +// STEP 0 +// Starting point: loop over all cascades and fill invariant mass histogram +// STEP 1 +// Apply selections on topological variables of Cascades + +struct strangeness_pbpb_tutorial { + // Histograms are defined with HistogramRegistry + HistogramRegistry rEventSelection{"eventSelection", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + HistogramRegistry rXi{"xi", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + HistogramRegistry rOmega{"omega", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + + // Configurable for histograms + Configurable nBins{"nBins", 100, "N bins in all histos"}; + + // Configurable for event selection + Configurable cutzvertex{"cutzvertex", 10.0f, "Accepted z-vertex range (cm)"}; + + // Configurable parameters for cascade selection + Configurable cascadesetting_cospa{"cascadesetting_cospa", 0.98, "Casc CosPA"}; + Configurable cascadesetting_v0cospa{"cascadesetting_v0cospa", 0.97, "V0 CosPA"}; + Configurable cascadesetting_dcacascdau{"cascadesetting_dcacascdau", 1.0, "DCA cascade daughters"}; + Configurable cascadesetting_dcav0dau{"cascadesetting_dcav0dau", 1.0, "DCA v0 daughters"}; + Configurable cascadesetting_dcabachtopv{"cascadesetting_dcabachtopv", 0.06, "DCA bachelor to PV"}; + Configurable cascadesetting_dcapostopv{"cascadesetting_dcapostopv", 0.06, "DCA positive to PV"}; + Configurable cascadesetting_dcanegtopv{"cascadesetting_dcanegtopv", 0.06, "DCA negative to PV"}; + Configurable cascadesetting_mindcav0topv{"cascadesetting_mindcav0topv", 0.01, "minimum V0 DCA to PV"}; + Configurable cascadesetting_cascradius{"cascadesetting_cascradius", 0.5, "cascradius"}; + Configurable cascadesetting_v0radius{"cascadesetting_v0radius", 1.2, "v0radius"}; + Configurable cascadesetting_v0masswindow{"cascadesetting_v0masswindow", 0.01, "v0 mass window"}; + Configurable cascadesetting_competingmassrej{"cascadesetting_competingmassrej", 0.008, "Competing mass rejection"}; + + // PDG data base + Service pdgDB; + + void init(InitContext const&) + { + // Axes + AxisSpec XiMassAxis = {100, 1.28f, 1.36f, "#it{M}_{inv} [GeV/#it{c}^{2}]"}; + AxisSpec OmegaMassAxis = {100, 1.63f, 1.7f, "#it{M}_{inv} [GeV/#it{c}^{2}]"}; + AxisSpec vertexZAxis = {nBins, -15., 15., "vrtx_{Z} [cm]"}; + + // Histograms + // Event selection + rEventSelection.add("hVertexZRec", "hVertexZRec", {HistType::kTH1F, {vertexZAxis}}); + + // Xi/Omega reconstruction + rXi.add("hMassXi", "hMassXi", {HistType::kTH1F, {XiMassAxis}}); + rXi.add("hMassXiSelected", "hMassXiSelected", {HistType::kTH1F, {XiMassAxis}}); + + rOmega.add("hMassOmega", "hMassOmega", {HistType::kTH1F, {OmegaMassAxis}}); + rOmega.add("hMassOmegaSelected", "hMassOmegaSelected", {HistType::kTH1F, {OmegaMassAxis}}); + + // Xi/Omega topological cuts + rXi.add("hCascDCAV0Daughters", "hCascDCAV0Daughters", {HistType::kTH1F, {{55, 0.0f, 2.2f}}}); + rXi.add("hCascCosPA", "hCascCosPA", {HistType::kTH1F, {{100, 0.95f, 1.f}}}); + + rOmega.add("hCascDCAV0Daughters", "hCascDCAV0Daughters", {HistType::kTH1F, {{55, 0.0f, 2.2f}}}); + rOmega.add("hCascCosPA", "hCascCosPA", {HistType::kTH1F, {{100, 0.95f, 1.f}}}); + } + + // Defining filters for events (event selection) + // Processed events will be already fulfilling the event selection requirements + Filter eventFilter = (o2::aod::evsel::sel8 == true); + Filter posZFilter = (nabs(o2::aod::collision::posZ) < cutzvertex); + + // Filters on Cascades + // Cannot filter on dynamic columns + Filter preFilterCascades = (aod::cascdata::dcaV0daughters < cascadesetting_dcav0dau && + nabs(aod::cascdata::dcapostopv) > cascadesetting_dcapostopv && + nabs(aod::cascdata::dcanegtopv) > cascadesetting_dcanegtopv && + nabs(aod::cascdata::dcabachtopv) > cascadesetting_dcabachtopv && + aod::cascdata::dcacascdaughters < cascadesetting_dcacascdau); + + void process(soa::Filtered>::iterator const& collision, + soa::Filtered> const& Cascades) + { + // Fill the event counter + rEventSelection.fill(HIST("hVertexZRec"), collision.posZ()); + + // Cascades + for (const auto& casc : Cascades) { + rXi.fill(HIST("hMassXi"), casc.mXi()); + rOmega.fill(HIST("hMassOmega"), casc.mOmega()); + + // Cut on dynamic columns + if (casc.casccosPA(collision.posX(), collision.posY(), collision.posZ()) < cascadesetting_cospa) + continue; + if (casc.v0cosPA(collision.posX(), collision.posY(), collision.posZ()) < cascadesetting_v0cospa) + continue; + if (TMath::Abs(casc.mLambda() - pdgDB->Mass(3122)) > cascadesetting_v0masswindow) + continue; + if (casc.dcav0topv(collision.posX(), collision.posY(), collision.posZ()) < cascadesetting_mindcav0topv) + continue; + if (casc.cascradius() < cascadesetting_cascradius) + continue; + if (casc.v0radius() < cascadesetting_v0radius) + continue; + + // Fill histograms! (if possible) + rXi.fill(HIST("hMassXiSelected"), casc.mXi()); + + rXi.fill(HIST("hCascDCAV0Daughters"), casc.dcaV0daughters()); + rXi.fill(HIST("hCascCosPA"), casc.casccosPA(collision.posX(), collision.posY(), collision.posZ())); + + if (TMath::Abs(casc.mXi() - pdgDB->Mass(3312)) > cascadesetting_competingmassrej) { // competing mass rejection, only in case of Omega + rOmega.fill(HIST("hMassOmegaSelected"), casc.mOmega()); + + rOmega.fill(HIST("hCascDCAV0Daughters"), casc.dcaV0daughters()); + rOmega.fill(HIST("hCascCosPA"), casc.casccosPA(collision.posX(), collision.posY(), collision.posZ())); + } + } + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc)}; +} diff --git a/Tutorials/PWGLF/Strangeness/PbPb/Analysis/strangeness_pbpb_step2.cxx b/Tutorials/PWGLF/Strangeness/PbPb/Analysis/strangeness_pbpb_step2.cxx new file mode 100644 index 00000000000..1558bb78052 --- /dev/null +++ b/Tutorials/PWGLF/Strangeness/PbPb/Analysis/strangeness_pbpb_step2.cxx @@ -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. +/// +/// \brief Step4 of the Strangeness tutorial +/// \author Romain Schotter +/// based on the original codes from: +/// \author Nepeivoda Roman (roman.nepeivoda@cern.ch) +/// \author Chiara De Martin (chiara.de.martin@cern.ch) + +#include "Framework/runDataProcessing.h" +#include "Framework/AnalysisTask.h" +#include "Common/DataModel/EventSelection.h" +#include "PWGLF/DataModel/LFStrangenessPIDTables.h" +#include "PWGLF/DataModel/LFStrangenessTables.h" +#include "Framework/O2DatabasePDGPlugin.h" + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; + +// STEP 0 +// Starting point: loop over all cascades and fill invariant mass histogram +// STEP 1 +// Apply selections on topological variables of Cascades +// STEP 2 +// Apply TPC PID selections on cascade daughter tracks + +struct strangeness_pbpb_tutorial { + // Histograms are defined with HistogramRegistry + HistogramRegistry rEventSelection{"eventSelection", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + HistogramRegistry rXi{"xi", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + HistogramRegistry rOmega{"omega", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + + // Configurable for histograms + Configurable nBins{"nBins", 100, "N bins in all histos"}; + + // Configurable for event selection + Configurable cutzvertex{"cutzvertex", 10.0f, "Accepted z-vertex range (cm)"}; + + // Configurable parameters for cascade selection + Configurable cascadesetting_cospa{"cascadesetting_cospa", 0.98, "Casc CosPA"}; + Configurable cascadesetting_v0cospa{"cascadesetting_v0cospa", 0.97, "V0 CosPA"}; + Configurable cascadesetting_dcacascdau{"cascadesetting_dcacascdau", 1.0, "DCA cascade daughters"}; + Configurable cascadesetting_dcav0dau{"cascadesetting_dcav0dau", 1.0, "DCA v0 daughters"}; + Configurable cascadesetting_dcabachtopv{"cascadesetting_dcabachtopv", 0.06, "DCA bachelor to PV"}; + Configurable cascadesetting_dcapostopv{"cascadesetting_dcapostopv", 0.06, "DCA positive to PV"}; + Configurable cascadesetting_dcanegtopv{"cascadesetting_dcanegtopv", 0.06, "DCA negative to PV"}; + Configurable cascadesetting_mindcav0topv{"cascadesetting_mindcav0topv", 0.01, "minimum V0 DCA to PV"}; + Configurable cascadesetting_cascradius{"cascadesetting_cascradius", 0.5, "cascradius"}; + Configurable cascadesetting_v0radius{"cascadesetting_v0radius", 1.2, "v0radius"}; + Configurable cascadesetting_v0masswindow{"cascadesetting_v0masswindow", 0.01, "v0 mass window"}; + Configurable cascadesetting_competingmassrej{"cascadesetting_competingmassrej", 0.008, "Competing mass rejection"}; + + // Configurable parameters for PID selection + Configurable NSigmaTPCPion{"NSigmaTPCPion", 4, "NSigmaTPCPion"}; + Configurable NSigmaTPCKaon{"NSigmaTPCKaon", 4, "NSigmaTPCKaon"}; + Configurable NSigmaTPCProton{"NSigmaTPCProton", 4, "NSigmaTPCProton"}; + + // PDG data base + Service pdgDB; + + void init(InitContext const&) + { + // Axes + AxisSpec XiMassAxis = {100, 1.28f, 1.36f, "#it{M}_{inv} [GeV/#it{c}^{2}]"}; + AxisSpec OmegaMassAxis = {100, 1.63f, 1.7f, "#it{M}_{inv} [GeV/#it{c}^{2}]"}; + AxisSpec vertexZAxis = {nBins, -15., 15., "vrtx_{Z} [cm]"}; + + // Histograms + // Event selection + rEventSelection.add("hVertexZRec", "hVertexZRec", {HistType::kTH1F, {vertexZAxis}}); + + // Xi/Omega reconstruction + rXi.add("hMassXi", "hMassXi", {HistType::kTH1F, {XiMassAxis}}); + rXi.add("hMassXiSelected", "hMassXiSelected", {HistType::kTH1F, {XiMassAxis}}); + + rOmega.add("hMassOmega", "hMassOmega", {HistType::kTH1F, {OmegaMassAxis}}); + rOmega.add("hMassOmegaSelected", "hMassOmegaSelected", {HistType::kTH1F, {OmegaMassAxis}}); + + // Xi/Omega topological cuts + rXi.add("hCascDCAV0Daughters", "hCascDCAV0Daughters", {HistType::kTH1F, {{55, 0.0f, 2.2f}}}); + rXi.add("hCascCosPA", "hCascCosPA", {HistType::kTH1F, {{100, 0.95f, 1.f}}}); + + rOmega.add("hCascDCAV0Daughters", "hCascDCAV0Daughters", {HistType::kTH1F, {{55, 0.0f, 2.2f}}}); + rOmega.add("hCascCosPA", "hCascCosPA", {HistType::kTH1F, {{100, 0.95f, 1.f}}}); + } + + // Defining filters for events (event selection) + // Processed events will be already fulfilling the event selection requirements + Filter eventFilter = (o2::aod::evsel::sel8 == true); + Filter posZFilter = (nabs(o2::aod::collision::posZ) < cutzvertex); + + // Filters on Cascades + // Cannot filter on dynamic columns + Filter preFilterCascades = (aod::cascdata::dcaV0daughters < cascadesetting_dcav0dau && + nabs(aod::cascdata::dcapostopv) > cascadesetting_dcapostopv && + nabs(aod::cascdata::dcanegtopv) > cascadesetting_dcanegtopv && + nabs(aod::cascdata::dcabachtopv) > cascadesetting_dcabachtopv && + aod::cascdata::dcacascdaughters < cascadesetting_dcacascdau); + + // Defining the type of the daughter tracks + using dauTracks = soa::Join; + + void process(soa::Filtered>::iterator const& collision, + soa::Filtered> const& Cascades, + dauTracks const&) + { + // Fill the event counter + rEventSelection.fill(HIST("hVertexZRec"), collision.posZ()); + + // Cascades + for (const auto& casc : Cascades) { + const auto& bachDaughterTrackCasc = casc.bachTrackExtra_as(); + const auto& posDaughterTrackCasc = casc.posTrackExtra_as(); + const auto& negDaughterTrackCasc = casc.negTrackExtra_as(); + + rXi.fill(HIST("hMassXi"), casc.mXi()); + rOmega.fill(HIST("hMassOmega"), casc.mOmega()); + + // Cut on dynamic columns + if (casc.casccosPA(collision.posX(), collision.posY(), collision.posZ()) < cascadesetting_cospa) + continue; + if (casc.v0cosPA(collision.posX(), collision.posY(), collision.posZ()) < cascadesetting_v0cospa) + continue; + if (TMath::Abs(casc.mLambda() - pdgDB->Mass(3122)) > cascadesetting_v0masswindow) + continue; + if (casc.dcav0topv(collision.posX(), collision.posY(), collision.posZ()) < cascadesetting_mindcav0topv) + continue; + if (casc.cascradius() < cascadesetting_cascradius) + continue; + if (casc.v0radius() < cascadesetting_v0radius) + continue; + + // PID selection + if (casc.sign() < 0) { + if (TMath::Abs(posDaughterTrackCasc.tpcNSigmaPr()) > NSigmaTPCProton) { + continue; + } + if (TMath::Abs(negDaughterTrackCasc.tpcNSigmaPi()) > NSigmaTPCPion) { + continue; + } + } else { + if (TMath::Abs(negDaughterTrackCasc.tpcNSigmaPr()) > NSigmaTPCProton) { + continue; + } + if (TMath::Abs(posDaughterTrackCasc.tpcNSigmaPi()) > NSigmaTPCPion) { + continue; + } + } + + // Fill histograms! (if possible) + if (TMath::Abs(bachDaughterTrackCasc.tpcNSigmaPi()) < NSigmaTPCPion) { // Xi case + rXi.fill(HIST("hMassXiSelected"), casc.mXi()); + + rXi.fill(HIST("hCascDCAV0Daughters"), casc.dcaV0daughters()); + rXi.fill(HIST("hCascCosPA"), casc.casccosPA(collision.posX(), collision.posY(), collision.posZ())); + } + if (TMath::Abs(bachDaughterTrackCasc.tpcNSigmaKa()) < NSigmaTPCKaon) { // Omega case + if (TMath::Abs(casc.mXi() - pdgDB->Mass(3312)) > cascadesetting_competingmassrej) { // competing mass rejection, only in case of Omega + rOmega.fill(HIST("hMassOmegaSelected"), casc.mOmega()); + + rOmega.fill(HIST("hCascDCAV0Daughters"), casc.dcaV0daughters()); + rOmega.fill(HIST("hCascCosPA"), casc.casccosPA(collision.posX(), collision.posY(), collision.posZ())); + } + } + } + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc)}; +} diff --git a/Tutorials/PWGLF/Strangeness/PbPb/Analysis/strangeness_pbpb_step3.cxx b/Tutorials/PWGLF/Strangeness/PbPb/Analysis/strangeness_pbpb_step3.cxx new file mode 100644 index 00000000000..f12a4f02560 --- /dev/null +++ b/Tutorials/PWGLF/Strangeness/PbPb/Analysis/strangeness_pbpb_step3.cxx @@ -0,0 +1,243 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does 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 Step4 of the Strangeness tutorial +/// \author Romain Schotter +/// based on the original codes from: +/// \author Nepeivoda Roman (roman.nepeivoda@cern.ch) +/// \author Chiara De Martin (chiara.de.martin@cern.ch) + +#include "Framework/runDataProcessing.h" +#include "Framework/AnalysisTask.h" +#include "Common/DataModel/EventSelection.h" +#include "PWGLF/DataModel/LFStrangenessPIDTables.h" +#include "PWGLF/DataModel/LFStrangenessTables.h" +#include "Framework/O2DatabasePDGPlugin.h" + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; + +// STEP 0 +// Starting point: loop over all cascades and fill invariant mass histogram +// STEP 1 +// Apply selections on topological variables of Cascades +// STEP 2 +// Apply TPC PID selections on cascade daughter tracks +// STEP 3 +// Apply TOF PID selections on cascade daugther tracks (if info is available) + +struct strangeness_pbpb_tutorial { + // Histograms are defined with HistogramRegistry + HistogramRegistry rEventSelection{"eventSelection", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + HistogramRegistry rXi{"xi", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + HistogramRegistry rOmega{"omega", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + + // Configurable for histograms + Configurable nBins{"nBins", 100, "N bins in all histos"}; + + // Configurable for event selection + Configurable cutzvertex{"cutzvertex", 10.0f, "Accepted z-vertex range (cm)"}; + + // Configurable parameters for cascade selection + Configurable cascadesetting_cospa{"cascadesetting_cospa", 0.98, "Casc CosPA"}; + Configurable cascadesetting_v0cospa{"cascadesetting_v0cospa", 0.97, "V0 CosPA"}; + Configurable cascadesetting_dcacascdau{"cascadesetting_dcacascdau", 1.0, "DCA cascade daughters"}; + Configurable cascadesetting_dcav0dau{"cascadesetting_dcav0dau", 1.0, "DCA v0 daughters"}; + Configurable cascadesetting_dcabachtopv{"cascadesetting_dcabachtopv", 0.06, "DCA bachelor to PV"}; + Configurable cascadesetting_dcapostopv{"cascadesetting_dcapostopv", 0.06, "DCA positive to PV"}; + Configurable cascadesetting_dcanegtopv{"cascadesetting_dcanegtopv", 0.06, "DCA negative to PV"}; + Configurable cascadesetting_mindcav0topv{"cascadesetting_mindcav0topv", 0.01, "minimum V0 DCA to PV"}; + Configurable cascadesetting_cascradius{"cascadesetting_cascradius", 0.5, "cascradius"}; + Configurable cascadesetting_v0radius{"cascadesetting_v0radius", 1.2, "v0radius"}; + Configurable cascadesetting_v0masswindow{"cascadesetting_v0masswindow", 0.01, "v0 mass window"}; + Configurable cascadesetting_competingmassrej{"cascadesetting_competingmassrej", 0.008, "Competing mass rejection"}; + + // Configurable parameters for PID selection + Configurable NSigmaTPCPion{"NSigmaTPCPion", 4, "NSigmaTPCPion"}; + Configurable NSigmaTPCKaon{"NSigmaTPCKaon", 4, "NSigmaTPCKaon"}; + Configurable NSigmaTPCProton{"NSigmaTPCProton", 4, "NSigmaTPCProton"}; + + // Configurable parameters for TOF PID selection + Configurable NSigmaTOFPion{"NSigmaTOFPion", 3, "NSigmaTOFPion"}; + Configurable NSigmaTOFKaon{"NSigmaTOFKaon", 3, "NSigmaTOFKaon"}; + Configurable NSigmaTOFProton{"NSigmaTOFProton", 3, "NSigmaTOFProton"}; + + // PDG data base + Service pdgDB; + + void init(InitContext const&) + { + // Axes + AxisSpec XiMassAxis = {100, 1.28f, 1.36f, "#it{M}_{inv} [GeV/#it{c}^{2}]"}; + AxisSpec OmegaMassAxis = {100, 1.63f, 1.7f, "#it{M}_{inv} [GeV/#it{c}^{2}]"}; + AxisSpec vertexZAxis = {nBins, -15., 15., "vrtx_{Z} [cm]"}; + + // Histograms + // Event selection + rEventSelection.add("hVertexZRec", "hVertexZRec", {HistType::kTH1F, {vertexZAxis}}); + + // Xi/Omega reconstruction + rXi.add("hMassXi", "hMassXi", {HistType::kTH1F, {XiMassAxis}}); + rXi.add("hMassXiSelected", "hMassXiSelected", {HistType::kTH1F, {XiMassAxis}}); + rXi.add("hMassXiSelectedWithTOF", "hMassXiSelectedWithTOF", {HistType::kTH1F, {XiMassAxis}}); + + rOmega.add("hMassOmega", "hMassOmega", {HistType::kTH1F, {OmegaMassAxis}}); + rOmega.add("hMassOmegaSelected", "hMassOmegaSelected", {HistType::kTH1F, {OmegaMassAxis}}); + rOmega.add("hMassOmegaSelectedWithTOF", "hMassOmegaSelectedWithTOF", {HistType::kTH1F, {OmegaMassAxis}}); + + // Xi/Omega topological cuts + rXi.add("hCascDCAV0Daughters", "hCascDCAV0Daughters", {HistType::kTH1F, {{55, 0.0f, 2.2f}}}); + rXi.add("hCascCosPA", "hCascCosPA", {HistType::kTH1F, {{100, 0.95f, 1.f}}}); + + rOmega.add("hCascDCAV0Daughters", "hCascDCAV0Daughters", {HistType::kTH1F, {{55, 0.0f, 2.2f}}}); + rOmega.add("hCascCosPA", "hCascCosPA", {HistType::kTH1F, {{100, 0.95f, 1.f}}}); + } + + // Defining filters for events (event selection) + // Processed events will be already fulfilling the event selection requirements + Filter eventFilter = (o2::aod::evsel::sel8 == true); + Filter posZFilter = (nabs(o2::aod::collision::posZ) < cutzvertex); + + // Filters on Cascades + // Cannot filter on dynamic columns + Filter preFilterCascades = (aod::cascdata::dcaV0daughters < cascadesetting_dcav0dau && + nabs(aod::cascdata::dcapostopv) > cascadesetting_dcapostopv && + nabs(aod::cascdata::dcanegtopv) > cascadesetting_dcanegtopv && + nabs(aod::cascdata::dcabachtopv) > cascadesetting_dcabachtopv && + aod::cascdata::dcacascdaughters < cascadesetting_dcacascdau); + + // Defining the type of the daughter tracks + using dauTracks = soa::Join; + + void process(soa::Filtered>::iterator const& collision, + soa::Filtered> const& Cascades, + dauTracks const&) + { + // Fill the event counter + rEventSelection.fill(HIST("hVertexZRec"), collision.posZ()); + + // Cascades + for (const auto& casc : Cascades) { + const auto& bachDaughterTrackCasc = casc.bachTrackExtra_as(); + const auto& posDaughterTrackCasc = casc.posTrackExtra_as(); + const auto& negDaughterTrackCasc = casc.negTrackExtra_as(); + + rXi.fill(HIST("hMassXi"), casc.mXi()); + rOmega.fill(HIST("hMassOmega"), casc.mOmega()); + + // Cut on dynamic columns + if (casc.casccosPA(collision.posX(), collision.posY(), collision.posZ()) < cascadesetting_cospa) + continue; + if (casc.v0cosPA(collision.posX(), collision.posY(), collision.posZ()) < cascadesetting_v0cospa) + continue; + if (TMath::Abs(casc.mLambda() - pdgDB->Mass(3122)) > cascadesetting_v0masswindow) + continue; + if (casc.dcav0topv(collision.posX(), collision.posY(), collision.posZ()) < cascadesetting_mindcav0topv) + continue; + if (casc.cascradius() < cascadesetting_cascradius) + continue; + if (casc.v0radius() < cascadesetting_v0radius) + continue; + + // PID selection + if (casc.sign() < 0) { + if (TMath::Abs(posDaughterTrackCasc.tpcNSigmaPr()) > NSigmaTPCProton) { + continue; + } + if (TMath::Abs(negDaughterTrackCasc.tpcNSigmaPi()) > NSigmaTPCPion) { + continue; + } + } else { + if (TMath::Abs(negDaughterTrackCasc.tpcNSigmaPr()) > NSigmaTPCProton) { + continue; + } + if (TMath::Abs(posDaughterTrackCasc.tpcNSigmaPi()) > NSigmaTPCPion) { + continue; + } + } + + // TOF PID check + bool xiPassTOFSelection = true; + bool omegaPassTOFSelection = true; + if (casc.sign() < 0) { + if (posDaughterTrackCasc.hasTOF()) { + if (TMath::Abs(casc.tofNSigmaXiLaPr()) > NSigmaTOFProton) { + xiPassTOFSelection &= false; + } + if (TMath::Abs(casc.tofNSigmaOmLaPr()) > NSigmaTOFProton) { + omegaPassTOFSelection &= false; + } + } + if (negDaughterTrackCasc.hasTOF()) { + if (TMath::Abs(casc.tofNSigmaXiLaPi()) > NSigmaTOFPion) { + xiPassTOFSelection &= false; + } + if (TMath::Abs(casc.tofNSigmaOmLaPi()) > NSigmaTOFPion) { + omegaPassTOFSelection &= false; + } + } + } else { + if (posDaughterTrackCasc.hasTOF()) { + if (TMath::Abs(casc.tofNSigmaXiLaPi()) > NSigmaTOFPion) { + xiPassTOFSelection &= false; + } + if (TMath::Abs(casc.tofNSigmaOmLaPi()) > NSigmaTOFPion) { + omegaPassTOFSelection &= false; + } + } + if (negDaughterTrackCasc.hasTOF()) { + if (TMath::Abs(casc.tofNSigmaXiLaPr()) > NSigmaTOFProton) { + xiPassTOFSelection &= false; + } + if (TMath::Abs(casc.tofNSigmaOmLaPr()) > NSigmaTOFProton) { + omegaPassTOFSelection &= false; + } + } + } + + if (bachDaughterTrackCasc.hasTOF()) { + if (TMath::Abs(casc.tofNSigmaXiPi()) > NSigmaTOFPion) { + xiPassTOFSelection &= false; + } + if (TMath::Abs(casc.tofNSigmaOmKa()) > NSigmaTOFKaon) { + omegaPassTOFSelection &= false; + } + } + + // Fill histograms! (if possible) + if (TMath::Abs(bachDaughterTrackCasc.tpcNSigmaPi()) < NSigmaTPCPion) { // Xi case + rXi.fill(HIST("hMassXiSelected"), casc.mXi()); + if (xiPassTOFSelection) + rXi.fill(HIST("hMassXiSelectedWithTOF"), casc.mXi()); + + rXi.fill(HIST("hCascDCAV0Daughters"), casc.dcaV0daughters()); + rXi.fill(HIST("hCascCosPA"), casc.casccosPA(collision.posX(), collision.posY(), collision.posZ())); + } + if (TMath::Abs(bachDaughterTrackCasc.tpcNSigmaKa()) < NSigmaTPCKaon) { // Omega case + if (TMath::Abs(casc.mXi() - pdgDB->Mass(3312)) > cascadesetting_competingmassrej) { // competing mass rejection, only in case of Omega + rOmega.fill(HIST("hMassOmegaSelected"), casc.mOmega()); + if (omegaPassTOFSelection) + rOmega.fill(HIST("hMassOmegaSelectedWithTOF"), casc.mOmega()); + + rOmega.fill(HIST("hCascDCAV0Daughters"), casc.dcaV0daughters()); + rOmega.fill(HIST("hCascCosPA"), casc.casccosPA(collision.posX(), collision.posY(), collision.posZ())); + } + } + } + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc)}; +} diff --git a/Tutorials/PWGLF/Strangeness/PbPb/Analysis/strangeness_pbpb_step4.cxx b/Tutorials/PWGLF/Strangeness/PbPb/Analysis/strangeness_pbpb_step4.cxx new file mode 100644 index 00000000000..d45ef3c26a1 --- /dev/null +++ b/Tutorials/PWGLF/Strangeness/PbPb/Analysis/strangeness_pbpb_step4.cxx @@ -0,0 +1,324 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does 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 Step4 of the Strangeness tutorial +/// \author Romain Schotter +/// based on the original codes from: +/// \author Nepeivoda Roman (roman.nepeivoda@cern.ch) +/// \author Chiara De Martin (chiara.de.martin@cern.ch) + +#include "Framework/runDataProcessing.h" +#include "Framework/AnalysisTask.h" +#include "Common/DataModel/EventSelection.h" +#include "PWGLF/DataModel/LFStrangenessPIDTables.h" +#include "PWGLF/DataModel/LFStrangenessTables.h" +#include "Framework/O2DatabasePDGPlugin.h" + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; + +// STEP 0 +// Starting point: loop over all cascades and fill invariant mass histogram +// STEP 1 +// Apply selections on topological variables of Cascades +// STEP 2 +// Apply TPC PID selections on cascade daughter tracks +// STEP 3 +// Apply TOF PID selections on cascade daugther tracks (if info is available) +// STEP 4 +// Check the MC information of the cascades + +struct strangeness_pbpb_tutorial { + // Histograms are defined with HistogramRegistry + HistogramRegistry rEventSelection{"eventSelection", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + HistogramRegistry rXi{"xi", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + HistogramRegistry rOmega{"omega", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + HistogramRegistry rGenParticles{"genParticles", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + + // Configurable for histograms + Configurable nBins{"nBins", 100, "N bins in all histos"}; + + // Configurable for event selection + Configurable cutzvertex{"cutzvertex", 10.0f, "Accepted z-vertex range (cm)"}; + + // Configurable parameters for cascade selection + Configurable cascadesetting_cospa{"cascadesetting_cospa", 0.98, "Casc CosPA"}; + Configurable cascadesetting_v0cospa{"cascadesetting_v0cospa", 0.97, "V0 CosPA"}; + Configurable cascadesetting_dcacascdau{"cascadesetting_dcacascdau", 1.0, "DCA cascade daughters"}; + Configurable cascadesetting_dcav0dau{"cascadesetting_dcav0dau", 1.0, "DCA v0 daughters"}; + Configurable cascadesetting_dcabachtopv{"cascadesetting_dcabachtopv", 0.06, "DCA bachelor to PV"}; + Configurable cascadesetting_dcapostopv{"cascadesetting_dcapostopv", 0.06, "DCA positive to PV"}; + Configurable cascadesetting_dcanegtopv{"cascadesetting_dcanegtopv", 0.06, "DCA negative to PV"}; + Configurable cascadesetting_mindcav0topv{"cascadesetting_mindcav0topv", 0.01, "minimum V0 DCA to PV"}; + Configurable cascadesetting_cascradius{"cascadesetting_cascradius", 0.5, "cascradius"}; + Configurable cascadesetting_v0radius{"cascadesetting_v0radius", 1.2, "v0radius"}; + Configurable cascadesetting_v0masswindow{"cascadesetting_v0masswindow", 0.01, "v0 mass window"}; + Configurable cascadesetting_competingmassrej{"cascadesetting_competingmassrej", 0.008, "Competing mass rejection"}; + + // Configurable parameters for PID selection + Configurable NSigmaTPCPion{"NSigmaTPCPion", 4, "NSigmaTPCPion"}; + Configurable NSigmaTPCKaon{"NSigmaTPCKaon", 4, "NSigmaTPCKaon"}; + Configurable NSigmaTPCProton{"NSigmaTPCProton", 4, "NSigmaTPCProton"}; + + // Configurable parameters for TOF PID selection + Configurable NSigmaTOFPion{"NSigmaTOFPion", 3, "NSigmaTOFPion"}; + Configurable NSigmaTOFKaon{"NSigmaTOFKaon", 3, "NSigmaTOFKaon"}; + Configurable NSigmaTOFProton{"NSigmaTOFProton", 3, "NSigmaTOFProton"}; + + // PDG data base + Service pdgDB; + + void init(InitContext const&) + { + // Axes + AxisSpec XiMassAxis = {100, 1.28f, 1.36f, "#it{M}_{inv} [GeV/#it{c}^{2}]"}; + AxisSpec OmegaMassAxis = {100, 1.63f, 1.7f, "#it{M}_{inv} [GeV/#it{c}^{2}]"}; + AxisSpec vertexZAxis = {nBins, -15., 15., "vrtx_{Z} [cm]"}; + AxisSpec ptAxis = {100, 0.0f, 10.0f, "#it{p}_{T} (GeV/#it{c})"}; + + // Histograms + // Event selection + rEventSelection.add("hVertexZRec", "hVertexZRec", {HistType::kTH1F, {vertexZAxis}}); + + // Xi/Omega reconstruction + rXi.add("hMassXi", "hMassXi", {HistType::kTH1F, {XiMassAxis}}); + rXi.add("hMassXiSelected", "hMassXiSelected", {HistType::kTH1F, {XiMassAxis}}); + rXi.add("hMassXiSelectedWithTOF", "hMassXiSelectedWithTOF", {HistType::kTH1F, {XiMassAxis}}); + rXi.add("hMassXiTrueRec", "hMassXiTrueRec", {HistType::kTH1F, {XiMassAxis}}); + rXi.add("hPtXiTrueRec", "hPtXiTrueRec", {HistType::kTH1F, {ptAxis}}); + rXi.add("hMassXiTrueRecWithTOF", "hMassXiTrueRecWithTOF", {HistType::kTH1F, {XiMassAxis}}); + rXi.add("hPtXiTrueRecWithTOF", "hPtXiTrueRecWithTOF", {HistType::kTH1F, {ptAxis}}); + + rOmega.add("hMassOmega", "hMassOmega", {HistType::kTH1F, {OmegaMassAxis}}); + rOmega.add("hMassOmegaSelected", "hMassOmegaSelected", {HistType::kTH1F, {OmegaMassAxis}}); + rOmega.add("hMassOmegaSelectedWithTOF", "hMassOmegaSelectedWithTOF", {HistType::kTH1F, {OmegaMassAxis}}); + rOmega.add("hMassOmegaTrueRec", "hMassOmegaTrueRec", {HistType::kTH1F, {OmegaMassAxis}}); + rOmega.add("hPtOmegaTrueRec", "hPtOmegaTrueRec", {HistType::kTH1F, {ptAxis}}); + rOmega.add("hMassOmegaTrueRecWithTOF", "hMassOmegaTrueRecWithTOF", {HistType::kTH1F, {OmegaMassAxis}}); + rOmega.add("hPtOmegaTrueRecWithTOF", "hPtOmegaTrueRecWithTOF", {HistType::kTH1F, {ptAxis}}); + + // Xi/Omega topological cuts + rXi.add("hCascDCAV0Daughters", "hCascDCAV0Daughters", {HistType::kTH1F, {{55, 0.0f, 2.2f}}}); + rXi.add("hCascCosPA", "hCascCosPA", {HistType::kTH1F, {{100, 0.95f, 1.f}}}); + + rOmega.add("hCascDCAV0Daughters", "hCascDCAV0Daughters", {HistType::kTH1F, {{55, 0.0f, 2.2f}}}); + rOmega.add("hCascCosPA", "hCascCosPA", {HistType::kTH1F, {{100, 0.95f, 1.f}}}); + + // Generated level histograms + rEventSelection.add("hVertexZGen", "hVertexZGen", {HistType::kTH1F, {vertexZAxis}}); + rGenParticles.add("hPtXiGen", "hPtXiGen", {HistType::kTH1F, {{ptAxis}}}); + rGenParticles.add("hPtOmegaGen", "hPtOmegaGen", {HistType::kTH1F, {{ptAxis}}}); + } + + // Defining filters for events (event selection) + // Processed events will be already fulfilling the event selection requirements + Filter eventFilter = (o2::aod::evsel::sel8 == true); + Filter posZFilter = (nabs(o2::aod::collision::posZ) < cutzvertex); + Filter posZFilterMC = (nabs(o2::aod::mccollision::posZ) < cutzvertex); + + // Filters on Cascades + // Cannot filter on dynamic columns + Filter preFilterCascades = (aod::cascdata::dcaV0daughters < cascadesetting_dcav0dau && + nabs(aod::cascdata::dcapostopv) > cascadesetting_dcapostopv && + nabs(aod::cascdata::dcanegtopv) > cascadesetting_dcanegtopv && + nabs(aod::cascdata::dcabachtopv) > cascadesetting_dcabachtopv && + aod::cascdata::dcacascdaughters < cascadesetting_dcacascdau); + + // Defining the type of the daughter tracks + using dauTracks = soa::Join; + + void processRecMC(soa::Filtered>::iterator const& collision, + soa::Filtered> const& Cascades, + dauTracks const&, + aod::CascMCCores const& /*cascmccores*/) + { + // Fill the event counter + rEventSelection.fill(HIST("hVertexZRec"), collision.posZ()); + + // Cascades + for (const auto& casc : Cascades) { + const auto& bachDaughterTrackCasc = casc.bachTrackExtra_as(); + const auto& posDaughterTrackCasc = casc.posTrackExtra_as(); + const auto& negDaughterTrackCasc = casc.negTrackExtra_as(); + + rXi.fill(HIST("hMassXi"), casc.mXi()); + rOmega.fill(HIST("hMassOmega"), casc.mOmega()); + + // Cut on dynamic columns + if (casc.casccosPA(collision.posX(), collision.posY(), collision.posZ()) < cascadesetting_cospa) + continue; + if (casc.v0cosPA(collision.posX(), collision.posY(), collision.posZ()) < cascadesetting_v0cospa) + continue; + if (TMath::Abs(casc.mLambda() - pdgDB->Mass(3122)) > cascadesetting_v0masswindow) + continue; + if (casc.dcav0topv(collision.posX(), collision.posY(), collision.posZ()) < cascadesetting_mindcav0topv) + continue; + if (casc.cascradius() < cascadesetting_cascradius) + continue; + if (casc.v0radius() < cascadesetting_v0radius) + continue; + + // PID selection + if (casc.sign() < 0) { + if (TMath::Abs(posDaughterTrackCasc.tpcNSigmaPr()) > NSigmaTPCProton) { + continue; + } + if (TMath::Abs(negDaughterTrackCasc.tpcNSigmaPi()) > NSigmaTPCPion) { + continue; + } + } else { + if (TMath::Abs(negDaughterTrackCasc.tpcNSigmaPr()) > NSigmaTPCProton) { + continue; + } + if (TMath::Abs(posDaughterTrackCasc.tpcNSigmaPi()) > NSigmaTPCPion) { + continue; + } + } + + // TOF PID check + bool xiPassTOFSelection = true; + bool omegaPassTOFSelection = true; + if (casc.sign() < 0) { + if (posDaughterTrackCasc.hasTOF()) { + if (TMath::Abs(casc.tofNSigmaXiLaPr()) > NSigmaTOFProton) { + xiPassTOFSelection &= false; + } + if (TMath::Abs(casc.tofNSigmaOmLaPr()) > NSigmaTOFProton) { + omegaPassTOFSelection &= false; + } + } + if (negDaughterTrackCasc.hasTOF()) { + if (TMath::Abs(casc.tofNSigmaXiLaPi()) > NSigmaTOFPion) { + xiPassTOFSelection &= false; + } + if (TMath::Abs(casc.tofNSigmaOmLaPi()) > NSigmaTOFPion) { + omegaPassTOFSelection &= false; + } + } + } else { + if (posDaughterTrackCasc.hasTOF()) { + if (TMath::Abs(casc.tofNSigmaXiLaPi()) > NSigmaTOFPion) { + xiPassTOFSelection &= false; + } + if (TMath::Abs(casc.tofNSigmaOmLaPi()) > NSigmaTOFPion) { + omegaPassTOFSelection &= false; + } + } + if (negDaughterTrackCasc.hasTOF()) { + if (TMath::Abs(casc.tofNSigmaXiLaPr()) > NSigmaTOFProton) { + xiPassTOFSelection &= false; + } + if (TMath::Abs(casc.tofNSigmaOmLaPr()) > NSigmaTOFProton) { + omegaPassTOFSelection &= false; + } + } + } + + if (bachDaughterTrackCasc.hasTOF()) { + if (TMath::Abs(casc.tofNSigmaXiPi()) > NSigmaTOFPion) { + xiPassTOFSelection &= false; + } + if (TMath::Abs(casc.tofNSigmaOmKa()) > NSigmaTOFKaon) { + omegaPassTOFSelection &= false; + } + } + + if (bachDaughterTrackCasc.hasTOF()) { + if (TMath::Abs(casc.tofNSigmaXiPi()) > NSigmaTOFPion) { + xiPassTOFSelection &= false; + } + if (TMath::Abs(casc.tofNSigmaOmKa()) > NSigmaTOFKaon) { + omegaPassTOFSelection &= false; + } + } + + // Fill histograms! (if possible) + if (TMath::Abs(bachDaughterTrackCasc.tpcNSigmaPi()) < NSigmaTPCPion) { // Xi case + rXi.fill(HIST("hMassXiSelected"), casc.mXi()); + if (xiPassTOFSelection) { + rXi.fill(HIST("hMassXiSelectedWithTOF"), casc.mXi()); + } + + rXi.fill(HIST("hCascDCAV0Daughters"), casc.dcaV0daughters()); + rXi.fill(HIST("hCascCosPA"), casc.casccosPA(collision.posX(), collision.posY(), collision.posZ())); + } + if (TMath::Abs(bachDaughterTrackCasc.tpcNSigmaKa()) < NSigmaTPCKaon) { // Omega case + if (TMath::Abs(casc.mXi() - pdgDB->Mass(3312)) > cascadesetting_competingmassrej) { // competing mass rejection, only in case of Omega + rOmega.fill(HIST("hMassOmegaSelected"), casc.mOmega()); + if (omegaPassTOFSelection) { + rOmega.fill(HIST("hMassOmegaSelectedWithTOF"), casc.mOmega()); + } + + rOmega.fill(HIST("hCascDCAV0Daughters"), casc.dcaV0daughters()); + rOmega.fill(HIST("hCascCosPA"), casc.casccosPA(collision.posX(), collision.posY(), collision.posZ())); + } + } + + // MC truth info + if (!casc.has_cascMCCore()) { + continue; + } + auto cascmccore = casc.cascMCCore_as(); + + // Checking that the cascade is a true Xi + if (TMath::Abs(cascmccore.pdgCode()) == 3312) { + if (TMath::Abs(bachDaughterTrackCasc.tpcNSigmaPi()) < NSigmaTPCPion) { // Xi case + rXi.fill(HIST("hMassXiTrueRec"), casc.mXi()); + rXi.fill(HIST("hPtXiTrueRec"), casc.pt()); + if (xiPassTOFSelection) { + rXi.fill(HIST("hMassXiTrueRecWithTOF"), casc.mXi()); + rXi.fill(HIST("hPtXiTrueRecWithTOF"), casc.pt()); + } + } + } + if (TMath::Abs(cascmccore.pdgCode()) == 3334) { + if (TMath::Abs(bachDaughterTrackCasc.tpcNSigmaKa()) < NSigmaTPCKaon) { // Omega case + if (TMath::Abs(casc.mXi() - pdgDB->Mass(3312)) > cascadesetting_competingmassrej) { // competing mass rejection, only in case of Omega + rOmega.fill(HIST("hMassOmegaTrueRec"), casc.mOmega()); + rOmega.fill(HIST("hPtOmegaTrueRec"), casc.pt()); + if (omegaPassTOFSelection) { + rOmega.fill(HIST("hMassOmegaTrueRecWithTOF"), casc.mOmega()); + rOmega.fill(HIST("hPtOmegaTrueRecWithTOF"), casc.pt()); + } + } + } + } + } + } + + void processGenMC(soa::Filtered::iterator const& mcCollision, + const soa::SmallGroups>& collisions, + const soa::SmallGroups>& cascMC) + { + if (collisions.size() < 1) // to process generated collisions that've been reconstructed at least once + return; + rEventSelection.fill(HIST("hVertexZGen"), mcCollision.posZ()); + + for (const auto& cascmc : cascMC) { + if (TMath::Abs(cascmc.pdgCode()) == 3312) { + rGenParticles.fill(HIST("hPtXiGen"), cascmc.ptMC()); + } + if (TMath::Abs(cascmc.pdgCode()) == 3334) { + rGenParticles.fill(HIST("hPtOmegaGen"), cascmc.ptMC()); + } + } + } + + PROCESS_SWITCH(strangeness_pbpb_tutorial, processRecMC, "Process Run 3 mc, reconstructed", true); + PROCESS_SWITCH(strangeness_pbpb_tutorial, processGenMC, "Process Run 3 mc, generated", true); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc)}; +} diff --git a/Tutorials/PWGLF/Strangeness/PbPb/CMakeLists.txt b/Tutorials/PWGLF/Strangeness/PbPb/CMakeLists.txt new file mode 100644 index 00000000000..f593f821726 --- /dev/null +++ b/Tutorials/PWGLF/Strangeness/PbPb/CMakeLists.txt @@ -0,0 +1,13 @@ +# Copyright 2019-2020 CERN and copyright holders of ALICE O2. +# See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +# All rights not expressly granted are reserved. +# +# This software is distributed under the terms of the GNU General Public +# License v3 (GPL Version 3), copied verbatim in the file "COPYING". +# +# In applying this license CERN does not waive the privileges and immunities +# granted to it by virtue of its status as an Intergovernmental Organization +# or submit itself to any jurisdiction. + +add_subdirectory(Analysis) +# add_subdirectory(DerivedDataProduction) \ No newline at end of file diff --git a/Tutorials/PWGLF/Strangeness/PbPb/DerivedDataProduction/Data/run.sh b/Tutorials/PWGLF/Strangeness/PbPb/DerivedDataProduction/Data/run.sh new file mode 100644 index 00000000000..632f8375470 --- /dev/null +++ b/Tutorials/PWGLF/Strangeness/PbPb/DerivedDataProduction/Data/run.sh @@ -0,0 +1,42 @@ +#!/bin/bash +# log file where the terminal output will be saved +STEP="deriveddata" +LOGFILE="log-${STEP}.txt" + +#directory of this script +DIR_THIS=$PWD + +OPTION="-b --configuration json://configuration.json" + +o2-analysis-pid-tof-base "${OPTION}" | + o2-analysis-event-selection "${OPTION}" | + o2-analysis-lf-lambdakzerobuilder "${OPTION}" | + o2-analysis-lf-cascadebuilder "${OPTION}" | + o2-analysis-multiplicity-table "${OPTION}" | + o2-analysis-centrality-table "${OPTION}" | + o2-analysis-lf-epvector "${OPTION}" | + o2-analysis-centrality-qa "${OPTION}" | + o2-analysis-ud-sgcand-producer "${OPTION}" | + o2-analysis-timestamp "${OPTION}" | + o2-analysis-ft0-corrected-table "${OPTION}" | + o2-analysis-track-propagation "${OPTION}" | + o2-analysis-pid-tpc-base "${OPTION}" | + o2-analysis-pid-tpc "${OPTION}" | + o2-analysis-trackselection "${OPTION}" | + o2-analysis-pid-tof-full "${OPTION}" | + o2-analysis-pid-tof-beta "${OPTION}" | + o2-analysis-lf-strangederivedbuilder "${OPTION}" --aod-file @input_data.txt --aod-writer-json OutputDirector.json >"$LOGFILE" 2>&1 + +# report status +rc=$? +if [ $rc -eq 0 ]; then + echo "No problems!" + mkdir -p "${DIR_THIS}/results/${STEP}" + mv AnalysisResults.root "${DIR_THIS}/results/${STEP}/AnalysisResults.root" + mv AO2D.root "${DIR_THIS}/results/${STEP}/AO2D.root" + mv dpl-config.json "${DIR_THIS}/results/${STEP}/${STEP}.json" +else + echo "Error: Exit code ${rc}" + echo "Check the log file ${LOGFILE}" + exit ${rc} +fi diff --git a/Tutorials/PWGLF/Strangeness/PbPb/DerivedDataProduction/MC/runMC.sh b/Tutorials/PWGLF/Strangeness/PbPb/DerivedDataProduction/MC/runMC.sh new file mode 100644 index 00000000000..e9e086e4f4e --- /dev/null +++ b/Tutorials/PWGLF/Strangeness/PbPb/DerivedDataProduction/MC/runMC.sh @@ -0,0 +1,44 @@ +#!/bin/bash +# log file where the terminal output will be saved +STEP="deriveddata" +LOGFILE="log-${STEP}.txt" + +#directory of this script +DIR_THIS=$PWD + +OPTION="-b --configuration json://configurationMC.json" + +o2-analysis-pid-tof-base "${OPTION}" | + o2-analysis-mccollisionextra "${OPTION}" | + o2-analysis-lf-lambdakzerobuilder "${OPTION}" | + o2-analysis-lf-cascadebuilder "${OPTION}" | + o2-analysis-lf-cascademcbuilder "${OPTION}" | + o2-analysis-centrality-table "${OPTION}" | + o2-analysis-lf-lambdakzeromcbuilder "${OPTION}" | + o2-analysis-mccollision-converter "${OPTION}" | + o2-analysis-ud-sgcand-producer "${OPTION}" | + o2-analysis-timestamp "${OPTION}" | + o2-analysis-ft0-corrected-table "${OPTION}" | + o2-analysis-track-propagation "${OPTION}" | + o2-analysis-pid-tpc-base "${OPTION}" | + o2-analysis-pid-tpc "${OPTION}" | + o2-analysis-multiplicity-table "${OPTION}" | + o2-analysis-trackselection "${OPTION}" | + o2-analysis-pid-tof-full "${OPTION}" | + o2-analysis-pid-tof-beta "${OPTION}" | + o2-analysis-event-selection "${OPTION}" | + o2-analysis-lf-strangederivedbuilder "${OPTION}" --aod-file @input_dataMC.txt --aod-writer-json OutputDirectorMC.json >"$LOGFILE" 2>&1 + +# report status +rc=$? +if [ $rc -eq 0 ]; then + echo "No problems!" + mkdir -p "${DIR_THIS}/results/${STEP}" + mv AnalysisResults.root "${DIR_THIS}/results/${STEP}/AnalysisResults.root" + mv AO2D.root "${DIR_THIS}/results/${STEP}/AO2D.root" + mv dpl-config.json "${DIR_THIS}/results/${STEP}/${STEP}.json" +else + echo "Error: Exit code ${rc}" + echo "Check the log file ${LOGFILE}" + exit ${rc} +fi diff --git a/Tutorials/PWGLF/Strangeness/README.md b/Tutorials/PWGLF/Strangeness/README.md index ee28059d0f8..1976051fe3b 100644 --- a/Tutorials/PWGLF/Strangeness/README.md +++ b/Tutorials/PWGLF/Strangeness/README.md @@ -1,13 +1,29 @@ # This is the base for the PWGLF tutorials for the O2AT -The tutorial (17-28 Apr 2023) can be still used and is a reference for the LF analyses. +The tutorial (14-18 Oct 2024) can be used as a reference for the LF analysis. It is built as a set of steps. Each step adds a level of complexity and is built in a separate executable. -The executables are defined in the `CMakeLists.txt`. -## Files -* `README.md` this readme +The tutorial is divided into two directories depending on the collision system: +## pp +This repository contains the codes to analyse V0 and cascade particles in proton-proton collisions: * `CMakeLists.txt` here are defined the source files to compile * `strangeness_step0.cxx` Starting point: loop over all V0s and fill invariant mass histogram * `strangeness_step1.cxx` Apply selections on topological variables of V0s * `strangeness_step2.cxx` Apply PID selections on V0 daughter tracks * `strangeness_step3.cxx` Check the MC information of the V0s and verify with the PID information of daughter tracks + +The introduction and hands-on sessions can be found here: https://indico.cern.ch/event/1326201/ + +## PbPb +This repository contains the code to analyse cascade particles in Pb-Pb collisions. +The tutorial revolves around two aspects: +i) the derived data production in the directory DerivedDataProduction, +ii) the analysis of the derived data in the directory Analysis, containing: +* `CMakeLists.txt` here are defined the source files to compile +* `strangeness_pbpb_step0.cxx` Starting point: loop over all cascades and fill invariant mass histogram +* `strangeness_pbpb_step1.cxx` Apply selections on topological variables of cascades +* `strangeness_pbpb_step2.cxx` Apply TPC PID selections on cascade daughter tracks +* `strangeness_pbpb_step3.cxx` Apply TOF PID selections on cascade daughter tracks (if available) +* `strangeness_pbpb_step4.cxx` Check the MC information of the cascade + +The introduction and hands-on sessions can be found here: https://indico.cern.ch/event/1425820/ \ No newline at end of file diff --git a/Tutorials/PWGLF/Strangeness/pp/CMakeLists.txt b/Tutorials/PWGLF/Strangeness/pp/CMakeLists.txt new file mode 100644 index 00000000000..f46ac1f9e0b --- /dev/null +++ b/Tutorials/PWGLF/Strangeness/pp/CMakeLists.txt @@ -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. + +# Strangeness analysis tutorial +o2physics_add_dpl_workflow(strangeness-step0 + SOURCES strangeness_step0.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore + COMPONENT_NAME AnalysisTutorial) + +o2physics_add_dpl_workflow(strangeness-step1 + SOURCES strangeness_step1.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore + COMPONENT_NAME AnalysisTutorial) + +o2physics_add_dpl_workflow(strangeness-step2 + SOURCES strangeness_step2.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore + COMPONENT_NAME AnalysisTutorial) + +o2physics_add_dpl_workflow(strangeness-step3 + SOURCES strangeness_step3.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore + COMPONENT_NAME AnalysisTutorial) + +o2physics_add_dpl_workflow(strangeness-step4 + SOURCES strangeness_step4.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore + COMPONENT_NAME AnalysisTutorial) \ No newline at end of file diff --git a/Tutorials/PWGLF/Strangeness/strangeness_step0.cxx b/Tutorials/PWGLF/Strangeness/pp/strangeness_step0.cxx similarity index 100% rename from Tutorials/PWGLF/Strangeness/strangeness_step0.cxx rename to Tutorials/PWGLF/Strangeness/pp/strangeness_step0.cxx diff --git a/Tutorials/PWGLF/Strangeness/strangeness_step1.cxx b/Tutorials/PWGLF/Strangeness/pp/strangeness_step1.cxx similarity index 100% rename from Tutorials/PWGLF/Strangeness/strangeness_step1.cxx rename to Tutorials/PWGLF/Strangeness/pp/strangeness_step1.cxx diff --git a/Tutorials/PWGLF/Strangeness/strangeness_step2.cxx b/Tutorials/PWGLF/Strangeness/pp/strangeness_step2.cxx similarity index 100% rename from Tutorials/PWGLF/Strangeness/strangeness_step2.cxx rename to Tutorials/PWGLF/Strangeness/pp/strangeness_step2.cxx diff --git a/Tutorials/PWGLF/Strangeness/strangeness_step3.cxx b/Tutorials/PWGLF/Strangeness/pp/strangeness_step3.cxx similarity index 100% rename from Tutorials/PWGLF/Strangeness/strangeness_step3.cxx rename to Tutorials/PWGLF/Strangeness/pp/strangeness_step3.cxx diff --git a/Tutorials/PWGLF/Strangeness/strangeness_step4.cxx b/Tutorials/PWGLF/Strangeness/pp/strangeness_step4.cxx similarity index 100% rename from Tutorials/PWGLF/Strangeness/strangeness_step4.cxx rename to Tutorials/PWGLF/Strangeness/pp/strangeness_step4.cxx diff --git a/Tutorials/PWGUD/CMakeLists.txt b/Tutorials/PWGUD/CMakeLists.txt index da52aa07b26..de978b518dc 100644 --- a/Tutorials/PWGUD/CMakeLists.txt +++ b/Tutorials/PWGUD/CMakeLists.txt @@ -39,3 +39,21 @@ o2physics_add_dpl_workflow(udtutorial-04 PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(udtutorial-05 + SOURCES UDTutorial_05.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(udtutorial-06 + SOURCES UDTutorial_06.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(udtutorial-07 + SOURCES UDTutorial_07.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + + + + diff --git a/Tutorials/PWGUD/UDTutorial_05.cxx b/Tutorials/PWGUD/UDTutorial_05.cxx new file mode 100644 index 00000000000..3a9bfb79605 --- /dev/null +++ b/Tutorials/PWGUD/UDTutorial_05.cxx @@ -0,0 +1,318 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. +// + +#include "iostream" +#include "TLorentzVector.h" +#include "TDatabasePDG.h" + +#include "Framework/runDataProcessing.h" +#include "Framework/AnalysisTask.h" +#include "Framework/AnalysisDataModel.h" +#include "PWGUD/DataModel/UDTables.h" +#include "PWGUD/Core/SGSelector.h" +#include "PWGUD/Core/SGTrackSelector.h" + +// using namespace std; +using namespace o2; +using namespace o2::aod; +using namespace o2::framework; +using namespace o2::framework::expressions; + +/// \brief Example task to study two pions candidates using SG derive data +/// \author Anisa Khatun +/// \date 10.10.2024 + +// Struct to define the analysis task +struct UDTutorial05 { + // SGSelector object to manage track and collision selections + SGSelector sgSelector; + + Configurable FV0_cut{"FV0", 100., "FV0A threshold"}; + Configurable FT0A_cut{"FT0A", 100., "FT0A threshold"}; + Configurable FT0C_cut{"FT0C", 50., "FT0C threshold"}; + Configurable FDDA_cut{"FDDA", 10000., "FDDA threshold"}; + Configurable FDDC_cut{"FDDC", 10000., "FDDC threshold"}; + Configurable ZDC_cut{"ZDC", 10., "ZDC threshold"}; + Configurable gap_Side{"gap", 2, "gap selection"}; + + // Track Selections + Configurable PV_cut{"PV_cut", 1.0, "Use Only PV tracks"}; + Configurable dcaZ_cut{"dcaZ_cut", 2.0, "dcaZ cut"}; + Configurable dcaXY_cut{"dcaXY_cut", 0.0, "dcaXY cut (0 for Pt-function)"}; + Configurable tpcChi2_cut{"tpcChi2_cut", 4, "Max tpcChi2NCl"}; + Configurable tpcNClsFindable_cut{"tpcNClsFindable_cut", 70, "Min tpcNClsFindable"}; + Configurable itsChi2_cut{"itsChi2_cut", 36, "Max itsChi2NCl"}; + Configurable eta_cut{"eta_cut", 0.9, "Track Pseudorapidity"}; + Configurable pt_cut{"pt_cut", 0.01, "Track Pt"}; + Configurable TPC_cluster{"TPC_cluster", 50, "No.of TPC cluster"}; + + // Kinmatic cuts + Configurable PID_cut{"PID_cut", 5, "TPC PID"}; + Configurable Rap_cut{"Rap_cut", 0.9, "Track rapidity"}; + Configurable Mass_Max{"Mass_Max", 10, "Invariant Mass range high"}; + Configurable Mass_Min{"Mass_Min", 0, "Invariant Mass range low"}; + Configurable Pt_coherent{"Pt_coherent", 0.15, "Coherent selection"}; + + // defining histograms using histogram registry + HistogramRegistry registry{"registry", {}, OutputObjHandlingPolicy::AnalysisObject}; + + //----------------------------------------------------------------------------------------------------------------------- + void init(o2::framework::InitContext&) + { + + registry.add("GapSide", "Gap Side; Entries", kTH1F, {{4, -1.5, 2.5}}); + registry.add("TrueGapSide", "Gap Side; Entries", kTH1F, {{4, -1.5, 2.5}}); + + // Fill counter to see effect of each selection criteria + auto hSelectionCounter = registry.add("hSelectionCounter", "hSelectionCounter;;NEvents", HistType::kTH1I, {{20, 0., 20.}}); + + TString SelectionCuts[16] = {"NoSelection", "gapside", "goodtracks", "truegap", "2collcontrib", "2goodtrk", "TPCPID", "Rap_cut", "unlikesign", "mass_cut", "coherent", "incoherent", "likesign", "mass_cut", "coherent", "incoherent"}; + + for (int i = 0; i < 16; i++) { + hSelectionCounter->GetXaxis()->SetBinLabel(i + 1, SelectionCuts[i].Data()); + } + // tracks + registry.add("hTracks", "N_{tracks}", kTH1F, {{100, -0.5, 99.5}}); + registry.add("hTracksPions", "N_{tracks}", kTH1F, {{100, -0.5, 99.5}}); + registry.add("TwoPion/h2TracksPions", "N_{tracks}", kTH1F, {{100, -0.5, 99.5}}); + + registry.add("hdEdx", "p vs dE/dx Signal", kTH2F, {{100, 0.0, 3.0}, {100, 0.0, 200.0}}); + registry.add("hdEdxPion", "p_{#pi} vs dE/dx Signal", kTH2F, {{100, 0.0, 3.0}, {100, 0.0, 200.0}}); + + registry.add("TwoPion/hNsigPi1vsPi2", "NSigmaPi(t1) vs NSigmapi (t2);n#sigma_{1};n#sigma_{2}", kTH2F, {{100, -15., 15.}, {100, -15., 15}}); + registry.add("TwoPion/hNsigEl1vsEl2", "NSigmaEl(t1) vs NSigmaEl (t2);n#sigma_{1};n#sigma_{2}", kTH2F, {{100, -15., 15.}, {100, -15., 15}}); + registry.add("TwoPion/hNsigPivsPt1", "Pt vs NSigmaPi (t1);#it{p_{t}}, GeV/c;n#sigma_{#pi}", kTH2F, {{100, 0., 2.5}, {100, -15., 15}}); + registry.add("TwoPion/hNsigPivsPt2", "Pt vs NSigmaPi (t2);#it{p_{t}}, GeV/c;n#sigma_{#pi}", kTH2F, {{100, 0., 2.5}, {100, -15., 15}}); + registry.add("TwoPion/hNsigElvsPt1", "Pt vs NSigmaEl (t1);#it{p_{t}}, GeV/c;n#sigma_{#e}", kTH2F, {{100, 0., 2.5}, {100, -15., 15}}); + registry.add("TwoPion/hNsigElvsPt2", "Pt vs NSigmaEl (t2);#it{p_{t}}, GeV/c;n#sigma_{#e}", kTH2F, {{100, 0., 2.5}, {100, -15., 15}}); + registry.add("TwoPion/hNsigMuvsPt1", "Pt vs NSigmaMu (t1);#it{p_{t}}, GeV/c;n#sigma_{#pi}", kTH2F, {{100, 0., 2.5}, {100, -15., 15}}); + registry.add("TwoPion/hNsigMuvsPt2", "Pt vs NSigmaMu (t2);#it{p_{t}}, GeV/c;n#sigma_{#pi}", kTH2F, {{100, 0., 2.5}, {100, -15., 15}}); + + registry.add("TwoPion/hPtsingle_track1", "Pt t1;#it{p_{t}}, GeV/c;", kTH1F, {{600, 0., 3.}}); + registry.add("TwoPion/hPtsingle_track2", "Pt t2;#it{p_{t}}, GeV/c;", kTH1F, {{600, 0., 3.}}); + registry.add("TwoPion/hEta_t1", "Eta of t1;#it{#eta};", kTH1F, {{100, -5., 5.}}); + registry.add("TwoPion/hEta_t2", "Eta of t2;#it{#eta};", kTH1F, {{100, -5., 5.}}); + registry.add("TwoPion/hP1", "P vs TPC signal;#it{P_{track}}, GeV/c; signal_{TPC} t1", kTH2F, {{100, 0., 2.}, {300, 0, 150}}); + registry.add("TwoPion/hTPCsig", "TPC signal;signal_{TPC} t2; signal_{TPC} t2", kTH2F, {{300, 0., 150.}, {300, 0, 150}}); + registry.add("TwoPion/hP2", "P vs TPC signal;#it{P_{track}}, GeV/c; signal_{TPC} t1", kTH2F, {{100, 0., 2.}, {300, 0, 150}}); + registry.add("TwoPion/hTPCsig1", "TPC signal;signal_{TPC} t2; signal_{TPC} t2", kTH2F, {{300, 0., 150.}, {300, 0, 150}}); + + registry.add("TwoPion/hMassLike", "m_{#pi#pi} [GeV/#it{c}^{2}]", kTH1F, {{20000, 0., 20.}}); + registry.add("TwoPion/hMassUnlike", "m_{#pi#pi} [GeV/#it{c}^{2}]", kTH1F, {{20000, 0., 20.}}); + registry.add("TwoPion/Coherent/hMassUnlikeCoherent", "m_{#pi#pi} [GeV/#it{c}^{2}]", kTH1F, {{20000, 0., 20.}}); + registry.add("TwoPion/Coherent/hMassLikeCoherent", "m_{#pi#pi} [GeV/#it{c}^{2}]", kTH1F, {{20000, 0., 20.}}); + registry.add("TwoPion/Incoherent/hMassUnlikeInCoherent", "m_{#pi#pi} [GeV/#it{c}^{2}]", kTH1F, {{20000, 0., 20.}}); + registry.add("TwoPion/Incoherent/hMassLikeInCoherent", "m_{#pi#pi} [GeV/#it{c}^{2}]", kTH1F, {{20000, 0., 20.}}); + + registry.add("TwoPion/hPt", "Pt;#it{p_{t}}, GeV/c;", kTH1D, {{1000, 0., 10.}}); + registry.add("TwoPion/hPtLike", "Pt;#it{p_{t}}, GeV/c;", kTH1D, {{1000, 0., 10.}}); + registry.add("TwoPion/hEta", "Eta;#it{#eta};", kTH1F, {{500, -10., 10.}}); + registry.add("TwoPion/hRap", "Rapidity;#it{y};", kTH1F, {{500, -10., 10.}}); + registry.add("TwoPion/hPhiSystem", "Phi;#it{#Phi};", kTH1F, {{250, 0. * TMath::Pi(), 2. * TMath::Pi()}}); + registry.add("TwoPion/hMPt", "Inv.M vs Pt;M, GeV/c^{2};#it{P_{t}}, GeV/c;", kTH2F, {{100, 0., 10.}, {100, 0., 10.}}); + } + + using udtracks = soa::Join; + using udtracksfull = soa::Join; + + using UDCollisionsFull = soa::Join; + + //__________________________________________________________________________ + // Main process + void process(UDCollisionsFull::iterator const& collision, udtracksfull const& tracks) + { + // No selection criteria + registry.fill(HIST("hSelectionCounter"), 0); + + // Accessing gap sides + int gapSide = collision.gapSide(); + if (gapSide < 0 || gapSide > 2) + return; + + registry.fill(HIST("hSelectionCounter"), 1); + + // Accessing FIT information for further exclusivity and/or inclusivity + float FIT_cut[5] = {FV0_cut, FT0A_cut, FT0C_cut, FDDA_cut, FDDC_cut}; + int truegapSide = sgSelector.trueGap(collision, FIT_cut[0], FIT_cut[1], FIT_cut[2], ZDC_cut); + + // Intiating track parameters to select good tracks, values to be optimized in the configurables, parameters will be taken from SGtrackselector.h task included in the header + std::vector parameters = {PV_cut, dcaZ_cut, dcaXY_cut, tpcChi2_cut, tpcNClsFindable_cut, itsChi2_cut, eta_cut, pt_cut}; + + registry.fill(HIST("GapSide"), gapSide); + registry.fill(HIST("TrueGapSide"), truegapSide); + + // Gap side to be selected in the configuables + gapSide = truegapSide; + + if (gapSide == gap_Side) { + + registry.fill(HIST("hSelectionCounter"), 2); + + //____________________________________________________________________________________ + + // Create LorentzVector to store all tracks, Pion tracks and TPC Pion PID + std::vector allTracks; + std::vector onlyPionTracks; + std::vector onlyPionSigma; + std::vector rawPionTracks; + TLorentzVector p; + + registry.fill(HIST("hTracks"), tracks.size()); + + for (auto t : tracks) { + // Apply good track selection criteria + if (!trackselector(t, parameters)) + continue; + + double dEdx = t.tpcSignal(); + + registry.fill(HIST("hdEdx"), t.tpcInnerParam() / t.sign(), dEdx); + + // Creating Lorenz vector to store raw tracks and piontracks + TLorentzVector a; + a.SetXYZM(t.px(), t.py(), t.pz(), o2::constants::physics::MassPionCharged); + allTracks.push_back(a); + + // Apply TPC pion sigma + auto nSigmaPi = t.tpcNSigmaPi(); + if (fabs(nSigmaPi) < PID_cut) { + onlyPionTracks.push_back(a); + onlyPionSigma.push_back(nSigmaPi); + rawPionTracks.push_back(t); + registry.fill(HIST("hdEdxPion"), t.tpcInnerParam() / t.sign(), dEdx); + } + } + + registry.fill(HIST("hTracksPions"), onlyPionTracks.size()); + //_____________________________________ + // Adding all onlypiontracks + for (auto pion : onlyPionTracks) { + p += pion; + } + + //_____________________________________ + // Selecting collisions with Two PV contributors + if (collision.numContrib() == 2) { + + registry.fill(HIST("hSelectionCounter"), 3); + + // Selecting only Two good tracks + if ((rawPionTracks.size() == 2) && (onlyPionTracks.size() == 2)) { + + registry.fill(HIST("hSelectionCounter"), 4); + + registry.fill(HIST("TwoPion/h2TracksPions"), onlyPionTracks.size()); + + registry.fill(HIST("TwoPion/hNsigPivsPt1"), onlyPionTracks[0].Pt(), rawPionTracks[0].tpcNSigmaPi()); + registry.fill(HIST("TwoPion/hNsigPivsPt2"), onlyPionTracks[1].Pt(), rawPionTracks[1].tpcNSigmaPi()); + registry.fill(HIST("TwoPion/hTPCsig"), rawPionTracks[0].tpcSignal(), rawPionTracks[1].tpcSignal()); + registry.fill(HIST("TwoPion/hNsigPi1vsPi2"), rawPionTracks[0].tpcNSigmaPi(), rawPionTracks[1].tpcNSigmaPi()); + + // Make sure two good tracks are with TPC pion sigma limit + if ((onlyPionSigma[0] * onlyPionSigma[0] + onlyPionSigma[1] * onlyPionSigma[1]) > (PID_cut * PID_cut)) { + return; + } + + registry.fill(HIST("hSelectionCounter"), 5); + + // Rapidity of midrapidity acceptance + if ((p.Rapidity() < -Rap_cut) || (p.Rapidity() > Rap_cut)) { + return; + } + + registry.fill(HIST("hSelectionCounter"), 6); + + // Two oppsotite sign tracks + if (rawPionTracks[0].sign() != rawPionTracks[1].sign()) { + + registry.fill(HIST("hSelectionCounter"), 7); + registry.fill(HIST("TwoPion/hMassUnlike"), p.M()); + + // Flexible mass limits, can be selected in the configurable + if ((p.M() > Mass_Min) && (p.M() < Mass_Max)) { + + registry.fill(HIST("hSelectionCounter"), 8); + + registry.fill(HIST("TwoPion/hPt"), p.Pt()); + registry.fill(HIST("TwoPion/hEta"), p.Eta()); + registry.fill(HIST("TwoPion/hRap"), p.Rapidity()); + registry.fill(HIST("TwoPion/hPhiSystem"), p.Phi()); + registry.fill(HIST("TwoPion/hMPt"), p.M(), p.Pt()); + + // flexible pt limit for selecting coherent Rho(0) + if (p.Pt() < Pt_coherent) { + + registry.fill(HIST("hSelectionCounter"), 9); + + // Quality Control plots after coherent Rho(0) selection + registry.fill(HIST("TwoPion/hEta_t1"), onlyPionTracks[0].Eta()); + registry.fill(HIST("TwoPion/hEta_t2"), onlyPionTracks[1].Eta()); + registry.fill(HIST("TwoPion/hPtsingle_track1"), onlyPionTracks[0].Pt()); + registry.fill(HIST("TwoPion/hPtsingle_track2"), onlyPionTracks[1].Pt()); + + registry.fill(HIST("TwoPion/hNsigMuvsPt1"), onlyPionTracks[0].Pt(), rawPionTracks[0].tpcNSigmaPi()); + registry.fill(HIST("TwoPion/hNsigMuvsPt2"), onlyPionTracks[1].Pt(), rawPionTracks[1].tpcNSigmaPi()); + registry.fill(HIST("TwoPion/hNsigElvsPt1"), onlyPionTracks[0].Pt(), rawPionTracks[0].tpcNSigmaEl()); + registry.fill(HIST("TwoPion/hNsigElvsPt2"), onlyPionTracks[1].Pt(), rawPionTracks[1].tpcNSigmaEl()); + registry.fill(HIST("TwoPion/hNsigEl1vsEl2"), rawPionTracks[0].tpcNSigmaPi(), rawPionTracks[1].tpcNSigmaPi()); + + registry.fill(HIST("TwoPion/hP1"), onlyPionTracks[0].P(), rawPionTracks[0].tpcSignal()); + registry.fill(HIST("TwoPion/hP2"), onlyPionTracks[1].P(), rawPionTracks[1].tpcSignal()); + registry.fill(HIST("TwoPion/hTPCsig1"), rawPionTracks[0].tpcSignal(), rawPionTracks[1].tpcSignal()); + + registry.fill(HIST("TwoPion/Coherent/hMassUnlikeCoherent"), p.M()); + } + // Incoherent Rho(0) selection + if (p.Pt() > Pt_coherent) { + registry.fill(HIST("hSelectionCounter"), 10); + registry.fill(HIST("TwoPion/Incoherent/hMassUnlikeInCoherent"), p.M()); + } + } + } + + // Same charge particles + if (rawPionTracks[0].sign() == rawPionTracks[1].sign()) { + + registry.fill(HIST("hSelectionCounter"), 11); + registry.fill(HIST("TwoPion/hMassLike"), p.M()); + + // Mass limit + if ((p.M() > Mass_Min) && (p.M() < Mass_Max)) { + + registry.fill(HIST("hSelectionCounter"), 12); + registry.fill(HIST("TwoPion/hPtLike"), p.Pt()); + + // Coherent Rho(0) selection + if (p.Pt() < Pt_coherent) { + + registry.fill(HIST("hSelectionCounter"), 13); + registry.fill(HIST("TwoPion/Coherent/hMassLikeCoherent"), p.M()); + } + // Incoherent Rho(0) selection + if (p.Pt() > Pt_coherent) { + + registry.fill(HIST("hSelectionCounter"), 14); + registry.fill(HIST("TwoPion/Incoherent/hMassLikeInCoherent"), p.M()); + } + } + } + } + } + } + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc, TaskName{"udtutorial05"})}; +} diff --git a/Tutorials/PWGUD/UDTutorial_06.cxx b/Tutorials/PWGUD/UDTutorial_06.cxx new file mode 100644 index 00000000000..9b1d1f55895 --- /dev/null +++ b/Tutorials/PWGUD/UDTutorial_06.cxx @@ -0,0 +1,232 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. +/// +/// \brief This task is to compute invariant mass of dimuon at forward rapidity for UPC events. +/// \author Anisa Khatun +/// \date 10.10.2024 + +// O2 headers +#include "Framework/runDataProcessing.h" +#include "Framework/AnalysisTask.h" +#include "Framework/AnalysisDataModel.h" + +// O2Physics headers +#include "PWGUD/DataModel/UDTables.h" +#include "PWGUD/Core/UDHelpers.h" +#include "CCDB/BasicCCDBManager.h" +#include "DataFormatsParameters/GRPLHCIFData.h" +#include "DataFormatsParameters/GRPECSObject.h" + +// ROOT headers +#include "TSystem.h" +#include "TDatabasePDG.h" +#include "TLorentzVector.h" +#include "TLorentzVector.h" +#include "TMath.h" + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace std; + +struct UDTutorial06 { + + // Histogram registry: an object to hold your histograms + HistogramRegistry registry{"registry", {}, OutputObjHandlingPolicy::AnalysisObject}; + Configurable nBinsPt{"nBinsPt", 500, "N bins in pT histo"}; + Configurable nBinsMass{"nBinsMass", 500, "N bins in InvMass histo"}; + + using UDCollisionsFwd = soa::Join; + using fwdtraks = soa::Join; + + void init(InitContext const&) + { + // define axes you want to use + const AxisSpec axisCounter{1, 0, +1, ""}; + const AxisSpec axisEta{80, -5.0, -2.0, "#eta"}; + const AxisSpec axisPt{nBinsPt, 0.0, 10.0, "p_{T}"}; + const AxisSpec axisM{nBinsMass, 0.0, 10.0, "M_{#pi#pi}"}; + const AxisSpec axisPhi{120, -TMath::Pi(), -TMath::Pi(), "#phi"}; + const AxisSpec axisRapidity{80, -5.0, -2.0, "#it{y}"}; + + // create histograms + // Fill counter to see effect of each selection criteria + auto hSelectionCounter = registry.add("hSelectionCounter", "hSelectionCounter;;NEvents", HistType::kTH1I, {{15, 0., 15.}}); + TString SelectionCuts[13] = {"NoSelection", "V0A", "rAbs1", "rAbs2", "trackmatch", "eta1", "eta2", "trackpt", "pair rapidity", "mass_cut", "unlikesign", "likesign"}; + + for (int i = 0; i < 12; i++) { + hSelectionCounter->GetXaxis()->SetBinLabel(i + 1, SelectionCuts[i].Data()); + } + + registry.add("eventCounter", "eventCounter", kTH1F, {axisCounter}); + registry.add("hnumContrib", "hnumContrib;;#counts", kTH1D, {{100, -0.5, 99.5}}); + registry.add("hTracks1", "N_{tracks}", kTH1F, {{100, -0.5, 99.5}}); + registry.add("hTracks2", "N_{tracks}", kTH1F, {{100, -0.5, 99.5}}); + registry.add("hTracksMuons", "N_{tracks}", kTH1F, {{100, -0.5, 99.5}}); + + registry.add("etaMuon1", "etaMuon1", kTH1F, {axisEta}); + registry.add("ptMuon1", "ptMuon1", kTH1F, {axisPt}); + registry.add("phiMuon1", "phiMuon1", kTH1F, {axisPhi}); + + registry.add("etaMuon2", "etaMuon2", kTH1F, {axisEta}); + registry.add("ptMuon2", "ptMuon2", kTH1F, {axisPt}); + registry.add("phiMuon2", "phiMuon2", kTH1F, {axisPhi}); + + registry.add("YJpsi", "YJpsi", kTH1F, {axisRapidity}); + registry.add("PhiJpsi", "PhiJpsi", kTH1F, {axisPhi}); + + registry.add("MJpsiUnlike", "MJpsi", kTH1F, {axisM}); + registry.add("PtJpsiUnlike", "PtJpsi", kTH1F, {axisPt}); + registry.add("MJpsiLike", "MJpsi", kTH1F, {axisM}); + registry.add("PtJpsiLike", "PtJpsi", kTH1F, {axisPt}); + } + + //____________________________________________________________________________________________ + + template + void processCandidate(UDCollisionsFwd::iterator const& collision, TTrack1& tr1, TTrack2& tr2) + { + registry.fill(HIST("eventCounter"), 0.5); + registry.fill(HIST("hnumContrib"), collision.numContrib()); + registry.fill(HIST("hTracks1"), tr1.size()); + registry.fill(HIST("hTracks2"), tr2.size()); + registry.fill(HIST("hSelectionCounter"), 0); + + // V0A selection + const auto& ampsV0A = collision.amplitudesV0A(); + const auto& ampsRelBCsV0A = collision.ampRelBCsV0A(); + for (unsigned int i = 0; i < ampsV0A.size(); ++i) { + if (std::abs(ampsRelBCsV0A[i]) <= 1) { + if (ampsV0A[i] > 100.) + return; + } + } + + // T0A selection + const auto& ampsT0A = collision.amplitudesT0A(); + const auto& ampsRelBCsT0A = collision.ampRelBCsT0A(); + for (unsigned int i = 0; i < ampsT0A.size(); ++i) { + if (std::abs(ampsRelBCsT0A[i]) <= 1) { + if (ampsT0A[i] > 100.) + return; + } + } + + registry.fill(HIST("hSelectionCounter"), 1); + + // absorber end selection + if (tr1.rAtAbsorberEnd() < 17.6 || tr1.rAtAbsorberEnd() > 89.5) + return; + registry.fill(HIST("hSelectionCounter"), 2); + if (tr2.rAtAbsorberEnd() < 17.6 || tr2.rAtAbsorberEnd() > 89.5) + return; + registry.fill(HIST("hSelectionCounter"), 3); + + // MCH-MID match selection + if ((tr1.chi2MatchMCHMID() < 0) || (tr2.chi2MatchMCHMID() < 0)) + return; + registry.fill(HIST("hSelectionCounter"), 4); + + bool isUnlikeSign = (tr1.sign() + tr2.sign()) == 0; + bool isLikeSign = ((tr1.sign() + tr2.sign()) != 0); + + // track selection + TLorentzVector p1, p2; + p1.SetXYZM(tr1.px(), tr1.py(), tr1.pz(), o2::constants::physics::MassMuon); + p2.SetXYZM(tr2.px(), tr2.py(), tr2.pz(), o2::constants::physics::MassMuon); + TLorentzVector p = p1 + p2; + + // eta cut on each track + if (p1.Eta() < -4.0 || p1.Eta() > -2.5) + return; + registry.fill(HIST("hSelectionCounter"), 5); + if (p2.Eta() < -4.0 || p2.Eta() > -2.5) + return; + registry.fill(HIST("hSelectionCounter"), 6); + + // pt cut on track + if ((p1.Pt() < 0.0) || (p2.Pt() < 0.0)) + return; + registry.fill(HIST("hSelectionCounter"), 7); + + if ((p.Rapidity() < -4.0) || (p.Rapidity() > -2.5)) + return; + registry.fill(HIST("hSelectionCounter"), 8); + + // cuts on pair kinematics + if (!(p.M() > 2.5 && p.M() < 5.0)) + return; + registry.fill(HIST("hSelectionCounter"), 9); + + registry.fill(HIST("hTracksMuons"), collision.numContrib()); + registry.fill(HIST("ptMuon1"), p1.Pt()); + registry.fill(HIST("ptMuon2"), p2.Pt()); + registry.fill(HIST("etaMuon1"), p1.Eta()); + registry.fill(HIST("etaMuon2"), p2.Eta()); + registry.fill(HIST("phiMuon1"), p1.Phi()); + registry.fill(HIST("phiMuon2"), p2.Phi()); + registry.fill(HIST("YJpsi"), p.Rapidity()); + registry.fill(HIST("PhiJpsi"), p.Phi()); + + if (isUnlikeSign) { + registry.fill(HIST("hSelectionCounter"), 10); + registry.fill(HIST("MJpsiUnlike"), p.M()); + registry.fill(HIST("PtJpsiUnlike"), p.Pt()); + } + + if (isLikeSign) { + registry.fill(HIST("hSelectionCounter"), 11); + registry.fill(HIST("MJpsiLike"), p.M()); + registry.fill(HIST("PtJpsiLike"), p.Pt()); + } + } + + //____________________________________________________________________________________________ + + // Template that collects all collision IDs and track per collision + template + void collectCandIDs(std::unordered_map>& tracksPerCand, TTracks& tracks) + { + for (const auto& tr : tracks) { + int32_t candId = tr.udCollisionId(); + if (candId < 0) { + continue; + } + tracksPerCand[candId].push_back(tr.globalIndex()); + } + } + + //____________________________________________________________________________________________ + + // process candidates with 2 forward tracks + void process(UDCollisionsFwd const& eventCandidates, + fwdtraks const& fwdTracks) + { + std::unordered_map> tracksPerCand; + collectCandIDs(tracksPerCand, fwdTracks); + + // assuming that candidates have exatly 2 forward tracks + for (const auto& item : tracksPerCand) { + int32_t trId1 = item.second[0]; + int32_t trId2 = item.second[1]; + int32_t candID = item.first; + const auto& collision = eventCandidates.iteratorAt(candID); + const auto& tr1 = fwdTracks.iteratorAt(trId1); + const auto& tr2 = fwdTracks.iteratorAt(trId2); + processCandidate(collision, tr1, tr2); + } + } +}; +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc, TaskName{"udtutorial06"})}; +} diff --git a/Tutorials/PWGUD/UDTutorial_07.cxx b/Tutorials/PWGUD/UDTutorial_07.cxx new file mode 100644 index 00000000000..f2a5616f00d --- /dev/null +++ b/Tutorials/PWGUD/UDTutorial_07.cxx @@ -0,0 +1,230 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does 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 "iostream" +#include +#include +#include "Framework/runDataProcessing.h" +#include "Framework/AnalysisTask.h" +#include "Framework/AnalysisDataModel.h" +#include "PWGUD/DataModel/UDTables.h" +#include "TLorentzVector.h" +#include "PWGUD/Core/SGSelector.h" +#include "PWGUD/Core/SGTrackSelector.h" + +using namespace std; +using namespace o2; +using namespace o2::aod; +using namespace o2::framework; +using namespace o2::framework::expressions; + +/// \brief This is an example to fill outputs in a tree, useful for post processing analysis +/// \author Amrit Gautam +/// \author Anisa Khatun +/// \date 10.10.2024 + +namespace o2::aod +{ +namespace tree +{ +// track tables +DECLARE_SOA_COLUMN(SIGMAPI, sigmapi, std::vector); +DECLARE_SOA_COLUMN(PT, Pt, float); +DECLARE_SOA_COLUMN(RAP, rap, float); +DECLARE_SOA_COLUMN(PHI, Phi, float); +DECLARE_SOA_COLUMN(TOTSIGN, totsign, int); +DECLARE_SOA_COLUMN(MASS, mass, float); +DECLARE_SOA_COLUMN(NPVTRACK, npvtrack, int); +DECLARE_SOA_COLUMN(PTS, Pts, std::vector); +DECLARE_SOA_COLUMN(ETAS, etas, std::vector); +DECLARE_SOA_COLUMN(PHIS, Phis, std::vector); +DECLARE_SOA_COLUMN(SIGNS, Signs, std::vector); +} // namespace tree + +DECLARE_SOA_TABLE(TREE, "AOD", "Tree", + tree::PT, + tree::RAP, + tree::PHI, + tree::MASS, + tree::TOTSIGN, + tree::NPVTRACK, + tree::SIGMAPI, + tree::PTS, + tree::ETAS, + tree::PHIS, + tree::SIGNS); + +} // namespace o2::aod + +struct UDTutorial07 { + SGSelector sgSelector; + Produces tree; + + Configurable FV0_cut{"FV0", 100., "FV0A threshold"}; + Configurable FT0A_cut{"FT0A", 200., "FT0A threshold"}; + Configurable FT0C_cut{"FT0C", 100., "FT0C threshold"}; + Configurable FDDA_cut{"FDDA", 10000., "FDDA threshold"}; + Configurable FDDC_cut{"FDDC", 10000., "FDDC threshold"}; + Configurable ZDC_cut{"ZDC", 10., "ZDC threshold"}; + Configurable gap_Side{"gap", 2, "gap selection"}; + + // Track Selections + Configurable PV_cut{"PV_cut", 1.0, "Use Only PV tracks"}; + Configurable dcaZ_cut{"dcaZ_cut", 2.0, "dcaZ cut"}; + Configurable dcaXY_cut{"dcaXY_cut", 0.0, "dcaXY cut (0 for Pt-function)"}; + Configurable tpcChi2_cut{"tpcChi2_cut", 4, "Max tpcChi2NCl"}; + Configurable tpcNClsFindable_cut{"tpcNClsFindable_cut", 70, "Min tpcNClsFindable"}; + Configurable itsChi2_cut{"itsChi2_cut", 36, "Max itsChi2NCl"}; + Configurable eta_cut{"eta_cut", 0.9, "Track Pseudorapidity"}; + Configurable pt_cut{"pt_cut", 0.1, "Track Pt"}; + Configurable TPC_cluster{"TPC_cluster", 50, "No.of TPC cluster"}; + + // Kinmatic cuts + Configurable PID_cut{"PID_cut", 5, "TPC PID"}; + Configurable Rap_cut{"Rap_cut", 0.9, "Track rapidity"}; + Configurable Mass_Max{"Mass_Max", 10, "Invariant Mass range high"}; + Configurable Mass_Min{"Mass_Min", 0, "Invariant Mass range low"}; + Configurable Pt_coherent{"Pt_coherent", 0.15, "Coherent selection"}; + + // defining histograms using histogram registry + HistogramRegistry registry{"registry", {}, OutputObjHandlingPolicy::AnalysisObject}; + + //----------------------------------------------------------------------------------------------------------------------- + void init(o2::framework::InitContext&) + { + + registry.add("GapSide", "Gap Side; Entries", kTH1F, {{4, -1.5, 2.5}}); + registry.add("TrueGapSide", "Gap Side; Entries", kTH1F, {{4, -1.5, 2.5}}); + + // Fill counter to see effect of each selection criteria + auto hSelectionCounter = registry.add("hSelectionCounter", "hSelectionCounter;;NEvents", HistType::kTH1I, {{10, 0., 10.}}); + TString SelectionCuts[7] = {"NoSelection", "gapside", "goodtracks", "truegap", "2collcontrib", "2goodtrk"}; + for (int i = 0; i < 7; i++) { + hSelectionCounter->GetXaxis()->SetBinLabel(i + 1, SelectionCuts[i].Data()); + } + + // Fill histograms to cross-check the selected numbers + registry.add("hTracks", "N_{tracks}", kTH1F, {{100, -0.5, 99.5}}); + registry.add("hTracksPions", "N_{tracks}", kTH1F, {{100, -0.5, 99.5}}); + } + + using udtracks = soa::Join; + using udtracksfull = soa::Join; + using UDCollisionsFull = soa::Join; + //__________________________________________________________________________ + // Main process + void process(UDCollisionsFull::iterator const& collision, udtracksfull const& tracks) + { + registry.fill(HIST("hSelectionCounter"), 0); + + // Accessing gap sides + int gapSide = collision.gapSide(); + if (gapSide < 0 || gapSide > 2) + return; + + registry.fill(HIST("hSelectionCounter"), 1); + + // Accessing FIT information for further exclusivity and/or inclusivity + float FIT_cut[5] = {FV0_cut, FT0A_cut, FT0C_cut, FDDA_cut, FDDC_cut}; + int truegapSide = sgSelector.trueGap(collision, FIT_cut[0], FIT_cut[1], FIT_cut[2], ZDC_cut); + + // Intiating track parameters to select good tracks, values to be optimized in the configurables, parameters will be taken from SGtrackselector.h task included in the header + std::vector parameters = {PV_cut, dcaZ_cut, dcaXY_cut, tpcChi2_cut, tpcNClsFindable_cut, itsChi2_cut, eta_cut, pt_cut}; + + registry.fill(HIST("GapSide"), gapSide); + registry.fill(HIST("TrueGapSide"), truegapSide); + + // Gap side to be selected in the configuables + gapSide = truegapSide; + + registry.fill(HIST("hSelectionCounter"), 2); + //_____________________________________ + // Create LorentzVector to store track information + std::vector allTracks; + std::vector onlyPionTracks; + std::vector onlyPionSigma; + std::vector rawPionTracks; + std::vector trackpt; + std::vector tracketa; + std::vector trackphi; + std::vector tracksign; + std::vector pitpcpid; + + TLorentzVector p; + + if (gapSide == gap_Side) { + + registry.fill(HIST("hSelectionCounter"), 3); + + for (auto t : tracks) { + + // Apply good track selection criteria + if (!trackselector(t, parameters)) + continue; + + // Creating Lorenz vector to store raw tracks and piontracks + TLorentzVector a; + a.SetXYZM(t.px(), t.py(), t.pz(), o2::constants::physics::MassPionCharged); + allTracks.push_back(a); + + // Apply TPC pion sigma + auto nSigmaPi = t.tpcNSigmaPi(); + if (fabs(nSigmaPi) < PID_cut) { + onlyPionTracks.push_back(a); + onlyPionSigma.push_back(nSigmaPi); + rawPionTracks.push_back(t); + } + } + registry.fill(HIST("hTracksPions"), onlyPionTracks.size()); + + //_____________________________________ + // Selecting collisions with Two PV contributors + if (collision.numContrib() == 2) { + + registry.fill(HIST("hSelectionCounter"), 4); + + // Selecting only Two good tracks + if ((rawPionTracks.size() == 2) && (allTracks.size() == 2)) { + + registry.fill(HIST("hSelectionCounter"), 4); + + // Creating rhos + for (auto pion : onlyPionTracks) { + p += pion; + } + + for (auto rtrk : rawPionTracks) { + TLorentzVector itrk; + itrk.SetXYZM(rtrk.px(), rtrk.py(), rtrk.pz(), o2::constants::physics::MassPionCharged); + trackpt.push_back(itrk.Pt()); + tracketa.push_back(itrk.Eta()); + trackphi.push_back(itrk.Phi()); + tracksign.push_back(rtrk.sign()); + pitpcpid.push_back(rtrk.tpcNSigmaPi()); + } + + int sign = 0; + for (auto rawPion : rawPionTracks) { + sign += rawPion.sign(); + } + // Filling tree, make to be consistent with the declared tables + tree(p.Pt(), p.Y(), p.Phi(), p.M(), sign, collision.numContrib(), pitpcpid, trackpt, tracketa, trackphi, tracksign); + } + } + } + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc, TaskName{"udtutorial07"})}; +}