From e12b51c5ccf8b67f2a0ea50c80723a9618760085 Mon Sep 17 00:00:00 2001 From: Victor Date: Sat, 17 Sep 2022 11:40:40 +0200 Subject: [PATCH 01/20] Two particle correlations skimming framework Fully working for collisions and tracks Collisions skimming implementing - basic non configurable selection based on number of contributors, vertex quality and EventCuts pilup decisions - fully configurable zvertex cut with default and variants - fully configurable centrality/multiplicity cut with default and variants Tracks skimming implementing - full track characteristics with default and variants support - Run 1 and 2 track types implemented Skimming ratio obtained 100 -> 15 Still pending - Advance pile-up rejection - Trigger selection - PID --- PWGCF/CMakeLists.txt | 1 + PWGCF/TwoParticleCorrelations/CMakeLists.txt | 14 + .../Core/CMakeLists.txt | 26 + .../Core/EventSelectionFilterAndAnalysis.cxx | 238 +++++ .../Core/EventSelectionFilterAndAnalysis.h | 162 +++ .../Core/PIDSelectionFilterAndAnalysis.cxx | 71 ++ .../Core/PIDSelectionFilterAndAnalysis.h | 86 ++ .../Core/SelectionFilterAndAnalysis.cxx | 47 + .../Core/SelectionFilterAndAnalysis.h | 59 ++ .../Core/SkimmingConfigurableCuts.cxx | 922 ++++++++++++++++++ .../Core/SkimmingConfigurableCuts.h | 471 +++++++++ .../Core/TrackSelectionFilterAndAnalysis.cxx | 294 ++++++ .../Core/TrackSelectionFilterAndAnalysis.h | 183 ++++ .../Core/TwoPartCorrLinkDef.h | 38 + .../TwoParticleCorrelationsSkimmed.h | 91 ++ .../TableProducer/CMakeLists.txt | 15 + .../TableProducer/skimmingconf.h | 46 + .../twoParticleCorrelationsSkimming.cxx | 194 ++++ .../Tasks/CMakeLists.txt | 11 + 19 files changed, 2969 insertions(+) create mode 100644 PWGCF/TwoParticleCorrelations/CMakeLists.txt create mode 100644 PWGCF/TwoParticleCorrelations/Core/CMakeLists.txt create mode 100644 PWGCF/TwoParticleCorrelations/Core/EventSelectionFilterAndAnalysis.cxx create mode 100644 PWGCF/TwoParticleCorrelations/Core/EventSelectionFilterAndAnalysis.h create mode 100644 PWGCF/TwoParticleCorrelations/Core/PIDSelectionFilterAndAnalysis.cxx create mode 100644 PWGCF/TwoParticleCorrelations/Core/PIDSelectionFilterAndAnalysis.h create mode 100644 PWGCF/TwoParticleCorrelations/Core/SelectionFilterAndAnalysis.cxx create mode 100644 PWGCF/TwoParticleCorrelations/Core/SelectionFilterAndAnalysis.h create mode 100644 PWGCF/TwoParticleCorrelations/Core/SkimmingConfigurableCuts.cxx create mode 100644 PWGCF/TwoParticleCorrelations/Core/SkimmingConfigurableCuts.h create mode 100644 PWGCF/TwoParticleCorrelations/Core/TrackSelectionFilterAndAnalysis.cxx create mode 100644 PWGCF/TwoParticleCorrelations/Core/TrackSelectionFilterAndAnalysis.h create mode 100644 PWGCF/TwoParticleCorrelations/Core/TwoPartCorrLinkDef.h create mode 100644 PWGCF/TwoParticleCorrelations/DataModel/TwoParticleCorrelationsSkimmed.h create mode 100644 PWGCF/TwoParticleCorrelations/TableProducer/CMakeLists.txt create mode 100644 PWGCF/TwoParticleCorrelations/TableProducer/skimmingconf.h create mode 100644 PWGCF/TwoParticleCorrelations/TableProducer/twoParticleCorrelationsSkimming.cxx create mode 100644 PWGCF/TwoParticleCorrelations/Tasks/CMakeLists.txt diff --git a/PWGCF/CMakeLists.txt b/PWGCF/CMakeLists.txt index 23afeaf6d0d..6e6be25110a 100644 --- a/PWGCF/CMakeLists.txt +++ b/PWGCF/CMakeLists.txt @@ -18,4 +18,5 @@ add_subdirectory(MultiparticleCorrelations) add_subdirectory(Tasks) add_subdirectory(TableProducer) add_subdirectory(Tutorial) +add_subdirectory(TwoParticleCorrelations) diff --git a/PWGCF/TwoParticleCorrelations/CMakeLists.txt b/PWGCF/TwoParticleCorrelations/CMakeLists.txt new file mode 100644 index 00000000000..0d3bb13ae7b --- /dev/null +++ b/PWGCF/TwoParticleCorrelations/CMakeLists.txt @@ -0,0 +1,14 @@ +# Copyright 2019-2020 CERN and copyright holders of ALICE O2. +# See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +# All rights not expressly granted are reserved. +# +# This software is distributed under the terms of the GNU General Public +# License v3 (GPL Version 3), copied verbatim in the file "COPYING". +# +# In applying this license CERN does 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(Core) +add_subdirectory(Tasks) +add_subdirectory(TableProducer) diff --git a/PWGCF/TwoParticleCorrelations/Core/CMakeLists.txt b/PWGCF/TwoParticleCorrelations/Core/CMakeLists.txt new file mode 100644 index 00000000000..c1a9696cee7 --- /dev/null +++ b/PWGCF/TwoParticleCorrelations/Core/CMakeLists.txt @@ -0,0 +1,26 @@ +# Copyright 2019-2020 CERN and copyright holders of ALICE O2. +# See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +# All rights not expressly granted are reserved. +# +# This software is distributed under the terms of the GNU General Public +# License v3 (GPL Version 3), copied verbatim in the file "COPYING". +# +# In applying this license CERN does not waive the privileges and immunities +# granted to it by virtue of its status as an Intergovernmental Organization +# or submit itself to any jurisdiction. + +o2physics_add_library(TwoPartCorrCore + SOURCES SkimmingConfigurableCuts.cxx + SelectionFilterAndAnalysis.cxx + TrackSelectionFilterAndAnalysis.cxx + PIDSelectionFilterAndAnalysis.cxx + EventSelectionFilterAndAnalysis.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore) + +o2physics_target_root_dictionary(TwoPartCorrCore + HEADERS SkimmingConfigurableCuts.h + SelectionFilterAndAnalysis.h + TrackSelectionFilterAndAnalysis.h + PIDSelectionFilterAndAnalysis.h + EventSelectionFilterAndAnalysis.h + LINKDEF TwoPartCorrLinkDef.h) diff --git a/PWGCF/TwoParticleCorrelations/Core/EventSelectionFilterAndAnalysis.cxx b/PWGCF/TwoParticleCorrelations/Core/EventSelectionFilterAndAnalysis.cxx new file mode 100644 index 00000000000..d0f8c89f3c8 --- /dev/null +++ b/PWGCF/TwoParticleCorrelations/Core/EventSelectionFilterAndAnalysis.cxx @@ -0,0 +1,238 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +#include +#include + +#include "Framework/AnalysisTask.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/ASoAHelpers.h" +#include "EventSelectionFilterAndAnalysis.h" + +using namespace o2; +using namespace o2::framework; +using namespace o2::soa; +using namespace o2::framework::expressions; +using namespace o2::analysis::PWGCF; +using namespace boost; + +ClassImp(EventSelectionFilterAndAnalysis); + +const int nNoOfMultiplicityEstimators = 3; +const char* multiplicityEstimators[nNoOfMultiplicityEstimators] = {"V0M", "CL0", "CL1"}; + +/// \brief Default constructor +EventSelectionFilterAndAnalysis::EventSelectionFilterAndAnalysis() + : SelectionFilterAndAnalysis(), + mMultiplicityClasses(nullptr), + mTriggerSelection(nullptr), + mZVertex(nullptr), + mPileUpRejection(nullptr), + mMultiplicities{}, + mDefaultMultiplicityEstimatorIndex(-1), + mAlternateMultiplicityEstimatorIndex{} +{ +} + +/// \brief Constructor from regular expression +EventSelectionFilterAndAnalysis::EventSelectionFilterAndAnalysis(const TString& cutstr, selmodes mode) + : SelectionFilterAndAnalysis("", mode), + mMultiplicityClasses(nullptr), + mTriggerSelection(nullptr), + mZVertex(nullptr), + mPileUpRejection(nullptr), + mMultiplicities{}, + mDefaultMultiplicityEstimatorIndex(-1), + mAlternateMultiplicityEstimatorIndex{} +{ + ConstructCutFromString(cutstr); +} + +/// \brief Constructor from the track selection configurable +EventSelectionFilterAndAnalysis::EventSelectionFilterAndAnalysis(const EventSelectionConfigurable& evtsel, selmodes mode) + : SelectionFilterAndAnalysis("", mode), + mMultiplicityClasses(nullptr), + mTriggerSelection(nullptr), + mZVertex(nullptr), + mPileUpRejection(nullptr), + mMultiplicities{}, + mDefaultMultiplicityEstimatorIndex(-1), + mAlternateMultiplicityEstimatorIndex{} +{ + TString cutString = "eventsel{"; + bool first = true; + + auto appendCut = [&cutString, &first](std::string str) { + if (str.size() > 0) { + if (first) { + cutString += str; + first = false; + } else { + cutString += "," + str; + } + } + }; + appendCut(evtsel.mMultSel); + appendCut(evtsel.mTriggerSel); + appendCut(evtsel.mZVertexSel); + appendCut(evtsel.mPileUpRejection); + + cutString += "}"; + ConstructCutFromString(cutString); +} + +/// \brief Calculates the length of the mask needed to store the selection cuts +int EventSelectionFilterAndAnalysis::CalculateMaskLength() +{ + int length = 0; + auto addLength = [&length](auto& brick) { + if (brick != nullptr) { + length += brick->Length(); + LOGF(info, "EventSelectionFilterAndAnalysis::CalculateMaskLength, cumulated length: %d", length); + } + }; + + addLength(mMultiplicityClasses); + addLength(mTriggerSelection); + addLength(mZVertex); + addLength(mPileUpRejection); + + return length; +} + +void EventSelectionFilterAndAnalysis::InitializeMultiplicityFilter() +{ + /* initialize the storage of multiplicities from the differente estimators */ + for (int i = 0; i < nNoOfMultiplicityEstimators; ++i) { + mMultiplicities.push_back(-1); + } + /* now initialize the filter machinery */ + if (mMultiplicityClasses != nullptr) { + if (mMultiplicityClasses->IsA() != CutWithVariations::Class()) { + /* no alternative estimators, just the default */ + LOGF(info, "Searching for default multiplicity estimator %s", mMultiplicityClasses->GetName()); + for (int i = 0; i < nNoOfMultiplicityEstimators; ++i) { + LOGF(info, "Checking multiplicity estimator %s", multiplicityEstimators[i]); + if (strcmp(multiplicityEstimators[i], mMultiplicityClasses->GetName()) == 0) { + mDefaultMultiplicityEstimatorIndex = i; + break; + } + } + if (mDefaultMultiplicityEstimatorIndex < 0) { + LOGF(fatal, "EventSelectionFilterAndAnalysis::InitializeMultiplicityFilter() default multiplicity class estimator not implemented"); + } + } else { + /* we have alternative estimators our brick is of kind cwv */ + /* first the default */ + TList& deflst = dynamic_cast*>(mMultiplicityClasses)->getDefaultBricks(); + if (deflst.GetEntries() > 1) { + LOGF(fatal, "EventSelectionFilterAndAnalysis::InitializeMultiplicityFilter() expected only one default multiplicity class estimator"); + } + LOGF(info, "Searching for default multiplicity estimator %s", deflst.At(0)->GetName()); + for (int i = 0; i < nNoOfMultiplicityEstimators; ++i) { + LOGF(info, "Checking multiplicity estimator %s", multiplicityEstimators[i]); + if (strcmp(multiplicityEstimators[i], deflst.At(0)->GetName()) == 0) { + mDefaultMultiplicityEstimatorIndex = i; + break; + } + } + if (mDefaultMultiplicityEstimatorIndex < 0) { + LOGF(fatal, "EventSelectionFilterAndAnalysis::InitializeMultiplicityFilter() default multiplicity class estimator not implemented"); + } + /* and now the variants */ + TList& varlst = dynamic_cast*>(mMultiplicityClasses)->getVariantBricks(); + for (int ivar = 0; ivar < varlst.GetEntries(); ++ivar) { + LOGF(info, "Searching for variant multiplicity estimator %s", varlst.At(ivar)->GetName()); + for (int i = 0; i < nNoOfMultiplicityEstimators; ++i) { + LOGF(info, "Checking multiplicity estimator %s", multiplicityEstimators[i]); + if (strcmp(multiplicityEstimators[i], varlst.At(ivar)->GetName()) == 0) { + mAlternateMultiplicityEstimatorIndex.push_back(i); + break; + } + } + } + if (mAlternateMultiplicityEstimatorIndex.size() != (uint)(varlst.GetEntries())) { + LOGF(fatal, "EventSelectionFilterAndAnalysis::InitializeMultiplicityFilter() variant multiplicity class estimators not all implemented"); + } + } + } else { + LOGF(fatal, "EventSelectionFilterAndAnalysis::InitializeMultiplicityFilter expected a multiplicity filter but it is not there"); + } +} + +void EventSelectionFilterAndAnalysis::ConstructCutFromString(const TString& cutstr) +{ + LOGF(info, "Cut string: %s", cutstr); + /* let's catch the first level */ + regex cutregex("^eventsel\\{?(\\w+\\{[\\w\\d.,:{}-]+})*}$", regex_constants::ECMAScript | regex_constants::icase); + std::string in(cutstr.Data()); + smatch m; + + bool res = regex_search(in, m, cutregex); + if (not res or m.empty() or (m.size() > 2)) { + Fatal("EventSelectionFilterAndAnalysis::::ConstructCutFromString", "Wrong RE: %s, try tracksel{ttype{FB32,FB96};ncls{th{70}},nxr{cwv{th{70},th{80}}}} for instance", cutstr.Data()); + } + this->SetName("EventSelectionFilterAndAnalysisCuts"); + this->SetTitle(cutstr.Data()); + + /* let's now handle the event characteristics */ + { + LOGF(info, "Captured %s", m[1].str().c_str()); + TString lev2str = m[1].str(); + while (lev2str.Length() != 0) { + std::set allowed = {"lim", "th", "rg", "xrg", "cwv", "mrg"}; + lev2str.Remove(TString::kLeading, ' '); + lev2str.Remove(TString::kLeading, ','); + lev2str.Remove(TString::kLeading, ' '); + if (lev2str.Length() == 0) { + break; + } + regex cutregex("^(\\w+)\\{((?:[^{}]++|\\{(?2)\\})*)\\}"); + std::string in(lev2str.Data()); + smatch m; + bool res = regex_search(in, m, cutregex); + + if (not res or m.empty() or (m.size() != 3)) { + Fatal("EventSelectionFilterAndAnalysis::::ConstructCutFromString", "Wrong RE: %s, try tracksel{ttype{FB32,FB96};nclstpc{th{70}},nxr{cwv{th{70},th{80}}}} for instance", cutstr.Data()); + } + LOGF(info, "Captured %s", m[1].str().c_str()); + auto storeIntCut = [&m, &allowed](CutBrick*& brickvar) { + if (brickvar != nullptr) { + delete brickvar; + } + brickvar = CutBrick::constructBrick(m[1].str().c_str(), m[2].str().c_str(), allowed); + }; + auto storeFloatCut = [&m, &allowed](CutBrick*& brickvar) { + if (brickvar != nullptr) { + delete brickvar; + } + brickvar = CutBrick::constructBrick(m[1].str().c_str(), m[2].str().c_str(), allowed); + }; + if (m[1].str() == "centmult") { + storeFloatCut(mMultiplicityClasses); + InitializeMultiplicityFilter(); + } else if (m[1].str() == "mtrigg") { + storeIntCut(mTriggerSelection); + } else if (m[1].str() == "zvtx") { + storeFloatCut(mZVertex); + } else if (m[1].str() == "pileup") { + storeIntCut(mPileUpRejection); + } + /* removing the already handled event characteristics cut */ + lev2str.Remove(0, m[0].length()); + } + } + mMaskLength = CalculateMaskLength(); + if (mMaskLength > 64) { + LOGF(fatal, "EventSelectionFilterAndAnalysis not ready for filter mask of %d bits. Just 64 available for the time being", mMaskLength); + } +} + diff --git a/PWGCF/TwoParticleCorrelations/Core/EventSelectionFilterAndAnalysis.h b/PWGCF/TwoParticleCorrelations/Core/EventSelectionFilterAndAnalysis.h new file mode 100644 index 00000000000..eb4494d3f5d --- /dev/null +++ b/PWGCF/TwoParticleCorrelations/Core/EventSelectionFilterAndAnalysis.h @@ -0,0 +1,162 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. +#ifndef EVENTSELECTIONFILTERANDANALYSIS_H +#define EVENTSELECTIONFILTERANDANALYSIS_H + +#include +#include +#include +#include +#include + +#include "SkimmingConfigurableCuts.h" +#include "SelectionFilterAndAnalysis.h" + +namespace o2 +{ +namespace analysis +{ +namespace PWGCF +{ +/* forward declaration */ +class EventSelectionFilterAndAnalysis; + +///\brief Convenince class for configurable access +class EventSelectionConfigurable +{ + friend class EventSelectionFilterAndAnalysis; + + public: + EventSelectionConfigurable(std::string multsel = "", + std::string trigsel = "", + std::string zvtxsel = "", + std::string pileuprej = "") + : mMultSel{multsel}, mTriggerSel{trigsel}, mZVertexSel{zvtxsel}, mPileUpRejection{pileuprej} + { + } + + private: + std::string mMultSel = ""; //! the multiplicity selection cuts + std::string mTriggerSel = ""; //! the trigger selection cuts + std::string mZVertexSel = ""; //! the z vertex selection cuts + std::string mPileUpRejection = ""; //! the pile-up rejection criteria + + private: + ClassDefNV(EventSelectionConfigurable, 1); +}; + +/// \brief Filter of tracks and track selection once filetered +class EventSelectionFilterAndAnalysis : public SelectionFilterAndAnalysis +{ + public: + EventSelectionFilterAndAnalysis(); + EventSelectionFilterAndAnalysis(const TString&, selmodes); + EventSelectionFilterAndAnalysis(const EventSelectionConfigurable&, selmodes); + + template + uint64_t Filter(CollisionToFilter const& col); + + private: + void ConstructCutFromString(const TString&); + void InitializeMultiplicityFilter(); + int CalculateMaskLength(); + + CutBrick* mMultiplicityClasses; //! the multiplicity default classes cuts + CutBrick* mTriggerSelection; //! the trigger selection cuts + CutBrick* mZVertex; //! the z vertex selection cuts + CutBrick* mPileUpRejection; //! the pile-up rejection criteria + std::vector mMultiplicities; // the collision multiplicities from the different implemented estimators + int mDefaultMultiplicityEstimatorIndex; // the default estimator index on the collision multiplicities array + std::vector mAlternateMultiplicityEstimatorIndex; // the vector of alternate estimators index on the collision multiplicities array + + ClassDef(EventSelectionFilterAndAnalysis, 1) +}; + +/// \brief Fills the filter cuts mask +template +uint64_t EventSelectionFilterAndAnalysis::Filter(CollisionToFilter const& col) +{ + /* store the collision multiplicities for the different estimators */ + /* TODO: we need to adapt this to the Run 3 scenario */ + /* this is hard coded with the estimator index declaration */ + mMultiplicities[0] = col.centRun2V0M(); + mMultiplicities[1] = col.centRun2CL0(); + mMultiplicities[2] = col.centRun2CL1(); + + uint64_t selectedMask = 0UL; + mSelectedMask = 0UL; + int bit = 0; + + auto filterBrickValue = [&](auto brick, auto value) { + bool atleastone = false; + std::vector res = brick->Filter(value); + for (auto b : res) { + if (b) { + atleastone = true; + SETBIT(selectedMask, bit); + } + bit++; + } + return atleastone; + }; + + /* we require the collision be accepted by the whole set of filters */ + bool acceptcollision = true; + if (mMultiplicityClasses != nullptr) { + if (mAlternateMultiplicityEstimatorIndex.size() > 0) { + bool atleastonealternative = false; + /* we have alternative estimators so our brick is of kind cwv */ + if (mMultiplicityClasses->IsA() != CutWithVariations::Class()) { + LOGF(fatal, "EventSelectionFilterAndAnalysis::Filter() expected class with variations cut but it is not there"); + } + /* first the default */ + TList& deflst = dynamic_cast*>(mMultiplicityClasses)->getDefaultBricks(); + if (deflst.GetEntries() > 1) { + LOGF(fatal, "EventSelectionFilterAndAnalysis::Filter() expected only one default multiplicity class estimator"); + } + bool acc = filterBrickValue((CutBrick*)deflst.At(0), mMultiplicities[mDefaultMultiplicityEstimatorIndex]); + atleastonealternative = atleastonealternative || acc; + /* and now the variants */ + TList& varlst = dynamic_cast*>(mMultiplicityClasses)->getVariantBricks(); + for (int i = 0; i < varlst.GetEntries(); ++i) { + if (varlst.At(i)->IsA() != CutBrickSelectorMultipleRanges::Class()) { + LOGF(fatal, "EventSelectionFilterAndAnalysis::Filter, expected a multirange selector"); + } + bool acc = filterBrickValue((CutBrick*)varlst.At(i), mMultiplicities[mAlternateMultiplicityEstimatorIndex[i]]); + atleastonealternative = atleastonealternative || acc; + } + acceptcollision = acceptcollision && atleastonealternative; + } else { + /* no alternative estimators, just the default */ + bool acc = filterBrickValue(mMultiplicityClasses, mMultiplicities[mDefaultMultiplicityEstimatorIndex]); + acceptcollision = acceptcollision && acc; + } + } + if (mTriggerSelection != nullptr) { + } + if (mZVertex != nullptr) { + bool acc = filterBrickValue(mZVertex, col.posZ()); + acceptcollision = acceptcollision && acc; + } + if (mPileUpRejection != nullptr) { + } + LOGF(debug, "EventSelectionFilterAndAnalysis::Filter(), %s collision", acceptcollision ? "accepted" : "rejected"); + if (acceptcollision) { + mSelectedMask = selectedMask; + } + return mSelectedMask; +} + +} // namespace PWGCF +} // namespace analysis +} // namespace o2 + +#endif // EVENTSELECTIONFILTERANDANALYSIS_H diff --git a/PWGCF/TwoParticleCorrelations/Core/PIDSelectionFilterAndAnalysis.cxx b/PWGCF/TwoParticleCorrelations/Core/PIDSelectionFilterAndAnalysis.cxx new file mode 100644 index 00000000000..74edf3e7c6d --- /dev/null +++ b/PWGCF/TwoParticleCorrelations/Core/PIDSelectionFilterAndAnalysis.cxx @@ -0,0 +1,71 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +#include +#include + +#include "Framework/AnalysisTask.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/ASoAHelpers.h" +#include "PIDSelectionFilterAndAnalysis.h" + +using namespace o2; +using namespace o2::framework; +using namespace o2::soa; +using namespace o2::framework::expressions; +using namespace o2::analysis::PWGCF; +using namespace boost; + +ClassImp(PIDSelectionFilterAndAnalysis); + +/// \brief Default constructor +PIDSelectionFilterAndAnalysis::PIDSelectionFilterAndAnalysis() + : SelectionFilterAndAnalysis(), + mPTOF(0.8f), + mRequireTOF(false), + mEllipticTPCTOF(false), + mInclusiveTrackPID(0), + mExclusiveTrackPID(0) +{ +} + +/// \brief Constructor from regular expression +PIDSelectionFilterAndAnalysis::PIDSelectionFilterAndAnalysis(const TString& cutstr, selmodes mode) + : SelectionFilterAndAnalysis("", mode), + mPTOF(0.8f), + mRequireTOF(false), + mEllipticTPCTOF(false), + mInclusiveTrackPID(0), + mExclusiveTrackPID(0) +{ + ConstructCutFromString(cutstr); +} + +/// \brief Calculates the length of the mask needed to store the selection cuts +int PIDSelectionFilterAndAnalysis::CalculateMaskLength() +{ + int length = 0; + for (auto brick : mInclusiveTrackPID) { + length += brick->Length(); + } + for (auto brick : mExclusiveTrackPID) { + length += brick->Length(); + } + return length; +} + +void PIDSelectionFilterAndAnalysis::ConstructCutFromString(const TString& cutstr) +{ + mMaskLength = CalculateMaskLength(); + if (mMaskLength > 64) { + LOGF(fatal, "PIDSelectionFilterAndAnalysis not ready for filter mask of %d bits. Just 64 available for the time being", mMaskLength); + } +} diff --git a/PWGCF/TwoParticleCorrelations/Core/PIDSelectionFilterAndAnalysis.h b/PWGCF/TwoParticleCorrelations/Core/PIDSelectionFilterAndAnalysis.h new file mode 100644 index 00000000000..27bde37b240 --- /dev/null +++ b/PWGCF/TwoParticleCorrelations/Core/PIDSelectionFilterAndAnalysis.h @@ -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. +#ifndef PIDSELECTIONFILTERANDANALYSIS_H +#define PIDSELECTIONFILTERANDANALYSIS_H + +#include +#include +#include +#include +#include + +#include "SkimmingConfigurableCuts.h" +#include "SelectionFilterAndAnalysis.h" + +namespace o2 +{ +namespace analysis +{ +namespace PWGCF +{ + +/// \brief Filter of tracks based on PID and track selection once filetered +class PIDSelectionFilterAndAnalysis : public SelectionFilterAndAnalysis +{ + public: + PIDSelectionFilterAndAnalysis(); + PIDSelectionFilterAndAnalysis(const TString&, selmodes); + + void SetPTOF(float ptof) { mPTOF = ptof; } + void SetRequireTOF(bool requiretof = false) { mRequireTOF = requiretof; } + void SetEllipticTPCTOF(bool elliptic = false) { mEllipticTPCTOF = elliptic; } + + template + uint64_t Filter(TrackToFilter const& track); + + private: + void ConstructCutFromString(const TString&); + int CalculateMaskLength(); + + float mPTOF = 0.8f; ///< the p threshold for cheking TOF information + bool mRequireTOF = false; ///< is TOF required + bool mEllipticTPCTOF = false; ///< 2D nsigmas elliptic TPC+TOF + std::vector mInclusiveTrackPID; ///< the list of species wanted to be detected + std::vector mExclusiveTrackPID; ///< the list of species wanted to be rejected + + ClassDef(PIDSelectionFilterAndAnalysis, 1) +}; + +/// \brief Fills the filter cuts mask +template +uint64_t PIDSelectionFilterAndAnalysis::Filter(TrackToFilter const& track) +{ + uint64_t selectedMask = 0UL; + int bit = 0; + + auto filterBrickTrack = [&](auto brick, auto track) { + std::vector res = brick->Filter(track); + for (auto b : res) { + if (b) { + SETBIT(selectedMask, bit++); + } + } + }; + + for (auto bricksp : mInclusiveTrackPID) { + filterBrickTrack(bricksp, track); + } + for (auto bricksp : mExclusiveTrackPID) { + filterBrickTrack(bricksp, track); + } + return mSelectedMask = selectedMask; +} + +} // namespace PWGCF +} // namespace analysis +} // namespace o2 + +#endif // PIDSELECTIONFILTERANDANALYSIS_H diff --git a/PWGCF/TwoParticleCorrelations/Core/SelectionFilterAndAnalysis.cxx b/PWGCF/TwoParticleCorrelations/Core/SelectionFilterAndAnalysis.cxx new file mode 100644 index 00000000000..e3ad4b8c452 --- /dev/null +++ b/PWGCF/TwoParticleCorrelations/Core/SelectionFilterAndAnalysis.cxx @@ -0,0 +1,47 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +#include +#include + +#include "Framework/AnalysisTask.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/ASoAHelpers.h" +#include "SelectionFilterAndAnalysis.h" + +using namespace o2; +using namespace o2::framework; +using namespace o2::soa; +using namespace o2::framework::expressions; +using namespace o2::analysis::PWGCF; + +ClassImp(SelectionFilterAndAnalysis); + +/// \brief Default constructor +SelectionFilterAndAnalysis::SelectionFilterAndAnalysis() + : TNamed(), + mMode(kFilter), + mMaskLength(0), + mSelectedMask(0UL), + mArmedMask(0UL) +{ +} + +/// \brief Named constructor for a concrete operating mode +SelectionFilterAndAnalysis::SelectionFilterAndAnalysis(const TString& name, selmodes mode) + : TNamed(name, name), + mMode(mode), + mMaskLength(0), + mSelectedMask(0UL), + mArmedMask(0UL) +{ +} + diff --git a/PWGCF/TwoParticleCorrelations/Core/SelectionFilterAndAnalysis.h b/PWGCF/TwoParticleCorrelations/Core/SelectionFilterAndAnalysis.h new file mode 100644 index 00000000000..f921f93832f --- /dev/null +++ b/PWGCF/TwoParticleCorrelations/Core/SelectionFilterAndAnalysis.h @@ -0,0 +1,59 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. +#ifndef SELECTIONFILTERANDANALYSIS_H +#define SELECTIONFILTERANDANALYSIS_H + +#include +#include +#include +#include +#include + +#include "SkimmingConfigurableCuts.h" + +namespace o2 +{ +namespace analysis +{ +namespace PWGCF +{ + +/// \brief Base class for filter and selection once filetered +class SelectionFilterAndAnalysis : public TNamed +{ + public: + /// \enum selmodes + /// \brief the modes in which the selection can operate + enum selmodes { + kFilter = 0, ///< filter mode to produce skimmed data + kAnalysis ///< analysis mode over already skimmed data + }; + + SelectionFilterAndAnalysis(); + SelectionFilterAndAnalysis(const TString& name, selmodes mode); + + private: + virtual int CalculateMaskLength() = 0; + + protected: + selmodes mMode = kFilter; /// the operating mode of the selection instance + int mMaskLength = 0; /// the length of the mask needed to filter the selection cuts + ULong64_t mSelectedMask = 0UL; /// the selection mask for the current passed collision + ULong64_t mArmedMask = 0UL; /// the armed mask identifying the significative selection cuts + + ClassDefNV(SelectionFilterAndAnalysis, 1) +}; + +} // namespace PWGCF +} // namespace analysis +} // namespace o2 + +#endif // SELECTIONFILTERANDANALYSIS_H diff --git a/PWGCF/TwoParticleCorrelations/Core/SkimmingConfigurableCuts.cxx b/PWGCF/TwoParticleCorrelations/Core/SkimmingConfigurableCuts.cxx new file mode 100644 index 00000000000..05f5ef79877 --- /dev/null +++ b/PWGCF/TwoParticleCorrelations/Core/SkimmingConfigurableCuts.cxx @@ -0,0 +1,922 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +#include +#include + +#include "Framework/AnalysisDataModel.h" +#include "Framework/ASoAHelpers.h" +#include "Common/DataModel/TrackSelectionTables.h" +#include "PWGCF/TwoParticleCorrelations/Core/SkimmingConfigurableCuts.h" + +using namespace o2; +using namespace o2::framework; +using namespace o2::soa; +using namespace o2::framework::expressions; +using namespace o2::analysis::PWGCF; + +/// \brief These are the implemented basic bricks +/// If more are implemented the list must be expanded and the +/// corresponding brick construction implemented +template +const char* CutBrick::mgImplementedbricks[] = {"lim", "th", "rg", "xrg", "mrg", "cwv"}; + +/////////////////////////////////////////////////////////////////////////////////////// +template +CutBrick* CutBrick::constructBrick(const char* name, const char* regex, const std::set& allowed) +{ + LOGF(info, "Construct brick %s from RE %s", name, regex); + CutBrick* thebrick = nullptr; + + bool found = false; + for (auto bname : allowed) { + if (TString(regex).BeginsWith(bname)) { + found = true; + break; + } + } + if (not found) { + ::Fatal("CutBrick* CutBrick::constructBrick", "Wrong RE: %s, trying to construct a not allowed basic cut brick", regex); + } + TString brickregex = TString(name) + "{" + TString(regex) + "}"; + + if (TString(regex).BeginsWith("lim")) { + thebrick = new CutBrickLimit(brickregex); + } else if (TString(regex).BeginsWith("th")) { + thebrick = new CutBrickThreshold(brickregex); + } else if (TString(regex).BeginsWith("rg")) { + thebrick = new CutBrickRange(brickregex); + } else if (TString(regex).BeginsWith("xrg")) { + thebrick = new CutBrickExtToRange(brickregex); + } else if (TString(regex).BeginsWith("mrg")) { + thebrick = new CutBrickSelectorMultipleRanges(brickregex); + } else if (TString(regex).BeginsWith("cwv")) { + thebrick = new CutWithVariations(brickregex); + } else { + ::Fatal("CutBrick* CutBrick::constructBrick", "Wrong RE: %s, trying to construct an unknown basic cut brick", regex); + } + return thebrick; +} + +/// Default constructor +template +CutBrick::CutBrick() + : TNamed(), + mState(kPASSIVE), + mMode(kUNSELECTED) +{ +} + +/// Named constructor +/// \param name The name of the brick +template +CutBrick::CutBrick(const char* name, const char* title) + : TNamed(name, title), + mState(kPASSIVE), + mMode(kUNSELECTED) +{ +} + +templateClassImp(CutBrick); + +/////////////////////////////////////////////////////////////////////////////////////// +/// Default constructor +template +CutBrickLimit::CutBrickLimit() + : CutBrick(), + mLimit(TValueToFilter(0)) +{ +} + +/// Named constructor +/// \param name The name of the brick +/// \param value The limit value +template +CutBrickLimit::CutBrickLimit(const char* name, const TValueToFilter& value) + : CutBrick(name, TString::Format("%s{lim{%f}}", name, float(value))), + mLimit(value) +{ +} + +/// \brief Cut string constructor +/// \param cutstr The cuts string +template +CutBrickLimit::CutBrickLimit(const TString& cutstr) + : CutBrick(), + mLimit(TValueToFilter(0)) +{ + ConstructCutFromString(cutstr); +} + +/// \brief Construct the cut from a cut string +/// \param cutstr The cut string +/// The cut string should have the structure +/// name{lim{val}} +/// If the cut string is correctly parsed the cut is correctly built +/// if not a fatal exception is rised +template +void CutBrickLimit::ConstructCutFromString(const TString& cutstr) +{ + LOGF(info, "Cut string: %s", cutstr.Data()); + + std::regex cutregex("^(\\w+)\\{lim\\{((?:-?[\\d]+\\.?[\\d]*)|(?:-?[\\d]*\\.?[\\d]+))}}$", std::regex_constants::ECMAScript | std::regex_constants::icase); + std::string in(cutstr.Data()); + std::smatch m; + + std::regex_search(in, m, cutregex); + if (m.empty() or (m.size() < 3)) { + Fatal("CutBrickLimit::ConstructCutFromString", "Wrong RE: %s, use pT{lim{2.0}} for instance", cutstr.Data()); + } else { + this->SetName(m[1].str().c_str()); + this->SetTitle(cutstr.Data()); + mLimit = TValueToFilter(std::stod(m[2])); + } +} + +/// \brief Filter the passed value to update the brick status accordingly +/// \param value The value to filter +/// \return true if the value passed the cut false otherwise +template +std::vector CutBrickLimit::Filter(const TValueToFilter& value) +{ + std::vector res; + if (value < mLimit) { + this->mState = this->kACTIVE; + res.push_back(true); + } else { + this->mState = this->kPASSIVE; + res.push_back(false); + } + return res; +} + +templateClassImp(CutBrickLimit); +template class o2::analysis::PWGCF::CutBrickLimit; +template class o2::analysis::PWGCF::CutBrickLimit; + +/////////////////////////////////////////////////////////////////////////////////////// +/// Default constructor +template +CutBrickThreshold::CutBrickThreshold() + : CutBrick(), + mThreshold(0) +{ +} + +/// Named constructor +/// \param name The name of the brick +/// \param value The threshold value +template +CutBrickThreshold::CutBrickThreshold(const char* name, const TValueToFilter& value) + : CutBrick(name, TString::Format("%s{th{%f}}", name, float(value))), + mThreshold(value) +{ +} + +/// \brief Cut string constructor +/// \param cutstr The cuts string +template +CutBrickThreshold::CutBrickThreshold(const TString& cutstr) + : CutBrick(), + mThreshold(0) +{ + ConstructCutFromString(cutstr); +} + +/// \brief Construct the cut from a cut string +/// \param cutstr The cut string +/// The cut string should have the structure +/// name{th{val}} +/// If the cut string is correctly parsed the cut is correctly built +/// if not a fatal exception is rised +template +void CutBrickThreshold::ConstructCutFromString(const TString& cutstr) +{ + LOGF(info, "Cut string: %s", cutstr.Data()); + + std::regex cutregex("^(\\w+)\\{th\\{((?:-?[\\d]+\\.?[\\d]*)|(?:-?[\\d]*\\.?[\\d]+))}}$", std::regex_constants::ECMAScript | std::regex_constants::icase); + std::string in(cutstr.Data()); + std::smatch m; + + std::regex_search(in, m, cutregex); + if (m.empty() or (m.size() < 3)) { + Fatal("CutBrickThreshold::ConstructCutFromString", "Wrong RE: %s, use pT{th{0.2}} for instance", cutstr.Data()); + } else { + this->SetName(m[1].str().c_str()); + this->SetTitle(cutstr.Data()); + mThreshold = TValueToFilter(std::stod(m[2])); + } +} + +/// \brief Filter the passed value to update the brick status accordingly +/// \param value The value to filter +/// \return true if the value passed the cut false otherwise +template +std::vector CutBrickThreshold::Filter(const TValueToFilter& value) +{ + std::vector res; + if (mThreshold <= value) { + this->mState = this->kACTIVE; + res.push_back(true); + } else { + this->mState = this->kPASSIVE; + res.push_back(false); + } + return res; +} + +templateClassImp(CutBrickThreshold); +template class o2::analysis::PWGCF::CutBrickThreshold; +template class o2::analysis::PWGCF::CutBrickThreshold; + +/////////////////////////////////////////////////////////////////////////////////////// +/// Default constructor +template +CutBrickRange::CutBrickRange() + : CutBrick(), + mLow(0), + mHigh(0) +{ +} + +/// Named constructor +/// \param name The name of the brick +/// \param low The low value for the cut range +/// \param high The high value for the cut range +template +CutBrickRange::CutBrickRange(const char* name, const TValueToFilter& low, const TValueToFilter& high) + : CutBrick(name, TString::Format("%s{rg{%f,%f}}", name, float(low), float(high))), + mLow(low), + mHigh(high) +{ +} + +/// \brief Cut string constructor +/// \param cutstr The cuts string +template +CutBrickRange::CutBrickRange(const TString& cutstr) + : CutBrick(), + mLow(0), + mHigh(0) +{ + ConstructCutFromString(cutstr); +} + +/// \brief Construct the cut from a cut string +/// \param cutstr The cut string +/// The cut string should have the structure +/// name{rg{low,high}} +/// If the cut string is correctly parsed the cut is correctly built +/// if not a fatal exception is rised +template +void CutBrickRange::ConstructCutFromString(const TString& cutstr) +{ + LOGF(info, "Cut string: %s", cutstr.Data()); + + std::regex cutregex("^(\\w+)\\{rg\\{((?:-?[\\d]+\\.?[\\d]*)|(?:-?[\\d]*\\.?[\\d]+)),((?:-?[\\d]+\\.?[\\d]*)|(?:-?[\\d]*\\.?[\\d]+))}}$", std::regex_constants::ECMAScript | std::regex_constants::icase); + std::string in(cutstr.Data()); + std::smatch m; + + std::regex_search(in, m, cutregex); + if (m.empty() or (m.size() < 4)) { + Fatal("CutBrickRange::ConstructCutFromString", "Wrong RE: %s, use pT{rg{0.2,2.0}} for instance", cutstr.Data()); + } else { + this->SetName(m[1].str().c_str()); + this->SetTitle(cutstr.Data()); + mLow = TValueToFilter(std::stod(m[2])); + mHigh = TValueToFilter(std::stod(m[3])); + } +} + +/// \brief Filter the passed value to update the brick status accordingly +/// \param value The value to filter +/// \return true if the value passed the cut false otherwise +template +std::vector CutBrickRange::Filter(const TValueToFilter& value) +{ + std::vector res; + if ((mLow <= value) and (value < mHigh)) { + this->mState = this->kACTIVE; + res.push_back(true); + } else { + this->mState = this->kPASSIVE; + res.push_back(false); + } + return res; +} + +templateClassImp(CutBrickRange); +template class o2::analysis::PWGCF::CutBrickRange; +template class o2::analysis::PWGCF::CutBrickRange; + +/////////////////////////////////////////////////////////////////////////////////////// +/// Default constructor +template +CutBrickExtToRange::CutBrickExtToRange() + : CutBrick(), + mLow(0), + mHigh(0) +{ +} + +/// Named constructor +/// \param name The name of the brick +/// \param low The low value for the cut excluded range +/// \param high The high value for the cut excluded range +template +CutBrickExtToRange::CutBrickExtToRange(const char* name, const TValueToFilter& low, const TValueToFilter& high) + : CutBrick(name, TString::Format("%s{xrg{%f,%f}}", name, float(low), float(high))), + mLow(low), + mHigh(high) +{ +} + +/// \brief Cut string constructor +/// \param cutstr The cuts string +template +CutBrickExtToRange::CutBrickExtToRange(const TString& cutstr) + : CutBrick(), + mLow(0), + mHigh(0) +{ + ConstructCutFromString(cutstr); +} + +/// \brief Construct the cut from a cut string +/// \param cutstr The cut string +/// The cut string should have the structure +/// name{xrg{low,high}} +/// If the cut string is correctly parsed the cut is correctly built +/// if not a fatal exception is rised +template +void CutBrickExtToRange::ConstructCutFromString(const TString& cutstr) +{ + LOGF(info, "Cut string: %s", cutstr.Data()); + + std::regex cutregex("^(\\w+)\\{xrg\\{((?:-?[\\d]+\\.?[\\d]*)|(?:-?[\\d]*\\.?[\\d]+)),((?:-?[\\d]+\\.?[\\d]*)|(?:-?[\\d]*\\.?[\\d]+))}}$", std::regex_constants::ECMAScript | std::regex_constants::icase); + std::string in(cutstr.Data()); + std::smatch m; + + std::regex_search(in, m, cutregex); + if (m.empty() or (m.size() < 4)) { + Fatal("CutBrickExtToRange::ConstructCutFromString", "Wrong RE: %s, use minv{xrg{0.02,0.04}} for instance", cutstr.Data()); + } else { + this->SetName(m[1].str().c_str()); + this->SetTitle(cutstr.Data()); + mLow = TValueToFilter(std::stod(m[2])); + mHigh = TValueToFilter(std::stod(m[3])); + } +} + +/// \brief Filter the passed value to update the brick status accordingly +/// \param value The value to filter +/// \return true if the value passed the cut false otherwise +template +std::vector CutBrickExtToRange::Filter(const TValueToFilter& value) +{ + std::vector res; + if ((value < mLow) or (mHigh <= value)) { + this->mState = this->kACTIVE; + res.push_back(true); + } else { + this->mState = this->kPASSIVE; + res.push_back(false); + } + return res; +} + +templateClassImp(CutBrickExtToRange); +template class o2::analysis::PWGCF::CutBrickExtToRange; +template class o2::analysis::PWGCF::CutBrickExtToRange; + +/////////////////////////////////////////////////////////////////////////////////////// +/// Default constructor +template +CutBrickSelectorMultipleRanges::CutBrickSelectorMultipleRanges() + : CutBrick() +{ +} + +/// Named constructor +/// \param name The name of the brick +/// \param edges Vector with the ranges edges +template +CutBrickSelectorMultipleRanges::CutBrickSelectorMultipleRanges(const char* name, const std::vector& edges) + : CutBrick(name, name) +{ + TString title = name; + title += "{"; + bool first = true; + for (auto edge : edges) { + mEdges.push_back(edge); + if (first) { + title += TString::Format("%.2f", float(edge)); + } else { + title += TString::Format(",%.2f", float(edge)); + } + } + title += "}"; + this->SetTitle(title.Data()); + for (unsigned int i = 1; i < mEdges.size(); ++i) { + mActive.push_back(false); + } +} + +/// \brief Cut string constructor +/// \param cutstr The cuts string +template +CutBrickSelectorMultipleRanges::CutBrickSelectorMultipleRanges(const TString& cutstr) + : CutBrick() +{ + ConstructCutFromString(cutstr); +} + +/// \brief Construct the cut from a cut string +/// \param cutstr The cut string +/// The cut string should have the structure +/// name{mrg{edge,edge, ...,edge}} +/// If the cut string is correctly parsed the cut is correctly built +/// if not a fatal exception is rised +template +void CutBrickSelectorMultipleRanges::ConstructCutFromString(const TString& cutstr) +{ + LOGF(info, "Cut string: %s", cutstr.Data()); + + std::regex cutregex("^(\\w+)\\{mrg\\{([a-zA-Z]\\w+)((?:,((?:-?[\\d]+\\.?[\\d]*)|(?:-?[\\d]*\\.?[\\d]+))){2,})}}$", std::regex_constants::ECMAScript | std::regex_constants::icase); + std::string in(cutstr.Data()); + std::smatch m; + + bool res = std::regex_search(in, m, cutregex); + if (not res or m.empty() or (m.size() < 5)) { + Fatal("CutBrickSelectorMultipleRanges::ConstructCutFromString", "Wrong RE: %s, use centmult{mrg{V0M,0,5,10,20,30,40,50,60,70,80}} for instance", cutstr.Data()); + } else { + this->SetName(m[2].str().c_str()); + this->SetTitle(cutstr.Data()); + /* list of edges */ + TObjArray* tokens = TString(m[3]).Tokenize(","); + for (int i = 0; i < tokens->GetEntries(); ++i) { + mEdges.push_back(TValueToFilter(TString(tokens->At(i)->GetName()).Atof())); + } + for (unsigned int i = 1; i < mEdges.size(); ++i) { + mActive.push_back(false); + } + delete tokens; + } +} + +/// \brief Filter the passed value to update the brick status accordingly +/// \param value The value to filter +/// \return true if the value passed the cut false otherwise +template +std::vector CutBrickSelectorMultipleRanges::Filter(const TValueToFilter& value) +{ + if ((mEdges.front() <= value) and (value < mEdges.back())) { + this->mState = this->kACTIVE; + unsigned int last = mActive.size(); + for (unsigned int i = 0; i < mActive.size(); ++i) { + if (value < mEdges[i + 1]) { + mActive[i] = true; + last = i; + break; + } else { + mActive[i] = false; + } + } + for (unsigned int i = last + 1; i < mActive.size(); ++i) { + mActive[i] = false; + } + } else { + this->mState = this->kPASSIVE; + for (unsigned int i = 0; i < mActive.size(); ++i) { + mActive[i] = false; + } + } + return std::vector(mActive); +} + +templateClassImp(CutBrickSelectorMultipleRanges); +template class o2::analysis::PWGCF::CutBrickSelectorMultipleRanges; +template class o2::analysis::PWGCF::CutBrickSelectorMultipleRanges; + +/////////////////////////////////////////////////////////////////////////////////////// +/// Default constructor +template +CutWithVariations::CutWithVariations() + : CutBrick(), + mAllowSeveralDefaults(false), + mDefaultBricks{}, + mVariationBricks{} +{ +} + +/// Named constructor +/// \param name The name of the brick +/// \param cutstr The string associated with the cut +/// \param severaldefaults The cut should allow multiple defaults values or not +template +CutWithVariations::CutWithVariations(const char* name, const char* cutstr, bool severaldefaults) + : CutBrick(name, cutstr), + mAllowSeveralDefaults(severaldefaults), + mDefaultBricks{}, + mVariationBricks{} +{ +} + +/// \brief Cut string constructor +/// \param cutstr The cuts string +template +CutWithVariations::CutWithVariations(const TString& cutstr) + : CutBrick(), + mAllowSeveralDefaults(false), + mDefaultBricks{}, + mVariationBricks{} +{ + ConstructCutFromString(cutstr); +} + +/// \brief Construct the cut from a cut string +/// \param cutstr The cuts string +/// The cut string should have the structure +/// name{def,def,..,def[;alt,alt,...,alt]} +/// where each of the def and alt are basic cut bricks +/// If the cut string is correctly parsed the cut is correctly built +/// if not a fatal exception is raised +template +void CutWithVariations::ConstructCutFromString(const TString& cutstr) +{ + /* let's catch the first level */ + LOGF(info, "Cut with variations: cut string: %s", cutstr.Data()); + + std::regex cutregex("^(\\w+)\\{cwv\\{([\\w\\d.,:{}-]+)}}$", std::regex_constants::ECMAScript | std::regex_constants::icase); + std::string in(cutstr.Data()); + std::smatch m; + + bool res = std::regex_search(in, m, cutregex); + if (not res or m.empty() or (m.size() < 3)) { + Fatal("CutWithVariations::ConstructCutFromString", "Wrong RE: %s, use pT{cwv{rg{0.2,10.0}}} for instance", cutstr.Data()); + } + this->SetName(m[1].str().c_str()); + this->SetTitle(cutstr.Data()); + + /* let's split default and variations */ + TObjArray* lev1toks = TString(m[2]).Tokenize(":"); + if (lev1toks->GetEntries() > 2) { + Fatal("CutWithVariations::ConstructCutFromString", "Wrong RE: %s, use pT{cwv{rg{0.2,10.0}}} for instance", cutstr.Data()); + } + auto addCuts = [&](TList& cutlist, std::string cuttxt, bool reqflag) { + std::smatch m; + while (cuttxt.length() > 0) { + std::set allowed = {"lim", "th", "rg", "xrg", "mrg"}; + std::regex cutregex("(\\w+\\{[\\w.,-]+}(?:-(?:no|yes))*)"); + bool res = regex_search(cuttxt, m, cutregex); + if (not res or m.empty() or m.size() != 2) { + Fatal("CutWithVariations::ConstructCutFromString", "Cut with variations malformed RE %s", cuttxt.c_str()); + } + TString brickre = m[1].str().c_str(); + bool isarmed = brickre.EndsWith("-yes"); + if (isarmed) { + brickre.Remove(brickre.Index("-yes"), strlen("-yes")); + } else if (brickre.EndsWith("-no")) { + brickre.Remove(brickre.Index("-no"), strlen("-no")); + } else if (reqflag) { + Fatal("CutWithVariations::ConstructCutFromString", "Wrong RE: %s, alternatives not correctly flagged", cuttxt.c_str()); + } + CutBrick* brick = CutBrick::constructBrick(this->GetName(), brickre, allowed); + brick->Arm(isarmed); + cutlist.Add(brick); + cuttxt = m.suffix(); + } + }; + /* let's handle the default values */ + { + LOGF(info, "Cut with variations, extracting defaults: cut string: %s", lev1toks->At(0)->GetName()); + addCuts(mDefaultBricks, lev1toks->At(0)->GetName(), false); + if (mDefaultBricks.GetEntries() > 1) { + /* TODO: several default options for track type and for track pid selection */ + Fatal("CutWithVariations::ConstructCutFromString", "Wrong RE: %s, several defaults only for trktype or trkpid pending of implementation", cutstr.Data()); + } + } + /* let's now handle the variations if any */ + if (lev1toks->GetEntries() > 1) { + LOGF(info, "Cut with variations, extracting variations: cut string: %s", lev1toks->At(1)->GetName()); + addCuts(mVariationBricks, lev1toks->At(1)->GetName(), true); + int narmed = 0; + for (auto cut : mVariationBricks) { + if (((CutBrick*)cut)->IsArmed()) { + narmed++; + } + } + if (narmed > 1) { + Fatal("CutWithVariations::ConstructCutFromString", "Wrong RE: %s, more than one alternative flagged", cutstr.Data()); + } + } + delete lev1toks; +} + +/// \brief Stores the brick with a default value for the cut +/// \param brick pointer to the brick to incorporate +/// \returns true if the brick was successfully added +/// If several default values are allowed it is only required +/// that the name of the new default brick were unique +/// If only one default value is allowed it is required that +/// no previous default were stored +/// If any of the above conditions fails the brick is not +/// added and false is returned +template +bool CutWithVariations::AddDefaultBrick(CutBrick* brick) +{ + if (mAllowSeveralDefaults) { + if (mDefaultBricks.FindObject(brick->GetName())) { + return false; + } else { + mDefaultBricks.Add(brick); + return true; + } + } else { + if (mDefaultBricks.GetEntries() > 0) { + return false; + } else { + mDefaultBricks.Add(brick); + return true; + } + } +} + +/// \brief Stores the brick with the variation to the default value for the cut +/// \param brick pointer to the brick to incorporate +/// \returns true if the brick was successfully added +/// It is required that the brick name were unique in the list of variation values brick +template +bool CutWithVariations::AddVariationBrick(CutBrick* brick) +{ + if (mVariationBricks.FindObject(brick->GetName())) { + return false; + } else { + mVariationBricks.Add(brick); + return true; + } +} + +/// Filters the passed value +/// The bricks on the default values list and in the variation +/// values list will change to active or passive accordingly to the passed value +/// \param value The value to filter +/// \returns true if the value activated any of the bricks + +template +std::vector CutWithVariations::Filter(const TValueToFilter& value) +{ + std::vector res; + res.reserve(Length()); + for (int i = 0; i < mDefaultBricks.GetEntries(); ++i) { + std::vector tmp = ((CutBrick*)mDefaultBricks.At(i))->Filter(value); + res.insert(res.end(), tmp.begin(), tmp.end()); + } + for (int i = 0; i < mVariationBricks.GetEntries(); ++i) { + std::vector tmp = ((CutBrick*)mVariationBricks.At(i))->Filter(value); + res.insert(res.end(), tmp.begin(), tmp.end()); + } + return res; +} + +/// Return the length needed to code the cut +/// The length is in brick units. The actual length is implementation dependent +/// \returns Cut length in units of bricks +template +int CutWithVariations::Length() +{ + /* TODO: should a single default cut without variations return zero length? */ + int length = 0; + for (int i = 0; i < mDefaultBricks.GetEntries(); ++i) { + length += ((CutBrick*)mDefaultBricks.At(i))->Length(); + } + for (int i = 0; i < mVariationBricks.GetEntries(); ++i) { + length += ((CutBrick*)mVariationBricks.At(i))->Length(); + } + return length; +} + +templateClassImp(o2::analysis::CutWithVariations); +template class o2::analysis::PWGCF::CutWithVariations; +template class o2::analysis::PWGCF::CutWithVariations; + +/// Default constructor +SpecialCutBrick::SpecialCutBrick() + : TNamed(), + mState(kPASSIVE), + mMode(kUNSELECTED) +{ +} + +/// Named constructor +/// \param name The name of the brick +SpecialCutBrick::SpecialCutBrick(const char* name, const char* title) + : TNamed(name, title), + mState(kPASSIVE), + mMode(kUNSELECTED) +{ +} + +ClassImp(SpecialCutBrick); + +/// \brief Constructor from regular expression +TrackSelectionBrick::TrackSelectionBrick(const TString& regex) : SpecialCutBrick(regex, regex) +{ + if (regex.EqualTo("FB1LHC2010")) { + constructFB1LHC2010(); + } else if (regex.EqualTo("FB1")) { + constructFB1LHC2011(); + } else if (regex.EqualTo("FB32LHC2010")) { + constructFB32LHC2010(); + } else if (regex.EqualTo("FB32")) { + constructFB32LHC2011(); + } else if (regex.EqualTo("FB64LHC2010")) { + constructFB64LHC2010(); + } else if (regex.EqualTo("FB64")) { + constructFB64LHC2011(); + } else { + ::Fatal("TrackSelectionBrick::TrackSelectionBrick", "Wrong RE: %s, trying to construct an unknown track type selector", regex.Data()); + } +} + +// Default TPC only track selection according to LHC2010 +void TrackSelectionBrick::constructFB1LHC2010() +{ + SetTrackType(o2::aod::track::Run2Track); + SetRequireGoldenChi2(true); + SetMinNClustersTPC(50); + SetMaxChi2PerClusterTPC(4.f); + SetMaxDcaXY(2.4f); + SetMaxDcaZ(3.2f); + /* TODO: 2D DCA cut */ +} + +// Default track selection requiring one hit in the SPD DCAxy according to LHC2010 +void TrackSelectionBrick::constructFB32LHC2010() +{ + SetTrackType(o2::aod::track::Run2Track); + SetRequireITSRefit(true); + SetRequireTPCRefit(true); + SetRequireGoldenChi2(true); + SetMinNCrossedRowsTPC(70); + SetMinNCrossedRowsOverFindableClustersTPC(0.8f); + SetMaxChi2PerClusterTPC(4.f); + SetRequireHitsInITSLayers(1, {0, 1}); // one hit in any SPD layer + SetMaxChi2PerClusterITS(36.f); + SetMaxDcaXYPtDep([](float pt) { return 0.0182f + 0.0350f / pow(pt, 1.01f); }); + SetMaxDcaZ(2.f); +} + +// Default track selection requiring no hit in the SPD and one in the innermost DCAxy according to LHC2010 +// SDD -> complementary tracks to global selection +void TrackSelectionBrick::constructFB64LHC2010() +{ + constructFB32LHC2010(); + ResetITSRequirements(); + SetRequireNoHitsInITSLayers({0, 1}); // no hit in SPD layers + SetRequireHitsInITSLayers(1, {2}); // one hit in first SDD layer +} + +// Default TPC only track selection according to LHC2011 +void TrackSelectionBrick::constructFB1LHC2011() +{ + /* the same as for LHC2010 */ + constructFB1LHC2010(); +} + +// Default track selection requiring one hit in the SPD DCAxy according to LHC2011 +void TrackSelectionBrick::constructFB32LHC2011() +{ + SetTrackType(o2::aod::track::Run2Track); + SetRequireITSRefit(true); + SetRequireTPCRefit(true); + SetRequireGoldenChi2(true); + SetMinNCrossedRowsTPC(70); + SetMinNCrossedRowsOverFindableClustersTPC(0.8f); + SetMaxChi2PerClusterTPC(4.f); + SetRequireHitsInITSLayers(1, {0, 1}); // one hit in any SPD layer + SetMaxChi2PerClusterITS(36.f); + SetMaxDcaXYPtDep([](float pt) { return 0.0105f + 0.0350f / pow(pt, 1.1f); }); + SetMaxDcaZ(2.f); +} + +// Default track selection requiring no hit in the SPD and one in the innermost DCAxy according to LHC2011 +// SDD -> complementary tracks to global selection +void TrackSelectionBrick::constructFB64LHC2011() +{ + constructFB32LHC2011(); + ResetITSRequirements(); + SetRequireNoHitsInITSLayers({0, 1}); // no hit in SPD layers + SetRequireHitsInITSLayers(1, {2}); // one hit in first SDD layer +} + +bool TrackSelectionBrick::FulfillsITSHitRequirements(uint8_t itsClusterMap) +{ + constexpr uint8_t bit = 1; + for (auto& itsRequirement : mRequiredITSHits) { + auto hits = std::count_if(itsRequirement.second.begin(), itsRequirement.second.end(), [&](auto&& requiredLayer) { return itsClusterMap & (bit << requiredLayer); }); + if ((itsRequirement.first == -1) && (hits > 0)) { + return false; // no hits were required in specified layers + } else if (hits < itsRequirement.first) { + return false; // not enough hits found in specified layers + } + } + return true; +} + +const std::string TrackSelectionBrick::mCutNames[static_cast(TrackSelectionBrick::TrackCuts::kNCuts)] = + { + "TrackType", + "TPCNCls", + "TPCCrossedRowsOverNCls", + "TPCRefit", + "ITSNCls", + "ITSChi2NDF", + "ITSRefit", + "ITSHits", + "GoldenChi2", + "DCAxy", + "DCAz"}; + +ClassImp(TrackSelectionBrick); + +/// \brief Construct object from regular expression +/// \param regex The brick regular expression +/// Regular expression has to be of the shape +/// {sp{tpc{cwv{rg{-2.0,2.0};rg{-3.0,3.0}};sp1{cwv{xrg{-2.0,2.0};xrg{-3.0,3.0}}}}}{tof ...}} +PIDSelectionBrick::PIDSelectionBrick(const TString& regex) : SpecialCutBrick(regex, regex) +{ + ConstructFromString(regex); +} + +/// \brief Construct object from regular expression +/// \param regex The brick regular expression +/// Regular expression has to be of the shape +/// {sp{tpc{cwv{rg{-2.0,2.0};rg{-3.0,3.0}};sp1{cwv{xrg{-2.0,2.0};xrg{-3.0,3.0}}}}}{tof ...}} +void PIDSelectionBrick::ConstructFromString(const TString&) +{ +} + +/// \brief Length of the brick +/// \return The brick length +/// Recover the length for each of the components +/// and returns their sum +int PIDSelectionBrick::Length() +{ + int len = 0; + for (auto brick : mCloseNsigmasTPC) { + if (brick != nullptr) { + len += brick->Length(); + } + } + for (auto brick : mCloseNsigmasTOF) { + if (brick != nullptr) { + len += brick->Length(); + } + } + return len; +} + +template +std::vector PIDSelectionBrick::Filter(TrackObject const& track) +{ + std::vector res; + res.reserve(Length()); + std::vector nsigmasTPC(kNoOfSpecies, 999); + std::vector nsigmasTOF(kNoOfSpecies, 999); + + nsigmasTPC[kElectron] = track.tpcNSigmaEl(); + nsigmasTPC[kMuon] = track.tpcNSigmaMu(); + nsigmasTPC[kPion] = track.tpcNSigmaPi(); + nsigmasTPC[kKaon] = track.tpcNSigmaKa(); + nsigmasTPC[kProton] = track.tpcNSigmaPr(); + nsigmasTOF[kElectron] = track.tofNSigmaEl(); + nsigmasTOF[kMuon] = track.tofNSigmaMu(); + nsigmasTOF[kPion] = track.tofNSigmaPi(); + nsigmasTOF[kKaon] = track.tofNSigmaKa(); + nsigmasTOF[kProton] = track.tofNSigmaPr(); + + for (int sp = 0; sp < kNoOfSpecies; ++sp) { + if (mCloseNsigmasTPC[sp] != nullptr) { + std::vector tmp = mCloseNsigmasTPC[sp]->Filter(nsigmasTPC[sp]); + res.insert(res.end(), tmp.begin(), tmp.end()); + } + } + for (int sp = 0; sp < kNoOfSpecies; ++sp) { + if (mCloseNsigmasTOF[sp] != nullptr) { + std::vector tmp = mCloseNsigmasTOF[sp]->Filter(nsigmasTOF[sp]); + res.insert(res.end(), tmp.begin(), tmp.end()); + } + } + return res; +} + +ClassImp(PIDSelectionBrick); diff --git a/PWGCF/TwoParticleCorrelations/Core/SkimmingConfigurableCuts.h b/PWGCF/TwoParticleCorrelations/Core/SkimmingConfigurableCuts.h new file mode 100644 index 00000000000..be802e4ca6e --- /dev/null +++ b/PWGCF/TwoParticleCorrelations/Core/SkimmingConfigurableCuts.h @@ -0,0 +1,471 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. +#ifndef SKIMMING_CONFIGURABLE_CUTS_CLASSES_H +#define SKIMMING_CONFIGURABLE_CUTS_CLASSES_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "Framework/Logger.h" +#include "Framework/DataTypes.h" + +namespace o2 +{ +namespace analysis +{ +namespace PWGCF +{ +/// \class CutBrick +/// \brief Virtual class which implements the base component of the selection cuts +/// +template +class CutBrick : public TNamed +{ + public: + CutBrick(); + CutBrick(const char*, const char*); + CutBrick(const CutBrick&) = delete; + virtual ~CutBrick() override = default; + CutBrick& operator=(const CutBrick&) = delete; + + public: + /// Returns whether the cut brick is active alowing the selection + /// \return true if the brick is active + bool IsActive() { return mState == kACTIVE; } + /// Returns whether the cut is brick is incorporated in the selection chain + bool IsArmed() { return mMode == kSELECTED; } + /// Pure virtual function. Filters the passed value + /// The brick or brick components will change to active if the passed value + /// fits within the brick or brick components scope + /// \returns a vector of booleans with true on the component for which the value activated the component brick + virtual std::vector Filter(const TValueToFilter&) = 0; + /// Pure virtual function. Return the length needed to code the brick status + /// The length is in brick units. The actual length is implementation dependent + /// \returns Brick length in units of bricks + virtual int Length() = 0; + + static CutBrick* constructBrick(const char* name, const char* regex, const std::set& allowed); + static const char* mgImplementedbricks[]; + + /// Set the status of the cut significative (or not) for the selection chain + void Arm(bool doit = true) { doit ? mMode = kSELECTED : mMode = kUNSELECTED; } + + protected: + /// \enum BrickStatus + /// \brief The status of the brick + enum BrickStatus { + kPASSIVE, ///< if the passed value does not comply whith the brick condition + kACTIVE ///< if the passed value comply whith the brick condition + }; + /// \enum BrickMode + /// \brief The mode of operation of the brick + enum BrickMode { + kUNSELECTED, ///< if the status of the brick is not significative + kSELECTED ///< if the status of the brick is significative + }; + + BrickStatus mState = kPASSIVE; + BrickMode mMode = kUNSELECTED; + + ClassDef(CutBrick, 1); +}; + +/// \class CutBrickLimit +/// \brief Class which implements a limiting cut brick. +/// The brick will be active if the filtered value is below the limit +template +class CutBrickLimit : public CutBrick +{ + public: + CutBrickLimit(); + CutBrickLimit(const char*, const TValueToFilter&); + CutBrickLimit(const TString&); + virtual ~CutBrickLimit() override = default; + CutBrickLimit(const CutBrickLimit&) = delete; + CutBrickLimit& operator=(const CutBrickLimit&) = delete; + + virtual std::vector Filter(const TValueToFilter&); + virtual int Length() { return 1; } + + private: + void ConstructCutFromString(const TString&); + + TValueToFilter mLimit; ///< the limiting upper value + ClassDef(CutBrickLimit, 1); +}; + +/// \class CutBrickThreshold +/// \brief Class which implements a threshold cut brick. +/// The brick will be active if the filtered value is above the threshold +template +class CutBrickThreshold : public CutBrick +{ + public: + CutBrickThreshold(); + CutBrickThreshold(const char*, const TValueToFilter&); + CutBrickThreshold(const TString&); + virtual ~CutBrickThreshold() override = default; + CutBrickThreshold(const CutBrickThreshold&) = delete; + CutBrickThreshold& operator=(const CutBrickThreshold&) = delete; + + virtual std::vector Filter(const TValueToFilter&); + virtual int Length() { return 1; } + + private: + void ConstructCutFromString(const TString&); + + TValueToFilter mThreshold; ///< the threshold value + ClassDef(CutBrickThreshold, 1); +}; + +/// \class CutBrickRange +/// \brief Class which implements a range cut brick. +/// The brick will be active if the filtered value is within the range +template +class CutBrickRange : public CutBrick +{ + public: + CutBrickRange(); + CutBrickRange(const char*, const TValueToFilter&, const TValueToFilter&); + CutBrickRange(const TString&); + virtual ~CutBrickRange() override = default; + CutBrickRange(const CutBrickRange&) = delete; + CutBrickRange& operator=(const CutBrickRange&) = delete; + + virtual std::vector Filter(const TValueToFilter&); + virtual int Length() { return 1; } + + private: + void ConstructCutFromString(const TString&); + + TValueToFilter mLow; ///< the lower value of the range + TValueToFilter mHigh; ///< the upper value of the range + ClassDef(CutBrickRange, 1); +}; + +/// \class CutBrickExtToRange +/// \brief Class which implements an external to range cut brick. +/// The brick will be active if the filtered value is outside the range +template +class CutBrickExtToRange : public CutBrick +{ + public: + CutBrickExtToRange(); + CutBrickExtToRange(const char*, const TValueToFilter&, const TValueToFilter&); + CutBrickExtToRange(const TString&); + virtual ~CutBrickExtToRange() override = default; + CutBrickExtToRange(const CutBrickExtToRange&) = delete; + CutBrickExtToRange& operator=(const CutBrickExtToRange&) = delete; + + virtual std::vector Filter(const TValueToFilter&); + virtual int Length() { return 1; } + + private: + void ConstructCutFromString(const TString&); + + TValueToFilter mLow; ///< the lower value of the range + TValueToFilter mHigh; ///< the upper value of the range + ClassDef(CutBrickExtToRange, 1); +}; + +/// \class CutBrickSelectorMultipleRanges +/// \brief Class which implements a string as selector an multiple ranges +/// The brick will be active if the filtered value is inside any of the multiple ranges +/// Otherwise it will be passive +/// Each range might be active in its own if the filtered value is within its scope +template +class CutBrickSelectorMultipleRanges : public CutBrick +{ + public: + CutBrickSelectorMultipleRanges(); + CutBrickSelectorMultipleRanges(const char*, const std::vector&); + CutBrickSelectorMultipleRanges(const TString&); + virtual ~CutBrickSelectorMultipleRanges() override = default; + CutBrickSelectorMultipleRanges(const CutBrickSelectorMultipleRanges&) = delete; + CutBrickSelectorMultipleRanges& operator=(const CutBrickSelectorMultipleRanges&) = delete; + + virtual std::vector Filter(const TValueToFilter&); + /// Return the length needed to code the brick status + /// The length is in brick units. The actual length is implementation dependent + /// \returns Brick length in units of bricks + virtual int Length() { return mActive.size(); } + + private: + void ConstructCutFromString(const TString&); + + std::vector mEdges; ///< the value of the ranges edges (len = nranges + 1) + std::vector mActive; ///< if the associated range is active with the passed value to filter (len = nranges) + ClassDef(CutBrickSelectorMultipleRanges, 1); +}; + +/// \class CutWithVariations +/// \brief Class which implements a cut with its default configuration +/// and its potential variations to be used for systematic tests +template +class CutWithVariations : public CutBrick +{ + public: + /// Default constructor + CutWithVariations(); + CutWithVariations(const char*, const char*, bool); + CutWithVariations(const TString&); + virtual ~CutWithVariations() override = default; + CutWithVariations(const CutWithVariations&) = delete; + CutWithVariations& operator=(const CutWithVariations&) = delete; + + bool AddDefaultBrick(CutBrick* brick); + bool AddVariationBrick(CutBrick* brick); + TList& getDefaultBricks() { return mDefaultBricks; } + TList& getVariantBricks() { return mVariationBricks; } + virtual std::vector Filter(const TValueToFilter&); + virtual int Length(); + + private: + void ConstructCutFromString(const TString&); + + bool mAllowSeveralDefaults; ///< true if allows to store several cut default values + TList mDefaultBricks; ///< the list with the cut default values bricks + TList mVariationBricks; ///< the list with the cut variation values bricks + ClassDef(CutWithVariations, 1); +}; + +/// \class SpecialCutBrick +/// \brief Virtual class which implements the base component of the special selection cuts +/// Special selection cuts are needed because the tables access seems cannot be +/// implemented in templated classes in the class dictionary. If this were found to be +/// feasible things will be easier deriving the special cut bricks directly from CutBrick +/// +class SpecialCutBrick : public TNamed +{ + public: + SpecialCutBrick(); + SpecialCutBrick(const char*, const char*); + SpecialCutBrick(const SpecialCutBrick&) = delete; + virtual ~SpecialCutBrick() override = default; + SpecialCutBrick& operator=(const SpecialCutBrick&) = delete; + + public: + /// Returns whether the cut brick is active alowing the selection + /// \return true if the brick is active + bool IsActive() { return mState == kACTIVE; } + /// Returns whether the cut is brick is incorporated in the selection chain + bool IsArmed() { return mMode == kSELECTED; } + /// Pure virtual function. Return the length needed to code the brick status + /// The length is in brick units. The actual length is implementation dependent + /// \returns Brick length in units of bricks + virtual int Length() = 0; + + protected: + /// Set the status of the cut significative (or not) for the selection chain + void Arm(bool doit = true) { doit ? mMode = kSELECTED : mMode = kUNSELECTED; } + + protected: + /// \enum BrickStatus + /// \brief The status of the brick + enum BrickStatus { + kPASSIVE, ///< if the passed value does not comply whith the brick condition + kACTIVE ///< if the passed value comply whith the brick condition + }; + /// \enum BrickMode + /// \brief The mode of operation of the brick + enum BrickMode { + kUNSELECTED, ///< if the status of the brick is not significative + kSELECTED ///< if the status of the brick is significative + }; + + BrickStatus mState = kPASSIVE; + BrickMode mMode = kUNSELECTED; + + ClassDef(SpecialCutBrick, 1); +}; + +class TrackSelectionBrick : public SpecialCutBrick +{ + public: + TrackSelectionBrick() = default; + TrackSelectionBrick(const TString&); + + enum class TrackCuts : int { + kTrackType = 0, + kTPCNCls, + kTPCCrossedRows, + kTPCCrossedRowsOverNCls, + kTPCChi2NDF, + kTPCRefit, + kITSNCls, + kITSChi2NDF, + kITSRefit, + kITSHits, + kGoldenChi2, + kDCAxy, + kDCAz, + kNCuts + }; + + static const std::string mCutNames[static_cast(TrackCuts::kNCuts)]; + + template + bool Filter(TrackToFilter const& track) + { + if ((track.trackType() == mTrackType) && + (not mCheckNClustersTPC or (track.tpcNClsFound() >= mMinNClustersTPC)) && + (not mCheckNCrossedRowsTPC or (track.tpcNClsCrossedRows() >= mMinNCrossedRowsTPC)) && + (not mCheckMinNCrossedRowsOverFindableClustersTPC or (track.tpcCrossedRowsOverFindableCls() >= mMinNCrossedRowsOverFindableClustersTPC)) && + (not mCheckNClustersITS or (track.itsNCls() >= mMinNClustersITS)) && + (not mCheckMaxChi2PerClusterITS or (track.itsChi2NCl() <= mMaxChi2PerClusterITS)) && + (not mCheckMaxChi2PerClusterTPC or (track.tpcChi2NCl() <= mMaxChi2PerClusterTPC)) && + ((mRequireITSRefit) ? (track.flags() & o2::aod::track::ITSrefit) : true) && + ((mRequireTPCRefit) ? (track.flags() & o2::aod::track::TPCrefit) : true) && + ((mRequireGoldenChi2) ? (track.flags() & o2::aod::track::GoldenChi2) : true) && + FulfillsITSHitRequirements(track.itsClusterMap()) && + (mCheckMaxDcaXY && (abs(track.dcaXY()) <= ((mMaxDcaXYPtDep) ? mMaxDcaXYPtDep(track.pt()) : mMaxDcaXY))) && + (mCheckMaxDcaZ && (abs(track.dcaZ()) <= mMaxDcaZ))) { + this->mState = this->kACTIVE; + return true; + } else { + this->mState = this->kPASSIVE; + return false; + } + } + + int Length() { return 1; } + + void SetTrackType(o2::aod::track::TrackTypeEnum trackType) { mTrackType = trackType; } + void SetRequireITSRefit(bool requireITSRefit = true) { mRequireITSRefit = requireITSRefit; } + void SetRequireTPCRefit(bool requireTPCRefit = true) { mRequireTPCRefit = requireTPCRefit; } + void SetRequireGoldenChi2(bool requireGoldenChi2 = true) { mRequireGoldenChi2 = requireGoldenChi2; } + void SetMinNClustersTPC(int minNClustersTPC) { mMinNClustersTPC = minNClustersTPC; } + void SetMinNCrossedRowsTPC(int minNCrossedRowsTPC) { mMinNCrossedRowsTPC = minNCrossedRowsTPC; } + void SetMinNCrossedRowsOverFindableClustersTPC(float minNCrossedRowsOverFindableClustersTPC) { mMinNCrossedRowsOverFindableClustersTPC = minNCrossedRowsOverFindableClustersTPC; } + void SetMinNClustersITS(int minNClustersITS) { mMinNClustersITS = minNClustersITS; } + void SetMaxChi2PerClusterTPC(float maxChi2PerClusterTPC) { mMaxChi2PerClusterTPC = maxChi2PerClusterTPC; } + void SetMaxChi2PerClusterITS(float maxChi2PerClusterITS) { mMaxChi2PerClusterITS = maxChi2PerClusterITS; } + void SetMaxDcaXY(float maxDcaXY) { mMaxDcaXY = maxDcaXY; } + void SetMaxDcaZ(float maxDcaZ) { mMaxDcaZ = maxDcaZ; } + + void SetMaxDcaXYPtDep(std::function ptDepCut) { mMaxDcaXYPtDep = ptDepCut; } + void SetRequireHitsInITSLayers(int8_t minNRequiredHits, std::set requiredLayers) { mRequiredITSHits.push_back(std::make_pair(minNRequiredHits, requiredLayers)); } + void SetRequireNoHitsInITSLayers(std::set excludedLayers) { mRequiredITSHits.push_back(std::make_pair(-1, excludedLayers)); } + void ResetITSRequirements() { mRequiredITSHits.clear(); } + + void DisableNClustersTPCCheck(bool disable = true) { mCheckNClustersTPC = not disable; } + void DisableNCrossedRowsTPCCheck(bool disable = true) { mCheckNCrossedRowsTPC = not disable; } + void DisableNClustersITSCheck(bool disable = true) { mCheckNClustersITS = not disable; } + void DisableMaxChi2PerClusterTPCCheck(bool disable = true) { mCheckMaxChi2PerClusterTPC = not disable; } + void DisableMaxChi2PerClusterITSCheck(bool disable = true) { mCheckMaxChi2PerClusterITS = not disable; } + void DisableMinNCrossedRowsOverFindableClustersTPCCheck(bool disable = true) { mCheckMinNCrossedRowsOverFindableClustersTPC = not disable; } + void DisableMaxDcaXYCheck(bool disable = true) { mCheckMaxDcaXY = not disable; } + void DisableMaxDcaZCheck(bool disable = true) { mCheckMaxDcaZ = not disable; } + + private: + void constructFB1LHC2010(); + void constructFB1LHC2011(); + void constructFB32LHC2010(); + void constructFB32LHC2011(); + void constructFB64LHC2010(); + void constructFB64LHC2011(); + + bool FulfillsITSHitRequirements(uint8_t itsClusterMap); + + o2::aod::track::TrackTypeEnum mTrackType{o2::aod::track::TrackTypeEnum::Track}; + + // track quality cuts + int mMinNClustersTPC{0}; // min number of TPC clusters + int mMinNCrossedRowsTPC{0}; // min number of crossed rows in TPC + int mMinNClustersITS{0}; // min number of ITS clusters + float mMaxChi2PerClusterTPC{1e10f}; // max tpc fit chi2 per TPC cluster + float mMaxChi2PerClusterITS{1e10f}; // max its fit chi2 per ITS cluster + float mMinNCrossedRowsOverFindableClustersTPC{0.f}; // min ratio crossed rows / findable clusters + + float mMaxDcaXY{1e10f}; // max dca in xy plane + float mMaxDcaZ{1e10f}; // max dca in z direction + std::function mMaxDcaXYPtDep{}; // max dca in xy plane as function of pT + + bool mRequireITSRefit{false}; // require refit in ITS + bool mRequireTPCRefit{false}; // require refit in TPC + bool mRequireGoldenChi2{false}; // require golden chi2 cut (Run 2 only) + + bool mCheckNClustersTPC{true}; // check the number of TPC clusters + bool mCheckNCrossedRowsTPC{true}; // check the number of crossed rows int TPC + bool mCheckNClustersITS{true}; // check the number of ITS clusters + bool mCheckMaxChi2PerClusterTPC{true}; // check max tpc fit chi2 per TPC cluster + bool mCheckMaxChi2PerClusterITS{true}; // check max its fit chi2 per ITS cluster + bool mCheckMinNCrossedRowsOverFindableClustersTPC{true}; // check min ratio crossed rows / findable clusters + bool mCheckMaxDcaXY{true}; // check max dca in xy plane + bool mCheckMaxDcaZ{true}; // check max dca in z direction + + // vector of ITS requirements (minNRequiredHits in specific requiredLayers) + std::vector>> mRequiredITSHits{}; + + ClassDef(TrackSelectionBrick, 1); +}; + +class PIDSelectionBrick : public SpecialCutBrick +{ + public: + PIDSelectionBrick() : SpecialCutBrick(), + mCloseNsigmasTPC(kNoOfSpecies, nullptr), + mCloseNsigmasTOF(kNoOfSpecies, nullptr) + { + } + PIDSelectionBrick(const TString&); + + enum PIDSpecies { + kElectron = 0, ///< electron + kMuon, ///< muon + kPion, ///< pion + kKaon, ///< kaon + kProton, ///< proton + kNoOfSpecies, ///< the number of considered species + kWrongSpecies = -1 + }; + + enum class PIDCuts : int { + kITS = 0, + kTPC, + kTOF, + kTPCTOF, + kNEARSIGMA, + kAWAYSIGMA, + kTOFREQ, + kNCuts + }; + + static const std::string mCutNames[static_cast(PIDCuts::kNCuts)]; + + template + std::vector Filter(TrackToFilter const& track); + + int Length(); + + private: + void ConstructFromString(const TString& cutstr); + + private: + PIDSpecies mSpeciesOfInterest = kWrongSpecies; + std::vector*> mCloseNsigmasTPC; + std::vector*> mCloseNsigmasTOF; + + ClassDef(PIDSelectionBrick, 1); +}; + +} // namespace PWGCF +} // namespace analysis +} // namespace o2 +#endif // SKIMMING_CONFIGURABLE_CUTS_CLASSES_H diff --git a/PWGCF/TwoParticleCorrelations/Core/TrackSelectionFilterAndAnalysis.cxx b/PWGCF/TwoParticleCorrelations/Core/TrackSelectionFilterAndAnalysis.cxx new file mode 100644 index 00000000000..cbac56b3a74 --- /dev/null +++ b/PWGCF/TwoParticleCorrelations/Core/TrackSelectionFilterAndAnalysis.cxx @@ -0,0 +1,294 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +#include +#include + +#include "Framework/AnalysisTask.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/ASoAHelpers.h" +#include "TrackSelectionFilterAndAnalysis.h" + +using namespace o2; +using namespace o2::framework; +using namespace o2::soa; +using namespace o2::framework::expressions; +using namespace o2::analysis::PWGCF; +using namespace boost; + +ClassImp(TrackSelectionFilterAndAnalysis); + +/// \brief Default constructor +TrackSelectionFilterAndAnalysis::TrackSelectionFilterAndAnalysis() + : SelectionFilterAndAnalysis(), + mNClustersTPC(nullptr), + mNCrossedRowsTPC(nullptr), + mNClustersITS(nullptr), + mMaxChi2PerClusterTPC(nullptr), + mMaxChi2PerClusterITS(nullptr), + mMinNCrossedRowsOverFindableClustersTPC(nullptr), + mMaxDcaXY(nullptr), + mMaxDcaZ(nullptr) +{ + /* we own the track types cuts objects */ + mTrackTypes.SetOwner(true); + /* at least we initialize by default pT and eta cuts */ + mPtRange = CutBrick::constructBrick("pT", "rg{0.2,10}", std::set{"rg"}); + mEtaRange = CutBrick::constructBrick("eta", "rg{-0.8,0.8}", std::set{"rg"}); +} + +/// \brief Constructor from regular expression +TrackSelectionFilterAndAnalysis::TrackSelectionFilterAndAnalysis(const TString& cutstr, selmodes mode) + : SelectionFilterAndAnalysis("", mode), + mNClustersTPC(nullptr), + mNCrossedRowsTPC(nullptr), + mNClustersITS(nullptr), + mMaxChi2PerClusterTPC(nullptr), + mMaxChi2PerClusterITS(nullptr), + mMinNCrossedRowsOverFindableClustersTPC(nullptr), + mMaxDcaXY(nullptr), + mMaxDcaZ(nullptr) +{ + /* we own the track types cuts objects */ + mTrackTypes.SetOwner(true); + /* at least we initialize by default pT and eta cuts */ + mPtRange = CutBrick::constructBrick("pT", "rg{0.2,10}", std::set{"rg"}); + mEtaRange = CutBrick::constructBrick("eta", "rg{-0.8,0.8}", std::set{"rg"}); + + ConstructCutFromString(cutstr); +} + +/// \brief Constructor from the track selection configurable +TrackSelectionFilterAndAnalysis::TrackSelectionFilterAndAnalysis(const TrackSelectionConfigurable& trcksel, selmodes mode) + : SelectionFilterAndAnalysis("", mode), + mNClustersTPC(nullptr), + mNCrossedRowsTPC(nullptr), + mNClustersITS(nullptr), + mMaxChi2PerClusterTPC(nullptr), + mMaxChi2PerClusterITS(nullptr), + mMinNCrossedRowsOverFindableClustersTPC(nullptr), + mMaxDcaXY(nullptr), + mMaxDcaZ(nullptr), + mPtRange(nullptr), + mEtaRange(nullptr) +{ + /* we own the track types cuts objects */ + mTrackTypes.SetOwner(true); + + TString cutString = "tracksel{" + trcksel.mTrackTypes; + if (trcksel.mNClustersTPC.size() > 0 or + trcksel.mNCrossedRowsTPC.size() > 0 or + trcksel.mNClustersITS.size() > 0 or + trcksel.mMaxChi2PerClusterTPC.size() > 0 or + trcksel.mMaxChi2PerClusterITS.size() > 0 or + trcksel.mMinNCrossedRowsOverFindableClustersTPC.size() > 0 or + trcksel.mMaxDcaXY.size() > 0 or + trcksel.mMaxDcaZ.size() > 0 or + trcksel.mPtRange.size() > 0 or + trcksel.mEtaRange.size() > 0) { + cutString += ";"; + bool first = true; + + auto appendCut = [&cutString, &first](std::string str) { + if (str.size() > 0) { + if (first) { + cutString += str; + first = false; + } else { + cutString += "," + str; + } + } + }; + appendCut(trcksel.mNClustersTPC); + appendCut(trcksel.mNCrossedRowsTPC); + appendCut(trcksel.mNClustersITS); + appendCut(trcksel.mMaxChi2PerClusterTPC); + appendCut(trcksel.mMaxChi2PerClusterITS); + appendCut(trcksel.mMinNCrossedRowsOverFindableClustersTPC); + appendCut(trcksel.mMaxDcaXY); + appendCut(trcksel.mMaxDcaZ); + appendCut(trcksel.mPtRange); + appendCut(trcksel.mEtaRange); + } + cutString += "}"; + ConstructCutFromString(cutString); +} + +/// \brief Calculates the length of the mask needed to store the selection cuts +int TrackSelectionFilterAndAnalysis::CalculateMaskLength() +{ + int length = 0; + for (int i = 0; i < mTrackTypes.GetEntries(); ++i) { + length += ((SpecialCutBrick*)mTrackTypes.At(i))->Length(); + } + if (mNClustersTPC != nullptr) { + length += mNClustersTPC->Length(); + } + if (mNCrossedRowsTPC != nullptr) { + length += mNCrossedRowsTPC->Length(); + } + if (mNClustersITS != nullptr) { + length += mNClustersITS->Length(); + } + if (mMaxChi2PerClusterTPC != nullptr) { + length += mMaxChi2PerClusterTPC->Length(); + } + if (mMaxChi2PerClusterITS != nullptr) { + length += mMaxChi2PerClusterITS->Length(); + } + if (mMinNCrossedRowsOverFindableClustersTPC != nullptr) { + length += mMinNCrossedRowsOverFindableClustersTPC->Length(); + } + if (mMaxDcaXY != nullptr) { + length += mMaxDcaXY->Length(); + } + if (mMaxDcaZ != nullptr) { + length += mMaxDcaZ->Length(); + } + if (mPtRange != nullptr) { + length += mPtRange->Length(); + } + if (mEtaRange != nullptr) { + length += mEtaRange->Length(); + } + return length; +} + +void TrackSelectionFilterAndAnalysis::SetPtRange(const TString& regex) +{ + if (mPtRange != nullptr) { + delete mPtRange; + } + mPtRange = CutBrick::constructBrick("pT", regex.Data(), std::set{"rg", "th", "lim", "xrg"}); + mMaskLength = CalculateMaskLength(); +} + +void TrackSelectionFilterAndAnalysis::SetEtaRange(const TString& regex) +{ + if (mEtaRange != nullptr) { + delete mEtaRange; + } + mEtaRange = CutBrick::constructBrick("eta", regex.Data(), std::set{"rg", "th", "lim", "xrg"}); + mMaskLength = CalculateMaskLength(); +} + +void TrackSelectionFilterAndAnalysis::ConstructCutFromString(const TString& cutstr) +{ + LOGF(info, "Cut string: %s", cutstr.Data()); + /* let's catch the first level */ + regex cutregex("^tracksel\\{ttype\\{([\\w\\d,]+)};?(\\w+\\{[\\w\\d.,:{}-]+})*}$", regex_constants::ECMAScript | regex_constants::icase); + std::string in(cutstr.Data()); + smatch m; + + bool res = regex_search(in, m, cutregex); + if (not res or m.empty() or (m.size() > 3)) { + Fatal("TrackSelectionFilterAndAnalysis::::ConstructCutFromString", "Wrong RE: %s, try tracksel{ttype{FB32,FB96};ncls{th{70}},nxr{cwv{th{70},th{80}}}} for instance", cutstr.Data()); + } + SetName("TrackSelectionFilterAndAnalysisCuts"); + SetTitle(cutstr.Data()); + + /* let's split the handling of track types and of its characteristics */ + /* let's handle the track types */ + { + LOGF(info, "Captured %s", m[1].str().c_str()); + TObjArray* lev2toks = TString(m[1].str()).Tokenize(","); + for (int i = 0; i < lev2toks->GetEntries(); ++i) { + mTrackTypes.Add(new TrackSelectionBrick(lev2toks->At(i)->GetName())); + } + delete lev2toks; + } + /* let's now handle the reco track characteristics */ + { + LOGF(info, "Captured %s", m[2].str().c_str()); + TString lev2str = m[2].str(); + while (lev2str.Length() != 0) { + std::set allowed = {"lim", "th", "rg", "xrg", "cwv"}; + lev2str.Remove(TString::kLeading, ' '); + lev2str.Remove(TString::kLeading, ','); + lev2str.Remove(TString::kLeading, ' '); + if (lev2str.Length() == 0) { + break; + } + regex cutregex("^(\\w+)\\{((?:[^{}]++|\\{(?2)\\})*)\\}"); + std::string in(lev2str.Data()); + smatch m; + bool res = regex_search(in, m, cutregex); + + if (not res or m.empty() or (m.size() != 3)) { + Fatal("TrackSelectionFilterAndAnalysis::::ConstructCutFromString", "Wrong RE: %s, try tracksel{ttype{FB32,FB96};nclstpc{th{70}},nxr{cwv{th{70},th{80}}}} for instance", cutstr.Data()); + } + LOGF(info, "Captured %s", m[1].str().c_str()); + auto storeIntCut = [&m, &allowed](CutBrick*& brickvar) { + if (brickvar != nullptr) { + delete brickvar; + } + brickvar = CutBrick::constructBrick(m[1].str().c_str(), m[2].str().c_str(), allowed); + }; + auto storeFloatCut = [&m, &allowed](CutBrick*& brickvar) { + if (brickvar != nullptr) { + delete brickvar; + } + brickvar = CutBrick::constructBrick(m[1].str().c_str(), m[2].str().c_str(), allowed); + }; + if (m[1].str() == "nclstpc") { + storeIntCut(mNClustersTPC); + for (int i = 0; i < mTrackTypes.GetEntries(); ++i) { + ((TrackSelectionBrick*)mTrackTypes.At(i))->DisableNClustersTPCCheck(); + } + } else if (m[1].str() == "nclsits") { + storeIntCut(mNClustersITS); + for (int i = 0; i < mTrackTypes.GetEntries(); ++i) { + ((TrackSelectionBrick*)mTrackTypes.At(i))->DisableNClustersITSCheck(); + } + } else if (m[1].str() == "nxrtpc") { + storeIntCut(mNCrossedRowsTPC); + for (int i = 0; i < mTrackTypes.GetEntries(); ++i) { + ((TrackSelectionBrick*)mTrackTypes.At(i))->DisableNCrossedRowsTPCCheck(); + } + } else if (m[1].str() == "chi2clustpc") { + storeFloatCut(mMaxChi2PerClusterTPC); + for (int i = 0; i < mTrackTypes.GetEntries(); ++i) { + ((TrackSelectionBrick*)mTrackTypes.At(i))->DisableMaxChi2PerClusterTPCCheck(); + } + } else if (m[1].str() == "chi2clusits") { + storeFloatCut(mMaxChi2PerClusterITS); + for (int i = 0; i < mTrackTypes.GetEntries(); ++i) { + ((TrackSelectionBrick*)mTrackTypes.At(i))->DisableMaxChi2PerClusterITSCheck(); + } + } else if (m[1].str() == "xrofctpc") { + storeFloatCut(mMinNCrossedRowsOverFindableClustersTPC); + for (int i = 0; i < mTrackTypes.GetEntries(); ++i) { + ((TrackSelectionBrick*)mTrackTypes.At(i))->DisableMinNCrossedRowsOverFindableClustersTPCCheck(); + } + } else if (m[1].str() == "dcaxy") { + storeFloatCut(mMaxDcaXY); + for (int i = 0; i < mTrackTypes.GetEntries(); ++i) { + ((TrackSelectionBrick*)mTrackTypes.At(i))->DisableMaxDcaXYCheck(); + } + } else if (m[1].str() == "dcaz") { + storeFloatCut(mMaxDcaZ); + for (int i = 0; i < mTrackTypes.GetEntries(); ++i) { + ((TrackSelectionBrick*)mTrackTypes.At(i))->DisableMaxDcaZCheck(); + } + } else if (m[1].str() == "pT") { + storeFloatCut(mPtRange); + } else if (m[1].str() == "eta") { + storeFloatCut(mEtaRange); + } else { + Fatal("TrackSelectionFilterAndAnalysis::::ConstructCutFromString", "Wrong RE: %s, cut on variable %s not implemented", cutstr.Data(), m[1].str().c_str()); + } + /* removing the already handled track characteristics cut */ + lev2str.Remove(0, m[0].length()); + } + } + mMaskLength = CalculateMaskLength(); +} + diff --git a/PWGCF/TwoParticleCorrelations/Core/TrackSelectionFilterAndAnalysis.h b/PWGCF/TwoParticleCorrelations/Core/TrackSelectionFilterAndAnalysis.h new file mode 100644 index 00000000000..76b96fecb66 --- /dev/null +++ b/PWGCF/TwoParticleCorrelations/Core/TrackSelectionFilterAndAnalysis.h @@ -0,0 +1,183 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. +#ifndef TRACKSELECTIONFILTERANDANALYSIS_H +#define TRACKSELECTIONFILTERANDANALYSIS_H + +#include +#include +#include +#include +#include + +#include "SkimmingConfigurableCuts.h" +#include "SelectionFilterAndAnalysis.h" + +namespace o2 +{ +namespace analysis +{ +namespace PWGCF +{ +/* forward de declaration */ +class TrackSelectionFilterAndAnalysis; + +///\brief Convenince class for configurable access +class TrackSelectionConfigurable +{ + friend class TrackSelectionFilterAndAnalysis; + + public: + TrackSelectionConfigurable(std::string ttype = "", + std::string nclstpc = "", + std::string nxrtpc = "", + std::string nclsits = "", + std::string chi2clustpc = "", + std::string chi2clusits = "", + std::string xrofctpc = "", + std::string dcaxy = "", + std::string dcaz = "", + std::string ptrange = "", + std::string etarange = "") + : mTrackTypes{ttype}, + mNClustersTPC{nclstpc}, + mNCrossedRowsTPC{nxrtpc}, + mNClustersITS{nclsits}, + mMaxChi2PerClusterTPC{chi2clustpc}, + mMaxChi2PerClusterITS{chi2clusits}, + mMinNCrossedRowsOverFindableClustersTPC{xrofctpc}, + mMaxDcaXY{dcaxy}, + mMaxDcaZ{dcaz}, + mPtRange{ptrange}, + mEtaRange{etarange} + { + } + + private: + std::string mTrackTypes = ""; /// the track types to select list + std::string mNClustersTPC = ""; //! the number of TPC clusters cuts + std::string mNCrossedRowsTPC = ""; //! the number of TPC crossed rows cuts + std::string mNClustersITS = ""; //! the number of ITS clusters cuts + std::string mMaxChi2PerClusterTPC = ""; //! the max Chi2 per TPC cluster cuts + std::string mMaxChi2PerClusterITS = ""; //! the max Chi2 per ITS cluster cuts + std::string mMinNCrossedRowsOverFindableClustersTPC = ""; //! the min ration crossed TPC rows over findable TPC clusters cuts + std::string mMaxDcaXY = ""; //! the DCAxy cuts + std::string mMaxDcaZ = ""; //! the DCAz cuts + std::string mPtRange = ""; //! the pT range cuts + std::string mEtaRange = ""; //! the eta range cuts + + private: + ClassDefNV(TrackSelectionConfigurable, 1); +}; + +/// \brief Filter of tracks and track selection once filetered +class TrackSelectionFilterAndAnalysis : public SelectionFilterAndAnalysis +{ + public: + TrackSelectionFilterAndAnalysis(); + TrackSelectionFilterAndAnalysis(const TString&, selmodes); + TrackSelectionFilterAndAnalysis(const TrackSelectionConfigurable&, selmodes); + + void SetPtRange(const TString&); + void SetEtaRange(const TString&); + + template + uint64_t Filter(TrackToFilter const& track); + + private: + void ConstructCutFromString(const TString&); + int CalculateMaskLength(); + + TList mTrackTypes; /// the track types to select list + CutBrick* mNClustersTPC; //! the number of TPC clusters cuts + CutBrick* mNCrossedRowsTPC; //! the number of TPC crossed rows cuts + CutBrick* mNClustersITS; //! the number of ITS clusters cuts + CutBrick* mMaxChi2PerClusterTPC; //! the max Chi2 per TPC cluster cuts + CutBrick* mMaxChi2PerClusterITS; //! the max Chi2 per ITS cluster cuts + CutBrick* mMinNCrossedRowsOverFindableClustersTPC; //! the min ration crossed TPC rows over findable TPC clusters cuts + CutBrick* mMaxDcaXY; //! the DCAxy cuts + CutBrick* mMaxDcaZ; //! the DCAz cuts + CutBrick* mPtRange; //! the pT range cuts + CutBrick* mEtaRange; //! the eta range cuts + + ClassDef(TrackSelectionFilterAndAnalysis, 1) +}; + +/// \brief Fills the filter cuts mask +template +uint64_t TrackSelectionFilterAndAnalysis::Filter(TrackToFilter const& track) +{ + /* limit for the current implementation */ + int length = CalculateMaskLength(); + if (length > 64) { + LOGF(fatal, "TrackSelectionFilterAndAnalysis not ready for filter mask of %d bits. Just 64 available for the time being"); + } + + uint64_t selectedMask = 0UL; + int bit = 0; + + auto filterTrackType = [&](TrackSelectionBrick* ttype, auto trk) { + if (ttype->Filter(trk)) { + SETBIT(selectedMask, bit); + } + bit++; + }; + + auto filterBrickValue = [&](auto brick, auto value) { + std::vector res = brick->Filter(value); + for (auto b : res) { + if (b) { + SETBIT(selectedMask, bit); + } + bit++; + } + }; + + for (int i = 0; i < mTrackTypes.GetEntries(); ++i) { + filterTrackType((TrackSelectionBrick*)mTrackTypes.At(i), track); + } + if (mNClustersTPC != nullptr) { + filterBrickValue(mNClustersTPC, track.tpcNClsFound()); + } + if (mNCrossedRowsTPC != nullptr) { + filterBrickValue(mNCrossedRowsTPC, track.tpcNClsCrossedRows()); + } + if (mNClustersITS != nullptr) { + filterBrickValue(mNClustersITS, track.itsNCls()); + } + if (mMaxChi2PerClusterTPC != nullptr) { + filterBrickValue(mMaxChi2PerClusterTPC, track.tpcChi2NCl()); + } + if (mMaxChi2PerClusterITS != nullptr) { + filterBrickValue(mMaxChi2PerClusterITS, track.itsChi2NCl()); + } + if (mMinNCrossedRowsOverFindableClustersTPC != nullptr) { + filterBrickValue(mMinNCrossedRowsOverFindableClustersTPC, track.tpcCrossedRowsOverFindableCls()); + } + if (mMaxDcaXY != nullptr) { + filterBrickValue(mMaxDcaXY, track.dcaXY()); + } + if (mMaxDcaZ != nullptr) { + filterBrickValue(mMaxDcaZ, track.dcaZ()); + } + if (mPtRange != nullptr) { + filterBrickValue(mPtRange, track.pt()); + } + if (mEtaRange != nullptr) { + filterBrickValue(mEtaRange, track.eta()); + } + return mSelectedMask = selectedMask; +} + +} // namespace PWGCF +} // namespace analysis +} // namespace o2 + +#endif // TRACKSELECTIONFILTERANDANALYSIS_H diff --git a/PWGCF/TwoParticleCorrelations/Core/TwoPartCorrLinkDef.h b/PWGCF/TwoParticleCorrelations/Core/TwoPartCorrLinkDef.h new file mode 100644 index 00000000000..e8fe6daeebb --- /dev/null +++ b/PWGCF/TwoParticleCorrelations/Core/TwoPartCorrLinkDef.h @@ -0,0 +1,38 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +#pragma link off all globals; +#pragma link off all classes; +#pragma link off all functions; + +#pragma link C++ class o2::analysis::PWGCF::CutBrick < float> + ; +#pragma link C++ class o2::analysis::PWGCF::CutBrick < int> + ; +#pragma link C++ class o2::analysis::PWGCF::CutBrickLimit < float> + ; +#pragma link C++ class o2::analysis::PWGCF::CutBrickLimit < int> + ; +#pragma link C++ class o2::analysis::PWGCF::CutBrickThreshold < float> + ; +#pragma link C++ class o2::analysis::PWGCF::CutBrickThreshold < int> + ; +#pragma link C++ class o2::analysis::PWGCF::CutBrickExtToRange < float> + ; +#pragma link C++ class o2::analysis::PWGCF::CutBrickRange < int> + ; +#pragma link C++ class o2::analysis::PWGCF::CutBrickRange < float> + ; +#pragma link C++ class o2::analysis::PWGCF::CutBrickExtToRange < int> + ; +#pragma link C++ class o2::analysis::PWGCF::CutBrickSelectorMultipleRanges < float> + ; +#pragma link C++ class o2::analysis::PWGCF::CutBrickSelectorMultipleRanges < int> + ; +#pragma link C++ class o2::analysis::PWGCF::CutWithVariations < float> + ; +#pragma link C++ class o2::analysis::PWGCF::CutWithVariations < int> + ; +#pragma link C++ class o2::analysis::PWGCF::SpecialCutBrick + ; +#pragma link C++ class o2::analysis::PWGCF::TrackSelectionBrick + ; +#pragma link C++ class o2::analysis::PWGCF::PIDSelectionBrick + ; +#pragma link C++ class o2::analysis::PWGCF::SelectionFilterAndAnalysis + ; +#pragma link C++ class o2::analysis::PWGCF::TrackSelectionConfigurable + ; +#pragma link C++ class o2::analysis::PWGCF::TrackSelectionFilterAndAnalysis + ; +#pragma link C++ class o2::analysis::PWGCF::PIDSelectionFilterAndAnalysis + ; +#pragma link C++ class o2::analysis::PWGCF::EventSelectionConfigurable + ; +#pragma link C++ class o2::analysis::PWGCF::EventSelectionFilterAndAnalysis + ; diff --git a/PWGCF/TwoParticleCorrelations/DataModel/TwoParticleCorrelationsSkimmed.h b/PWGCF/TwoParticleCorrelations/DataModel/TwoParticleCorrelationsSkimmed.h new file mode 100644 index 00000000000..c784f9c86c0 --- /dev/null +++ b/PWGCF/TwoParticleCorrelations/DataModel/TwoParticleCorrelationsSkimmed.h @@ -0,0 +1,91 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +#include "Framework/AnalysisTask.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/ASoAHelpers.h" +#include "Common/DataModel/TrackSelectionTables.h" +#include "Common/DataModel/Centrality.h" +#include "PWGCF/TwoParticleCorrelations/Core/SkimmingConfigurableCuts.h" +#include "PWGCF/TwoParticleCorrelations/Core/EventSelectionFilterAndAnalysis.h" +#include "PWGCF/TwoParticleCorrelations/Core/TrackSelectionFilterAndAnalysis.h" +#include "PWGCF/TwoParticleCorrelations/Core/PIDSelectionFilterAndAnalysis.h" +#include "Framework/runDataProcessing.h" + +/* TODO: this will go to its proper header at some point */ +#ifndef O2_ANALYSIS_TWOPSKIMMED_H +#define O2_ANALYSIS_TWOPSKIMMED_H + +#include "Framework/ASoA.h" +#include "Framework/AnalysisDataModel.h" + +namespace o2 +{ +namespace aod +{ +/* we have to change from int to bool when bool columns work properly */ +namespace twopskim +{ +DECLARE_SOA_COLUMN(TwoPSkimmedCollisionCentMult, centmult, float); //! The centrality/multiplicity pecentile +DECLARE_SOA_COLUMN(TwoPSkimmedCollisionFlags, selflags, uint64_t); //! The skimming flags for collision selection +} // namespace twopskim +DECLARE_SOA_TABLE(TwoPSkimmedCollisions, "AOD", "TWOPSKMDCOLL", //! Accepted reconstructed collisions/events filtered table + o2::soa::Index<>, + collision::PosZ, + twopskim::TwoPSkimmedCollisionCentMult, + twopskim::TwoPSkimmedCollisionFlags); +using TwoPSkimmedCollision = TwoPSkimmedCollisions::iterator; +DECLARE_SOA_TABLE(TwoPSkimmedGenCollisions, "AOD", "TWOPSKMDGENCOLL", //! Accepted generated collisions/events filtered table + o2::soa::Index<>, + mccollision::PosZ, + twopskim::TwoPSkimmedCollisionCentMult, + twopskim::TwoPSkimmedCollisionFlags); +using TwoPSkimmedGenCollision = TwoPSkimmedGenCollisions::iterator; +namespace twopskim +{ +DECLARE_SOA_INDEX_COLUMN(TwoPSkimmedCollision, event); //! Reconstructed collision/event +DECLARE_SOA_INDEX_COLUMN(TwoPSkimmedGenCollision, mcevent); //! Generated collision/event +DECLARE_SOA_COLUMN(TwoPSkimmedTrackFlags, trackflags, uint64_t); //! The skimming flags for track selection +DECLARE_SOA_COLUMN(sPt, spt, float); //! The track charge signed transverse momentum +DECLARE_SOA_DYNAMIC_COLUMN(Pt, pt, //! The track transverse momentum + [](float signedpt) -> float { + return abs(signedpt); + }); +DECLARE_SOA_COLUMN(Eta, eta, float); //! The track pseudorapidity +DECLARE_SOA_COLUMN(Phi, phi, float); //! The track azimuthal angle +DECLARE_SOA_COLUMN(Charge, charge, int8_t); //! Charge: in units of electric charge +DECLARE_SOA_DYNAMIC_COLUMN(Sign, sign, //! The track transverse momentum + [](float signedpt) -> short { + return (signedpt >= 0) ? 1 : -1; + }); +} // namespace twopskim +DECLARE_SOA_TABLE(TwoPSkimmedTracks, "AOD", "TWOPSKMDTRKS", //! The reconstructed tracks filtered table + twopskim::TwoPSkimmedCollisionId, + twopskim::TwoPSkimmedTrackFlags, + twopskim::sPt, + twopskim::Eta, + twopskim::Phi, + twopskim::Pt, + twopskim::Sign); +DECLARE_SOA_TABLE(TwoPSkimmedParticles, "AOD", "TWOPSKMDPARTS", //! The generated particles filtered table + twopskim::TwoPSkimmedGenCollisionId, + twopskim::TwoPSkimmedTrackFlags, + twopskim::sPt, + twopskim::Eta, + twopskim::Phi, + twopskim::Pt, + twopskim::Sign); +} // namespace aod +} // namespace o2 + +#endif // O2_ANALYSIS_TWOPSKIMMED_H + + diff --git a/PWGCF/TwoParticleCorrelations/TableProducer/CMakeLists.txt b/PWGCF/TwoParticleCorrelations/TableProducer/CMakeLists.txt new file mode 100644 index 00000000000..63efdc12601 --- /dev/null +++ b/PWGCF/TwoParticleCorrelations/TableProducer/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(twopartcorr-skim + SOURCES twoParticleCorrelationsSkimming.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::TwoPartCorrCore + COMPONENT_NAME Analysis) diff --git a/PWGCF/TwoParticleCorrelations/TableProducer/skimmingconf.h b/PWGCF/TwoParticleCorrelations/TableProducer/skimmingconf.h new file mode 100644 index 00000000000..cb0fcbd9d01 --- /dev/null +++ b/PWGCF/TwoParticleCorrelations/TableProducer/skimmingconf.h @@ -0,0 +1,46 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. +#ifndef O2_ANALYSIS_DPTDPTSKIMCONF_H +#define O2_ANALYSIS_DPTDPTSKIMCONF_H + +#include "Framework/AnalysisTask.h" +#include "Framework/ASoAHelpers.h" + +struct : ConfigurableGroup { + Configurable zvtxsel{"evtflt_zvtx", "zvtx{cwv{rg{-7.0,7.0}:rg{-10.0,10.0}-no,rg{-3.0,3.0}-no}}", "Z vertex cut: zvtx{rg{-7.0,7.0}} or zvtx{cwv{def:var1,var2@,..}}"}; + Configurable centmultsel{"evtflt_centmult", "centmult{cwv{mrg{V0M,0,5,10,20,30,40,50,60,70,80}-yes:mrg{CL1,0,5,10,20,30,40,50,60,70,80}-no}}", "Centrality/Multiplicity cut: centmult{mrg{V0M,0,5,10,20,30,40,50,60,70,80}}"}; +} eventfilter; + +struct : ConfigurableGroup { + Configurable ttype{"trkflt_ttype", "ttype{FB1,FB32,FB64}", "Track types to filter"}; + Configurable nclstpc{"trkflt_nclstpc", "nclstpc{cwv{th{70}:th{80}-no,th{90}-no}}", "Min no of TPC clusters: nclstpc{th{70}} or nclstpc{cwv{def:var1,var2,...}}"}; + // Configurable nxrtpc{"trkflt_nxrtpc", "nxrtpc{}", "Min no of TPC crossed rows: nxrtpc{th{70}} or nxrtpc{cwv{def;var1,var2,...}}"}; + Configurable nxrtpc{"trkflt_nxrtpc", "", "Min no of TPC crossed rows: nxrtpc{th{70}} or nxrtpc{cwv{def;var1,var2,...}}"}; + // Configurable nclsits{"trkflt_nclsits", "nclsits{}", "Min no of ITS clusters: nclsits{th{3}} or nclsits{cwv{def;var1,var2,...}}"}; + Configurable nclsits{"trkflt_nclsits", "", "Min no of ITS clusters: nclsits{th{3}} or nclsits{cwv{def;var1,var2,...}}"}; + Configurable chi2clustpc{"trkflt_chi2clustpc", "chi2clustpc{cwv{lim{4}:lim{3}-no,lim{90}-no}}", "Max Chi^2 per TPC cluster: chi2clustpc{lim{4}} or chi2clustpc{cwv{def:var1,var2,...}}"}; + // Configurable chi2clusits{"trkflt_chi2clusits", "chi2clusits{}", "Max Chi^2 per ITS cluster: chi2clusits{lim{4}} or chi2clusits{cwv{def;var1,var2,...}}"}; + Configurable chi2clusits{"trkflt_chi2clusits", "", "Max Chi^2 per ITS cluster: chi2clusits{lim{4}} or chi2clusits{cwv{def;var1,var2,...}}"}; + // Configurable xrofctpc{"trkflt_xrofctpc", "xrofctpc{}", "Min no of TPC crossed rows over findable clusters: xrofctpc{th{0.70}} or xrofctpc{cwv{def;var1,var2,...}}"}; + Configurable xrofctpc{"trkflt_xrofctpc", "", "Min no of TPC crossed rows over findable clusters: xrofctpc{th{0.70}} or xrofctpc{cwv{def;var1,var2,...}}"}; + // Configurable dcaxy{"trkflt_dcaxy", "dcaxy{}", "Max DCAxy: dcaxy{lim{2.3}} or dcaxy{cwv{def;var1,var2,...}}"}; + Configurable dcaxy{"trkflt_dcaxy", "", "Max DCAxy: dcaxy{lim{2.3}} or dcaxy{cwv{def;var1,var2,...}}"}; + // Configurable dcaz{"trkflt_dcaz", "dcaz{}", "Max DCAz: dcaz{lim{3.0}} or dcaz{cwv{def;var1,var2,...}}"}; + Configurable dcaz{"trkflt_dcaz", "", "Max DCAz: dcaz{lim{3.0}} or dcaz{cwv{def;var1,var2,...}}"}; + Configurable ptrange{"trkflt_pt", "pT{rg{0.2,10.0}}", "pT range: pT{th{0.2}} or pT{cwv{def;var1,var2,...}}"}; + Configurable etarange{"trkflt_eta", "eta{rg{-0.8,0.8}}", "eta range: eta{rg{-0.9,0.9}} or eta{cwv{def;var1,var2,...}}"}; +} trackfilter; + +struct : ConfigurableGroup { + +} pidfilter; + +#endif // O2_ANALYSIS_DPTDPTSKIMCONF_H diff --git a/PWGCF/TwoParticleCorrelations/TableProducer/twoParticleCorrelationsSkimming.cxx b/PWGCF/TwoParticleCorrelations/TableProducer/twoParticleCorrelationsSkimming.cxx new file mode 100644 index 00000000000..d83840f3616 --- /dev/null +++ b/PWGCF/TwoParticleCorrelations/TableProducer/twoParticleCorrelationsSkimming.cxx @@ -0,0 +1,194 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +#include "Framework/AnalysisTask.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/ASoAHelpers.h" +#include "Common/DataModel/TrackSelectionTables.h" +#include "Common/DataModel/Centrality.h" +#include "PWGCF/TwoParticleCorrelations/DataModel/TwoParticleCorrelationsSkimmed.h" +#include "PWGCF/TwoParticleCorrelations/Core/SkimmingConfigurableCuts.h" +#include "PWGCF/TwoParticleCorrelations/Core/EventSelectionFilterAndAnalysis.h" +#include "PWGCF/TwoParticleCorrelations/Core/TrackSelectionFilterAndAnalysis.h" +#include "PWGCF/TwoParticleCorrelations/Core/PIDSelectionFilterAndAnalysis.h" +#include "Framework/runDataProcessing.h" + +using namespace o2; +using namespace o2::framework; +using namespace o2::soa; +using namespace o2::framework::expressions; +using namespace o2::analysis; + +namespace o2::analysis::twopskim +{ +#define LOGTRACKCOLLISIONS debug +#define LOGTRACKTRACKS debug + +PWGCF::TrackSelectionFilterAndAnalysis* fTrackFilter = nullptr; +PWGCF::EventSelectionFilterAndAnalysis* fEventFilter = nullptr; +} + +using namespace twopskim; + +void setEventCutsLabels(std::shared_ptr h) +{ + using namespace aod::run2; + + /* labels taken from O2/Framework DataTypes.h */ + const char* evcutslabel[kTRDHEE + 1] = { + "kINELgtZERO", + "kPileupInMultBins", + "kConsistencySPDandTrackVertices", + "kTrackletsVsClusters", + "kNonZeroNContribs", + "kIncompleteDAQ", + "kPileUpMV", + "kTPCPileUp", + "kTimeRangeCut", + "kEMCALEDCut", + "kAliEventCutsAccepted", + "kIsPileupFromSPD", + "kIsV0PFPileup", + "kIsTPCHVdip", + "kIsTPCLaserWarmUp", + "kTRDHCO", + "kTRDHJT", + "kTRDHSE", + "kTRDHQU", + "kTRDHEE"}; + + for (int bit = kINELgtZERO; bit <= kTRDHEE; ++bit) { + h->GetXaxis()->SetBinLabel(bit + 1, evcutslabel[bit]); + } +} + +void reportEventCuts(std::shared_ptr h, uint32_t eventcuts) +{ + using namespace aod::run2; + auto entries = h->GetEntries(); + for (int bit = kINELgtZERO; bit <= kTRDHEE; ++bit) { + if (TESTBIT(eventcuts, bit)) { + h->Fill(bit + 0.5); + } + } + h->SetEntries(entries + 1); +} + +struct TwoParticleCorrelationsSkimming { + /* skimmed data tables */ + Produces skimmedcollision; + Produces skimmedtrack; + Produces skimmedgencollision; + Produces skimmedparticles; + +#include "skimmingconf.h" + + int nReportedTracks; + HistogramRegistry historeg; + + void init(InitContext const&) + { + using namespace twopskim; + + LOGF(info, "DptDptSkimTask::init()"); + + /* collision filtering configuration */ + PWGCF::EventSelectionConfigurable eventsel(eventfilter.centmultsel, "", eventfilter.zvtxsel, ""); + fEventFilter = new PWGCF::EventSelectionFilterAndAnalysis(eventsel, PWGCF::SelectionFilterAndAnalysis::kFilter); + + /* track filtering configuration */ + PWGCF::TrackSelectionConfigurable trksel(trackfilter.ttype, trackfilter.nclstpc, trackfilter.nxrtpc, trackfilter.nclsits, trackfilter.chi2clustpc, + trackfilter.chi2clusits, trackfilter.xrofctpc, trackfilter.dcaxy, trackfilter.dcaz, trackfilter.ptrange, trackfilter.etarange); + fTrackFilter = new PWGCF::TrackSelectionFilterAndAnalysis(trksel, PWGCF::SelectionFilterAndAnalysis::kFilter); + nReportedTracks = 0; + + historeg.add("EventCuts", "EventCuts", {HistType::kTH1F, {{aod::run2::kTRDHEE + 1, 0, aod::run2::kTRDHEE + 1}}}); + setEventCutsLabels(historeg.get(HIST("EventCuts"))); + } + + template + uint64_t filterRun2Collision(Coll const& collision, BcInfo const& bcinfo) + { + using namespace aod::run2; + using namespace aod::collision; + + uint32_t eventcuts = bcinfo.eventCuts(); + bool accepted = true; + + // NOT CONFIGURABLE EVENT SELECTION + /* incomplete data acquisition */ + if (not TESTBIT(eventcuts, kIncompleteDAQ)) { + accepted = false; + } + /* pile-up */ + /* TODO: check if this is also valid for Run 1 data */ + if (not TESTBIT(eventcuts, kPileupInMultBins) or + not TESTBIT(eventcuts, kTrackletsVsClusters) or + not TESTBIT(eventcuts, kPileUpMV) or + not TESTBIT(eventcuts, kTimeRangeCut) or + not TESTBIT(eventcuts, kTPCPileUp) or + TESTBIT(eventcuts, kIsPileupFromSPD) or + TESTBIT(eventcuts, kIsV0PFPileup)) { + accepted = false; + } + /* TPC issues*/ + if (TESTBIT(eventcuts, kIsTPCHVdip) or + TESTBIT(eventcuts, kIsTPCLaserWarmUp)) { + accepted = false; + } + /* vertex */ + if (not TESTBIT(eventcuts, kNonZeroNContribs) or + (((collision.flags() & Run2VertexerZ) == Run2VertexerZ) && collision.covZZ() < 0.25)) { + accepted = false; + } + reportEventCuts(historeg.get(HIST("EventCuts")), eventcuts); + + // CONFIGURABLE EVENT SELECTION + if (accepted) { + return fEventFilter->Filter(collision); + } else { + return 0UL; + } + } + + void processRun2(soa::Join::iterator const& collision, soa::Join const&, soa::Join const& tracks) + { + /* for the time being this will apply only to Run 1+2 converted data */ + LOGF(LOGTRACKCOLLISIONS, "Got a new collision with zvtx %.2f and V0M %.2f, CL0 %.2f, CL1 %.2f", collision.posZ(), collision.centRun2V0M(), collision.centRun2CL0(), collision.centRun2CL1()); + + auto colmask = filterRun2Collision(collision, collision.bc_as>()); + LOGF(LOGTRACKCOLLISIONS, "Got mask 0x%lx", colmask); + + if (colmask != 0UL) { + skimmedcollision(collision.posZ(), 50.0, colmask); + for (auto const& track : tracks) { + auto trkmask = fTrackFilter->Filter(track); + if (trkmask != 0UL) { + skimmedtrack(skimmedcollision.lastIndex(), trkmask, track.pt() * track.sign(), track.eta(), track.phi()); + } + if ((trkmask & 0xFFFFF9FF) != 0UL and nReportedTracks < 1000) { + LOGF(LOGTRACKTRACKS, " Got track mask 0x%lx, TPC clusters %d, Chi2 per TPC cluster %f, pT %f, eta %f, track type %d", + trkmask, track.tpcNClsFound(), track.tpcChi2NCl(), track.pt(), track.eta(), track.trackType()); + nReportedTracks++; + } + } + } + } + PROCESS_SWITCH(TwoParticleCorrelationsSkimming, processRun2, "Process on Run 1 or Run 2 data", true); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + WorkflowSpec workflow{ + adaptAnalysisTask(cfgc)}; + return workflow; +} + diff --git a/PWGCF/TwoParticleCorrelations/Tasks/CMakeLists.txt b/PWGCF/TwoParticleCorrelations/Tasks/CMakeLists.txt new file mode 100644 index 00000000000..17bb6e42f65 --- /dev/null +++ b/PWGCF/TwoParticleCorrelations/Tasks/CMakeLists.txt @@ -0,0 +1,11 @@ +# Copyright 2019-2020 CERN and copyright holders of ALICE O2. +# See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +# All rights not expressly granted are reserved. +# +# This software is distributed under the terms of the GNU General Public +# License v3 (GPL Version 3), copied verbatim in the file "COPYING". +# +# In applying this license CERN does not waive the privileges and immunities +# granted to it by virtue of its status as an Intergovernmental Organization +# or submit itself to any jurisdiction. + From ee3c1296aefe90bee8dfe937747335890657d79a Mon Sep 17 00:00:00 2001 From: ALICE Action Bot Date: Sat, 17 Sep 2022 13:56:29 +0000 Subject: [PATCH 02/20] Please consider the following formatting changes --- .../Core/EventSelectionFilterAndAnalysis.cxx | 1 - .../Core/EventSelectionFilterAndAnalysis.h | 10 +++++----- .../Core/SelectionFilterAndAnalysis.cxx | 1 - .../Core/TrackSelectionFilterAndAnalysis.cxx | 1 - .../DataModel/TwoParticleCorrelationsSkimmed.h | 2 -- .../TableProducer/twoParticleCorrelationsSkimming.cxx | 3 +-- 6 files changed, 6 insertions(+), 12 deletions(-) diff --git a/PWGCF/TwoParticleCorrelations/Core/EventSelectionFilterAndAnalysis.cxx b/PWGCF/TwoParticleCorrelations/Core/EventSelectionFilterAndAnalysis.cxx index d0f8c89f3c8..769e76a22e3 100644 --- a/PWGCF/TwoParticleCorrelations/Core/EventSelectionFilterAndAnalysis.cxx +++ b/PWGCF/TwoParticleCorrelations/Core/EventSelectionFilterAndAnalysis.cxx @@ -235,4 +235,3 @@ void EventSelectionFilterAndAnalysis::ConstructCutFromString(const TString& cuts LOGF(fatal, "EventSelectionFilterAndAnalysis not ready for filter mask of %d bits. Just 64 available for the time being", mMaskLength); } } - diff --git a/PWGCF/TwoParticleCorrelations/Core/EventSelectionFilterAndAnalysis.h b/PWGCF/TwoParticleCorrelations/Core/EventSelectionFilterAndAnalysis.h index eb4494d3f5d..8481cbd65c7 100644 --- a/PWGCF/TwoParticleCorrelations/Core/EventSelectionFilterAndAnalysis.h +++ b/PWGCF/TwoParticleCorrelations/Core/EventSelectionFilterAndAnalysis.h @@ -69,11 +69,11 @@ class EventSelectionFilterAndAnalysis : public SelectionFilterAndAnalysis void InitializeMultiplicityFilter(); int CalculateMaskLength(); - CutBrick* mMultiplicityClasses; //! the multiplicity default classes cuts - CutBrick* mTriggerSelection; //! the trigger selection cuts - CutBrick* mZVertex; //! the z vertex selection cuts - CutBrick* mPileUpRejection; //! the pile-up rejection criteria - std::vector mMultiplicities; // the collision multiplicities from the different implemented estimators + CutBrick* mMultiplicityClasses; //! the multiplicity default classes cuts + CutBrick* mTriggerSelection; //! the trigger selection cuts + CutBrick* mZVertex; //! the z vertex selection cuts + CutBrick* mPileUpRejection; //! the pile-up rejection criteria + std::vector mMultiplicities; // the collision multiplicities from the different implemented estimators int mDefaultMultiplicityEstimatorIndex; // the default estimator index on the collision multiplicities array std::vector mAlternateMultiplicityEstimatorIndex; // the vector of alternate estimators index on the collision multiplicities array diff --git a/PWGCF/TwoParticleCorrelations/Core/SelectionFilterAndAnalysis.cxx b/PWGCF/TwoParticleCorrelations/Core/SelectionFilterAndAnalysis.cxx index e3ad4b8c452..808ad9d56cd 100644 --- a/PWGCF/TwoParticleCorrelations/Core/SelectionFilterAndAnalysis.cxx +++ b/PWGCF/TwoParticleCorrelations/Core/SelectionFilterAndAnalysis.cxx @@ -44,4 +44,3 @@ SelectionFilterAndAnalysis::SelectionFilterAndAnalysis(const TString& name, selm mArmedMask(0UL) { } - diff --git a/PWGCF/TwoParticleCorrelations/Core/TrackSelectionFilterAndAnalysis.cxx b/PWGCF/TwoParticleCorrelations/Core/TrackSelectionFilterAndAnalysis.cxx index cbac56b3a74..090595cdd8f 100644 --- a/PWGCF/TwoParticleCorrelations/Core/TrackSelectionFilterAndAnalysis.cxx +++ b/PWGCF/TwoParticleCorrelations/Core/TrackSelectionFilterAndAnalysis.cxx @@ -291,4 +291,3 @@ void TrackSelectionFilterAndAnalysis::ConstructCutFromString(const TString& cuts } mMaskLength = CalculateMaskLength(); } - diff --git a/PWGCF/TwoParticleCorrelations/DataModel/TwoParticleCorrelationsSkimmed.h b/PWGCF/TwoParticleCorrelations/DataModel/TwoParticleCorrelationsSkimmed.h index c784f9c86c0..80d08788bf1 100644 --- a/PWGCF/TwoParticleCorrelations/DataModel/TwoParticleCorrelationsSkimmed.h +++ b/PWGCF/TwoParticleCorrelations/DataModel/TwoParticleCorrelationsSkimmed.h @@ -87,5 +87,3 @@ DECLARE_SOA_TABLE(TwoPSkimmedParticles, "AOD", "TWOPSKMDPARTS", //! The generate } // namespace o2 #endif // O2_ANALYSIS_TWOPSKIMMED_H - - diff --git a/PWGCF/TwoParticleCorrelations/TableProducer/twoParticleCorrelationsSkimming.cxx b/PWGCF/TwoParticleCorrelations/TableProducer/twoParticleCorrelationsSkimming.cxx index d83840f3616..1954a01a8ae 100644 --- a/PWGCF/TwoParticleCorrelations/TableProducer/twoParticleCorrelationsSkimming.cxx +++ b/PWGCF/TwoParticleCorrelations/TableProducer/twoParticleCorrelationsSkimming.cxx @@ -34,7 +34,7 @@ namespace o2::analysis::twopskim PWGCF::TrackSelectionFilterAndAnalysis* fTrackFilter = nullptr; PWGCF::EventSelectionFilterAndAnalysis* fEventFilter = nullptr; -} +} // namespace o2::analysis::twopskim using namespace twopskim; @@ -191,4 +191,3 @@ WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) adaptAnalysisTask(cfgc)}; return workflow; } - From 608b6d7674aa181dbe6fd2072b8a35fd554ac5e7 Mon Sep 17 00:00:00 2001 From: Victor Date: Tue, 20 Sep 2022 23:34:25 +0200 Subject: [PATCH 03/20] Implementation of the two particle correlations filter task --- .../TwoParticleCorrelationsFiltered.h | 62 +++++++++++++++ .../TwoParticleCorrelationsSkimmed.h | 2 +- .../TableProducer/CMakeLists.txt | 5 ++ .../twoParticleCorrelationsFiltering.cxx | 79 +++++++++++++++++++ 4 files changed, 147 insertions(+), 1 deletion(-) create mode 100644 PWGCF/TwoParticleCorrelations/DataModel/TwoParticleCorrelationsFiltered.h create mode 100644 PWGCF/TwoParticleCorrelations/TableProducer/twoParticleCorrelationsFiltering.cxx diff --git a/PWGCF/TwoParticleCorrelations/DataModel/TwoParticleCorrelationsFiltered.h b/PWGCF/TwoParticleCorrelations/DataModel/TwoParticleCorrelationsFiltered.h new file mode 100644 index 00000000000..af5cd5a462a --- /dev/null +++ b/PWGCF/TwoParticleCorrelations/DataModel/TwoParticleCorrelationsFiltered.h @@ -0,0 +1,62 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. +#ifndef O2_ANALYSIS_TWOPARTFILTERED_H +#define O2_ANALYSIS_TWOPARTFILTERED_H + +#include "Framework/ASoA.h" +#include "Framework/AnalysisDataModel.h" +#include "TwoParticleCorrelationsSkimmed.h" + +namespace o2 +{ +namespace aod +{ +/* we have to change from int to bool when bool columns work properly */ +namespace twopfilter +{ +DECLARE_SOA_COLUMN(TwoPCollisionCentMult, centmult, float); //! The centrality/multiplicity pecentile +} // namespace twopfilter +DECLARE_SOA_TABLE(TwoPAcceptedCollisions, "AOD", "TWOPACCCOLL", //! Accepted reconstructed collisions/events filtered table + o2::soa::Index<>, + collision::BCId, + collision::PosZ, + twopfilter::TwoPCollisionCentMult); +using TowPAcceptedCollision = TwoPAcceptedCollisions::iterator; +DECLARE_SOA_TABLE(TwoPAcceptedGenCollisions, "AOD", "TWOPACCGENCOLL", //! Accepted generated collisions/events filtered table + o2::soa::Index<>, + collision::BCId, + mccollision::PosZ, + twopfilter::TwoPCollisionCentMult); +using TwoPAcceptedGenCollision = TwoPAcceptedGenCollisions::iterator; +namespace twopfilter +{ +DECLARE_SOA_INDEX_COLUMN(TwoPAcceptedCollision, collision); //! Reconstructed collision/event +DECLARE_SOA_INDEX_COLUMN(TwoPAcceptedGenCollision, mccollision); //! Generated collision/event +DECLARE_SOA_COLUMN(TwoPTrackacceptedAs, twoptrackacceptedas, uint8_t); //! Track accepted as type 0..255, even positive or particle, odd negative or antiparticle +} // namespace twopfilter +DECLARE_SOA_TABLE(TwoPFilteredTracks, "AOD", "FILTEREDTRKS", //! The reconstructed tracks filtered table + twopfilter::TwoPAcceptedCollisionId, + twopfilter::TwoPTrackacceptedAs, + twopskim::sPt, + twopskim::Eta, + twopskim::Phi, + twopskim::Sign); +DECLARE_SOA_TABLE(TwoPFilteredParticles, "AOD", "FILTEREDGENTRKS", //! The generated particles filtered table + twopfilter::TwoPAcceptedGenCollisionId, + twopfilter::TwoPTrackacceptedAs, + twopskim::sPt, + twopskim::Eta, + twopskim::Phi, + twopskim::Sign); +} // namespace aod +} // namespace o2 + +#endif // O2_ANALYSIS_TWOPARTFILTERED_H diff --git a/PWGCF/TwoParticleCorrelations/DataModel/TwoParticleCorrelationsSkimmed.h b/PWGCF/TwoParticleCorrelations/DataModel/TwoParticleCorrelationsSkimmed.h index 80d08788bf1..6dffe0736e6 100644 --- a/PWGCF/TwoParticleCorrelations/DataModel/TwoParticleCorrelationsSkimmed.h +++ b/PWGCF/TwoParticleCorrelations/DataModel/TwoParticleCorrelationsSkimmed.h @@ -57,7 +57,7 @@ DECLARE_SOA_COLUMN(TwoPSkimmedTrackFlags, trackflags, uint64_t); //! The skimmin DECLARE_SOA_COLUMN(sPt, spt, float); //! The track charge signed transverse momentum DECLARE_SOA_DYNAMIC_COLUMN(Pt, pt, //! The track transverse momentum [](float signedpt) -> float { - return abs(signedpt); + return std::abs(signedpt); }); DECLARE_SOA_COLUMN(Eta, eta, float); //! The track pseudorapidity DECLARE_SOA_COLUMN(Phi, phi, float); //! The track azimuthal angle diff --git a/PWGCF/TwoParticleCorrelations/TableProducer/CMakeLists.txt b/PWGCF/TwoParticleCorrelations/TableProducer/CMakeLists.txt index 63efdc12601..53721e68464 100644 --- a/PWGCF/TwoParticleCorrelations/TableProducer/CMakeLists.txt +++ b/PWGCF/TwoParticleCorrelations/TableProducer/CMakeLists.txt @@ -13,3 +13,8 @@ o2physics_add_dpl_workflow(twopartcorr-skim SOURCES twoParticleCorrelationsSkimming.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::TwoPartCorrCore COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(twopartcorr-filter + SOURCES twoParticleCorrelationsFiltering.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::TwoPartCorrCore + COMPONENT_NAME Analysis) diff --git a/PWGCF/TwoParticleCorrelations/TableProducer/twoParticleCorrelationsFiltering.cxx b/PWGCF/TwoParticleCorrelations/TableProducer/twoParticleCorrelationsFiltering.cxx new file mode 100644 index 00000000000..644d26632e7 --- /dev/null +++ b/PWGCF/TwoParticleCorrelations/TableProducer/twoParticleCorrelationsFiltering.cxx @@ -0,0 +1,79 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +#include "Framework/AnalysisTask.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/ASoAHelpers.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/Centrality.h" +#include "Common/Core/TrackSelection.h" +#include "Common/Core/TrackSelectionDefaults.h" +#include "Common/DataModel/PIDResponse.h" +#include "PWGCF/TwoParticleCorrelations/Core/EventSelectionFilterAndAnalysis.h" +#include "PWGCF/TwoParticleCorrelations/Core/TrackSelectionFilterAndAnalysis.h" +#include "PWGCF/TwoParticleCorrelations/Core/PIDSelectionFilterAndAnalysis.h" +#include "PWGCF/TwoParticleCorrelations/DataModel/TwoParticleCorrelationsSkimmed.h" +#include "PWGCF/TwoParticleCorrelations/DataModel/TwoParticleCorrelationsFiltered.h" +#include "Framework/runDataProcessing.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +using namespace o2; +using namespace o2::framework; +using namespace o2::aod; +using namespace o2::soa; +using namespace o2::framework::expressions; +using namespace o2::analysis; + +#define TWOPFILTERLOGCOLLISIONS info +#define TWOPFILTERLOGTRACKS info + +struct TwoParticleCorrelationsFilter { + Produces acceptedcollisions; + Produces accepteddtracks; + Produces acceptedgencollisions; + Produces acceptedgentracks; + +#include "skimmingconf.h" + + void init(InitContext const&) + { + using namespace twopfilter; + using namespace twopskim; + + LOGF(info, "TwoParticleCorrelationsFilter::init()"); + } + + void processRun2(aod::TwoPSkimmedCollision const& collision, aod::TwoPSkimmedTracks const& tracks) + { + using namespace twopfilter; + + LOGF(TWOPFILTERLOGCOLLISIONS, "Received filtered collision with mask 0x%lx", collision.selflags()); + } + PROCESS_SWITCH(TwoParticleCorrelationsFilter, processRun2, "Process Run 2 two particle correlations filtering", true); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + WorkflowSpec workflow{ + adaptAnalysisTask(cfgc)}; + return workflow; +} From 31c3d48a62852068805edfe1d89b920036330b81 Mon Sep 17 00:00:00 2001 From: Victor Date: Fri, 23 Sep 2022 20:17:29 +0200 Subject: [PATCH 04/20] Incorporated the user task which uses the skimmed data The skimmed data now incorporates also required the multiplicities according to the skimming configuration The preserved skimmed tracks are from 0.1 to 50.0 GeV and |eta| < 1.0 and still does not include the PID mask (a 64b word per track) Skimming ratio 100 -> 8 The user task filters additionally the skimmed data but for the selected configuration, default, systematic test, ... with similar aim as the dptdptfilter task --- .../Core/EventSelectionFilterAndAnalysis.cxx | 70 ++++++- .../Core/EventSelectionFilterAndAnalysis.h | 26 ++- .../Core/SelectionFilterAndAnalysis.h | 23 ++- .../Core/SkimmingConfigurableCuts.cxx | 188 +++++++++++++++--- .../Core/SkimmingConfigurableCuts.h | 29 ++- .../Core/TrackSelectionFilterAndAnalysis.cxx | 73 ++++++- .../Core/TrackSelectionFilterAndAnalysis.h | 20 +- .../TwoParticleCorrelationsSkimmed.h | 10 +- .../TableProducer/skimmingconf.h | 8 +- .../twoParticleCorrelationsFiltering.cxx | 71 +++++-- .../twoParticleCorrelationsSkimming.cxx | 13 +- 11 files changed, 453 insertions(+), 78 deletions(-) diff --git a/PWGCF/TwoParticleCorrelations/Core/EventSelectionFilterAndAnalysis.cxx b/PWGCF/TwoParticleCorrelations/Core/EventSelectionFilterAndAnalysis.cxx index 769e76a22e3..588a40c5a70 100644 --- a/PWGCF/TwoParticleCorrelations/Core/EventSelectionFilterAndAnalysis.cxx +++ b/PWGCF/TwoParticleCorrelations/Core/EventSelectionFilterAndAnalysis.cxx @@ -13,14 +13,9 @@ #include #include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/ASoAHelpers.h" #include "EventSelectionFilterAndAnalysis.h" using namespace o2; -using namespace o2::framework; -using namespace o2::soa; -using namespace o2::framework::expressions; using namespace o2::analysis::PWGCF; using namespace boost; @@ -234,4 +229,69 @@ void EventSelectionFilterAndAnalysis::ConstructCutFromString(const TString& cuts if (mMaskLength > 64) { LOGF(fatal, "EventSelectionFilterAndAnalysis not ready for filter mask of %d bits. Just 64 available for the time being", mMaskLength); } + StoreArmedMask(); +} + +/// \brief Fills the filter cuts mask +void EventSelectionFilterAndAnalysis::StoreArmedMask() +{ + uint64_t armedMask = 0UL; + uint64_t optMask = 0UL; + uint64_t forcedMask = 0UL; + mArmedMask = 0UL; + mOptArmedMask = 0UL; + mForcedArmedMask = 0UL; + int bit = 0; + + auto armedBrick = [&](auto brick, bool opt = false) { + std::vector res = brick->IsArmed(); + for (auto b : res) { + if (b) { + SETBIT(armedMask, bit); + if (opt) { + SETBIT(optMask, bit); + } else { + SETBIT(forcedMask, bit); + } + } + bit++; + } + }; + + if (mMultiplicityClasses != nullptr) { + if (mAlternateMultiplicityEstimatorIndex.size() > 0) { + /* we have alternative estimators so our brick is of kind cwv */ + if (mMultiplicityClasses->IsA() != CutWithVariations::Class()) { + LOGF(fatal, "EventSelectionFilterAndAnalysis::Filter() expected class with variations cut but it is not there"); + } + /* first the default */ + TList& deflst = dynamic_cast*>(mMultiplicityClasses)->getDefaultBricks(); + if (deflst.GetEntries() > 1) { + LOGF(fatal, "EventSelectionFilterAndAnalysis::Filter() expected only one default multiplicity class estimator"); + } + armedBrick((CutBrick*)deflst.At(0), true); + /* and now the variants */ + TList& varlst = dynamic_cast*>(mMultiplicityClasses)->getVariantBricks(); + for (int i = 0; i < varlst.GetEntries(); ++i) { + if (varlst.At(i)->IsA() != CutBrickSelectorMultipleRanges::Class()) { + LOGF(fatal, "EventSelectionFilterAndAnalysis::Filter, expected a multirange selector"); + } + armedBrick((CutBrick*)varlst.At(i), true); + } + } else { + /* no alternative estimators, just the default */ + armedBrick(mMultiplicityClasses, true); + } + } + if (mTriggerSelection != nullptr) { + } + if (mZVertex != nullptr) { + armedBrick(mZVertex); + } + if (mPileUpRejection != nullptr) { + } + LOGF(info, "EventSelectionFilterAndAnalysis::StoreArmedMask(), masks 0x%08lx, 0x%08lx, 0x%08lx", armedMask, optMask, forcedMask); + mArmedMask = armedMask; + mOptArmedMask = optMask; + mForcedArmedMask = forcedMask; } diff --git a/PWGCF/TwoParticleCorrelations/Core/EventSelectionFilterAndAnalysis.h b/PWGCF/TwoParticleCorrelations/Core/EventSelectionFilterAndAnalysis.h index 8481cbd65c7..86897ed82c1 100644 --- a/PWGCF/TwoParticleCorrelations/Core/EventSelectionFilterAndAnalysis.h +++ b/PWGCF/TwoParticleCorrelations/Core/EventSelectionFilterAndAnalysis.h @@ -63,11 +63,13 @@ class EventSelectionFilterAndAnalysis : public SelectionFilterAndAnalysis template uint64_t Filter(CollisionToFilter const& col); + std::vector GetMultiplicities(); private: void ConstructCutFromString(const TString&); void InitializeMultiplicityFilter(); int CalculateMaskLength(); + virtual void StoreArmedMask(); CutBrick* mMultiplicityClasses; //! the multiplicity default classes cuts CutBrick* mTriggerSelection; //! the trigger selection cuts @@ -82,7 +84,7 @@ class EventSelectionFilterAndAnalysis : public SelectionFilterAndAnalysis /// \brief Fills the filter cuts mask template -uint64_t EventSelectionFilterAndAnalysis::Filter(CollisionToFilter const& col) +inline uint64_t EventSelectionFilterAndAnalysis::Filter(CollisionToFilter const& col) { /* store the collision multiplicities for the different estimators */ /* TODO: we need to adapt this to the Run 3 scenario */ @@ -155,6 +157,28 @@ uint64_t EventSelectionFilterAndAnalysis::Filter(CollisionToFilter const& col) return mSelectedMask; } +/// \brief Fills the filter cuts mask +inline std::vector EventSelectionFilterAndAnalysis::GetMultiplicities() +{ + std::vector res; + + if (mMultiplicityClasses != nullptr) { + if (mAlternateMultiplicityEstimatorIndex.size() > 0) { + /* first the default */ + res.push_back(mMultiplicities[mDefaultMultiplicityEstimatorIndex]); + /* and now the variants */ + TList& varlst = dynamic_cast*>(mMultiplicityClasses)->getVariantBricks(); + for (int i = 0; i < varlst.GetEntries(); ++i) { + res.push_back(mMultiplicities[mAlternateMultiplicityEstimatorIndex[i]]); + } + } else { + /* no alternative estimators, just the default */ + res.push_back(mMultiplicities[mDefaultMultiplicityEstimatorIndex]); + } + } + return res; +} + } // namespace PWGCF } // namespace analysis } // namespace o2 diff --git a/PWGCF/TwoParticleCorrelations/Core/SelectionFilterAndAnalysis.h b/PWGCF/TwoParticleCorrelations/Core/SelectionFilterAndAnalysis.h index f921f93832f..413e2446e9e 100644 --- a/PWGCF/TwoParticleCorrelations/Core/SelectionFilterAndAnalysis.h +++ b/PWGCF/TwoParticleCorrelations/Core/SelectionFilterAndAnalysis.h @@ -17,8 +17,6 @@ #include #include -#include "SkimmingConfigurableCuts.h" - namespace o2 { namespace analysis @@ -40,14 +38,31 @@ class SelectionFilterAndAnalysis : public TNamed SelectionFilterAndAnalysis(); SelectionFilterAndAnalysis(const TString& name, selmodes mode); + /// \brief get the valid (armed) mask associated to the configuration + /// \return the armed mask + uint64_t getMask() { return mArmedMask; } + /// \brief get the valid (armed) optional part mask associated to the configuration + /// \return the armed optional mask + /// A clear example of the optional part mask is the mask of the multiplicity classes + /// where only one of the available in the whole mask will be flagged + uint64_t getOptMask() { return mOptArmedMask; } + /// \brief get the valid (armed) mandatory part mask associated to the configuration + /// \return the armed optional mask + /// A clear example of the mandatory part mask is the mask of the zvertex and their + /// alternatives where only one concrete one is required to be flagged + uint64_t getForcedMask() { return mForcedArmedMask; } + private: virtual int CalculateMaskLength() = 0; + virtual void StoreArmedMask() = 0; protected: selmodes mMode = kFilter; /// the operating mode of the selection instance int mMaskLength = 0; /// the length of the mask needed to filter the selection cuts - ULong64_t mSelectedMask = 0UL; /// the selection mask for the current passed collision - ULong64_t mArmedMask = 0UL; /// the armed mask identifying the significative selection cuts + uint64_t mSelectedMask = 0UL; /// the selection mask for the current passed collision + uint64_t mArmedMask = 0UL; /// the complete armed mask identifying the applicable selection cuts + uint64_t mOptArmedMask = 0UL; /// the armed mask for options of the applicable selection cuts + uint64_t mForcedArmedMask = 0UL; /// the mandatory armed mask of the applicable selection cuts ClassDefNV(SelectionFilterAndAnalysis, 1) }; diff --git a/PWGCF/TwoParticleCorrelations/Core/SkimmingConfigurableCuts.cxx b/PWGCF/TwoParticleCorrelations/Core/SkimmingConfigurableCuts.cxx index 05f5ef79877..a780cbf4e17 100644 --- a/PWGCF/TwoParticleCorrelations/Core/SkimmingConfigurableCuts.cxx +++ b/PWGCF/TwoParticleCorrelations/Core/SkimmingConfigurableCuts.cxx @@ -12,15 +12,10 @@ #include #include -#include "Framework/AnalysisDataModel.h" -#include "Framework/ASoAHelpers.h" -#include "Common/DataModel/TrackSelectionTables.h" +#include "Framework/Logger.h" #include "PWGCF/TwoParticleCorrelations/Core/SkimmingConfigurableCuts.h" using namespace o2; -using namespace o2::framework; -using namespace o2::soa; -using namespace o2::framework::expressions; using namespace o2::analysis::PWGCF; /// \brief These are the implemented basic bricks @@ -141,6 +136,20 @@ void CutBrickLimit::ConstructCutFromString(const TString& cutstr } } +/// \brief Returns wether the cut brick is incorporated in the selection chain +/// \return true if the cut brick is incorporated +template +std::vector CutBrickLimit::IsArmed() +{ + std::vector res; + if (this->mMode == this->kSELECTED) { + res.push_back(true); + } else { + res.push_back(false); + } + return res; +} + /// \brief Filter the passed value to update the brick status accordingly /// \param value The value to filter /// \return true if the value passed the cut false otherwise @@ -216,6 +225,20 @@ void CutBrickThreshold::ConstructCutFromString(const TString& cu } } +/// \brief Returns wether the cut brick is incorporated in the selection chain +/// \return true if the cut brick is incorporated +template +std::vector CutBrickThreshold::IsArmed() +{ + std::vector res; + if (this->mMode == this->kSELECTED) { + res.push_back(true); + } else { + res.push_back(false); + } + return res; +} + /// \brief Filter the passed value to update the brick status accordingly /// \param value The value to filter /// \return true if the value passed the cut false otherwise @@ -296,6 +319,20 @@ void CutBrickRange::ConstructCutFromString(const TString& cutstr } } +/// \brief Returns wether the cut brick is incorporated in the selection chain +/// \return true if the cut brick is incorporated +template +std::vector CutBrickRange::IsArmed() +{ + std::vector res; + if (this->mMode == this->kSELECTED) { + res.push_back(true); + } else { + res.push_back(false); + } + return res; +} + /// \brief Filter the passed value to update the brick status accordingly /// \param value The value to filter /// \return true if the value passed the cut false otherwise @@ -376,6 +413,20 @@ void CutBrickExtToRange::ConstructCutFromString(const TString& c } } +/// \brief Returns wether the cut brick is incorporated in the selection chain +/// \return true if the cut brick is incorporated +template +std::vector CutBrickExtToRange::IsArmed() +{ + std::vector res; + if (this->mMode == this->kSELECTED) { + res.push_back(true); + } else { + res.push_back(false); + } + return res; +} + /// \brief Filter the passed value to update the brick status accordingly /// \param value The value to filter /// \return true if the value passed the cut false otherwise @@ -472,6 +523,25 @@ void CutBrickSelectorMultipleRanges::ConstructCutFromString(cons } } +/// \brief Returns wether the cut brick is incorporated in the selection chain +/// \return true if the cut brick is incorporated +template +std::vector CutBrickSelectorMultipleRanges::IsArmed() +{ + std::vector res; + res.reserve(Length()); + if (this->mMode == this->kSELECTED) { + for (unsigned int i = 0; i < mActive.size(); ++i) { + res.push_back(true); + } + } else { + for (unsigned int i = 0; i < mActive.size(); ++i) { + res.push_back(false); + } + } + return res; +} + /// \brief Filter the passed value to update the brick status accordingly /// \param value The value to filter /// \return true if the value passed the cut false otherwise @@ -571,6 +641,7 @@ void CutWithVariations::ConstructCutFromString(const TString& cu if (lev1toks->GetEntries() > 2) { Fatal("CutWithVariations::ConstructCutFromString", "Wrong RE: %s, use pT{cwv{rg{0.2,10.0}}} for instance", cutstr.Data()); } + bool atleastonearmed = false; auto addCuts = [&](TList& cutlist, std::string cuttxt, bool reqflag) { std::smatch m; while (cuttxt.length() > 0) { @@ -591,6 +662,7 @@ void CutWithVariations::ConstructCutFromString(const TString& cu } CutBrick* brick = CutBrick::constructBrick(this->GetName(), brickre, allowed); brick->Arm(isarmed); + atleastonearmed = atleastonearmed || isarmed; cutlist.Add(brick); cuttxt = m.suffix(); } @@ -598,7 +670,7 @@ void CutWithVariations::ConstructCutFromString(const TString& cu /* let's handle the default values */ { LOGF(info, "Cut with variations, extracting defaults: cut string: %s", lev1toks->At(0)->GetName()); - addCuts(mDefaultBricks, lev1toks->At(0)->GetName(), false); + addCuts(mDefaultBricks, lev1toks->At(0)->GetName(), true); if (mDefaultBricks.GetEntries() > 1) { /* TODO: several default options for track type and for track pid selection */ Fatal("CutWithVariations::ConstructCutFromString", "Wrong RE: %s, several defaults only for trktype or trkpid pending of implementation", cutstr.Data()); @@ -608,16 +680,8 @@ void CutWithVariations::ConstructCutFromString(const TString& cu if (lev1toks->GetEntries() > 1) { LOGF(info, "Cut with variations, extracting variations: cut string: %s", lev1toks->At(1)->GetName()); addCuts(mVariationBricks, lev1toks->At(1)->GetName(), true); - int narmed = 0; - for (auto cut : mVariationBricks) { - if (((CutBrick*)cut)->IsArmed()) { - narmed++; - } - } - if (narmed > 1) { - Fatal("CutWithVariations::ConstructCutFromString", "Wrong RE: %s, more than one alternative flagged", cutstr.Data()); - } } + this->Arm(atleastonearmed); delete lev1toks; } @@ -665,6 +729,45 @@ bool CutWithVariations::AddVariationBrick(CutBrick +std::vector CutWithVariations::IsArmed() +{ + std::vector res; + res.reserve(Length()); + if (this->mMode == this->kSELECTED) { + int nArmedDefaults = 0; + int nArmedVariants = 0; + for (int i = 0; i < mDefaultBricks.GetEntries(); ++i) { + std::vector tmp = ((CutBrick*)mDefaultBricks.At(i))->IsArmed(); + res.insert(res.end(), tmp.begin(), tmp.end()); + for (bool iarmed : tmp) { + if (iarmed) { + nArmedDefaults++; + } + } + } + for (int i = 0; i < mVariationBricks.GetEntries(); ++i) { + std::vector tmp = ((CutBrick*)mVariationBricks.At(i))->IsArmed(); + res.insert(res.end(), tmp.begin(), tmp.end()); + for (bool iarmed : tmp) { + if (iarmed) { + nArmedVariants++; + } + } + } + if (nArmedDefaults > 1 or nArmedVariants > 1 or (nArmedDefaults + nArmedVariants) > 1) { + LOGF(fatal, "CutWithVariations::IsArmed(%s), More than one alternative selected. Default armed %d, variants armed %d", this->GetName(), nArmedDefaults, nArmedVariants); + } + } else { + for (int i = 0; i < Length(); ++i) { + res.push_back(false); + } + } + return res; +} + /// Filters the passed value /// The bricks on the default values list and in the variation /// values list will change to active or passive accordingly to the passed value @@ -728,23 +831,35 @@ SpecialCutBrick::SpecialCutBrick(const char* name, const char* title) ClassImp(SpecialCutBrick); /// \brief Constructor from regular expression -TrackSelectionBrick::TrackSelectionBrick(const TString& regex) : SpecialCutBrick(regex, regex) +TrackSelectionBrick::TrackSelectionBrick(const TString& regex) : SpecialCutBrick() { - if (regex.EqualTo("FB1LHC2010")) { + bool armed = false; + TString name = regex; + if (regex.EndsWith("-yes")) { + name.Remove(regex.Index("-", strlen("-yes"))); + armed = true; + } else if (regex.EndsWith("-no")) { + name.Remove(regex.Index("-", strlen("-no"))); + armed = false; + } + SetName(name); + SetTitle(regex); + if (name.EqualTo("FB1LHC2010")) { constructFB1LHC2010(); - } else if (regex.EqualTo("FB1")) { + } else if (name.EqualTo("FB1")) { constructFB1LHC2011(); - } else if (regex.EqualTo("FB32LHC2010")) { + } else if (name.EqualTo("FB32LHC2010")) { constructFB32LHC2010(); - } else if (regex.EqualTo("FB32")) { + } else if (name.EqualTo("FB32")) { constructFB32LHC2011(); - } else if (regex.EqualTo("FB64LHC2010")) { + } else if (name.EqualTo("FB64LHC2010")) { constructFB64LHC2010(); - } else if (regex.EqualTo("FB64")) { + } else if (name.EqualTo("FB64")) { constructFB64LHC2011(); } else { ::Fatal("TrackSelectionBrick::TrackSelectionBrick", "Wrong RE: %s, trying to construct an unknown track type selector", regex.Data()); } + this->Arm(armed); } // Default TPC only track selection according to LHC2010 @@ -846,6 +961,19 @@ const std::string TrackSelectionBrick::mCutNames[static_cast(TrackSelection "DCAxy", "DCAz"}; +/// \brief Returns wether the cut brick is incorporated in the selection chain +/// \return true if the cut brick is incorporated +std::vector TrackSelectionBrick::IsArmed() +{ + std::vector res; + if (this->mMode == this->kSELECTED) { + res.push_back(true); + } else { + res.push_back(false); + } + return res; +} + ClassImp(TrackSelectionBrick); /// \brief Construct object from regular expression @@ -885,6 +1013,20 @@ int PIDSelectionBrick::Length() return len; } +/// \brief Returns wether the cut brick is incorporated in the selection chain +/// \return true if the cut brick is incorporated +std::vector PIDSelectionBrick::IsArmed() +{ + /* TODO: still not the final version */ + std::vector res; + if (this->mMode == this->kSELECTED) { + res.push_back(true); + } else { + res.push_back(false); + } + return res; +} + template std::vector PIDSelectionBrick::Filter(TrackObject const& track) { diff --git a/PWGCF/TwoParticleCorrelations/Core/SkimmingConfigurableCuts.h b/PWGCF/TwoParticleCorrelations/Core/SkimmingConfigurableCuts.h index be802e4ca6e..2aee2dae76e 100644 --- a/PWGCF/TwoParticleCorrelations/Core/SkimmingConfigurableCuts.h +++ b/PWGCF/TwoParticleCorrelations/Core/SkimmingConfigurableCuts.h @@ -22,7 +22,6 @@ #include #include -#include "Framework/Logger.h" #include "Framework/DataTypes.h" namespace o2 @@ -48,8 +47,9 @@ class CutBrick : public TNamed /// Returns whether the cut brick is active alowing the selection /// \return true if the brick is active bool IsActive() { return mState == kACTIVE; } - /// Returns whether the cut is brick is incorporated in the selection chain - bool IsArmed() { return mMode == kSELECTED; } + /// Pure virual function + /// Returns whether the cut brick is incorporated in the selection chain + virtual std::vector IsArmed() = 0; /// Pure virtual function. Filters the passed value /// The brick or brick components will change to active if the passed value /// fits within the brick or brick components scope @@ -100,6 +100,7 @@ class CutBrickLimit : public CutBrick CutBrickLimit(const CutBrickLimit&) = delete; CutBrickLimit& operator=(const CutBrickLimit&) = delete; + virtual std::vector IsArmed(); virtual std::vector Filter(const TValueToFilter&); virtual int Length() { return 1; } @@ -124,6 +125,7 @@ class CutBrickThreshold : public CutBrick CutBrickThreshold(const CutBrickThreshold&) = delete; CutBrickThreshold& operator=(const CutBrickThreshold&) = delete; + virtual std::vector IsArmed(); virtual std::vector Filter(const TValueToFilter&); virtual int Length() { return 1; } @@ -148,6 +150,7 @@ class CutBrickRange : public CutBrick CutBrickRange(const CutBrickRange&) = delete; CutBrickRange& operator=(const CutBrickRange&) = delete; + virtual std::vector IsArmed(); virtual std::vector Filter(const TValueToFilter&); virtual int Length() { return 1; } @@ -173,6 +176,7 @@ class CutBrickExtToRange : public CutBrick CutBrickExtToRange(const CutBrickExtToRange&) = delete; CutBrickExtToRange& operator=(const CutBrickExtToRange&) = delete; + virtual std::vector IsArmed(); virtual std::vector Filter(const TValueToFilter&); virtual int Length() { return 1; } @@ -200,11 +204,12 @@ class CutBrickSelectorMultipleRanges : public CutBrick CutBrickSelectorMultipleRanges(const CutBrickSelectorMultipleRanges&) = delete; CutBrickSelectorMultipleRanges& operator=(const CutBrickSelectorMultipleRanges&) = delete; - virtual std::vector Filter(const TValueToFilter&); + virtual std::vector IsArmed() override; + virtual std::vector Filter(const TValueToFilter&) override; /// Return the length needed to code the brick status /// The length is in brick units. The actual length is implementation dependent /// \returns Brick length in units of bricks - virtual int Length() { return mActive.size(); } + virtual int Length() override { return mActive.size(); } private: void ConstructCutFromString(const TString&); @@ -233,6 +238,7 @@ class CutWithVariations : public CutBrick bool AddVariationBrick(CutBrick* brick); TList& getDefaultBricks() { return mDefaultBricks; } TList& getVariantBricks() { return mVariationBricks; } + virtual std::vector IsArmed(); virtual std::vector Filter(const TValueToFilter&); virtual int Length(); @@ -264,8 +270,9 @@ class SpecialCutBrick : public TNamed /// Returns whether the cut brick is active alowing the selection /// \return true if the brick is active bool IsActive() { return mState == kACTIVE; } - /// Returns whether the cut is brick is incorporated in the selection chain - bool IsArmed() { return mMode == kSELECTED; } + /// Pure virtual function + /// Returns whether the cut brick is incorporated in the selection chain + virtual std::vector IsArmed() = 0; /// Pure virtual function. Return the length needed to code the brick status /// The length is in brick units. The actual length is implementation dependent /// \returns Brick length in units of bricks @@ -300,6 +307,7 @@ class TrackSelectionBrick : public SpecialCutBrick public: TrackSelectionBrick() = default; TrackSelectionBrick(const TString&); + virtual ~TrackSelectionBrick() override = default; enum class TrackCuts : int { kTrackType = 0, @@ -320,6 +328,7 @@ class TrackSelectionBrick : public SpecialCutBrick static const std::string mCutNames[static_cast(TrackCuts::kNCuts)]; + virtual std::vector IsArmed() override; template bool Filter(TrackToFilter const& track) { @@ -344,7 +353,7 @@ class TrackSelectionBrick : public SpecialCutBrick } } - int Length() { return 1; } + int Length() override { return 1; } void SetTrackType(o2::aod::track::TrackTypeEnum trackType) { mTrackType = trackType; } void SetRequireITSRefit(bool requireITSRefit = true) { mRequireITSRefit = requireITSRefit; } @@ -425,6 +434,7 @@ class PIDSelectionBrick : public SpecialCutBrick { } PIDSelectionBrick(const TString&); + virtual ~PIDSelectionBrick() override = default; enum PIDSpecies { kElectron = 0, ///< electron @@ -449,10 +459,11 @@ class PIDSelectionBrick : public SpecialCutBrick static const std::string mCutNames[static_cast(PIDCuts::kNCuts)]; + virtual std::vector IsArmed() override; template std::vector Filter(TrackToFilter const& track); - int Length(); + int Length() override; private: void ConstructFromString(const TString& cutstr); diff --git a/PWGCF/TwoParticleCorrelations/Core/TrackSelectionFilterAndAnalysis.cxx b/PWGCF/TwoParticleCorrelations/Core/TrackSelectionFilterAndAnalysis.cxx index 090595cdd8f..0f8d86213ca 100644 --- a/PWGCF/TwoParticleCorrelations/Core/TrackSelectionFilterAndAnalysis.cxx +++ b/PWGCF/TwoParticleCorrelations/Core/TrackSelectionFilterAndAnalysis.cxx @@ -12,15 +12,10 @@ #include #include -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/ASoAHelpers.h" +#include "Framework/Logger.h" #include "TrackSelectionFilterAndAnalysis.h" using namespace o2; -using namespace o2::framework; -using namespace o2::soa; -using namespace o2::framework::expressions; using namespace o2::analysis::PWGCF; using namespace boost; @@ -120,6 +115,10 @@ TrackSelectionFilterAndAnalysis::TrackSelectionFilterAndAnalysis(const TrackSele } cutString += "}"; ConstructCutFromString(cutString); + if (mode == kAnalysis) { + /* TODO: check cuts consistency. In principle it should be there except for the ttype valid combinations */ + StoreArmedMask(); + } } /// \brief Calculates the length of the mask needed to store the selection cuts @@ -184,7 +183,7 @@ void TrackSelectionFilterAndAnalysis::ConstructCutFromString(const TString& cuts { LOGF(info, "Cut string: %s", cutstr.Data()); /* let's catch the first level */ - regex cutregex("^tracksel\\{ttype\\{([\\w\\d,]+)};?(\\w+\\{[\\w\\d.,:{}-]+})*}$", regex_constants::ECMAScript | regex_constants::icase); + regex cutregex("^tracksel\\{ttype\\{([\\w\\d,-]+)};?(\\w+\\{[\\w\\d.,:{}-]+})*}$", regex_constants::ECMAScript | regex_constants::icase); std::string in(cutstr.Data()); smatch m; @@ -291,3 +290,63 @@ void TrackSelectionFilterAndAnalysis::ConstructCutFromString(const TString& cuts } mMaskLength = CalculateMaskLength(); } + +/// \brief Fills the filter cuts mask +void TrackSelectionFilterAndAnalysis::StoreArmedMask() +{ + uint64_t armedMask = 0UL; + uint64_t optMask = 0UL; + uint64_t forcedMask = 0UL; + mArmedMask = 0UL; + mOptArmedMask = 0UL; + mForcedArmedMask = 0UL; + int bit = 0; + + auto armedBrick = [&](auto brick, bool opt = false) { + std::vector res = brick->IsArmed(); + for (auto b : res) { + if (b) { + SETBIT(armedMask, bit); + if (opt) { + SETBIT(optMask, bit); + } else { + SETBIT(forcedMask, bit); + } + } + bit++; + } + }; + + for (int i = 0; i < mTrackTypes.GetEntries(); ++i) { + armedBrick((TrackSelectionBrick*)mTrackTypes.At(i), true); + } + if (mNClustersTPC != nullptr) { + armedBrick(mNClustersTPC); + } + if (mNCrossedRowsTPC != nullptr) { + armedBrick(mNCrossedRowsTPC); + } + if (mNClustersITS != nullptr) { + armedBrick(mNClustersITS); + } + if (mMaxChi2PerClusterTPC != nullptr) { + armedBrick(mMaxChi2PerClusterTPC); + } + if (mMaxChi2PerClusterITS != nullptr) { + armedBrick(mMaxChi2PerClusterITS); + } + if (mMinNCrossedRowsOverFindableClustersTPC != nullptr) { + armedBrick(mMinNCrossedRowsOverFindableClustersTPC); + } + if (mMaxDcaXY != nullptr) { + armedBrick(mMaxDcaXY); + } + if (mMaxDcaZ != nullptr) { + armedBrick(mMaxDcaZ); + } + /* for the time being the pT and eta bricks dont go to the mask */ + LOGF(info, "TrackSelectionFilterAndAnalysis::StoreArmedMask(), masks 0x%08lx, 0x%08lx, 0x%08lx", armedMask, optMask, forcedMask); + mArmedMask = armedMask; + mOptArmedMask = optMask; + mForcedArmedMask = forcedMask; +} diff --git a/PWGCF/TwoParticleCorrelations/Core/TrackSelectionFilterAndAnalysis.h b/PWGCF/TwoParticleCorrelations/Core/TrackSelectionFilterAndAnalysis.h index 76b96fecb66..93c8b7f6b0b 100644 --- a/PWGCF/TwoParticleCorrelations/Core/TrackSelectionFilterAndAnalysis.h +++ b/PWGCF/TwoParticleCorrelations/Core/TrackSelectionFilterAndAnalysis.h @@ -17,6 +17,7 @@ #include #include +#include "Framework/Logger.h" #include "SkimmingConfigurableCuts.h" #include "SelectionFilterAndAnalysis.h" @@ -94,6 +95,7 @@ class TrackSelectionFilterAndAnalysis : public SelectionFilterAndAnalysis private: void ConstructCutFromString(const TString&); int CalculateMaskLength(); + void StoreArmedMask(); TList mTrackTypes; /// the track types to select list CutBrick* mNClustersTPC; //! the number of TPC clusters cuts @@ -140,6 +142,16 @@ uint64_t TrackSelectionFilterAndAnalysis::Filter(TrackToFilter const& track) } }; + auto filterBrickValueNoMask = [](auto brick, auto value) { + std::vector res = brick->Filter(value); + for (auto b : res) { + if (b) { + return true; + } + } + return false; + }; + for (int i = 0; i < mTrackTypes.GetEntries(); ++i) { filterTrackType((TrackSelectionBrick*)mTrackTypes.At(i), track); } @@ -168,10 +180,14 @@ uint64_t TrackSelectionFilterAndAnalysis::Filter(TrackToFilter const& track) filterBrickValue(mMaxDcaZ, track.dcaZ()); } if (mPtRange != nullptr) { - filterBrickValue(mPtRange, track.pt()); + if (not filterBrickValueNoMask(mPtRange, track.pt())) { + selectedMask = 0UL; + } } if (mEtaRange != nullptr) { - filterBrickValue(mEtaRange, track.eta()); + if (not filterBrickValueNoMask(mEtaRange, track.pt())) { + selectedMask = 0UL; + } } return mSelectedMask = selectedMask; } diff --git a/PWGCF/TwoParticleCorrelations/DataModel/TwoParticleCorrelationsSkimmed.h b/PWGCF/TwoParticleCorrelations/DataModel/TwoParticleCorrelationsSkimmed.h index 6dffe0736e6..46e9643937d 100644 --- a/PWGCF/TwoParticleCorrelations/DataModel/TwoParticleCorrelationsSkimmed.h +++ b/PWGCF/TwoParticleCorrelations/DataModel/TwoParticleCorrelationsSkimmed.h @@ -34,20 +34,20 @@ namespace aod /* we have to change from int to bool when bool columns work properly */ namespace twopskim { -DECLARE_SOA_COLUMN(TwoPSkimmedCollisionCentMult, centmult, float); //! The centrality/multiplicity pecentile +DECLARE_SOA_COLUMN(TwoPSkimmedCollisionCentMult, centmult, std::vector); //! The centrality/multiplicity pecentile DECLARE_SOA_COLUMN(TwoPSkimmedCollisionFlags, selflags, uint64_t); //! The skimming flags for collision selection } // namespace twopskim DECLARE_SOA_TABLE(TwoPSkimmedCollisions, "AOD", "TWOPSKMDCOLL", //! Accepted reconstructed collisions/events filtered table o2::soa::Index<>, collision::PosZ, - twopskim::TwoPSkimmedCollisionCentMult, - twopskim::TwoPSkimmedCollisionFlags); + twopskim::TwoPSkimmedCollisionFlags, + twopskim::TwoPSkimmedCollisionCentMult); using TwoPSkimmedCollision = TwoPSkimmedCollisions::iterator; DECLARE_SOA_TABLE(TwoPSkimmedGenCollisions, "AOD", "TWOPSKMDGENCOLL", //! Accepted generated collisions/events filtered table o2::soa::Index<>, mccollision::PosZ, - twopskim::TwoPSkimmedCollisionCentMult, - twopskim::TwoPSkimmedCollisionFlags); + twopskim::TwoPSkimmedCollisionFlags, + twopskim::TwoPSkimmedCollisionCentMult); using TwoPSkimmedGenCollision = TwoPSkimmedGenCollisions::iterator; namespace twopskim { diff --git a/PWGCF/TwoParticleCorrelations/TableProducer/skimmingconf.h b/PWGCF/TwoParticleCorrelations/TableProducer/skimmingconf.h index cb0fcbd9d01..11a5fd1288c 100644 --- a/PWGCF/TwoParticleCorrelations/TableProducer/skimmingconf.h +++ b/PWGCF/TwoParticleCorrelations/TableProducer/skimmingconf.h @@ -15,18 +15,18 @@ #include "Framework/ASoAHelpers.h" struct : ConfigurableGroup { - Configurable zvtxsel{"evtflt_zvtx", "zvtx{cwv{rg{-7.0,7.0}:rg{-10.0,10.0}-no,rg{-3.0,3.0}-no}}", "Z vertex cut: zvtx{rg{-7.0,7.0}} or zvtx{cwv{def:var1,var2@,..}}"}; + Configurable zvtxsel{"evtflt_zvtx", "zvtx{cwv{rg{-7.0,7.0}-yes:rg{-10.0,10.0}-no,rg{-3.0,3.0}-no}}", "Z vertex cut: zvtx{rg{-7.0,7.0}} or zvtx{cwv{def:var1,var2@,..}}"}; Configurable centmultsel{"evtflt_centmult", "centmult{cwv{mrg{V0M,0,5,10,20,30,40,50,60,70,80}-yes:mrg{CL1,0,5,10,20,30,40,50,60,70,80}-no}}", "Centrality/Multiplicity cut: centmult{mrg{V0M,0,5,10,20,30,40,50,60,70,80}}"}; } eventfilter; struct : ConfigurableGroup { - Configurable ttype{"trkflt_ttype", "ttype{FB1,FB32,FB64}", "Track types to filter"}; - Configurable nclstpc{"trkflt_nclstpc", "nclstpc{cwv{th{70}:th{80}-no,th{90}-no}}", "Min no of TPC clusters: nclstpc{th{70}} or nclstpc{cwv{def:var1,var2,...}}"}; + Configurable ttype{"trkflt_ttype", "ttype{FB1-no,FB32-yes,FB64-yes}", "Track types to filter"}; + Configurable nclstpc{"trkflt_nclstpc", "nclstpc{cwv{th{70}-yes:th{80}-no,th{90}-no}}", "Min no of TPC clusters: nclstpc{th{70}} or nclstpc{cwv{def:var1,var2,...}}"}; // Configurable nxrtpc{"trkflt_nxrtpc", "nxrtpc{}", "Min no of TPC crossed rows: nxrtpc{th{70}} or nxrtpc{cwv{def;var1,var2,...}}"}; Configurable nxrtpc{"trkflt_nxrtpc", "", "Min no of TPC crossed rows: nxrtpc{th{70}} or nxrtpc{cwv{def;var1,var2,...}}"}; // Configurable nclsits{"trkflt_nclsits", "nclsits{}", "Min no of ITS clusters: nclsits{th{3}} or nclsits{cwv{def;var1,var2,...}}"}; Configurable nclsits{"trkflt_nclsits", "", "Min no of ITS clusters: nclsits{th{3}} or nclsits{cwv{def;var1,var2,...}}"}; - Configurable chi2clustpc{"trkflt_chi2clustpc", "chi2clustpc{cwv{lim{4}:lim{3}-no,lim{90}-no}}", "Max Chi^2 per TPC cluster: chi2clustpc{lim{4}} or chi2clustpc{cwv{def:var1,var2,...}}"}; + Configurable chi2clustpc{"trkflt_chi2clustpc", "chi2clustpc{cwv{lim{4}-yes:lim{3}-no,lim{90}-no}}", "Max Chi^2 per TPC cluster: chi2clustpc{lim{4}} or chi2clustpc{cwv{def:var1,var2,...}}"}; // Configurable chi2clusits{"trkflt_chi2clusits", "chi2clusits{}", "Max Chi^2 per ITS cluster: chi2clusits{lim{4}} or chi2clusits{cwv{def;var1,var2,...}}"}; Configurable chi2clusits{"trkflt_chi2clusits", "", "Max Chi^2 per ITS cluster: chi2clusits{lim{4}} or chi2clusits{cwv{def;var1,var2,...}}"}; // Configurable xrofctpc{"trkflt_xrofctpc", "xrofctpc{}", "Min no of TPC crossed rows over findable clusters: xrofctpc{th{0.70}} or xrofctpc{cwv{def;var1,var2,...}}"}; diff --git a/PWGCF/TwoParticleCorrelations/TableProducer/twoParticleCorrelationsFiltering.cxx b/PWGCF/TwoParticleCorrelations/TableProducer/twoParticleCorrelationsFiltering.cxx index 644d26632e7..ed09d66df2c 100644 --- a/PWGCF/TwoParticleCorrelations/TableProducer/twoParticleCorrelationsFiltering.cxx +++ b/PWGCF/TwoParticleCorrelations/TableProducer/twoParticleCorrelationsFiltering.cxx @@ -10,16 +10,8 @@ // or submit itself to any jurisdiction. #include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/ASoAHelpers.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/Centrality.h" -#include "Common/Core/TrackSelection.h" -#include "Common/Core/TrackSelectionDefaults.h" -#include "Common/DataModel/PIDResponse.h" #include "PWGCF/TwoParticleCorrelations/Core/EventSelectionFilterAndAnalysis.h" #include "PWGCF/TwoParticleCorrelations/Core/TrackSelectionFilterAndAnalysis.h" -#include "PWGCF/TwoParticleCorrelations/Core/PIDSelectionFilterAndAnalysis.h" #include "PWGCF/TwoParticleCorrelations/DataModel/TwoParticleCorrelationsSkimmed.h" #include "PWGCF/TwoParticleCorrelations/DataModel/TwoParticleCorrelationsFiltered.h" #include "Framework/runDataProcessing.h" @@ -38,14 +30,21 @@ using namespace o2; using namespace o2::framework; -using namespace o2::aod; using namespace o2::soa; using namespace o2::framework::expressions; using namespace o2::analysis; +namespace o2::analysis::twopfilter +{ #define TWOPFILTERLOGCOLLISIONS info #define TWOPFILTERLOGTRACKS info +PWGCF::EventSelectionFilterAndAnalysis* fCollisionFilter = nullptr; +PWGCF::TrackSelectionFilterAndAnalysis* fTrackFilter = nullptr; +} // namespace o2::analysis::twopfilter + +using namespace o2::aod::twopskim; + struct TwoParticleCorrelationsFilter { Produces acceptedcollisions; Produces accepteddtracks; @@ -54,19 +53,65 @@ struct TwoParticleCorrelationsFilter { #include "skimmingconf.h" + int nReportedTracks; + // HistogramRegistry historeg; + + uint64_t collisionmask = 0UL; + uint64_t collisionmask_opt = 0UL; + uint64_t collisionmask_forced = 0UL; + uint64_t trackmask = 0UL; + uint64_t trackmask_opt = 0UL; + uint64_t trackmask_forced = 0UL; + void init(InitContext const&) { using namespace twopfilter; - using namespace twopskim; LOGF(info, "TwoParticleCorrelationsFilter::init()"); + + /* collision filtering configuration */ + PWGCF::EventSelectionConfigurable eventsel(eventfilter.centmultsel, "", eventfilter.zvtxsel, ""); + fCollisionFilter = new PWGCF::EventSelectionFilterAndAnalysis(eventsel, PWGCF::SelectionFilterAndAnalysis::kAnalysis); + + /* track filtering configuration */ + PWGCF::TrackSelectionConfigurable trksel(trackfilter.ttype, trackfilter.nclstpc, trackfilter.nxrtpc, trackfilter.nclsits, trackfilter.chi2clustpc, + trackfilter.chi2clusits, trackfilter.xrofctpc, trackfilter.dcaxy, trackfilter.dcaz, trackfilter.ptrange, trackfilter.etarange); + fTrackFilter = new PWGCF::TrackSelectionFilterAndAnalysis(trksel, PWGCF::SelectionFilterAndAnalysis::kAnalysis); + + nReportedTracks = 0; + collisionmask = fCollisionFilter->getMask(); + collisionmask_opt = fCollisionFilter->getOptMask(); + collisionmask_forced = fCollisionFilter->getForcedMask(); + trackmask = fTrackFilter->getMask(); + trackmask_opt = fTrackFilter->getOptMask(); + trackmask_forced = fTrackFilter->getForcedMask(); + LOGF(info, "TwoParticleCorrelationsFilter::init(), collision selection masks 0x%08lx, 0x%08lx, and 0x%08lx ", collisionmask, collisionmask_opt, collisionmask_forced); + LOGF(info, "TwoParticleCorrelationsFilter::init(), track selection masks 0x%08lx, 0x%08lx, and 0x%08lx ", trackmask, trackmask_opt, trackmask_forced); + if (collisionmask == uint64_t(0) or trackmask == uint64_t(0)) { + LOGF(fatal, "TwoParticleCorrelationsFilter::init() null masks, selecting everything!!!"); + } } - void processRun2(aod::TwoPSkimmedCollision const& collision, aod::TwoPSkimmedTracks const& tracks) + Filter onlyacceptedcolls = ((aod::twopskim::selflags & static_cast(collisionmask_forced)) == static_cast(collisionmask_forced)); + Filter onlyacceptedtracks = ((aod::twopskim::trackflags & static_cast(trackmask_forced)) == static_cast(trackmask_forced)); + + void processRun2(soa::Filtered::iterator const& collision, soa::Filtered const& tracks) { - using namespace twopfilter; + LOGF(TWOPFILTERLOGCOLLISIONS, "Received collision with mask 0x%08lx and %ld tracks", collision.selflags(), tracks.size()); - LOGF(TWOPFILTERLOGCOLLISIONS, "Received filtered collision with mask 0x%lx", collision.selflags()); + /* for some reason we cannot apply this condition in the filter, it does not work */ + if ((collision.selflags() & collisionmask_opt) != 0UL) { + acceptedcollisions(0, 0, 0); + int nAcceptedTracks = 0; + for (const auto& track : tracks) { + /* for some reason we cannot apply this condition in the filter, it does not work */ + if ((track.trackflags() & trackmask_opt) != 0UL) { + accepteddtracks(acceptedcollisions.lastIndex(), 0, track.spt(), track.eta(), track.phi()); + nAcceptedTracks++; + } + } + LOGF(TWOPFILTERLOGCOLLISIONS, ">> Accepted collision with mask 0x%08lx and %d accepted tracks", collision.selflags(), nAcceptedTracks); + } } PROCESS_SWITCH(TwoParticleCorrelationsFilter, processRun2, "Process Run 2 two particle correlations filtering", true); }; diff --git a/PWGCF/TwoParticleCorrelations/TableProducer/twoParticleCorrelationsSkimming.cxx b/PWGCF/TwoParticleCorrelations/TableProducer/twoParticleCorrelationsSkimming.cxx index 1954a01a8ae..f2eef9a5966 100644 --- a/PWGCF/TwoParticleCorrelations/TableProducer/twoParticleCorrelationsSkimming.cxx +++ b/PWGCF/TwoParticleCorrelations/TableProducer/twoParticleCorrelationsSkimming.cxx @@ -29,8 +29,8 @@ using namespace o2::analysis; namespace o2::analysis::twopskim { -#define LOGTRACKCOLLISIONS debug -#define LOGTRACKTRACKS debug +#define LOGTRACKCOLLISIONS info +#define LOGTRACKTRACKS info PWGCF::TrackSelectionFilterAndAnalysis* fTrackFilter = nullptr; PWGCF::EventSelectionFilterAndAnalysis* fEventFilter = nullptr; @@ -168,18 +168,21 @@ struct TwoParticleCorrelationsSkimming { LOGF(LOGTRACKCOLLISIONS, "Got mask 0x%lx", colmask); if (colmask != 0UL) { - skimmedcollision(collision.posZ(), 50.0, colmask); + skimmedcollision(collision.posZ(), colmask, fEventFilter->GetMultiplicities()); + int nFilteredTracks = 0; for (auto const& track : tracks) { auto trkmask = fTrackFilter->Filter(track); if (trkmask != 0UL) { skimmedtrack(skimmedcollision.lastIndex(), trkmask, track.pt() * track.sign(), track.eta(), track.phi()); + nFilteredTracks++; } - if ((trkmask & 0xFFFFF9FF) != 0UL and nReportedTracks < 1000) { - LOGF(LOGTRACKTRACKS, " Got track mask 0x%lx, TPC clusters %d, Chi2 per TPC cluster %f, pT %f, eta %f, track type %d", + if (trkmask != 0UL and nReportedTracks < 1000) { + LOGF(LOGTRACKTRACKS, " Got track mask 0x%08lx, TPC clusters %d, Chi2 per TPC cluster %f, pT %f, eta %f, track type %d", trkmask, track.tpcNClsFound(), track.tpcChi2NCl(), track.pt(), track.eta(), track.trackType()); nReportedTracks++; } } + LOGF(LOGTRACKCOLLISIONS, ">> Filtered %d tracks", nFilteredTracks); } } PROCESS_SWITCH(TwoParticleCorrelationsSkimming, processRun2, "Process on Run 1 or Run 2 data", true); From 2f7ce716bd80abaef049f51cb56e2f2835e76204 Mon Sep 17 00:00:00 2001 From: ALICE Action Bot Date: Fri, 23 Sep 2022 18:20:42 +0000 Subject: [PATCH 05/20] Please consider the following formatting changes --- .../Core/SelectionFilterAndAnalysis.h | 10 +++++----- .../DataModel/TwoParticleCorrelationsSkimmed.h | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/PWGCF/TwoParticleCorrelations/Core/SelectionFilterAndAnalysis.h b/PWGCF/TwoParticleCorrelations/Core/SelectionFilterAndAnalysis.h index 413e2446e9e..6e5c78cb86a 100644 --- a/PWGCF/TwoParticleCorrelations/Core/SelectionFilterAndAnalysis.h +++ b/PWGCF/TwoParticleCorrelations/Core/SelectionFilterAndAnalysis.h @@ -57,11 +57,11 @@ class SelectionFilterAndAnalysis : public TNamed virtual void StoreArmedMask() = 0; protected: - selmodes mMode = kFilter; /// the operating mode of the selection instance - int mMaskLength = 0; /// the length of the mask needed to filter the selection cuts - uint64_t mSelectedMask = 0UL; /// the selection mask for the current passed collision - uint64_t mArmedMask = 0UL; /// the complete armed mask identifying the applicable selection cuts - uint64_t mOptArmedMask = 0UL; /// the armed mask for options of the applicable selection cuts + selmodes mMode = kFilter; /// the operating mode of the selection instance + int mMaskLength = 0; /// the length of the mask needed to filter the selection cuts + uint64_t mSelectedMask = 0UL; /// the selection mask for the current passed collision + uint64_t mArmedMask = 0UL; /// the complete armed mask identifying the applicable selection cuts + uint64_t mOptArmedMask = 0UL; /// the armed mask for options of the applicable selection cuts uint64_t mForcedArmedMask = 0UL; /// the mandatory armed mask of the applicable selection cuts ClassDefNV(SelectionFilterAndAnalysis, 1) diff --git a/PWGCF/TwoParticleCorrelations/DataModel/TwoParticleCorrelationsSkimmed.h b/PWGCF/TwoParticleCorrelations/DataModel/TwoParticleCorrelationsSkimmed.h index 46e9643937d..08eeb7f96d8 100644 --- a/PWGCF/TwoParticleCorrelations/DataModel/TwoParticleCorrelationsSkimmed.h +++ b/PWGCF/TwoParticleCorrelations/DataModel/TwoParticleCorrelationsSkimmed.h @@ -35,7 +35,7 @@ namespace aod namespace twopskim { DECLARE_SOA_COLUMN(TwoPSkimmedCollisionCentMult, centmult, std::vector); //! The centrality/multiplicity pecentile -DECLARE_SOA_COLUMN(TwoPSkimmedCollisionFlags, selflags, uint64_t); //! The skimming flags for collision selection +DECLARE_SOA_COLUMN(TwoPSkimmedCollisionFlags, selflags, uint64_t); //! The skimming flags for collision selection } // namespace twopskim DECLARE_SOA_TABLE(TwoPSkimmedCollisions, "AOD", "TWOPSKMDCOLL", //! Accepted reconstructed collisions/events filtered table o2::soa::Index<>, From 88232db1b08481ff80d8dba0fb43b71bda97db45 Mon Sep 17 00:00:00 2001 From: Victor Date: Sun, 25 Sep 2022 00:31:40 +0200 Subject: [PATCH 06/20] Incorporation of the skimming cuts signature Pending to store it and recover it from CCDB --- .../Core/EventSelectionFilterAndAnalysis.cxx | 13 ++++++++----- .../Core/EventSelectionFilterAndAnalysis.h | 4 ++-- .../Core/SelectionFilterAndAnalysis.cxx | 10 ++++++++-- .../Core/SelectionFilterAndAnalysis.h | 1 + .../Core/TrackSelectionFilterAndAnalysis.cxx | 8 ++++++-- 5 files changed, 25 insertions(+), 11 deletions(-) diff --git a/PWGCF/TwoParticleCorrelations/Core/EventSelectionFilterAndAnalysis.cxx b/PWGCF/TwoParticleCorrelations/Core/EventSelectionFilterAndAnalysis.cxx index 588a40c5a70..1e4dfdfed92 100644 --- a/PWGCF/TwoParticleCorrelations/Core/EventSelectionFilterAndAnalysis.cxx +++ b/PWGCF/TwoParticleCorrelations/Core/EventSelectionFilterAndAnalysis.cxx @@ -51,7 +51,7 @@ EventSelectionFilterAndAnalysis::EventSelectionFilterAndAnalysis(const TString& ConstructCutFromString(cutstr); } -/// \brief Constructor from the track selection configurable +/// \brief Constructor from the event selection configurable EventSelectionFilterAndAnalysis::EventSelectionFilterAndAnalysis(const EventSelectionConfigurable& evtsel, selmodes mode) : SelectionFilterAndAnalysis("", mode), mMultiplicityClasses(nullptr), @@ -82,6 +82,13 @@ EventSelectionFilterAndAnalysis::EventSelectionFilterAndAnalysis(const EventSele cutString += "}"; ConstructCutFromString(cutString); + if (mMaskLength > 64) { + LOGF(fatal, "EventSelectionFilterAndAnalysis not ready for filter mask of %d bits. Just 64 available for the time being", mMaskLength); + } + mCutStringSignature = cutString.ReplaceAll("-yes", "").ReplaceAll("-no", ""); + if (mode == kAnalysis) { + StoreArmedMask(); + } } /// \brief Calculates the length of the mask needed to store the selection cuts @@ -226,10 +233,6 @@ void EventSelectionFilterAndAnalysis::ConstructCutFromString(const TString& cuts } } mMaskLength = CalculateMaskLength(); - if (mMaskLength > 64) { - LOGF(fatal, "EventSelectionFilterAndAnalysis not ready for filter mask of %d bits. Just 64 available for the time being", mMaskLength); - } - StoreArmedMask(); } /// \brief Fills the filter cuts mask diff --git a/PWGCF/TwoParticleCorrelations/Core/EventSelectionFilterAndAnalysis.h b/PWGCF/TwoParticleCorrelations/Core/EventSelectionFilterAndAnalysis.h index 86897ed82c1..44ba7d58877 100644 --- a/PWGCF/TwoParticleCorrelations/Core/EventSelectionFilterAndAnalysis.h +++ b/PWGCF/TwoParticleCorrelations/Core/EventSelectionFilterAndAnalysis.h @@ -68,8 +68,8 @@ class EventSelectionFilterAndAnalysis : public SelectionFilterAndAnalysis private: void ConstructCutFromString(const TString&); void InitializeMultiplicityFilter(); - int CalculateMaskLength(); - virtual void StoreArmedMask(); + int CalculateMaskLength() override; + virtual void StoreArmedMask() override; CutBrick* mMultiplicityClasses; //! the multiplicity default classes cuts CutBrick* mTriggerSelection; //! the trigger selection cuts diff --git a/PWGCF/TwoParticleCorrelations/Core/SelectionFilterAndAnalysis.cxx b/PWGCF/TwoParticleCorrelations/Core/SelectionFilterAndAnalysis.cxx index 808ad9d56cd..ed7f0c5b17e 100644 --- a/PWGCF/TwoParticleCorrelations/Core/SelectionFilterAndAnalysis.cxx +++ b/PWGCF/TwoParticleCorrelations/Core/SelectionFilterAndAnalysis.cxx @@ -29,9 +29,12 @@ ClassImp(SelectionFilterAndAnalysis); SelectionFilterAndAnalysis::SelectionFilterAndAnalysis() : TNamed(), mMode(kFilter), + mCutStringSignature(), mMaskLength(0), mSelectedMask(0UL), - mArmedMask(0UL) + mArmedMask(0UL), + mOptArmedMask(0UL), + mForcedArmedMask(0UL) { } @@ -39,8 +42,11 @@ SelectionFilterAndAnalysis::SelectionFilterAndAnalysis() SelectionFilterAndAnalysis::SelectionFilterAndAnalysis(const TString& name, selmodes mode) : TNamed(name, name), mMode(mode), + mCutStringSignature(), mMaskLength(0), mSelectedMask(0UL), - mArmedMask(0UL) + mArmedMask(0UL), + mOptArmedMask(0UL), + mForcedArmedMask(0UL) { } diff --git a/PWGCF/TwoParticleCorrelations/Core/SelectionFilterAndAnalysis.h b/PWGCF/TwoParticleCorrelations/Core/SelectionFilterAndAnalysis.h index 6e5c78cb86a..a230de3453a 100644 --- a/PWGCF/TwoParticleCorrelations/Core/SelectionFilterAndAnalysis.h +++ b/PWGCF/TwoParticleCorrelations/Core/SelectionFilterAndAnalysis.h @@ -58,6 +58,7 @@ class SelectionFilterAndAnalysis : public TNamed protected: selmodes mMode = kFilter; /// the operating mode of the selection instance + TString mCutStringSignature; /// the signature of the cut string, i.e. without the alternative selection tags int mMaskLength = 0; /// the length of the mask needed to filter the selection cuts uint64_t mSelectedMask = 0UL; /// the selection mask for the current passed collision uint64_t mArmedMask = 0UL; /// the complete armed mask identifying the applicable selection cuts diff --git a/PWGCF/TwoParticleCorrelations/Core/TrackSelectionFilterAndAnalysis.cxx b/PWGCF/TwoParticleCorrelations/Core/TrackSelectionFilterAndAnalysis.cxx index 0f8d86213ca..93cb3fa24f2 100644 --- a/PWGCF/TwoParticleCorrelations/Core/TrackSelectionFilterAndAnalysis.cxx +++ b/PWGCF/TwoParticleCorrelations/Core/TrackSelectionFilterAndAnalysis.cxx @@ -55,8 +55,8 @@ TrackSelectionFilterAndAnalysis::TrackSelectionFilterAndAnalysis(const TString& /* we own the track types cuts objects */ mTrackTypes.SetOwner(true); /* at least we initialize by default pT and eta cuts */ - mPtRange = CutBrick::constructBrick("pT", "rg{0.2,10}", std::set{"rg"}); - mEtaRange = CutBrick::constructBrick("eta", "rg{-0.8,0.8}", std::set{"rg"}); + mPtRange = CutBrick::constructBrick("pT", "rg{0.1,50}", std::set{"rg"}); + mEtaRange = CutBrick::constructBrick("eta", "rg{-1.0,1.0}", std::set{"rg"}); ConstructCutFromString(cutstr); } @@ -115,6 +115,10 @@ TrackSelectionFilterAndAnalysis::TrackSelectionFilterAndAnalysis(const TrackSele } cutString += "}"; ConstructCutFromString(cutString); + if (mMaskLength > 64) { + LOGF(fatal, "TrackSelectionFilterAndAnalysis not ready for filter mask of %d bits. Just 64 available for the time being", mMaskLength); + } + mCutStringSignature = cutString.ReplaceAll("-yes", "").ReplaceAll("-no", ""); if (mode == kAnalysis) { /* TODO: check cuts consistency. In principle it should be there except for the ttype valid combinations */ StoreArmedMask(); From 4014dbd831c0aadfabd413e124150a8a25206772 Mon Sep 17 00:00:00 2001 From: Victor Date: Sun, 25 Sep 2022 00:32:27 +0200 Subject: [PATCH 07/20] First step towards PID skimming support --- .../Core/PIDSelectionFilterAndAnalysis.cxx | 133 ++++++++++++++++-- .../Core/PIDSelectionFilterAndAnalysis.h | 113 ++++++++++++--- .../Core/SkimmingConfigurableCuts.cxx | 86 ----------- .../Core/SkimmingConfigurableCuts.h | 51 ------- .../Core/TwoPartCorrLinkDef.h | 2 +- .../TableProducer/skimmingconf.h | 54 ++++--- 6 files changed, 254 insertions(+), 185 deletions(-) diff --git a/PWGCF/TwoParticleCorrelations/Core/PIDSelectionFilterAndAnalysis.cxx b/PWGCF/TwoParticleCorrelations/Core/PIDSelectionFilterAndAnalysis.cxx index 74edf3e7c6d..a6799c62311 100644 --- a/PWGCF/TwoParticleCorrelations/Core/PIDSelectionFilterAndAnalysis.cxx +++ b/PWGCF/TwoParticleCorrelations/Core/PIDSelectionFilterAndAnalysis.cxx @@ -32,8 +32,9 @@ PIDSelectionFilterAndAnalysis::PIDSelectionFilterAndAnalysis() mPTOF(0.8f), mRequireTOF(false), mEllipticTPCTOF(false), - mInclusiveTrackPID(0), - mExclusiveTrackPID(0) + mCloseNsigmasITS(kNoOfSpecies, nullptr), + mCloseNsigmasTPC(kNoOfSpecies, nullptr), + mCloseNsigmasTOF(kNoOfSpecies, nullptr) { } @@ -43,29 +44,135 @@ PIDSelectionFilterAndAnalysis::PIDSelectionFilterAndAnalysis(const TString& cuts mPTOF(0.8f), mRequireTOF(false), mEllipticTPCTOF(false), - mInclusiveTrackPID(0), - mExclusiveTrackPID(0) + mCloseNsigmasITS(kNoOfSpecies, nullptr), + mCloseNsigmasTPC(kNoOfSpecies, nullptr), + mCloseNsigmasTOF(kNoOfSpecies, nullptr) { ConstructCutFromString(cutstr); } +/// \brief Constructor from the PID selection configurable +PIDSelectionFilterAndAnalysis::PIDSelectionFilterAndAnalysis(const PIDSelectionConfigurable& pidsel, selmodes mode) + : SelectionFilterAndAnalysis("", mode), + mPTOF(0.8f), + mRequireTOF(false), + mEllipticTPCTOF(false), + mCloseNsigmasITS(kNoOfSpecies, nullptr), + mCloseNsigmasTPC(kNoOfSpecies, nullptr), + mCloseNsigmasTOF(kNoOfSpecies, nullptr) +{ + TString cutString = "pidsel{"; + bool first = true; + + auto appendCut = [&cutString, &first](std::string str) { + if (str.size() > 0) { + if (first) { + cutString += str; + first = false; + } else { + cutString += "," + str; + } + } + }; + /* TODO: interlace the different detectors */ + appendCut(pidsel.mPidItsSel_el); + appendCut(pidsel.mPidItsSel_mu); + appendCut(pidsel.mPidItsSel_pi); + appendCut(pidsel.mPidItsSel_ka); + appendCut(pidsel.mPidItsSel_pr); + appendCut(pidsel.mPidTpcSel_el); + appendCut(pidsel.mPidTpcSel_mu); + appendCut(pidsel.mPidTpcSel_pi); + appendCut(pidsel.mPidTpcSel_ka); + appendCut(pidsel.mPidTpcSel_pr); + appendCut(pidsel.mPidTofSel_el); + appendCut(pidsel.mPidTofSel_mu); + appendCut(pidsel.mPidTofSel_pi); + appendCut(pidsel.mPidTofSel_ka); + appendCut(pidsel.mPidTofSel_pr); + + cutString += "}"; + ConstructCutFromString(cutString); + if (mMaskLength > 64) { + LOGF(fatal, "EventSelectionFilterAndAnalysis not ready for filter mask of %d bits. Just 64 available for the time being", mMaskLength); + } + mCutStringSignature = cutString.ReplaceAll("-yes", "").ReplaceAll("-no", ""); + if (mode == kAnalysis) { + StoreArmedMask(); + } +} + +/// \brief Destructor +/// Releases the taken memory +PIDSelectionFilterAndAnalysis::~PIDSelectionFilterAndAnalysis() +{ + for (auto brick : mCloseNsigmasITS) { + delete brick; + } + for (auto brick : mCloseNsigmasTPC) { + delete brick; + } + for (auto brick : mCloseNsigmasTOF) { + delete brick; + } +} + /// \brief Calculates the length of the mask needed to store the selection cuts int PIDSelectionFilterAndAnalysis::CalculateMaskLength() { int length = 0; - for (auto brick : mInclusiveTrackPID) { - length += brick->Length(); - } - for (auto brick : mExclusiveTrackPID) { - length += brick->Length(); - } + auto addLength = [&](auto bricklst) { + for (auto brick : bricklst) { + length += brick->Length(); + } + }; + addLength(mCloseNsigmasITS); + addLength(mCloseNsigmasTPC); + addLength(mCloseNsigmasTOF); return length; } void PIDSelectionFilterAndAnalysis::ConstructCutFromString(const TString& cutstr) { mMaskLength = CalculateMaskLength(); - if (mMaskLength > 64) { - LOGF(fatal, "PIDSelectionFilterAndAnalysis not ready for filter mask of %d bits. Just 64 available for the time being", mMaskLength); - } +} + +void PIDSelectionFilterAndAnalysis::StoreArmedMask() +{ + uint64_t armedMask = 0UL; + uint64_t optMask = 0UL; + uint64_t forcedMask = 0UL; + mArmedMask = 0UL; + mOptArmedMask = 0UL; + mForcedArmedMask = 0UL; + int bit = 0; + auto armedList = [&](auto bricklst) { + auto armedBrick = [&](auto brick, bool opt = false) { + if (brick != nullptr) { + std::vector res = brick->IsArmed(); + for (auto b : res) { + if (b) { + SETBIT(armedMask, bit); + if (opt) { + SETBIT(optMask, bit); + } else { + SETBIT(forcedMask, bit); + } + } + bit++; + } + } + }; + for (auto brick : bricklst) { + armedBrick(brick, true); + } + }; + armedList(mCloseNsigmasITS); + armedList(mCloseNsigmasTPC); + armedList(mCloseNsigmasTOF); + + LOGF(info, "PIDSelectionFilterAndAnalysis::StoreArmedMask(), masks 0x%08lx, 0x%08lx, 0x%08lx", armedMask, optMask, forcedMask); + mArmedMask = armedMask; + mOptArmedMask = optMask; + mForcedArmedMask = forcedMask; } diff --git a/PWGCF/TwoParticleCorrelations/Core/PIDSelectionFilterAndAnalysis.h b/PWGCF/TwoParticleCorrelations/Core/PIDSelectionFilterAndAnalysis.h index 27bde37b240..dcbc437b58a 100644 --- a/PWGCF/TwoParticleCorrelations/Core/PIDSelectionFilterAndAnalysis.h +++ b/PWGCF/TwoParticleCorrelations/Core/PIDSelectionFilterAndAnalysis.h @@ -26,6 +26,42 @@ namespace analysis { namespace PWGCF { +/* forward declaration */ +class PIDSelectionFilterAndAnalysis; + +///\brief Convenience class for configuration access +class PIDSelectionConfigurable +{ + friend class PIDSelectionFilterAndAnalysis; + + public: + PIDSelectionConfigurable(std::string piditsel = "", std::string piditsmu = "", std::string piditspi = "", std::string piditska = "", std::string piditspr = "", + std::string pidtpcel = "", std::string pidtpcmu = "", std::string pidtpcpi = "", std::string pidtpcka = "", std::string pidtpcpr = "", + std::string pidtofel = "", std::string pidtofmu = "", std::string pidtofpi = "", std::string pidtofka = "", std::string pidtofpr = "") + : mPidItsSel_el{piditsel}, mPidItsSel_mu{piditsmu}, mPidItsSel_pi{piditspi}, mPidItsSel_ka{piditska}, mPidItsSel_pr{piditspr}, mPidTpcSel_el{pidtpcel}, mPidTpcSel_mu{pidtpcmu}, mPidTpcSel_pi{pidtpcpi}, mPidTpcSel_ka{pidtpcka}, mPidTpcSel_pr{pidtpcpr}, mPidTofSel_el{pidtofel}, mPidTofSel_mu{pidtofmu}, mPidTofSel_pi{pidtofpi}, mPidTofSel_ka{pidtofka}, mPidTofSel_pr{pidtofpr} + { + } + + private: + std::string mPidItsSel_el = ""; + std::string mPidItsSel_mu = ""; + std::string mPidItsSel_pi = ""; + std::string mPidItsSel_ka = ""; + std::string mPidItsSel_pr = ""; + std::string mPidTpcSel_el = ""; + std::string mPidTpcSel_mu = ""; + std::string mPidTpcSel_pi = ""; + std::string mPidTpcSel_ka = ""; + std::string mPidTpcSel_pr = ""; + std::string mPidTofSel_el = ""; + std::string mPidTofSel_mu = ""; + std::string mPidTofSel_pi = ""; + std::string mPidTofSel_ka = ""; + std::string mPidTofSel_pr = ""; + + private: + ClassDefNV(PIDSelectionConfigurable, 1); +}; /// \brief Filter of tracks based on PID and track selection once filetered class PIDSelectionFilterAndAnalysis : public SelectionFilterAndAnalysis @@ -33,6 +69,8 @@ class PIDSelectionFilterAndAnalysis : public SelectionFilterAndAnalysis public: PIDSelectionFilterAndAnalysis(); PIDSelectionFilterAndAnalysis(const TString&, selmodes); + PIDSelectionFilterAndAnalysis(const PIDSelectionConfigurable& pidsel, selmodes mode); + virtual ~PIDSelectionFilterAndAnalysis() override; void SetPTOF(float ptof) { mPTOF = ptof; } void SetRequireTOF(bool requiretof = false) { mRequireTOF = requiretof; } @@ -41,42 +79,83 @@ class PIDSelectionFilterAndAnalysis : public SelectionFilterAndAnalysis template uint64_t Filter(TrackToFilter const& track); + enum PIDSpecies { + kElectron = 0, ///< electron + kMuon, ///< muon + kPion, ///< pion + kKaon, ///< kaon + kProton, ///< proton + kNoOfSpecies, ///< the number of considered species + kWrongSpecies = -1 + }; + + enum class PIDCuts : int { + kITS = 0, + kTPC, + kTOF, + kTPCTOF, + kNEARSIGMA, + kAWAYSIGMA, + kTOFREQ, + kNCuts + }; + + static const std::string mCutNames[static_cast(PIDCuts::kNCuts)]; + private: void ConstructCutFromString(const TString&); - int CalculateMaskLength(); + virtual int CalculateMaskLength() override; + virtual void StoreArmedMask() override; float mPTOF = 0.8f; ///< the p threshold for cheking TOF information bool mRequireTOF = false; ///< is TOF required bool mEllipticTPCTOF = false; ///< 2D nsigmas elliptic TPC+TOF - std::vector mInclusiveTrackPID; ///< the list of species wanted to be detected - std::vector mExclusiveTrackPID; ///< the list of species wanted to be rejected - ClassDef(PIDSelectionFilterAndAnalysis, 1) + PIDSpecies mSpeciesOfInterest = kWrongSpecies; + std::vector*> mCloseNsigmasITS; + std::vector*> mCloseNsigmasTPC; + std::vector*> mCloseNsigmasTOF; + + ClassDef(PIDSelectionFilterAndAnalysis, 1); }; /// \brief Fills the filter cuts mask template -uint64_t PIDSelectionFilterAndAnalysis::Filter(TrackToFilter const& track) +inline uint64_t PIDSelectionFilterAndAnalysis::Filter(TrackToFilter const& track) { uint64_t selectedMask = 0UL; + mSelectedMask = 0UL; int bit = 0; - auto filterBrickTrack = [&](auto brick, auto track) { - std::vector res = brick->Filter(track); - for (auto b : res) { - if (b) { - SETBIT(selectedMask, bit++); + auto filterBrickValue = [&](auto brick, auto value) { + if (brick != nullptr) { + std::vector res = brick->Filter(value); + for (auto b : res) { + if (b) { + SETBIT(selectedMask, bit); + } + bit++; } } }; + filterBrickValue(mCloseNsigmasITS[kElectron], track.itsNSigmaEl()); + filterBrickValue(mCloseNsigmasITS[kMuon], track.itsNSigmaMu()); + filterBrickValue(mCloseNsigmasITS[kPion], track.itsNSigmaPi()); + filterBrickValue(mCloseNsigmasITS[kKaon], track.itsNSigmaKa()); + filterBrickValue(mCloseNsigmasITS[kProton], track.itsNSigmaPr()); + filterBrickValue(mCloseNsigmasTPC[kElectron], track.tpcNSigmaEl()); + filterBrickValue(mCloseNsigmasTPC[kMuon], track.tpcNSigmaMu()); + filterBrickValue(mCloseNsigmasTPC[kPion], track.tpcNSigmaPi()); + filterBrickValue(mCloseNsigmasTPC[kKaon], track.tpcNSigmaKa()); + filterBrickValue(mCloseNsigmasTPC[kProton], track.tpcNSigmaPr()); + filterBrickValue(mCloseNsigmasTOF[kElectron], track.tofNSigmaEl()); + filterBrickValue(mCloseNsigmasTOF[kMuon], track.tofNSigmaMu()); + filterBrickValue(mCloseNsigmasTOF[kPion], track.tofNSigmaPi()); + filterBrickValue(mCloseNsigmasTOF[kKaon], track.tofNSigmaKa()); + filterBrickValue(mCloseNsigmasTOF[kProton], track.tofNSigmaPr()); - for (auto bricksp : mInclusiveTrackPID) { - filterBrickTrack(bricksp, track); - } - for (auto bricksp : mExclusiveTrackPID) { - filterBrickTrack(bricksp, track); - } - return mSelectedMask = selectedMask; + mSelectedMask = selectedMask; + return mSelectedMask; } } // namespace PWGCF diff --git a/PWGCF/TwoParticleCorrelations/Core/SkimmingConfigurableCuts.cxx b/PWGCF/TwoParticleCorrelations/Core/SkimmingConfigurableCuts.cxx index a780cbf4e17..b283059c68c 100644 --- a/PWGCF/TwoParticleCorrelations/Core/SkimmingConfigurableCuts.cxx +++ b/PWGCF/TwoParticleCorrelations/Core/SkimmingConfigurableCuts.cxx @@ -976,89 +976,3 @@ std::vector TrackSelectionBrick::IsArmed() ClassImp(TrackSelectionBrick); -/// \brief Construct object from regular expression -/// \param regex The brick regular expression -/// Regular expression has to be of the shape -/// {sp{tpc{cwv{rg{-2.0,2.0};rg{-3.0,3.0}};sp1{cwv{xrg{-2.0,2.0};xrg{-3.0,3.0}}}}}{tof ...}} -PIDSelectionBrick::PIDSelectionBrick(const TString& regex) : SpecialCutBrick(regex, regex) -{ - ConstructFromString(regex); -} - -/// \brief Construct object from regular expression -/// \param regex The brick regular expression -/// Regular expression has to be of the shape -/// {sp{tpc{cwv{rg{-2.0,2.0};rg{-3.0,3.0}};sp1{cwv{xrg{-2.0,2.0};xrg{-3.0,3.0}}}}}{tof ...}} -void PIDSelectionBrick::ConstructFromString(const TString&) -{ -} - -/// \brief Length of the brick -/// \return The brick length -/// Recover the length for each of the components -/// and returns their sum -int PIDSelectionBrick::Length() -{ - int len = 0; - for (auto brick : mCloseNsigmasTPC) { - if (brick != nullptr) { - len += brick->Length(); - } - } - for (auto brick : mCloseNsigmasTOF) { - if (brick != nullptr) { - len += brick->Length(); - } - } - return len; -} - -/// \brief Returns wether the cut brick is incorporated in the selection chain -/// \return true if the cut brick is incorporated -std::vector PIDSelectionBrick::IsArmed() -{ - /* TODO: still not the final version */ - std::vector res; - if (this->mMode == this->kSELECTED) { - res.push_back(true); - } else { - res.push_back(false); - } - return res; -} - -template -std::vector PIDSelectionBrick::Filter(TrackObject const& track) -{ - std::vector res; - res.reserve(Length()); - std::vector nsigmasTPC(kNoOfSpecies, 999); - std::vector nsigmasTOF(kNoOfSpecies, 999); - - nsigmasTPC[kElectron] = track.tpcNSigmaEl(); - nsigmasTPC[kMuon] = track.tpcNSigmaMu(); - nsigmasTPC[kPion] = track.tpcNSigmaPi(); - nsigmasTPC[kKaon] = track.tpcNSigmaKa(); - nsigmasTPC[kProton] = track.tpcNSigmaPr(); - nsigmasTOF[kElectron] = track.tofNSigmaEl(); - nsigmasTOF[kMuon] = track.tofNSigmaMu(); - nsigmasTOF[kPion] = track.tofNSigmaPi(); - nsigmasTOF[kKaon] = track.tofNSigmaKa(); - nsigmasTOF[kProton] = track.tofNSigmaPr(); - - for (int sp = 0; sp < kNoOfSpecies; ++sp) { - if (mCloseNsigmasTPC[sp] != nullptr) { - std::vector tmp = mCloseNsigmasTPC[sp]->Filter(nsigmasTPC[sp]); - res.insert(res.end(), tmp.begin(), tmp.end()); - } - } - for (int sp = 0; sp < kNoOfSpecies; ++sp) { - if (mCloseNsigmasTOF[sp] != nullptr) { - std::vector tmp = mCloseNsigmasTOF[sp]->Filter(nsigmasTOF[sp]); - res.insert(res.end(), tmp.begin(), tmp.end()); - } - } - return res; -} - -ClassImp(PIDSelectionBrick); diff --git a/PWGCF/TwoParticleCorrelations/Core/SkimmingConfigurableCuts.h b/PWGCF/TwoParticleCorrelations/Core/SkimmingConfigurableCuts.h index 2aee2dae76e..57d158f47e6 100644 --- a/PWGCF/TwoParticleCorrelations/Core/SkimmingConfigurableCuts.h +++ b/PWGCF/TwoParticleCorrelations/Core/SkimmingConfigurableCuts.h @@ -425,57 +425,6 @@ class TrackSelectionBrick : public SpecialCutBrick ClassDef(TrackSelectionBrick, 1); }; -class PIDSelectionBrick : public SpecialCutBrick -{ - public: - PIDSelectionBrick() : SpecialCutBrick(), - mCloseNsigmasTPC(kNoOfSpecies, nullptr), - mCloseNsigmasTOF(kNoOfSpecies, nullptr) - { - } - PIDSelectionBrick(const TString&); - virtual ~PIDSelectionBrick() override = default; - - enum PIDSpecies { - kElectron = 0, ///< electron - kMuon, ///< muon - kPion, ///< pion - kKaon, ///< kaon - kProton, ///< proton - kNoOfSpecies, ///< the number of considered species - kWrongSpecies = -1 - }; - - enum class PIDCuts : int { - kITS = 0, - kTPC, - kTOF, - kTPCTOF, - kNEARSIGMA, - kAWAYSIGMA, - kTOFREQ, - kNCuts - }; - - static const std::string mCutNames[static_cast(PIDCuts::kNCuts)]; - - virtual std::vector IsArmed() override; - template - std::vector Filter(TrackToFilter const& track); - - int Length() override; - - private: - void ConstructFromString(const TString& cutstr); - - private: - PIDSpecies mSpeciesOfInterest = kWrongSpecies; - std::vector*> mCloseNsigmasTPC; - std::vector*> mCloseNsigmasTOF; - - ClassDef(PIDSelectionBrick, 1); -}; - } // namespace PWGCF } // namespace analysis } // namespace o2 diff --git a/PWGCF/TwoParticleCorrelations/Core/TwoPartCorrLinkDef.h b/PWGCF/TwoParticleCorrelations/Core/TwoPartCorrLinkDef.h index e8fe6daeebb..4fa46994eda 100644 --- a/PWGCF/TwoParticleCorrelations/Core/TwoPartCorrLinkDef.h +++ b/PWGCF/TwoParticleCorrelations/Core/TwoPartCorrLinkDef.h @@ -29,10 +29,10 @@ #pragma link C++ class o2::analysis::PWGCF::CutWithVariations < int> + ; #pragma link C++ class o2::analysis::PWGCF::SpecialCutBrick + ; #pragma link C++ class o2::analysis::PWGCF::TrackSelectionBrick + ; -#pragma link C++ class o2::analysis::PWGCF::PIDSelectionBrick + ; #pragma link C++ class o2::analysis::PWGCF::SelectionFilterAndAnalysis + ; #pragma link C++ class o2::analysis::PWGCF::TrackSelectionConfigurable + ; #pragma link C++ class o2::analysis::PWGCF::TrackSelectionFilterAndAnalysis + ; +#pragma link C++ class o2::analysis::PWGCF::PIDSelectionConfigurable + ; #pragma link C++ class o2::analysis::PWGCF::PIDSelectionFilterAndAnalysis + ; #pragma link C++ class o2::analysis::PWGCF::EventSelectionConfigurable + ; #pragma link C++ class o2::analysis::PWGCF::EventSelectionFilterAndAnalysis + ; diff --git a/PWGCF/TwoParticleCorrelations/TableProducer/skimmingconf.h b/PWGCF/TwoParticleCorrelations/TableProducer/skimmingconf.h index 11a5fd1288c..b71385d6450 100644 --- a/PWGCF/TwoParticleCorrelations/TableProducer/skimmingconf.h +++ b/PWGCF/TwoParticleCorrelations/TableProducer/skimmingconf.h @@ -14,33 +14,53 @@ #include "Framework/AnalysisTask.h" #include "Framework/ASoAHelpers.h" -struct : ConfigurableGroup { - Configurable zvtxsel{"evtflt_zvtx", "zvtx{cwv{rg{-7.0,7.0}-yes:rg{-10.0,10.0}-no,rg{-3.0,3.0}-no}}", "Z vertex cut: zvtx{rg{-7.0,7.0}} or zvtx{cwv{def:var1,var2@,..}}"}; - Configurable centmultsel{"evtflt_centmult", "centmult{cwv{mrg{V0M,0,5,10,20,30,40,50,60,70,80}-yes:mrg{CL1,0,5,10,20,30,40,50,60,70,80}-no}}", "Centrality/Multiplicity cut: centmult{mrg{V0M,0,5,10,20,30,40,50,60,70,80}}"}; +struct : o2::framework::ConfigurableGroup { + o2::framework::Configurable zvtxsel{"evtflt_zvtx", "zvtx{cwv{rg{-7.0,7.0}-yes:rg{-10.0,10.0}-no,rg{-3.0,3.0}-no}}", "Z vertex cut: zvtx{rg{-7.0,7.0}} or zvtx{cwv{def:var1,var2@,..}}"}; + o2::framework::Configurable centmultsel{"evtflt_centmult", "centmult{cwv{mrg{V0M,0,5,10,20,30,40,50,60,70,80}-yes:mrg{CL1,0,5,10,20,30,40,50,60,70,80}-no}}", "Centrality/Multiplicity cut: centmult{mrg{V0M,0,5,10,20,30,40,50,60,70,80}}"}; } eventfilter; -struct : ConfigurableGroup { - Configurable ttype{"trkflt_ttype", "ttype{FB1-no,FB32-yes,FB64-yes}", "Track types to filter"}; - Configurable nclstpc{"trkflt_nclstpc", "nclstpc{cwv{th{70}-yes:th{80}-no,th{90}-no}}", "Min no of TPC clusters: nclstpc{th{70}} or nclstpc{cwv{def:var1,var2,...}}"}; +struct : o2::framework::ConfigurableGroup { + o2::framework::Configurable ttype{"trkflt_ttype", "ttype{FB1-no,FB32-yes,FB64-yes}", "Track types to filter"}; + o2::framework::Configurable nclstpc{"trkflt_nclstpc", "nclstpc{cwv{th{70}-yes:th{80}-no,th{90}-no}}", "Min no of TPC clusters: nclstpc{th{70}} or nclstpc{cwv{def:var1,var2,...}}"}; // Configurable nxrtpc{"trkflt_nxrtpc", "nxrtpc{}", "Min no of TPC crossed rows: nxrtpc{th{70}} or nxrtpc{cwv{def;var1,var2,...}}"}; - Configurable nxrtpc{"trkflt_nxrtpc", "", "Min no of TPC crossed rows: nxrtpc{th{70}} or nxrtpc{cwv{def;var1,var2,...}}"}; + o2::framework::Configurable nxrtpc{"trkflt_nxrtpc", "", "Min no of TPC crossed rows: nxrtpc{th{70}} or nxrtpc{cwv{def;var1,var2,...}}"}; // Configurable nclsits{"trkflt_nclsits", "nclsits{}", "Min no of ITS clusters: nclsits{th{3}} or nclsits{cwv{def;var1,var2,...}}"}; - Configurable nclsits{"trkflt_nclsits", "", "Min no of ITS clusters: nclsits{th{3}} or nclsits{cwv{def;var1,var2,...}}"}; - Configurable chi2clustpc{"trkflt_chi2clustpc", "chi2clustpc{cwv{lim{4}-yes:lim{3}-no,lim{90}-no}}", "Max Chi^2 per TPC cluster: chi2clustpc{lim{4}} or chi2clustpc{cwv{def:var1,var2,...}}"}; + o2::framework::Configurable nclsits{"trkflt_nclsits", "", "Min no of ITS clusters: nclsits{th{3}} or nclsits{cwv{def;var1,var2,...}}"}; + o2::framework::Configurable chi2clustpc{"trkflt_chi2clustpc", "chi2clustpc{cwv{lim{4}-yes:lim{3}-no,lim{90}-no}}", "Max Chi^2 per TPC cluster: chi2clustpc{lim{4}} or chi2clustpc{cwv{def:var1,var2,...}}"}; // Configurable chi2clusits{"trkflt_chi2clusits", "chi2clusits{}", "Max Chi^2 per ITS cluster: chi2clusits{lim{4}} or chi2clusits{cwv{def;var1,var2,...}}"}; - Configurable chi2clusits{"trkflt_chi2clusits", "", "Max Chi^2 per ITS cluster: chi2clusits{lim{4}} or chi2clusits{cwv{def;var1,var2,...}}"}; + o2::framework::Configurable chi2clusits{"trkflt_chi2clusits", "", "Max Chi^2 per ITS cluster: chi2clusits{lim{4}} or chi2clusits{cwv{def;var1,var2,...}}"}; // Configurable xrofctpc{"trkflt_xrofctpc", "xrofctpc{}", "Min no of TPC crossed rows over findable clusters: xrofctpc{th{0.70}} or xrofctpc{cwv{def;var1,var2,...}}"}; - Configurable xrofctpc{"trkflt_xrofctpc", "", "Min no of TPC crossed rows over findable clusters: xrofctpc{th{0.70}} or xrofctpc{cwv{def;var1,var2,...}}"}; + o2::framework::Configurable xrofctpc{"trkflt_xrofctpc", "", "Min no of TPC crossed rows over findable clusters: xrofctpc{th{0.70}} or xrofctpc{cwv{def;var1,var2,...}}"}; // Configurable dcaxy{"trkflt_dcaxy", "dcaxy{}", "Max DCAxy: dcaxy{lim{2.3}} or dcaxy{cwv{def;var1,var2,...}}"}; - Configurable dcaxy{"trkflt_dcaxy", "", "Max DCAxy: dcaxy{lim{2.3}} or dcaxy{cwv{def;var1,var2,...}}"}; + o2::framework::Configurable dcaxy{"trkflt_dcaxy", "", "Max DCAxy: dcaxy{lim{2.3}} or dcaxy{cwv{def;var1,var2,...}}"}; // Configurable dcaz{"trkflt_dcaz", "dcaz{}", "Max DCAz: dcaz{lim{3.0}} or dcaz{cwv{def;var1,var2,...}}"}; - Configurable dcaz{"trkflt_dcaz", "", "Max DCAz: dcaz{lim{3.0}} or dcaz{cwv{def;var1,var2,...}}"}; - Configurable ptrange{"trkflt_pt", "pT{rg{0.2,10.0}}", "pT range: pT{th{0.2}} or pT{cwv{def;var1,var2,...}}"}; - Configurable etarange{"trkflt_eta", "eta{rg{-0.8,0.8}}", "eta range: eta{rg{-0.9,0.9}} or eta{cwv{def;var1,var2,...}}"}; + o2::framework::Configurable dcaz{"trkflt_dcaz", "", "Max DCAz: dcaz{lim{3.0}} or dcaz{cwv{def;var1,var2,...}}"}; + o2::framework::Configurable ptrange{"trkflt_pt", "pT{rg{0.2,10.0}}", "pT range: pT{th{0.2}} or pT{cwv{def;var1,var2,...}}"}; + o2::framework::Configurable etarange{"trkflt_eta", "eta{rg{-0.8,0.8}}", "eta range: eta{rg{-0.9,0.9}} or eta{cwv{def;var1,var2,...}}"}; } trackfilter; -struct : ConfigurableGroup { - +struct : o2::framework::ConfigurableGroup { + struct : ConfigurableGroup { + o2::framework::Configurable itsel{"pidflt_its_el", "itsel{cwv{rg{-3.0,3.0}:rg{-2.0,2.0},rg{-3.0,5.0}}}", "nsigmas to the its electron dE/dx line, below/above"}; + o2::framework::Configurable itsmu{"pidflt_its_mu", "itsmu{cwv{rg{-3.0,3.0}:rg{-2.0,2.0},rg{-3.0,5.0}}}", "nsigmas to the its muon dE/dx line, below/above"}; + o2::framework::Configurable itspi{"pidflt_its_pi", "itspi{cwv{rg{-3.0,3.0}:rg{-2.0,2.0},rg{-3.0,5.0}}}", "nsigmas to the its pion dE/dx line, below/above"}; + o2::framework::Configurable itska{"pidflt_its_ka", "itska{cwv{rg{-3.0,3.0}:rg{-2.0,2.0},rg{-3.0,5.0}}}", "nsigmas to the its kaon dE/dx line, below/above"}; + o2::framework::Configurable itspr{"pidflt_its_pr", "itspr{cwv{rg{-3.0,3.0}:rg{-2.0,2.0},rg{-3.0,5.0}}}", "nsigmas to the its proton dE/dx line, below/above"}; + } piditsfilter; + struct : ConfigurableGroup { + o2::framework::Configurable tpcel{"pidflt_tpc_el", "tpcel{cwv{rg{-3.0,3.0}:rg{-2.0,2.0},rg{-3.0,5.0}}}", "nsigmas to the tpc electron dE/dx line, below/above"}; + o2::framework::Configurable tpcmu{"pidflt_tpc_mu", "tpcmu{cwv{rg{-3.0,3.0}:rg{-2.0,2.0},rg{-3.0,5.0}}}", "nsigmas to the tpc muon dE/dx line, below/above"}; + o2::framework::Configurable tpcpi{"pidflt_tpc_pi", "tpcpi{cwv{rg{-3.0,3.0}:rg{-2.0,2.0},rg{-3.0,5.0}}}", "nsigmas to the tpc pion dE/dx line, below/above"}; + o2::framework::Configurable tpcka{"pidflt_tpc_ka", "tpcks{cwv{rg{-3.0,3.0}:rg{-2.0,2.0},rg{-3.0,5.0}}}", "nsigmas to the tpc kaon dE/dx line, below/above"}; + o2::framework::Configurable tpcpr{"pidflt_tpc_pr", "tpcpr{cwv{rg{-3.0,3.0}:rg{-2.0,2.0},rg{-3.0,5.0}}}", "nsigmas to the tpc proton dE/dx line, below/above"}; + } pidtpcfilter; + struct : ConfigurableGroup { + o2::framework::Configurable tpcel{"pidflt_tof_el", "tofel{cwv{rg{-3.0,3.0}:rg{-2.0,2.0},rg{-3.0,5.0}}}", "nsigmas to the tof electron line, below/above"}; + o2::framework::Configurable tpcmu{"pidflt_tof_mu", "tofmu{cwv{rg{-3.0,3.0}:rg{-2.0,2.0},rg{-3.0,5.0}}}", "nsigmas to the tof muon line, below/above"}; + o2::framework::Configurable tpcpi{"pidflt_tof_pi", "tofpi{cwv{rg{-3.0,3.0}:rg{-2.0,2.0},rg{-3.0,5.0}}}", "nsigmas to the tof pion line, below/above"}; + o2::framework::Configurable tpcka{"pidflt_tof_ka", "tofks{cwv{rg{-3.0,3.0}:rg{-2.0,2.0},rg{-3.0,5.0}}}", "nsigmas to the tof kaon line, below/above"}; + o2::framework::Configurable tpcpr{"pidflt_tof_pr", "tofpr{cwv{rg{-3.0,3.0}:rg{-2.0,2.0},rg{-3.0,5.0}}}", "nsigmas to the tof proton line, below/above"}; + } pidtoffilter; } pidfilter; #endif // O2_ANALYSIS_DPTDPTSKIMCONF_H From 25e969484df0c76851d4465ba036097d14383023 Mon Sep 17 00:00:00 2001 From: ALICE Action Bot Date: Sat, 24 Sep 2022 22:37:18 +0000 Subject: [PATCH 08/20] Please consider the following formatting changes --- .../Core/PIDSelectionFilterAndAnalysis.h | 6 +++--- .../Core/SkimmingConfigurableCuts.cxx | 1 - 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/PWGCF/TwoParticleCorrelations/Core/PIDSelectionFilterAndAnalysis.h b/PWGCF/TwoParticleCorrelations/Core/PIDSelectionFilterAndAnalysis.h index dcbc437b58a..c8e05e25690 100644 --- a/PWGCF/TwoParticleCorrelations/Core/PIDSelectionFilterAndAnalysis.h +++ b/PWGCF/TwoParticleCorrelations/Core/PIDSelectionFilterAndAnalysis.h @@ -107,9 +107,9 @@ class PIDSelectionFilterAndAnalysis : public SelectionFilterAndAnalysis virtual int CalculateMaskLength() override; virtual void StoreArmedMask() override; - float mPTOF = 0.8f; ///< the p threshold for cheking TOF information - bool mRequireTOF = false; ///< is TOF required - bool mEllipticTPCTOF = false; ///< 2D nsigmas elliptic TPC+TOF + float mPTOF = 0.8f; ///< the p threshold for cheking TOF information + bool mRequireTOF = false; ///< is TOF required + bool mEllipticTPCTOF = false; ///< 2D nsigmas elliptic TPC+TOF PIDSpecies mSpeciesOfInterest = kWrongSpecies; std::vector*> mCloseNsigmasITS; diff --git a/PWGCF/TwoParticleCorrelations/Core/SkimmingConfigurableCuts.cxx b/PWGCF/TwoParticleCorrelations/Core/SkimmingConfigurableCuts.cxx index b283059c68c..cf1bf1e720a 100644 --- a/PWGCF/TwoParticleCorrelations/Core/SkimmingConfigurableCuts.cxx +++ b/PWGCF/TwoParticleCorrelations/Core/SkimmingConfigurableCuts.cxx @@ -975,4 +975,3 @@ std::vector TrackSelectionBrick::IsArmed() } ClassImp(TrackSelectionBrick); - From 30b33f873fe6bc02ac18d5c9d20237ef48286957 Mon Sep 17 00:00:00 2001 From: Victor Date: Sun, 25 Sep 2022 20:25:11 +0200 Subject: [PATCH 09/20] Incorporated the PID skimming masks support --- .../Core/PIDSelectionFilterAndAnalysis.cxx | 115 +++++++++++++++--- .../Core/PIDSelectionFilterAndAnalysis.h | 17 +-- .../Core/SelectionFilterAndAnalysis.h | 2 + .../TwoParticleCorrelationsSkimmed.h | 2 + .../TableProducer/skimmingconf.h | 27 ++-- .../twoParticleCorrelationsFiltering.cxx | 15 +++ .../twoParticleCorrelationsSkimming.cxx | 23 +++- 7 files changed, 150 insertions(+), 51 deletions(-) diff --git a/PWGCF/TwoParticleCorrelations/Core/PIDSelectionFilterAndAnalysis.cxx b/PWGCF/TwoParticleCorrelations/Core/PIDSelectionFilterAndAnalysis.cxx index a6799c62311..2f3a3519a28 100644 --- a/PWGCF/TwoParticleCorrelations/Core/PIDSelectionFilterAndAnalysis.cxx +++ b/PWGCF/TwoParticleCorrelations/Core/PIDSelectionFilterAndAnalysis.cxx @@ -15,6 +15,7 @@ #include "Framework/AnalysisTask.h" #include "Framework/AnalysisDataModel.h" #include "Framework/ASoAHelpers.h" +#include "Common/DataModel/PIDResponse.h" #include "PIDSelectionFilterAndAnalysis.h" using namespace o2; @@ -26,13 +27,15 @@ using namespace boost; ClassImp(PIDSelectionFilterAndAnalysis); +/// \brief species supported +const std::vector PIDSelectionFilterAndAnalysis::mSpeciesNames = {"el", "mu", "pi", "ka", "pr"}; + /// \brief Default constructor PIDSelectionFilterAndAnalysis::PIDSelectionFilterAndAnalysis() : SelectionFilterAndAnalysis(), mPTOF(0.8f), mRequireTOF(false), mEllipticTPCTOF(false), - mCloseNsigmasITS(kNoOfSpecies, nullptr), mCloseNsigmasTPC(kNoOfSpecies, nullptr), mCloseNsigmasTOF(kNoOfSpecies, nullptr) { @@ -44,7 +47,6 @@ PIDSelectionFilterAndAnalysis::PIDSelectionFilterAndAnalysis(const TString& cuts mPTOF(0.8f), mRequireTOF(false), mEllipticTPCTOF(false), - mCloseNsigmasITS(kNoOfSpecies, nullptr), mCloseNsigmasTPC(kNoOfSpecies, nullptr), mCloseNsigmasTOF(kNoOfSpecies, nullptr) { @@ -57,7 +59,6 @@ PIDSelectionFilterAndAnalysis::PIDSelectionFilterAndAnalysis(const PIDSelectionC mPTOF(0.8f), mRequireTOF(false), mEllipticTPCTOF(false), - mCloseNsigmasITS(kNoOfSpecies, nullptr), mCloseNsigmasTPC(kNoOfSpecies, nullptr), mCloseNsigmasTOF(kNoOfSpecies, nullptr) { @@ -74,24 +75,22 @@ PIDSelectionFilterAndAnalysis::PIDSelectionFilterAndAnalysis(const PIDSelectionC } } }; - /* TODO: interlace the different detectors */ - appendCut(pidsel.mPidItsSel_el); - appendCut(pidsel.mPidItsSel_mu); - appendCut(pidsel.mPidItsSel_pi); - appendCut(pidsel.mPidItsSel_ka); - appendCut(pidsel.mPidItsSel_pr); + cutString += "tpcsel{"; + first = true; appendCut(pidsel.mPidTpcSel_el); appendCut(pidsel.mPidTpcSel_mu); appendCut(pidsel.mPidTpcSel_pi); appendCut(pidsel.mPidTpcSel_ka); appendCut(pidsel.mPidTpcSel_pr); + cutString += "},tofsel{"; + first = true; appendCut(pidsel.mPidTofSel_el); appendCut(pidsel.mPidTofSel_mu); appendCut(pidsel.mPidTofSel_pi); appendCut(pidsel.mPidTofSel_ka); appendCut(pidsel.mPidTofSel_pr); - cutString += "}"; + cutString += "}}"; ConstructCutFromString(cutString); if (mMaskLength > 64) { LOGF(fatal, "EventSelectionFilterAndAnalysis not ready for filter mask of %d bits. Just 64 available for the time being", mMaskLength); @@ -106,9 +105,6 @@ PIDSelectionFilterAndAnalysis::PIDSelectionFilterAndAnalysis(const PIDSelectionC /// Releases the taken memory PIDSelectionFilterAndAnalysis::~PIDSelectionFilterAndAnalysis() { - for (auto brick : mCloseNsigmasITS) { - delete brick; - } for (auto brick : mCloseNsigmasTPC) { delete brick; } @@ -123,10 +119,11 @@ int PIDSelectionFilterAndAnalysis::CalculateMaskLength() int length = 0; auto addLength = [&](auto bricklst) { for (auto brick : bricklst) { - length += brick->Length(); + if (brick != nullptr) { + length += brick->Length(); + } } }; - addLength(mCloseNsigmasITS); addLength(mCloseNsigmasTPC); addLength(mCloseNsigmasTOF); return length; @@ -134,6 +131,93 @@ int PIDSelectionFilterAndAnalysis::CalculateMaskLength() void PIDSelectionFilterAndAnalysis::ConstructCutFromString(const TString& cutstr) { + LOGF(info, "Cut string: %s", cutstr); + /* let's catch the first level */ + regex cutregex("^pidsel\\{?(\\w+\\{[\\w\\d.,:{}-]+})*}$", regex_constants::ECMAScript | regex_constants::icase); + std::string in(cutstr.Data()); + smatch m; + + bool res = regex_search(in, m, cutregex); + if (not res or m.empty() or (m.size() > 2)) { + Fatal("PIDSelectionFilterAndAnalysis::::ConstructCutFromString", "Wrong RE: %s, try pidsel{tpcsel{tpcpi{cwv{rg{-3.0,3.0}:rg{-2.0,2.0},rg{-3.0,5.0}}}}} for instance", cutstr.Data()); + } + this->SetName("EventSelectionFilterAndAnalysisCuts"); + this->SetTitle(cutstr.Data()); + + /* let's now handle each of the detectors requirements */ + { + LOGF(info, "Captured %s", m[1].str().c_str()); + TString lev2str = m[1].str(); + while (lev2str.Length() != 0) { + lev2str.Remove(TString::kLeading, ' '); + lev2str.Remove(TString::kLeading, ','); + lev2str.Remove(TString::kLeading, ' '); + if (lev2str.Length() == 0) { + break; + } + regex cutregex("^(\\w+)\\{((?:[^{}]++|\\{(?2)\\})*)\\}"); + std::string in(lev2str.Data()); + smatch m; + bool res = regex_search(in, m, cutregex); + + if (not res or m.empty() or (m.size() != 3)) { + LOGF(fatal, "PIDSelectionFilterAndAnalysis::::ConstructCutFromString. Wrong RE: %s, try pidsel{tpcsel{tpcpi{cwv{rg{-3.0,3.0}:rg{-2.0,2.0},rg{-3.0,5.0}}}}} for instance", cutstr.Data()); + } + LOGF(info, "Captured %s", m[1].str().c_str()); + auto handleDetectorLevel = [](std::string detector, auto& bricklst, std::string cut) { + std::set allowed = {"lim", "th", "rg", "xrg", "cwv", "mrg"}; + TString lev3str = cut; + while (lev3str.Length() != 0) { + regex cutregex3l("^(\\w+)\\{((?:[^{}]++|\\{(?2)\\})*)\\}"); + smatch m3l; + auto storeCut = [&m3l, &allowed](CutBrick*& brickvar) { + if (brickvar != nullptr) { + delete brickvar; + } + brickvar = CutBrick::constructBrick(m3l[1].str().c_str(), m3l[2].str().c_str(), allowed); + }; + lev3str.Remove(TString::kLeading, ' '); + lev3str.Remove(TString::kLeading, ','); + lev3str.Remove(TString::kLeading, ' '); + if (lev3str.Length() == 0) { + break; + } + std::string in3l(lev3str.Data()); + bool res3l = regex_search(in3l, m3l, cutregex3l); + if (not res3l or m3l.empty() or (m3l.size() != 3)) { + LOGF(fatal, "PIDSelectionFilterAndAnalysis::::ConstructCutFromString. Wrong RE for detector %s: %s, try tpcpi{cwv{rg{-3.0,3.0}:rg{-2.0,2.0},rg{-3.0,5.0}}} for instance", detector.c_str(), cut.c_str()); + } + LOGF(info, "Captured %s", m3l[1].str().c_str()); + /* let's search for the involved species index */ + int spindex = -1; + for (uint i = 0; i < mSpeciesNames.size(); ++i) { + TString spname = detector + mSpeciesNames[i]; + LOGF(info, "Checking %s vs %s", spname.Data(), m3l[1].str().c_str()); + if (spname.EqualTo(m3l[1].str().c_str())) { + spindex = i; + break; + } + } + if (spindex < 0) { + LOGF(fatal, "PIDSelectionFilterAndAnalysis::::ConstructCutFromString. Wrong species %s for detector %s: %s, try tpcpi{cwv{rg{-3.0,3.0}:rg{-2.0,2.0},rg{-3.0,5.0}}} for instance", m3l[1].str().c_str(), detector.c_str(), cut.c_str()); + } else { + storeCut(bricklst[spindex]); + } + /* removing the already handled species requirements */ + lev3str.Remove(0, m3l[0].length()); + } + }; + if (m[1].str() == "tpcsel") { + handleDetectorLevel("tpc", mCloseNsigmasTPC, m[2].str()); + } else if (m[1].str() == "tofsel") { + handleDetectorLevel("tof", mCloseNsigmasTOF, m[2].str()); + } else { + Fatal("PIDSelectionFilterAndAnalysis::::ConstructCutFromString", "Wrong RE detector %s, use tpcsel, or tofsel only", m[1].str().c_str()); + } + /* removing the already handled detector requirements */ + lev2str.Remove(0, m[0].length()); + } + } mMaskLength = CalculateMaskLength(); } @@ -167,7 +251,6 @@ void PIDSelectionFilterAndAnalysis::StoreArmedMask() armedBrick(brick, true); } }; - armedList(mCloseNsigmasITS); armedList(mCloseNsigmasTPC); armedList(mCloseNsigmasTOF); diff --git a/PWGCF/TwoParticleCorrelations/Core/PIDSelectionFilterAndAnalysis.h b/PWGCF/TwoParticleCorrelations/Core/PIDSelectionFilterAndAnalysis.h index c8e05e25690..3b0fbf725ee 100644 --- a/PWGCF/TwoParticleCorrelations/Core/PIDSelectionFilterAndAnalysis.h +++ b/PWGCF/TwoParticleCorrelations/Core/PIDSelectionFilterAndAnalysis.h @@ -35,19 +35,13 @@ class PIDSelectionConfigurable friend class PIDSelectionFilterAndAnalysis; public: - PIDSelectionConfigurable(std::string piditsel = "", std::string piditsmu = "", std::string piditspi = "", std::string piditska = "", std::string piditspr = "", - std::string pidtpcel = "", std::string pidtpcmu = "", std::string pidtpcpi = "", std::string pidtpcka = "", std::string pidtpcpr = "", + PIDSelectionConfigurable(std::string pidtpcel = "", std::string pidtpcmu = "", std::string pidtpcpi = "", std::string pidtpcka = "", std::string pidtpcpr = "", std::string pidtofel = "", std::string pidtofmu = "", std::string pidtofpi = "", std::string pidtofka = "", std::string pidtofpr = "") - : mPidItsSel_el{piditsel}, mPidItsSel_mu{piditsmu}, mPidItsSel_pi{piditspi}, mPidItsSel_ka{piditska}, mPidItsSel_pr{piditspr}, mPidTpcSel_el{pidtpcel}, mPidTpcSel_mu{pidtpcmu}, mPidTpcSel_pi{pidtpcpi}, mPidTpcSel_ka{pidtpcka}, mPidTpcSel_pr{pidtpcpr}, mPidTofSel_el{pidtofel}, mPidTofSel_mu{pidtofmu}, mPidTofSel_pi{pidtofpi}, mPidTofSel_ka{pidtofka}, mPidTofSel_pr{pidtofpr} + : mPidTpcSel_el{pidtpcel}, mPidTpcSel_mu{pidtpcmu}, mPidTpcSel_pi{pidtpcpi}, mPidTpcSel_ka{pidtpcka}, mPidTpcSel_pr{pidtpcpr}, mPidTofSel_el{pidtofel}, mPidTofSel_mu{pidtofmu}, mPidTofSel_pi{pidtofpi}, mPidTofSel_ka{pidtofka}, mPidTofSel_pr{pidtofpr} { } private: - std::string mPidItsSel_el = ""; - std::string mPidItsSel_mu = ""; - std::string mPidItsSel_pi = ""; - std::string mPidItsSel_ka = ""; - std::string mPidItsSel_pr = ""; std::string mPidTpcSel_el = ""; std::string mPidTpcSel_mu = ""; std::string mPidTpcSel_pi = ""; @@ -101,6 +95,7 @@ class PIDSelectionFilterAndAnalysis : public SelectionFilterAndAnalysis }; static const std::string mCutNames[static_cast(PIDCuts::kNCuts)]; + static const std::vector mSpeciesNames; private: void ConstructCutFromString(const TString&); @@ -112,7 +107,6 @@ class PIDSelectionFilterAndAnalysis : public SelectionFilterAndAnalysis bool mEllipticTPCTOF = false; ///< 2D nsigmas elliptic TPC+TOF PIDSpecies mSpeciesOfInterest = kWrongSpecies; - std::vector*> mCloseNsigmasITS; std::vector*> mCloseNsigmasTPC; std::vector*> mCloseNsigmasTOF; @@ -138,11 +132,6 @@ inline uint64_t PIDSelectionFilterAndAnalysis::Filter(TrackToFilter const& track } } }; - filterBrickValue(mCloseNsigmasITS[kElectron], track.itsNSigmaEl()); - filterBrickValue(mCloseNsigmasITS[kMuon], track.itsNSigmaMu()); - filterBrickValue(mCloseNsigmasITS[kPion], track.itsNSigmaPi()); - filterBrickValue(mCloseNsigmasITS[kKaon], track.itsNSigmaKa()); - filterBrickValue(mCloseNsigmasITS[kProton], track.itsNSigmaPr()); filterBrickValue(mCloseNsigmasTPC[kElectron], track.tpcNSigmaEl()); filterBrickValue(mCloseNsigmasTPC[kMuon], track.tpcNSigmaMu()); filterBrickValue(mCloseNsigmasTPC[kPion], track.tpcNSigmaPi()); diff --git a/PWGCF/TwoParticleCorrelations/Core/SelectionFilterAndAnalysis.h b/PWGCF/TwoParticleCorrelations/Core/SelectionFilterAndAnalysis.h index a230de3453a..1ac20df0a7d 100644 --- a/PWGCF/TwoParticleCorrelations/Core/SelectionFilterAndAnalysis.h +++ b/PWGCF/TwoParticleCorrelations/Core/SelectionFilterAndAnalysis.h @@ -51,6 +51,8 @@ class SelectionFilterAndAnalysis : public TNamed /// A clear example of the mandatory part mask is the mask of the zvertex and their /// alternatives where only one concrete one is required to be flagged uint64_t getForcedMask() { return mForcedArmedMask; } + /// \brief get the cut string signature + const TString& getCutStringSignature() { return mCutStringSignature; } private: virtual int CalculateMaskLength() = 0; diff --git a/PWGCF/TwoParticleCorrelations/DataModel/TwoParticleCorrelationsSkimmed.h b/PWGCF/TwoParticleCorrelations/DataModel/TwoParticleCorrelationsSkimmed.h index 08eeb7f96d8..2b5c8edae82 100644 --- a/PWGCF/TwoParticleCorrelations/DataModel/TwoParticleCorrelationsSkimmed.h +++ b/PWGCF/TwoParticleCorrelations/DataModel/TwoParticleCorrelationsSkimmed.h @@ -54,6 +54,7 @@ namespace twopskim DECLARE_SOA_INDEX_COLUMN(TwoPSkimmedCollision, event); //! Reconstructed collision/event DECLARE_SOA_INDEX_COLUMN(TwoPSkimmedGenCollision, mcevent); //! Generated collision/event DECLARE_SOA_COLUMN(TwoPSkimmedTrackFlags, trackflags, uint64_t); //! The skimming flags for track selection +DECLARE_SOA_COLUMN(TwoPSkimmedPidFlags, pidflags, uint64_t); //! The PID skimming flags for track selection DECLARE_SOA_COLUMN(sPt, spt, float); //! The track charge signed transverse momentum DECLARE_SOA_DYNAMIC_COLUMN(Pt, pt, //! The track transverse momentum [](float signedpt) -> float { @@ -70,6 +71,7 @@ DECLARE_SOA_DYNAMIC_COLUMN(Sign, sign, //! The track transverse momentum DECLARE_SOA_TABLE(TwoPSkimmedTracks, "AOD", "TWOPSKMDTRKS", //! The reconstructed tracks filtered table twopskim::TwoPSkimmedCollisionId, twopskim::TwoPSkimmedTrackFlags, + twopskim::TwoPSkimmedPidFlags, twopskim::sPt, twopskim::Eta, twopskim::Phi, diff --git a/PWGCF/TwoParticleCorrelations/TableProducer/skimmingconf.h b/PWGCF/TwoParticleCorrelations/TableProducer/skimmingconf.h index b71385d6450..86371ef865d 100644 --- a/PWGCF/TwoParticleCorrelations/TableProducer/skimmingconf.h +++ b/PWGCF/TwoParticleCorrelations/TableProducer/skimmingconf.h @@ -41,25 +41,18 @@ struct : o2::framework::ConfigurableGroup { struct : o2::framework::ConfigurableGroup { struct : ConfigurableGroup { - o2::framework::Configurable itsel{"pidflt_its_el", "itsel{cwv{rg{-3.0,3.0}:rg{-2.0,2.0},rg{-3.0,5.0}}}", "nsigmas to the its electron dE/dx line, below/above"}; - o2::framework::Configurable itsmu{"pidflt_its_mu", "itsmu{cwv{rg{-3.0,3.0}:rg{-2.0,2.0},rg{-3.0,5.0}}}", "nsigmas to the its muon dE/dx line, below/above"}; - o2::framework::Configurable itspi{"pidflt_its_pi", "itspi{cwv{rg{-3.0,3.0}:rg{-2.0,2.0},rg{-3.0,5.0}}}", "nsigmas to the its pion dE/dx line, below/above"}; - o2::framework::Configurable itska{"pidflt_its_ka", "itska{cwv{rg{-3.0,3.0}:rg{-2.0,2.0},rg{-3.0,5.0}}}", "nsigmas to the its kaon dE/dx line, below/above"}; - o2::framework::Configurable itspr{"pidflt_its_pr", "itspr{cwv{rg{-3.0,3.0}:rg{-2.0,2.0},rg{-3.0,5.0}}}", "nsigmas to the its proton dE/dx line, below/above"}; - } piditsfilter; - struct : ConfigurableGroup { - o2::framework::Configurable tpcel{"pidflt_tpc_el", "tpcel{cwv{rg{-3.0,3.0}:rg{-2.0,2.0},rg{-3.0,5.0}}}", "nsigmas to the tpc electron dE/dx line, below/above"}; - o2::framework::Configurable tpcmu{"pidflt_tpc_mu", "tpcmu{cwv{rg{-3.0,3.0}:rg{-2.0,2.0},rg{-3.0,5.0}}}", "nsigmas to the tpc muon dE/dx line, below/above"}; - o2::framework::Configurable tpcpi{"pidflt_tpc_pi", "tpcpi{cwv{rg{-3.0,3.0}:rg{-2.0,2.0},rg{-3.0,5.0}}}", "nsigmas to the tpc pion dE/dx line, below/above"}; - o2::framework::Configurable tpcka{"pidflt_tpc_ka", "tpcks{cwv{rg{-3.0,3.0}:rg{-2.0,2.0},rg{-3.0,5.0}}}", "nsigmas to the tpc kaon dE/dx line, below/above"}; - o2::framework::Configurable tpcpr{"pidflt_tpc_pr", "tpcpr{cwv{rg{-3.0,3.0}:rg{-2.0,2.0},rg{-3.0,5.0}}}", "nsigmas to the tpc proton dE/dx line, below/above"}; + o2::framework::Configurable tpcel{"pidflt_tpc_el", "tpcel{cwv{rg{-3.0,3.0}-yes:rg{-2.0,2.0}-no,rg{-3.0,5.0}-no}}", "nsigmas to the tpc electron dE/dx line, below/above"}; + o2::framework::Configurable tpcmu{"pidflt_tpc_mu", "tpcmu{cwv{rg{-3.0,3.0}-yes:rg{-2.0,2.0}-no,rg{-3.0,5.0}-no}}", "nsigmas to the tpc muon dE/dx line, below/above"}; + o2::framework::Configurable tpcpi{"pidflt_tpc_pi", "tpcpi{cwv{rg{-3.0,3.0}-yes:rg{-2.0,2.0}-no,rg{-3.0,5.0}-no}}", "nsigmas to the tpc pion dE/dx line, below/above"}; + o2::framework::Configurable tpcka{"pidflt_tpc_ka", "tpcka{cwv{rg{-3.0,3.0}-yes:rg{-2.0,2.0}-no,rg{-3.0,5.0}-no}}", "nsigmas to the tpc kaon dE/dx line, below/above"}; + o2::framework::Configurable tpcpr{"pidflt_tpc_pr", "tpcpr{cwv{rg{-3.0,3.0}-yes:rg{-2.0,2.0}-no,rg{-3.0,5.0}-no}}", "nsigmas to the tpc proton dE/dx line, below/above"}; } pidtpcfilter; struct : ConfigurableGroup { - o2::framework::Configurable tpcel{"pidflt_tof_el", "tofel{cwv{rg{-3.0,3.0}:rg{-2.0,2.0},rg{-3.0,5.0}}}", "nsigmas to the tof electron line, below/above"}; - o2::framework::Configurable tpcmu{"pidflt_tof_mu", "tofmu{cwv{rg{-3.0,3.0}:rg{-2.0,2.0},rg{-3.0,5.0}}}", "nsigmas to the tof muon line, below/above"}; - o2::framework::Configurable tpcpi{"pidflt_tof_pi", "tofpi{cwv{rg{-3.0,3.0}:rg{-2.0,2.0},rg{-3.0,5.0}}}", "nsigmas to the tof pion line, below/above"}; - o2::framework::Configurable tpcka{"pidflt_tof_ka", "tofks{cwv{rg{-3.0,3.0}:rg{-2.0,2.0},rg{-3.0,5.0}}}", "nsigmas to the tof kaon line, below/above"}; - o2::framework::Configurable tpcpr{"pidflt_tof_pr", "tofpr{cwv{rg{-3.0,3.0}:rg{-2.0,2.0},rg{-3.0,5.0}}}", "nsigmas to the tof proton line, below/above"}; + o2::framework::Configurable tpcel{"pidflt_tof_el", "tofel{cwv{rg{-3.0,3.0}-yes:rg{-2.0,2.0}-no,rg{-3.0,5.0}-no}}", "nsigmas to the tof electron line, below/above"}; + o2::framework::Configurable tpcmu{"pidflt_tof_mu", "tofmu{cwv{rg{-3.0,3.0}-yes:rg{-2.0,2.0}-no,rg{-3.0,5.0}-no}}", "nsigmas to the tof muon line, below/above"}; + o2::framework::Configurable tpcpi{"pidflt_tof_pi", "tofpi{cwv{rg{-3.0,3.0}-yes:rg{-2.0,2.0}-no,rg{-3.0,5.0}-no}}", "nsigmas to the tof pion line, below/above"}; + o2::framework::Configurable tpcka{"pidflt_tof_ka", "tofka{cwv{rg{-3.0,3.0}-yes:rg{-2.0,2.0}-no,rg{-3.0,5.0}-no}}", "nsigmas to the tof kaon line, below/above"}; + o2::framework::Configurable tpcpr{"pidflt_tof_pr", "tofpr{cwv{rg{-3.0,3.0}-yes:rg{-2.0,2.0}-no,rg{-3.0,5.0}-no}}", "nsigmas to the tof proton line, below/above"}; } pidtoffilter; } pidfilter; diff --git a/PWGCF/TwoParticleCorrelations/TableProducer/twoParticleCorrelationsFiltering.cxx b/PWGCF/TwoParticleCorrelations/TableProducer/twoParticleCorrelationsFiltering.cxx index ed09d66df2c..83752c1c3a1 100644 --- a/PWGCF/TwoParticleCorrelations/TableProducer/twoParticleCorrelationsFiltering.cxx +++ b/PWGCF/TwoParticleCorrelations/TableProducer/twoParticleCorrelationsFiltering.cxx @@ -41,6 +41,7 @@ namespace o2::analysis::twopfilter PWGCF::EventSelectionFilterAndAnalysis* fCollisionFilter = nullptr; PWGCF::TrackSelectionFilterAndAnalysis* fTrackFilter = nullptr; +PWGCF::PIDSelectionFilterAndAnalysis* fPIDFilter = nullptr; } // namespace o2::analysis::twopfilter using namespace o2::aod::twopskim; @@ -62,6 +63,9 @@ struct TwoParticleCorrelationsFilter { uint64_t trackmask = 0UL; uint64_t trackmask_opt = 0UL; uint64_t trackmask_forced = 0UL; + uint64_t pidmask = 0UL; + uint64_t pidmask_opt = 0UL; + uint64_t pidmask_forced = 0UL; void init(InitContext const&) { @@ -77,6 +81,9 @@ struct TwoParticleCorrelationsFilter { PWGCF::TrackSelectionConfigurable trksel(trackfilter.ttype, trackfilter.nclstpc, trackfilter.nxrtpc, trackfilter.nclsits, trackfilter.chi2clustpc, trackfilter.chi2clusits, trackfilter.xrofctpc, trackfilter.dcaxy, trackfilter.dcaz, trackfilter.ptrange, trackfilter.etarange); fTrackFilter = new PWGCF::TrackSelectionFilterAndAnalysis(trksel, PWGCF::SelectionFilterAndAnalysis::kAnalysis); + PWGCF::PIDSelectionConfigurable pidsel(pidfilter.pidtpcfilter.tpcel, pidfilter.pidtpcfilter.tpcmu, pidfilter.pidtpcfilter.tpcpi, pidfilter.pidtpcfilter.tpcka, pidfilter.pidtpcfilter.tpcpr, + pidfilter.pidtoffilter.tpcel, pidfilter.pidtoffilter.tpcmu, pidfilter.pidtoffilter.tpcpi, pidfilter.pidtoffilter.tpcka, pidfilter.pidtoffilter.tpcpr); + fPIDFilter = new PWGCF::PIDSelectionFilterAndAnalysis(pidsel, PWGCF::SelectionFilterAndAnalysis::kFilter); nReportedTracks = 0; collisionmask = fCollisionFilter->getMask(); @@ -85,11 +92,19 @@ struct TwoParticleCorrelationsFilter { trackmask = fTrackFilter->getMask(); trackmask_opt = fTrackFilter->getOptMask(); trackmask_forced = fTrackFilter->getForcedMask(); + pidmask = fPIDFilter->getMask(); + pidmask_opt = fPIDFilter->getOptMask(); + pidmask_forced = fPIDFilter->getForcedMask(); LOGF(info, "TwoParticleCorrelationsFilter::init(), collision selection masks 0x%08lx, 0x%08lx, and 0x%08lx ", collisionmask, collisionmask_opt, collisionmask_forced); LOGF(info, "TwoParticleCorrelationsFilter::init(), track selection masks 0x%08lx, 0x%08lx, and 0x%08lx ", trackmask, trackmask_opt, trackmask_forced); + LOGF(info, "TwoParticleCorrelationsFilter::init(), PID selection masks 0x%08lx, 0x%08lx, and 0x%08lx ", pidmask, pidmask_opt, pidmask_forced); if (collisionmask == uint64_t(0) or trackmask == uint64_t(0)) { LOGF(fatal, "TwoParticleCorrelationsFilter::init() null masks, selecting everything!!!"); } + /* TODO: check the cuts signatures against the CCDB contents */ + LOGF(info, "Collision skimming signature: %s", fCollisionFilter->getCutStringSignature().Data()); + LOGF(info, "Track skimming signature: %s", fTrackFilter->getCutStringSignature().Data()); + LOGF(info, "PID skimming signature: %s", fPIDFilter->getCutStringSignature().Data()); } Filter onlyacceptedcolls = ((aod::twopskim::selflags & static_cast(collisionmask_forced)) == static_cast(collisionmask_forced)); diff --git a/PWGCF/TwoParticleCorrelations/TableProducer/twoParticleCorrelationsSkimming.cxx b/PWGCF/TwoParticleCorrelations/TableProducer/twoParticleCorrelationsSkimming.cxx index f2eef9a5966..89c101877f5 100644 --- a/PWGCF/TwoParticleCorrelations/TableProducer/twoParticleCorrelationsSkimming.cxx +++ b/PWGCF/TwoParticleCorrelations/TableProducer/twoParticleCorrelationsSkimming.cxx @@ -14,6 +14,7 @@ #include "Framework/ASoAHelpers.h" #include "Common/DataModel/TrackSelectionTables.h" #include "Common/DataModel/Centrality.h" +#include "Common/DataModel/PIDResponse.h" #include "PWGCF/TwoParticleCorrelations/DataModel/TwoParticleCorrelationsSkimmed.h" #include "PWGCF/TwoParticleCorrelations/Core/SkimmingConfigurableCuts.h" #include "PWGCF/TwoParticleCorrelations/Core/EventSelectionFilterAndAnalysis.h" @@ -32,8 +33,12 @@ namespace o2::analysis::twopskim #define LOGTRACKCOLLISIONS info #define LOGTRACKTRACKS info +using pidTables = soa::Join; + PWGCF::TrackSelectionFilterAndAnalysis* fTrackFilter = nullptr; PWGCF::EventSelectionFilterAndAnalysis* fEventFilter = nullptr; +PWGCF::PIDSelectionFilterAndAnalysis* fPIDFilter = nullptr; } // namespace o2::analysis::twopskim using namespace twopskim; @@ -108,8 +113,16 @@ struct TwoParticleCorrelationsSkimming { PWGCF::TrackSelectionConfigurable trksel(trackfilter.ttype, trackfilter.nclstpc, trackfilter.nxrtpc, trackfilter.nclsits, trackfilter.chi2clustpc, trackfilter.chi2clusits, trackfilter.xrofctpc, trackfilter.dcaxy, trackfilter.dcaz, trackfilter.ptrange, trackfilter.etarange); fTrackFilter = new PWGCF::TrackSelectionFilterAndAnalysis(trksel, PWGCF::SelectionFilterAndAnalysis::kFilter); + PWGCF::PIDSelectionConfigurable pidsel(pidfilter.pidtpcfilter.tpcel, pidfilter.pidtpcfilter.tpcmu, pidfilter.pidtpcfilter.tpcpi, pidfilter.pidtpcfilter.tpcka, pidfilter.pidtpcfilter.tpcpr, + pidfilter.pidtoffilter.tpcel, pidfilter.pidtoffilter.tpcmu, pidfilter.pidtoffilter.tpcpi, pidfilter.pidtoffilter.tpcka, pidfilter.pidtoffilter.tpcpr); + fPIDFilter = new PWGCF::PIDSelectionFilterAndAnalysis(pidsel, PWGCF::SelectionFilterAndAnalysis::kFilter); nReportedTracks = 0; + /* TODO: upload the cuts signatures to the CCDB */ + LOGF(info, "Collision skimming signature: %s", fEventFilter->getCutStringSignature().Data()); + LOGF(info, "Track skimming signature: %s", fTrackFilter->getCutStringSignature().Data()); + LOGF(info, "PID skimming signature: %s", fPIDFilter->getCutStringSignature().Data()); + historeg.add("EventCuts", "EventCuts", {HistType::kTH1F, {{aod::run2::kTRDHEE + 1, 0, aod::run2::kTRDHEE + 1}}}); setEventCutsLabels(historeg.get(HIST("EventCuts"))); } @@ -159,7 +172,8 @@ struct TwoParticleCorrelationsSkimming { } } - void processRun2(soa::Join::iterator const& collision, soa::Join const&, soa::Join const& tracks) + void processRun2(soa::Join::iterator const& collision, + soa::Join const&, soa::Join const& tracks) { /* for the time being this will apply only to Run 1+2 converted data */ LOGF(LOGTRACKCOLLISIONS, "Got a new collision with zvtx %.2f and V0M %.2f, CL0 %.2f, CL1 %.2f", collision.posZ(), collision.centRun2V0M(), collision.centRun2CL0(), collision.centRun2CL1()); @@ -172,13 +186,14 @@ struct TwoParticleCorrelationsSkimming { int nFilteredTracks = 0; for (auto const& track : tracks) { auto trkmask = fTrackFilter->Filter(track); + auto pidmask = fPIDFilter->Filter(track); if (trkmask != 0UL) { - skimmedtrack(skimmedcollision.lastIndex(), trkmask, track.pt() * track.sign(), track.eta(), track.phi()); + skimmedtrack(skimmedcollision.lastIndex(), trkmask, pidmask, track.pt() * track.sign(), track.eta(), track.phi()); nFilteredTracks++; } if (trkmask != 0UL and nReportedTracks < 1000) { - LOGF(LOGTRACKTRACKS, " Got track mask 0x%08lx, TPC clusters %d, Chi2 per TPC cluster %f, pT %f, eta %f, track type %d", - trkmask, track.tpcNClsFound(), track.tpcChi2NCl(), track.pt(), track.eta(), track.trackType()); + LOGF(LOGTRACKTRACKS, " Got track mask 0x%08lx and PID mask 0x%08lx, TPC clusters %d, Chi2 per TPC cluster %f, pT %f, eta %f, track type %d", + trkmask, pidmask, track.tpcNClsFound(), track.tpcChi2NCl(), track.pt(), track.eta(), track.trackType()); nReportedTracks++; } } From 64683c930fa4104d5f716123259cf10d59c4c9a7 Mon Sep 17 00:00:00 2001 From: Victor Date: Wed, 28 Sep 2022 19:01:37 +0200 Subject: [PATCH 10/20] Renaming the data model The skimmed collision table now - contains the run number and timestamp The skimmed tracks table now - does not have the signed pT - the sign of the charge will be extracted from the track mask once implemented Incorporated the MC labels tables for skimmed collisions and tracks --- .../TwoParticleCorrelationsFiltered.h | 16 +-- .../TwoParticleCorrelationsSkimmed.h | 104 +++++++++--------- .../twoParticleCorrelationsFiltering.cxx | 12 +- .../twoParticleCorrelationsSkimming.cxx | 38 ++++--- 4 files changed, 89 insertions(+), 81 deletions(-) diff --git a/PWGCF/TwoParticleCorrelations/DataModel/TwoParticleCorrelationsFiltered.h b/PWGCF/TwoParticleCorrelations/DataModel/TwoParticleCorrelationsFiltered.h index af5cd5a462a..9dec8d949a2 100644 --- a/PWGCF/TwoParticleCorrelations/DataModel/TwoParticleCorrelationsFiltered.h +++ b/PWGCF/TwoParticleCorrelations/DataModel/TwoParticleCorrelationsFiltered.h @@ -26,13 +26,11 @@ DECLARE_SOA_COLUMN(TwoPCollisionCentMult, centmult, float); //! The centrality/m } // namespace twopfilter DECLARE_SOA_TABLE(TwoPAcceptedCollisions, "AOD", "TWOPACCCOLL", //! Accepted reconstructed collisions/events filtered table o2::soa::Index<>, - collision::BCId, collision::PosZ, twopfilter::TwoPCollisionCentMult); using TowPAcceptedCollision = TwoPAcceptedCollisions::iterator; DECLARE_SOA_TABLE(TwoPAcceptedGenCollisions, "AOD", "TWOPACCGENCOLL", //! Accepted generated collisions/events filtered table o2::soa::Index<>, - collision::BCId, mccollision::PosZ, twopfilter::TwoPCollisionCentMult); using TwoPAcceptedGenCollision = TwoPAcceptedGenCollisions::iterator; @@ -45,17 +43,15 @@ DECLARE_SOA_COLUMN(TwoPTrackacceptedAs, twoptrackacceptedas, uint8_t); //! Track DECLARE_SOA_TABLE(TwoPFilteredTracks, "AOD", "FILTEREDTRKS", //! The reconstructed tracks filtered table twopfilter::TwoPAcceptedCollisionId, twopfilter::TwoPTrackacceptedAs, - twopskim::sPt, - twopskim::Eta, - twopskim::Phi, - twopskim::Sign); + cfskim::Pt, + cfskim::Eta, + cfskim::Phi); DECLARE_SOA_TABLE(TwoPFilteredParticles, "AOD", "FILTEREDGENTRKS", //! The generated particles filtered table twopfilter::TwoPAcceptedGenCollisionId, twopfilter::TwoPTrackacceptedAs, - twopskim::sPt, - twopskim::Eta, - twopskim::Phi, - twopskim::Sign); + cfskim::Pt, + cfskim::Eta, + cfskim::Phi); } // namespace aod } // namespace o2 diff --git a/PWGCF/TwoParticleCorrelations/DataModel/TwoParticleCorrelationsSkimmed.h b/PWGCF/TwoParticleCorrelations/DataModel/TwoParticleCorrelationsSkimmed.h index 2b5c8edae82..669da02c148 100644 --- a/PWGCF/TwoParticleCorrelations/DataModel/TwoParticleCorrelationsSkimmed.h +++ b/PWGCF/TwoParticleCorrelations/DataModel/TwoParticleCorrelationsSkimmed.h @@ -21,8 +21,8 @@ #include "Framework/runDataProcessing.h" /* TODO: this will go to its proper header at some point */ -#ifndef O2_ANALYSIS_TWOPSKIMMED_H -#define O2_ANALYSIS_TWOPSKIMMED_H +#ifndef O2_ANALYSIS_cfskimMED_H +#define O2_ANALYSIS_cfskimMED_H #include "Framework/ASoA.h" #include "Framework/AnalysisDataModel.h" @@ -32,60 +32,64 @@ namespace o2 namespace aod { /* we have to change from int to bool when bool columns work properly */ -namespace twopskim +namespace cfskim { -DECLARE_SOA_COLUMN(TwoPSkimmedCollisionCentMult, centmult, std::vector); //! The centrality/multiplicity pecentile -DECLARE_SOA_COLUMN(TwoPSkimmedCollisionFlags, selflags, uint64_t); //! The skimming flags for collision selection -} // namespace twopskim -DECLARE_SOA_TABLE(TwoPSkimmedCollisions, "AOD", "TWOPSKMDCOLL", //! Accepted reconstructed collisions/events filtered table +DECLARE_SOA_COLUMN(CFCollisionCentMult, centmult, std::vector); //! The centrality/multiplicity pecentile +DECLARE_SOA_COLUMN(CFCollisionFlags, selflags, uint64_t); //! The skimming flags for collision selection +} // namespace cfskim +DECLARE_SOA_TABLE(CFCollisions, "AOD", "CFCOLLISION", //! Accepted reconstructed collisions/events filtered table o2::soa::Index<>, collision::PosZ, - twopskim::TwoPSkimmedCollisionFlags, - twopskim::TwoPSkimmedCollisionCentMult); -using TwoPSkimmedCollision = TwoPSkimmedCollisions::iterator; -DECLARE_SOA_TABLE(TwoPSkimmedGenCollisions, "AOD", "TWOPSKMDGENCOLL", //! Accepted generated collisions/events filtered table + bc::RunNumber, + timestamp::Timestamp, + cfskim::CFCollisionFlags, + cfskim::CFCollisionCentMult); +using CFCollision = CFCollisions::iterator; +DECLARE_SOA_TABLE(CFMCCollisions, "AOD", "CFMCCOLLISION", //! Accepted generated collisions/events filtered table o2::soa::Index<>, mccollision::PosZ, - twopskim::TwoPSkimmedCollisionFlags, - twopskim::TwoPSkimmedCollisionCentMult); -using TwoPSkimmedGenCollision = TwoPSkimmedGenCollisions::iterator; -namespace twopskim + cfskim::CFCollisionFlags, + cfskim::CFCollisionCentMult); //! To check if to have this columng does make sense for generated collisions +using CFMCCollision = CFMCCollisions::iterator; +namespace cfskim { -DECLARE_SOA_INDEX_COLUMN(TwoPSkimmedCollision, event); //! Reconstructed collision/event -DECLARE_SOA_INDEX_COLUMN(TwoPSkimmedGenCollision, mcevent); //! Generated collision/event -DECLARE_SOA_COLUMN(TwoPSkimmedTrackFlags, trackflags, uint64_t); //! The skimming flags for track selection -DECLARE_SOA_COLUMN(TwoPSkimmedPidFlags, pidflags, uint64_t); //! The PID skimming flags for track selection -DECLARE_SOA_COLUMN(sPt, spt, float); //! The track charge signed transverse momentum -DECLARE_SOA_DYNAMIC_COLUMN(Pt, pt, //! The track transverse momentum - [](float signedpt) -> float { - return std::abs(signedpt); - }); -DECLARE_SOA_COLUMN(Eta, eta, float); //! The track pseudorapidity -DECLARE_SOA_COLUMN(Phi, phi, float); //! The track azimuthal angle -DECLARE_SOA_COLUMN(Charge, charge, int8_t); //! Charge: in units of electric charge -DECLARE_SOA_DYNAMIC_COLUMN(Sign, sign, //! The track transverse momentum - [](float signedpt) -> short { - return (signedpt >= 0) ? 1 : -1; - }); -} // namespace twopskim -DECLARE_SOA_TABLE(TwoPSkimmedTracks, "AOD", "TWOPSKMDTRKS", //! The reconstructed tracks filtered table - twopskim::TwoPSkimmedCollisionId, - twopskim::TwoPSkimmedTrackFlags, - twopskim::TwoPSkimmedPidFlags, - twopskim::sPt, - twopskim::Eta, - twopskim::Phi, - twopskim::Pt, - twopskim::Sign); -DECLARE_SOA_TABLE(TwoPSkimmedParticles, "AOD", "TWOPSKMDPARTS", //! The generated particles filtered table - twopskim::TwoPSkimmedGenCollisionId, - twopskim::TwoPSkimmedTrackFlags, - twopskim::sPt, - twopskim::Eta, - twopskim::Phi, - twopskim::Pt, - twopskim::Sign); +DECLARE_SOA_INDEX_COLUMN(CFCollision, cfcollision); //! Reconstructed collision/event +DECLARE_SOA_INDEX_COLUMN(CFMCCollision, cfmccollision); //! Generated collision/event +DECLARE_SOA_COLUMN(CFTrackFlags, trackflags, uint64_t); //! The skimming flags for track selection, B0 track/particle positive charge, B1 track/particle negative charge +DECLARE_SOA_COLUMN(CFPidFlags, pidflags, uint64_t); //! The PID skimming flags for track selection +DECLARE_SOA_COLUMN(Pt, pt, float); //! The track transverse momentum +DECLARE_SOA_COLUMN(Eta, eta, float); //! The track pseudorapidity +DECLARE_SOA_COLUMN(Phi, phi, float); //! The track azimuthal angle +} // namespace cfskim +DECLARE_SOA_TABLE(CFTracks, "AOD", "CFTRACK", //! The reconstructed tracks filtered table + cfskim::CFCollisionId, + cfskim::CFTrackFlags, + cfskim::Pt, + cfskim::Eta, + cfskim::Phi); +using CFTrack = CFTracks::iterator; +DECLARE_SOA_TABLE(CFTrackPIDs, "AOD", "CFTRACKPID", //! The reconstructed tracks PID filtered table + cfskim::CFPidFlags); +using CFTrackPID = CFTrackPIDs::iterator; +DECLARE_SOA_TABLE(CFMCParticles, "AOD", "CFMCPARICLE", //! The generated particles filtered table + o2::soa::Index<>, + cfskim::CFMCCollisionId, + cfskim::CFTrackFlags, + cfskim::Pt, + cfskim::Eta, + cfskim::Phi); +using CFMCParticle = CFMCParticles::iterator; +namespace cfskim +{ +DECLARE_SOA_INDEX_COLUMN(CFMCParticle, mcparticle); +} +DECLARE_SOA_TABLE(CFMCCollisionLbls, "AOD", "CFMCCOLLISONLBL", + cfskim::CFMCCollisionId, + mccollisionlabel::McMask); +DECLARE_SOA_TABLE(CFMCTrakLabels, "AOD", "CFMCTRACKLABEL", + cfskim::CFMCParticleId, + mctracklabel::McMask); } // namespace aod } // namespace o2 -#endif // O2_ANALYSIS_TWOPSKIMMED_H +#endif // O2_ANALYSIS_cfskimMED_H diff --git a/PWGCF/TwoParticleCorrelations/TableProducer/twoParticleCorrelationsFiltering.cxx b/PWGCF/TwoParticleCorrelations/TableProducer/twoParticleCorrelationsFiltering.cxx index 83752c1c3a1..2d9898f921b 100644 --- a/PWGCF/TwoParticleCorrelations/TableProducer/twoParticleCorrelationsFiltering.cxx +++ b/PWGCF/TwoParticleCorrelations/TableProducer/twoParticleCorrelationsFiltering.cxx @@ -44,7 +44,7 @@ PWGCF::TrackSelectionFilterAndAnalysis* fTrackFilter = nullptr; PWGCF::PIDSelectionFilterAndAnalysis* fPIDFilter = nullptr; } // namespace o2::analysis::twopfilter -using namespace o2::aod::twopskim; +using namespace o2::aod::cfskim; struct TwoParticleCorrelationsFilter { Produces acceptedcollisions; @@ -107,21 +107,21 @@ struct TwoParticleCorrelationsFilter { LOGF(info, "PID skimming signature: %s", fPIDFilter->getCutStringSignature().Data()); } - Filter onlyacceptedcolls = ((aod::twopskim::selflags & static_cast(collisionmask_forced)) == static_cast(collisionmask_forced)); - Filter onlyacceptedtracks = ((aod::twopskim::trackflags & static_cast(trackmask_forced)) == static_cast(trackmask_forced)); + Filter onlyacceptedcolls = ((aod::cfskim::selflags & static_cast(collisionmask_forced)) == static_cast(collisionmask_forced)); + Filter onlyacceptedtracks = ((aod::cfskim::trackflags & static_cast(trackmask_forced)) == static_cast(trackmask_forced)); - void processRun2(soa::Filtered::iterator const& collision, soa::Filtered const& tracks) + void processRun2(soa::Filtered::iterator const& collision, soa::Filtered const& tracks) { LOGF(TWOPFILTERLOGCOLLISIONS, "Received collision with mask 0x%08lx and %ld tracks", collision.selflags(), tracks.size()); /* for some reason we cannot apply this condition in the filter, it does not work */ if ((collision.selflags() & collisionmask_opt) != 0UL) { - acceptedcollisions(0, 0, 0); + acceptedcollisions(collision.posZ(), collision.centmult()[0]); int nAcceptedTracks = 0; for (const auto& track : tracks) { /* for some reason we cannot apply this condition in the filter, it does not work */ if ((track.trackflags() & trackmask_opt) != 0UL) { - accepteddtracks(acceptedcollisions.lastIndex(), 0, track.spt(), track.eta(), track.phi()); + accepteddtracks(acceptedcollisions.lastIndex(), 0, track.pt(), track.eta(), track.phi()); nAcceptedTracks++; } } diff --git a/PWGCF/TwoParticleCorrelations/TableProducer/twoParticleCorrelationsSkimming.cxx b/PWGCF/TwoParticleCorrelations/TableProducer/twoParticleCorrelationsSkimming.cxx index 89c101877f5..c6cd942b694 100644 --- a/PWGCF/TwoParticleCorrelations/TableProducer/twoParticleCorrelationsSkimming.cxx +++ b/PWGCF/TwoParticleCorrelations/TableProducer/twoParticleCorrelationsSkimming.cxx @@ -28,7 +28,7 @@ using namespace o2::soa; using namespace o2::framework::expressions; using namespace o2::analysis; -namespace o2::analysis::twopskim +namespace o2::analysis::cfskim { #define LOGTRACKCOLLISIONS info #define LOGTRACKTRACKS info @@ -39,9 +39,9 @@ using pidTables = soa::Join h) { @@ -89,10 +89,11 @@ void reportEventCuts(std::shared_ptr h, uint32_t eventcuts) struct TwoParticleCorrelationsSkimming { /* skimmed data tables */ - Produces skimmedcollision; - Produces skimmedtrack; - Produces skimmedgencollision; - Produces skimmedparticles; + Produces skimmedcollision; + Produces skimmedtrack; + Produces skimmtrackpid; + Produces skimmedgencollision; + Produces skimmedparticles; #include "skimmingconf.h" @@ -101,7 +102,7 @@ struct TwoParticleCorrelationsSkimming { void init(InitContext const&) { - using namespace twopskim; + using namespace cfskim; LOGF(info, "DptDptSkimTask::init()"); @@ -173,28 +174,35 @@ struct TwoParticleCorrelationsSkimming { } void processRun2(soa::Join::iterator const& collision, - soa::Join const&, soa::Join const& tracks) + soa::Join const&, soa::Join const& tracks) { /* for the time being this will apply only to Run 1+2 converted data */ LOGF(LOGTRACKCOLLISIONS, "Got a new collision with zvtx %.2f and V0M %.2f, CL0 %.2f, CL1 %.2f", collision.posZ(), collision.centRun2V0M(), collision.centRun2CL0(), collision.centRun2CL1()); - auto colmask = filterRun2Collision(collision, collision.bc_as>()); + auto bc = collision.bc_as>(); + auto colmask = filterRun2Collision(collision, bc); LOGF(LOGTRACKCOLLISIONS, "Got mask 0x%lx", colmask); if (colmask != 0UL) { - skimmedcollision(collision.posZ(), colmask, fEventFilter->GetMultiplicities()); + skimmedcollision(collision.posZ(), bc.runNumber(), bc.timestamp(), colmask, fEventFilter->GetMultiplicities()); int nFilteredTracks = 0; + int nCollisionReportedTracks = 0; for (auto const& track : tracks) { auto trkmask = fTrackFilter->Filter(track); auto pidmask = fPIDFilter->Filter(track); if (trkmask != 0UL) { - skimmedtrack(skimmedcollision.lastIndex(), trkmask, pidmask, track.pt() * track.sign(), track.eta(), track.phi()); + skimmedtrack(skimmedcollision.lastIndex(), trkmask, track.pt(), track.eta(), track.phi()); + skimmtrackpid(pidmask); nFilteredTracks++; } if (trkmask != 0UL and nReportedTracks < 1000) { - LOGF(LOGTRACKTRACKS, " Got track mask 0x%08lx and PID mask 0x%08lx, TPC clusters %d, Chi2 per TPC cluster %f, pT %f, eta %f, track type %d", - trkmask, pidmask, track.tpcNClsFound(), track.tpcChi2NCl(), track.pt(), track.eta(), track.trackType()); - nReportedTracks++; + if (nCollisionReportedTracks < 20) { + LOGF(LOGTRACKTRACKS, " Got track mask 0x%08lx and PID mask 0x%08lx", trkmask, pidmask); + LOGF(LOGTRACKTRACKS, " TPC clusters %d, Chi2 per TPC cluster %f, pT %f, eta %f, track type %d", + track.tpcNClsFound(), track.tpcChi2NCl(), track.pt(), track.eta(), track.trackType()); + nCollisionReportedTracks++; + nReportedTracks++; + } } } LOGF(LOGTRACKCOLLISIONS, ">> Filtered %d tracks", nFilteredTracks); From c24053e42b84604e5f356403cba02de17e15ba32 Mon Sep 17 00:00:00 2001 From: Victor Date: Fri, 30 Sep 2022 19:29:38 +0200 Subject: [PATCH 11/20] New configurable format for easier changes tracking from hyperloop Also - incorporated Byesian PID to the PID mask --- .../Core/EventSelectionFilterAndAnalysis.cxx | 45 ++++++++++ .../Core/EventSelectionFilterAndAnalysis.h | 4 + .../Core/PIDSelectionFilterAndAnalysis.cxx | 89 ++++++++++++++++++- .../Core/PIDSelectionFilterAndAnalysis.h | 19 +++- .../Core/TrackSelectionFilterAndAnalysis.cxx | 80 +++++++++++++++++ .../Core/TrackSelectionFilterAndAnalysis.h | 11 +++ .../TableProducer/skimmingconf.h | 59 ++++++------ .../twoParticleCorrelationsFiltering.cxx | 7 +- .../twoParticleCorrelationsSkimming.cxx | 12 +-- 9 files changed, 284 insertions(+), 42 deletions(-) diff --git a/PWGCF/TwoParticleCorrelations/Core/EventSelectionFilterAndAnalysis.cxx b/PWGCF/TwoParticleCorrelations/Core/EventSelectionFilterAndAnalysis.cxx index 1e4dfdfed92..bc26b5840f2 100644 --- a/PWGCF/TwoParticleCorrelations/Core/EventSelectionFilterAndAnalysis.cxx +++ b/PWGCF/TwoParticleCorrelations/Core/EventSelectionFilterAndAnalysis.cxx @@ -19,6 +19,51 @@ using namespace o2; using namespace o2::analysis::PWGCF; using namespace boost; +EventSelectionConfigurable::EventSelectionConfigurable(std::vector multsel, + std::vector trigsel, + std::vector zvtxsel, + std::vector pileuprej) + : mMultSel(""), + mTriggerSel(""), + mZVertexSel(""), + mPileUpRejection("") +{ + auto storeCutString = [](auto& selvector, std::string selname) { + if (selvector.size() != 0) { + if (selvector.size() == 1) { + if (selvector[0].size() != 0) { + return TString::Format("%s{%s}", selname.c_str(), selvector[0].c_str()); + } else { + return TString(""); + } + } else { + TString scut = selname + "{cwv{"; + bool def = true; + bool firstvar = true; + for (auto cut : selvector) { + if (def) { + scut += cut + ':'; + def = false; + } else { + if (not firstvar) { + scut += ','; + } + scut += cut; + firstvar = false; + } + } + scut += "}}"; + return scut; + } + } + return TString(""); + }; + mMultSel = storeCutString(multsel, "centmult"); + mTriggerSel = storeCutString(trigsel, "trigger"); + mZVertexSel = storeCutString(zvtxsel, "zvtx"); + mPileUpRejection = storeCutString(pileuprej, "pileup"); +} + ClassImp(EventSelectionFilterAndAnalysis); const int nNoOfMultiplicityEstimators = 3; diff --git a/PWGCF/TwoParticleCorrelations/Core/EventSelectionFilterAndAnalysis.h b/PWGCF/TwoParticleCorrelations/Core/EventSelectionFilterAndAnalysis.h index 44ba7d58877..8159eabcb44 100644 --- a/PWGCF/TwoParticleCorrelations/Core/EventSelectionFilterAndAnalysis.h +++ b/PWGCF/TwoParticleCorrelations/Core/EventSelectionFilterAndAnalysis.h @@ -42,6 +42,10 @@ class EventSelectionConfigurable : mMultSel{multsel}, mTriggerSel{trigsel}, mZVertexSel{zvtxsel}, mPileUpRejection{pileuprej} { } + EventSelectionConfigurable(std::vector multsel, + std::vector trigsel, + std::vector zvtxsel, + std::vector pileuprej); private: std::string mMultSel = ""; //! the multiplicity selection cuts diff --git a/PWGCF/TwoParticleCorrelations/Core/PIDSelectionFilterAndAnalysis.cxx b/PWGCF/TwoParticleCorrelations/Core/PIDSelectionFilterAndAnalysis.cxx index 2f3a3519a28..985ab3bc2c8 100644 --- a/PWGCF/TwoParticleCorrelations/Core/PIDSelectionFilterAndAnalysis.cxx +++ b/PWGCF/TwoParticleCorrelations/Core/PIDSelectionFilterAndAnalysis.cxx @@ -25,6 +25,72 @@ using namespace o2::framework::expressions; using namespace o2::analysis::PWGCF; using namespace boost; +PIDSelectionConfigurable::PIDSelectionConfigurable(std::vector pidtpcel, std::vector pidtpcmu, std::vector pidtpcpi, std::vector pidtpcka, std::vector pidtpcpr, + std::vector pidtofel, std::vector pidtofmu, std::vector pidtofpi, std::vector pidtofka, std::vector pidtofpr, + std::vector pidbayel, std::vector pidbaymu, std::vector pidbaypi, std::vector pidbayka, std::vector pidbaypr) + : mPidTpcSel_el{}, + mPidTpcSel_mu{}, + mPidTpcSel_pi{}, + mPidTpcSel_ka{}, + mPidTpcSel_pr{}, + mPidTofSel_el{}, + mPidTofSel_mu{}, + mPidTofSel_pi{}, + mPidTofSel_ka{}, + mPidTofSel_pr{}, + mPidBaySel_el{}, + mPidBaySel_mu{}, + mPidBaySel_pi{}, + mPidBaySel_ka{}, + mPidBaySel_pr{} +{ + auto storeCutString = [](auto& selvector, std::string selname) { + if (selvector.size() != 0) { + if (selvector.size() == 1) { + if (selvector[0].size() != 0) { + return TString::Format("%s{%s}", selname.c_str(), selvector[0].c_str()); + } else { + return TString(""); + } + } else { + TString scut = selname + "{cwv{"; + bool def = true; + bool firstvar = true; + for (auto cut : selvector) { + if (def) { + scut += cut + ':'; + def = false; + } else { + if (not firstvar) { + scut += ','; + } + scut += cut; + firstvar = false; + } + } + scut += "}}"; + return scut; + } + } + return TString(""); + }; + mPidTpcSel_el = storeCutString(pidtpcel, "tpcel"); + mPidTpcSel_mu = storeCutString(pidtpcmu, "tpcmu"); + mPidTpcSel_pi = storeCutString(pidtpcpi, "tpcpi"); + mPidTpcSel_ka = storeCutString(pidtpcka, "tpcka"); + mPidTpcSel_pr = storeCutString(pidtpcpr, "tpcpr"); + mPidTofSel_el = storeCutString(pidtofel, "tofel"); + mPidTofSel_mu = storeCutString(pidtofmu, "tofmu"); + mPidTofSel_pi = storeCutString(pidtofpi, "tofpi"); + mPidTofSel_ka = storeCutString(pidtofka, "tofka"); + mPidTofSel_pr = storeCutString(pidtofpr, "tofpr"); + mPidBaySel_el = storeCutString(pidbayel, "bayel"); + mPidBaySel_mu = storeCutString(pidbaymu, "baymu"); + mPidBaySel_pi = storeCutString(pidbaypi, "baypi"); + mPidBaySel_ka = storeCutString(pidbayka, "bayka"); + mPidBaySel_pr = storeCutString(pidbaypr, "baypr"); +} + ClassImp(PIDSelectionFilterAndAnalysis); /// \brief species supported @@ -37,7 +103,8 @@ PIDSelectionFilterAndAnalysis::PIDSelectionFilterAndAnalysis() mRequireTOF(false), mEllipticTPCTOF(false), mCloseNsigmasTPC(kNoOfSpecies, nullptr), - mCloseNsigmasTOF(kNoOfSpecies, nullptr) + mCloseNsigmasTOF(kNoOfSpecies, nullptr), + mBayesProbability(kNoOfSpecies, nullptr) { } @@ -48,7 +115,8 @@ PIDSelectionFilterAndAnalysis::PIDSelectionFilterAndAnalysis(const TString& cuts mRequireTOF(false), mEllipticTPCTOF(false), mCloseNsigmasTPC(kNoOfSpecies, nullptr), - mCloseNsigmasTOF(kNoOfSpecies, nullptr) + mCloseNsigmasTOF(kNoOfSpecies, nullptr), + mBayesProbability(kNoOfSpecies, nullptr) { ConstructCutFromString(cutstr); } @@ -60,7 +128,8 @@ PIDSelectionFilterAndAnalysis::PIDSelectionFilterAndAnalysis(const PIDSelectionC mRequireTOF(false), mEllipticTPCTOF(false), mCloseNsigmasTPC(kNoOfSpecies, nullptr), - mCloseNsigmasTOF(kNoOfSpecies, nullptr) + mCloseNsigmasTOF(kNoOfSpecies, nullptr), + mBayesProbability(kNoOfSpecies, nullptr) { TString cutString = "pidsel{"; bool first = true; @@ -89,6 +158,13 @@ PIDSelectionFilterAndAnalysis::PIDSelectionFilterAndAnalysis(const PIDSelectionC appendCut(pidsel.mPidTofSel_pi); appendCut(pidsel.mPidTofSel_ka); appendCut(pidsel.mPidTofSel_pr); + cutString += "},baysel{"; + first = true; + appendCut(pidsel.mPidBaySel_el); + appendCut(pidsel.mPidBaySel_mu); + appendCut(pidsel.mPidBaySel_pi); + appendCut(pidsel.mPidBaySel_ka); + appendCut(pidsel.mPidBaySel_pr); cutString += "}}"; ConstructCutFromString(cutString); @@ -111,6 +187,9 @@ PIDSelectionFilterAndAnalysis::~PIDSelectionFilterAndAnalysis() for (auto brick : mCloseNsigmasTOF) { delete brick; } + for (auto brick : mBayesProbability) { + delete brick; + } } /// \brief Calculates the length of the mask needed to store the selection cuts @@ -126,6 +205,7 @@ int PIDSelectionFilterAndAnalysis::CalculateMaskLength() }; addLength(mCloseNsigmasTPC); addLength(mCloseNsigmasTOF); + addLength(mBayesProbability); return length; } @@ -211,6 +291,8 @@ void PIDSelectionFilterAndAnalysis::ConstructCutFromString(const TString& cutstr handleDetectorLevel("tpc", mCloseNsigmasTPC, m[2].str()); } else if (m[1].str() == "tofsel") { handleDetectorLevel("tof", mCloseNsigmasTOF, m[2].str()); + } else if (m[1].str() == "baysel") { + handleDetectorLevel("bay", mBayesProbability, m[2].str()); } else { Fatal("PIDSelectionFilterAndAnalysis::::ConstructCutFromString", "Wrong RE detector %s, use tpcsel, or tofsel only", m[1].str().c_str()); } @@ -253,6 +335,7 @@ void PIDSelectionFilterAndAnalysis::StoreArmedMask() }; armedList(mCloseNsigmasTPC); armedList(mCloseNsigmasTOF); + armedList(mBayesProbability); LOGF(info, "PIDSelectionFilterAndAnalysis::StoreArmedMask(), masks 0x%08lx, 0x%08lx, 0x%08lx", armedMask, optMask, forcedMask); mArmedMask = armedMask; diff --git a/PWGCF/TwoParticleCorrelations/Core/PIDSelectionFilterAndAnalysis.h b/PWGCF/TwoParticleCorrelations/Core/PIDSelectionFilterAndAnalysis.h index 3b0fbf725ee..4ac7a29654f 100644 --- a/PWGCF/TwoParticleCorrelations/Core/PIDSelectionFilterAndAnalysis.h +++ b/PWGCF/TwoParticleCorrelations/Core/PIDSelectionFilterAndAnalysis.h @@ -36,10 +36,14 @@ class PIDSelectionConfigurable public: PIDSelectionConfigurable(std::string pidtpcel = "", std::string pidtpcmu = "", std::string pidtpcpi = "", std::string pidtpcka = "", std::string pidtpcpr = "", - std::string pidtofel = "", std::string pidtofmu = "", std::string pidtofpi = "", std::string pidtofka = "", std::string pidtofpr = "") - : mPidTpcSel_el{pidtpcel}, mPidTpcSel_mu{pidtpcmu}, mPidTpcSel_pi{pidtpcpi}, mPidTpcSel_ka{pidtpcka}, mPidTpcSel_pr{pidtpcpr}, mPidTofSel_el{pidtofel}, mPidTofSel_mu{pidtofmu}, mPidTofSel_pi{pidtofpi}, mPidTofSel_ka{pidtofka}, mPidTofSel_pr{pidtofpr} + std::string pidtofel = "", std::string pidtofmu = "", std::string pidtofpi = "", std::string pidtofka = "", std::string pidtofpr = "", + std::string pidbayel = "", std::string pidbaymu = "", std::string pidbaypi = "", std::string pidbayka = "", std::string pidbaypr = "") + : mPidTpcSel_el{pidtpcel}, mPidTpcSel_mu{pidtpcmu}, mPidTpcSel_pi{pidtpcpi}, mPidTpcSel_ka{pidtpcka}, mPidTpcSel_pr{pidtpcpr}, mPidTofSel_el{pidtofel}, mPidTofSel_mu{pidtofmu}, mPidTofSel_pi{pidtofpi}, mPidTofSel_ka{pidtofka}, mPidTofSel_pr{pidtofpr}, mPidBaySel_el{pidbayel}, mPidBaySel_mu{pidbaymu}, mPidBaySel_pi{pidbaypi}, mPidBaySel_ka{pidbayka}, mPidBaySel_pr{pidbaypr} { } + PIDSelectionConfigurable(std::vector pidtpcel, std::vector pidtpcmu, std::vector pidtpcpi, std::vector pidtpcka, std::vector pidtpcpr, + std::vector pidtofel, std::vector pidtofmu, std::vector pidtofpi, std::vector pidtofka, std::vector pidtofpr, + std::vector pidbayel, std::vector pidbaymu, std::vector pidbaypi, std::vector pidbayka, std::vector pidbaypr); private: std::string mPidTpcSel_el = ""; @@ -52,6 +56,11 @@ class PIDSelectionConfigurable std::string mPidTofSel_pi = ""; std::string mPidTofSel_ka = ""; std::string mPidTofSel_pr = ""; + std::string mPidBaySel_el = ""; + std::string mPidBaySel_mu = ""; + std::string mPidBaySel_pi = ""; + std::string mPidBaySel_ka = ""; + std::string mPidBaySel_pr = ""; private: ClassDefNV(PIDSelectionConfigurable, 1); @@ -109,6 +118,7 @@ class PIDSelectionFilterAndAnalysis : public SelectionFilterAndAnalysis PIDSpecies mSpeciesOfInterest = kWrongSpecies; std::vector*> mCloseNsigmasTPC; std::vector*> mCloseNsigmasTOF; + std::vector*> mBayesProbability; ClassDef(PIDSelectionFilterAndAnalysis, 1); }; @@ -142,6 +152,11 @@ inline uint64_t PIDSelectionFilterAndAnalysis::Filter(TrackToFilter const& track filterBrickValue(mCloseNsigmasTOF[kPion], track.tofNSigmaPi()); filterBrickValue(mCloseNsigmasTOF[kKaon], track.tofNSigmaKa()); filterBrickValue(mCloseNsigmasTOF[kProton], track.tofNSigmaPr()); + filterBrickValue(mBayesProbability[kElectron], track.bayesEl()); + filterBrickValue(mBayesProbability[kMuon], track.bayesMu()); + filterBrickValue(mBayesProbability[kPion], track.bayesPi()); + filterBrickValue(mBayesProbability[kKaon], track.bayesKa()); + filterBrickValue(mBayesProbability[kProton], track.bayesPr()); mSelectedMask = selectedMask; return mSelectedMask; diff --git a/PWGCF/TwoParticleCorrelations/Core/TrackSelectionFilterAndAnalysis.cxx b/PWGCF/TwoParticleCorrelations/Core/TrackSelectionFilterAndAnalysis.cxx index 93cb3fa24f2..15f283aba2b 100644 --- a/PWGCF/TwoParticleCorrelations/Core/TrackSelectionFilterAndAnalysis.cxx +++ b/PWGCF/TwoParticleCorrelations/Core/TrackSelectionFilterAndAnalysis.cxx @@ -19,6 +19,86 @@ using namespace o2; using namespace o2::analysis::PWGCF; using namespace boost; +/// \brief Constructor adapted to hyperloop +TrackSelectionConfigurable::TrackSelectionConfigurable(std::vector ttype, + std::vector nclstpc, + std::vector nxrtpc, + std::vector nclsits, + std::vector chi2clustpc, + std::vector chi2clusits, + std::vector xrofctpc, + std::vector dcaxy, + std::vector dcaz, + std::vector ptrange, + std::vector etarange) + : mTrackTypes{}, + mNClustersTPC{}, + mNCrossedRowsTPC{}, + mNClustersITS{}, + mMaxChi2PerClusterTPC{}, + mMaxChi2PerClusterITS{}, + mMinNCrossedRowsOverFindableClustersTPC{}, + mMaxDcaXY{}, + mMaxDcaZ{}, + mPtRange{}, + mEtaRange{} +{ + auto storeCutString = [](auto& selvector, std::string selname) { + if (selvector.size() != 0) { + if (selvector.size() == 1) { + if (selvector[0].size() != 0) { + return TString::Format("%s{%s}", selname.c_str(), selvector[0].c_str()); + } else { + return TString(""); + } + } else { + TString scut = selname + "{cwv{"; + bool def = true; + bool firstvar = true; + for (auto cut : selvector) { + if (def) { + scut += cut + ':'; + def = false; + } else { + if (not firstvar) { + scut += ','; + } + scut += cut; + firstvar = false; + } + } + scut += "}}"; + return scut; + } + } + return TString(""); + }; + /* track types are a bit specific */ + { + TString ttypes = "ttype{"; + bool first = true; + for (auto& type : ttype) { + if (not first) { + ttypes += ','; + } + ttypes += type; + first = false; + } + ttypes += "}"; + mTrackTypes = ttypes; + } + mNClustersTPC = storeCutString(nclstpc, "nclstpc"); + mNCrossedRowsTPC = storeCutString(nxrtpc, "nxrtpc"); + mNClustersITS = storeCutString(nclsits, "nclsits"); + mMaxChi2PerClusterTPC = storeCutString(chi2clustpc, "chi2clustpc"); + mMaxChi2PerClusterITS = storeCutString(chi2clusits, "chi2clusits"); + mMinNCrossedRowsOverFindableClustersTPC = storeCutString(xrofctpc, "xrofctpc"); + mMaxDcaXY = storeCutString(dcaxy, "dcaxy"); + mMaxDcaZ = storeCutString(dcaz, "dcaz"); + mPtRange = storeCutString(ptrange, "pT"); + mEtaRange = storeCutString(etarange, "eta"); +} + ClassImp(TrackSelectionFilterAndAnalysis); /// \brief Default constructor diff --git a/PWGCF/TwoParticleCorrelations/Core/TrackSelectionFilterAndAnalysis.h b/PWGCF/TwoParticleCorrelations/Core/TrackSelectionFilterAndAnalysis.h index 93c8b7f6b0b..ca8526ffea7 100644 --- a/PWGCF/TwoParticleCorrelations/Core/TrackSelectionFilterAndAnalysis.h +++ b/PWGCF/TwoParticleCorrelations/Core/TrackSelectionFilterAndAnalysis.h @@ -60,6 +60,17 @@ class TrackSelectionConfigurable mEtaRange{etarange} { } + TrackSelectionConfigurable(std::vector ttype, + std::vector nclstpc, + std::vector nxrtpc, + std::vector nclsits, + std::vector chi2clustpc, + std::vector chi2clusits, + std::vector xrofctpc, + std::vector dcaxy, + std::vector dcaz, + std::vector ptrange, + std::vector etarange); private: std::string mTrackTypes = ""; /// the track types to select list diff --git a/PWGCF/TwoParticleCorrelations/TableProducer/skimmingconf.h b/PWGCF/TwoParticleCorrelations/TableProducer/skimmingconf.h index 86371ef865d..a198e5c878a 100644 --- a/PWGCF/TwoParticleCorrelations/TableProducer/skimmingconf.h +++ b/PWGCF/TwoParticleCorrelations/TableProducer/skimmingconf.h @@ -15,45 +15,46 @@ #include "Framework/ASoAHelpers.h" struct : o2::framework::ConfigurableGroup { - o2::framework::Configurable zvtxsel{"evtflt_zvtx", "zvtx{cwv{rg{-7.0,7.0}-yes:rg{-10.0,10.0}-no,rg{-3.0,3.0}-no}}", "Z vertex cut: zvtx{rg{-7.0,7.0}} or zvtx{cwv{def:var1,var2@,..}}"}; - o2::framework::Configurable centmultsel{"evtflt_centmult", "centmult{cwv{mrg{V0M,0,5,10,20,30,40,50,60,70,80}-yes:mrg{CL1,0,5,10,20,30,40,50,60,70,80}-no}}", "Centrality/Multiplicity cut: centmult{mrg{V0M,0,5,10,20,30,40,50,60,70,80}}"}; + o2::framework::Configurable> zvtxsel{"evtflt_zvtx", {"rg{-7.0,7.0}-yes", "rg{-10.0,10.0}-no", "rg{-3.0,3.0}-no"}, "Z vertex cut: first, default value, next, alternatives"}; + o2::framework::Configurable> centmultsel{"evtflt_centmult", {"mrg{V0M,0,5,10,20,30,40,50,60,70,80}-yes", "mrg{CL1,0,5,10,20,30,40,50,60,70,80}-no"}, "Centrality/Multiplicity cut:: first; default, next, alternatives"}; } eventfilter; struct : o2::framework::ConfigurableGroup { - o2::framework::Configurable ttype{"trkflt_ttype", "ttype{FB1-no,FB32-yes,FB64-yes}", "Track types to filter"}; - o2::framework::Configurable nclstpc{"trkflt_nclstpc", "nclstpc{cwv{th{70}-yes:th{80}-no,th{90}-no}}", "Min no of TPC clusters: nclstpc{th{70}} or nclstpc{cwv{def:var1,var2,...}}"}; - // Configurable nxrtpc{"trkflt_nxrtpc", "nxrtpc{}", "Min no of TPC crossed rows: nxrtpc{th{70}} or nxrtpc{cwv{def;var1,var2,...}}"}; - o2::framework::Configurable nxrtpc{"trkflt_nxrtpc", "", "Min no of TPC crossed rows: nxrtpc{th{70}} or nxrtpc{cwv{def;var1,var2,...}}"}; - // Configurable nclsits{"trkflt_nclsits", "nclsits{}", "Min no of ITS clusters: nclsits{th{3}} or nclsits{cwv{def;var1,var2,...}}"}; - o2::framework::Configurable nclsits{"trkflt_nclsits", "", "Min no of ITS clusters: nclsits{th{3}} or nclsits{cwv{def;var1,var2,...}}"}; - o2::framework::Configurable chi2clustpc{"trkflt_chi2clustpc", "chi2clustpc{cwv{lim{4}-yes:lim{3}-no,lim{90}-no}}", "Max Chi^2 per TPC cluster: chi2clustpc{lim{4}} or chi2clustpc{cwv{def:var1,var2,...}}"}; - // Configurable chi2clusits{"trkflt_chi2clusits", "chi2clusits{}", "Max Chi^2 per ITS cluster: chi2clusits{lim{4}} or chi2clusits{cwv{def;var1,var2,...}}"}; - o2::framework::Configurable chi2clusits{"trkflt_chi2clusits", "", "Max Chi^2 per ITS cluster: chi2clusits{lim{4}} or chi2clusits{cwv{def;var1,var2,...}}"}; - // Configurable xrofctpc{"trkflt_xrofctpc", "xrofctpc{}", "Min no of TPC crossed rows over findable clusters: xrofctpc{th{0.70}} or xrofctpc{cwv{def;var1,var2,...}}"}; - o2::framework::Configurable xrofctpc{"trkflt_xrofctpc", "", "Min no of TPC crossed rows over findable clusters: xrofctpc{th{0.70}} or xrofctpc{cwv{def;var1,var2,...}}"}; - // Configurable dcaxy{"trkflt_dcaxy", "dcaxy{}", "Max DCAxy: dcaxy{lim{2.3}} or dcaxy{cwv{def;var1,var2,...}}"}; - o2::framework::Configurable dcaxy{"trkflt_dcaxy", "", "Max DCAxy: dcaxy{lim{2.3}} or dcaxy{cwv{def;var1,var2,...}}"}; - // Configurable dcaz{"trkflt_dcaz", "dcaz{}", "Max DCAz: dcaz{lim{3.0}} or dcaz{cwv{def;var1,var2,...}}"}; - o2::framework::Configurable dcaz{"trkflt_dcaz", "", "Max DCAz: dcaz{lim{3.0}} or dcaz{cwv{def;var1,var2,...}}"}; - o2::framework::Configurable ptrange{"trkflt_pt", "pT{rg{0.2,10.0}}", "pT range: pT{th{0.2}} or pT{cwv{def;var1,var2,...}}"}; - o2::framework::Configurable etarange{"trkflt_eta", "eta{rg{-0.8,0.8}}", "eta range: eta{rg{-0.9,0.9}} or eta{cwv{def;var1,var2,...}}"}; + o2::framework::Configurable> ttype{"trkflt_ttype", {"FB1-no", "FB32-yes", "FB64-yes"}, "Track types to filter"}; + o2::framework::Configurable> nclstpc{"trkflt_nclstpc", {"th{70}-yes", "th{80}-no", "th{90}-no"}, "Min no of TPC clusters: first, default value, next, alternatives"}; + o2::framework::Configurable> nxrtpc{"trkflt_nxrtpc", {""}, "Min no of TPC crossed rows: first, default value, next, alternatives"}; + o2::framework::Configurable> nclsits{"trkflt_nclsits", {""}, "Min no of ITS clusters: first, default value, next, alternatives"}; + o2::framework::Configurable> chi2clustpc{"trkflt_chi2clustpc", {"lim{4}-yes", "lim{3}-no", "lim{90}-no"}, "Max Chi^2 per TPC cluster: first, default value, next, alternatives"}; + o2::framework::Configurable> chi2clusits{"trkflt_chi2clusits", {""}, "Max Chi^2 per ITS cluster: first, default value, next, alternatives"}; + o2::framework::Configurable> xrofctpc{"trkflt_xrofctpc", {""}, "Min no of TPC crossed rows over findable clusters: first, default value, next, alternatives"}; + o2::framework::Configurable> dcaxy{"trkflt_dcaxy", {""}, "Max DCAxy: first, default value, next, alternatives"}; + o2::framework::Configurable> dcaz{"trkflt_dcaz", {""}, "Max DCAz: first, default value, next, alternatives"}; + o2::framework::Configurable> ptrange{"trkflt_pt", {"rg{0.2,10.0}"}, "pT range"}; + o2::framework::Configurable> etarange{"trkflt_eta", {"rg{-1.0,1.0}"}, "eta range"}; } trackfilter; struct : o2::framework::ConfigurableGroup { struct : ConfigurableGroup { - o2::framework::Configurable tpcel{"pidflt_tpc_el", "tpcel{cwv{rg{-3.0,3.0}-yes:rg{-2.0,2.0}-no,rg{-3.0,5.0}-no}}", "nsigmas to the tpc electron dE/dx line, below/above"}; - o2::framework::Configurable tpcmu{"pidflt_tpc_mu", "tpcmu{cwv{rg{-3.0,3.0}-yes:rg{-2.0,2.0}-no,rg{-3.0,5.0}-no}}", "nsigmas to the tpc muon dE/dx line, below/above"}; - o2::framework::Configurable tpcpi{"pidflt_tpc_pi", "tpcpi{cwv{rg{-3.0,3.0}-yes:rg{-2.0,2.0}-no,rg{-3.0,5.0}-no}}", "nsigmas to the tpc pion dE/dx line, below/above"}; - o2::framework::Configurable tpcka{"pidflt_tpc_ka", "tpcka{cwv{rg{-3.0,3.0}-yes:rg{-2.0,2.0}-no,rg{-3.0,5.0}-no}}", "nsigmas to the tpc kaon dE/dx line, below/above"}; - o2::framework::Configurable tpcpr{"pidflt_tpc_pr", "tpcpr{cwv{rg{-3.0,3.0}-yes:rg{-2.0,2.0}-no,rg{-3.0,5.0}-no}}", "nsigmas to the tpc proton dE/dx line, below/above"}; + o2::framework::Configurable> tpcel{"pidflt_tpc_el", {"rg{-3.0,3.0}-yes", "rg{-2.0,2.0}-no", "rg{-3.0,5.0}-no"}, "nsigmas to the tpc electron dE/dx line, below/above: first, default value, next, alternatives"}; + o2::framework::Configurable> tpcmu{"pidflt_tpc_mu", {"rg{-3.0,3.0}-yes", "rg{-2.0,2.0}-no", "rg{-3.0,5.0}-no"}, "nsigmas to the tpc muon dE/dx line, below/above: first, default value, next, alternatives"}; + o2::framework::Configurable> tpcpi{"pidflt_tpc_pi", {"rg{-3.0,3.0}-yes", "rg{-2.0,2.0}-no", "rg{-3.0,5.0}-no"}, "nsigmas to the tpc pion dE/dx line, below/above: first, default value, next, alternatives"}; + o2::framework::Configurable> tpcka{"pidflt_tpc_ka", {"rg{-3.0,3.0}-yes", "rg{-2.0,2.0}-no", "rg{-3.0,5.0}-no"}, "nsigmas to the tpc kaon dE/dx line, below/above: first, default value, next, alternatives"}; + o2::framework::Configurable> tpcpr{"pidflt_tpc_pr", {"rg{-3.0,3.0}-yes", "rg{-2.0,2.0}-no", "rg{-3.0,5.0}-no"}, "nsigmas to the tpc proton dE/dx line, below/above: first, default value, next, alternatives"}; } pidtpcfilter; struct : ConfigurableGroup { - o2::framework::Configurable tpcel{"pidflt_tof_el", "tofel{cwv{rg{-3.0,3.0}-yes:rg{-2.0,2.0}-no,rg{-3.0,5.0}-no}}", "nsigmas to the tof electron line, below/above"}; - o2::framework::Configurable tpcmu{"pidflt_tof_mu", "tofmu{cwv{rg{-3.0,3.0}-yes:rg{-2.0,2.0}-no,rg{-3.0,5.0}-no}}", "nsigmas to the tof muon line, below/above"}; - o2::framework::Configurable tpcpi{"pidflt_tof_pi", "tofpi{cwv{rg{-3.0,3.0}-yes:rg{-2.0,2.0}-no,rg{-3.0,5.0}-no}}", "nsigmas to the tof pion line, below/above"}; - o2::framework::Configurable tpcka{"pidflt_tof_ka", "tofka{cwv{rg{-3.0,3.0}-yes:rg{-2.0,2.0}-no,rg{-3.0,5.0}-no}}", "nsigmas to the tof kaon line, below/above"}; - o2::framework::Configurable tpcpr{"pidflt_tof_pr", "tofpr{cwv{rg{-3.0,3.0}-yes:rg{-2.0,2.0}-no,rg{-3.0,5.0}-no}}", "nsigmas to the tof proton line, below/above"}; + o2::framework::Configurable> tpcel{"pidflt_tof_el", {"rg{-3.0,3.0}-yes", "rg{-2.0,2.0}-no", "rg{-3.0,5.0}-no"}, "nsigmas to the tof electron line, below/above: first, default value, next, alternatives"}; + o2::framework::Configurable> tpcmu{"pidflt_tof_mu", {"rg{-3.0,3.0}-yes", "rg{-2.0,2.0}-no", "rg{-3.0,5.0}-no"}, "nsigmas to the tof muon line, below/above: first, default value, next, alternatives"}; + o2::framework::Configurable> tpcpi{"pidflt_tof_pi", {"rg{-3.0,3.0}-yes", "rg{-2.0,2.0}-no", "rg{-3.0,5.0}-no"}, "nsigmas to the tof pion line, below/above: first, default value, next, alternatives"}; + o2::framework::Configurable> tpcka{"pidflt_tof_ka", {"rg{-3.0,3.0}-yes", "rg{-2.0,2.0}-no", "rg{-3.0,5.0}-no"}, "nsigmas to the tof kaon line, below/above: first, default value, next, alternatives"}; + o2::framework::Configurable> tpcpr{"pidflt_tof_pr", {"rg{-3.0,3.0}-yes", "rg{-2.0,2.0}-no", "rg{-3.0,5.0}-no"}, "nsigmas to the tof proton line, below/above: first, default value, next, alternatives"}; } pidtoffilter; + struct : ConfigurableGroup { + o2::framework::Configurable> bayel{"pidflt_bayes_el", {"th{80}-yes", "th{70}-no", "th{90}-no"}, "Bayesian probability for electron (%%): first, default value, next, alternatives"}; + o2::framework::Configurable> baymu{"pidflt_bayes_mu", {"th{80}-yes", "th{70}-no", "th{90}-no"}, "Bayesian probability for muon (%%): first, default value, next, alternatives"}; + o2::framework::Configurable> baypi{"pidflt_bayes_pi", {"th{80}-yes", "th{70}-no", "th{90}-no"}, "Bayesian probability for pion (%%): first, default value, next, alternatives"}; + o2::framework::Configurable> bayka{"pidflt_bayes_ka", {"th{80}-yes", "th{70}-no", "th{90}-no"}, "Bayesian probability for kaon (%%): first, default value, next, alternatives"}; + o2::framework::Configurable> baypr{"pidflt_bayes_pr", {"th{80}-yes", "th{70}-no", "th{90}-no"}, "Bayesian probability for proton (%%): first, default value, next, alternatives"}; + } pidbayesfilter; } pidfilter; #endif // O2_ANALYSIS_DPTDPTSKIMCONF_H diff --git a/PWGCF/TwoParticleCorrelations/TableProducer/twoParticleCorrelationsFiltering.cxx b/PWGCF/TwoParticleCorrelations/TableProducer/twoParticleCorrelationsFiltering.cxx index 2d9898f921b..b7972e29192 100644 --- a/PWGCF/TwoParticleCorrelations/TableProducer/twoParticleCorrelationsFiltering.cxx +++ b/PWGCF/TwoParticleCorrelations/TableProducer/twoParticleCorrelationsFiltering.cxx @@ -74,7 +74,7 @@ struct TwoParticleCorrelationsFilter { LOGF(info, "TwoParticleCorrelationsFilter::init()"); /* collision filtering configuration */ - PWGCF::EventSelectionConfigurable eventsel(eventfilter.centmultsel, "", eventfilter.zvtxsel, ""); + PWGCF::EventSelectionConfigurable eventsel(eventfilter.centmultsel, {}, eventfilter.zvtxsel, {}); fCollisionFilter = new PWGCF::EventSelectionFilterAndAnalysis(eventsel, PWGCF::SelectionFilterAndAnalysis::kAnalysis); /* track filtering configuration */ @@ -82,7 +82,8 @@ struct TwoParticleCorrelationsFilter { trackfilter.chi2clusits, trackfilter.xrofctpc, trackfilter.dcaxy, trackfilter.dcaz, trackfilter.ptrange, trackfilter.etarange); fTrackFilter = new PWGCF::TrackSelectionFilterAndAnalysis(trksel, PWGCF::SelectionFilterAndAnalysis::kAnalysis); PWGCF::PIDSelectionConfigurable pidsel(pidfilter.pidtpcfilter.tpcel, pidfilter.pidtpcfilter.tpcmu, pidfilter.pidtpcfilter.tpcpi, pidfilter.pidtpcfilter.tpcka, pidfilter.pidtpcfilter.tpcpr, - pidfilter.pidtoffilter.tpcel, pidfilter.pidtoffilter.tpcmu, pidfilter.pidtoffilter.tpcpi, pidfilter.pidtoffilter.tpcka, pidfilter.pidtoffilter.tpcpr); + pidfilter.pidtoffilter.tpcel, pidfilter.pidtoffilter.tpcmu, pidfilter.pidtoffilter.tpcpi, pidfilter.pidtoffilter.tpcka, pidfilter.pidtoffilter.tpcpr, + pidfilter.pidbayesfilter.bayel, pidfilter.pidbayesfilter.baymu, pidfilter.pidbayesfilter.baypi, pidfilter.pidbayesfilter.bayka, pidfilter.pidbayesfilter.baypr); fPIDFilter = new PWGCF::PIDSelectionFilterAndAnalysis(pidsel, PWGCF::SelectionFilterAndAnalysis::kFilter); nReportedTracks = 0; @@ -112,7 +113,7 @@ struct TwoParticleCorrelationsFilter { void processRun2(soa::Filtered::iterator const& collision, soa::Filtered const& tracks) { - LOGF(TWOPFILTERLOGCOLLISIONS, "Received collision with mask 0x%08lx and %ld tracks", collision.selflags(), tracks.size()); + LOGF(TWOPFILTERLOGCOLLISIONS, "Received collision with mask 0x%016lx and %ld tracks", collision.selflags(), tracks.size()); /* for some reason we cannot apply this condition in the filter, it does not work */ if ((collision.selflags() & collisionmask_opt) != 0UL) { diff --git a/PWGCF/TwoParticleCorrelations/TableProducer/twoParticleCorrelationsSkimming.cxx b/PWGCF/TwoParticleCorrelations/TableProducer/twoParticleCorrelationsSkimming.cxx index c6cd942b694..833f9c21aa3 100644 --- a/PWGCF/TwoParticleCorrelations/TableProducer/twoParticleCorrelationsSkimming.cxx +++ b/PWGCF/TwoParticleCorrelations/TableProducer/twoParticleCorrelationsSkimming.cxx @@ -34,7 +34,8 @@ namespace o2::analysis::cfskim #define LOGTRACKTRACKS info using pidTables = soa::Join; + aod::pidTOFEl, aod::pidTOFMu, aod::pidTOFPi, aod::pidTOFKa, aod::pidTOFPr, + aod::pidBayesEl, aod::pidBayesMu, aod::pidBayesPi, aod::pidBayesKa, aod::pidBayesPr>; PWGCF::TrackSelectionFilterAndAnalysis* fTrackFilter = nullptr; PWGCF::EventSelectionFilterAndAnalysis* fEventFilter = nullptr; @@ -107,7 +108,7 @@ struct TwoParticleCorrelationsSkimming { LOGF(info, "DptDptSkimTask::init()"); /* collision filtering configuration */ - PWGCF::EventSelectionConfigurable eventsel(eventfilter.centmultsel, "", eventfilter.zvtxsel, ""); + PWGCF::EventSelectionConfigurable eventsel(eventfilter.centmultsel, {}, eventfilter.zvtxsel, {}); fEventFilter = new PWGCF::EventSelectionFilterAndAnalysis(eventsel, PWGCF::SelectionFilterAndAnalysis::kFilter); /* track filtering configuration */ @@ -115,7 +116,8 @@ struct TwoParticleCorrelationsSkimming { trackfilter.chi2clusits, trackfilter.xrofctpc, trackfilter.dcaxy, trackfilter.dcaz, trackfilter.ptrange, trackfilter.etarange); fTrackFilter = new PWGCF::TrackSelectionFilterAndAnalysis(trksel, PWGCF::SelectionFilterAndAnalysis::kFilter); PWGCF::PIDSelectionConfigurable pidsel(pidfilter.pidtpcfilter.tpcel, pidfilter.pidtpcfilter.tpcmu, pidfilter.pidtpcfilter.tpcpi, pidfilter.pidtpcfilter.tpcka, pidfilter.pidtpcfilter.tpcpr, - pidfilter.pidtoffilter.tpcel, pidfilter.pidtoffilter.tpcmu, pidfilter.pidtoffilter.tpcpi, pidfilter.pidtoffilter.tpcka, pidfilter.pidtoffilter.tpcpr); + pidfilter.pidtoffilter.tpcel, pidfilter.pidtoffilter.tpcmu, pidfilter.pidtoffilter.tpcpi, pidfilter.pidtoffilter.tpcka, pidfilter.pidtoffilter.tpcpr, + pidfilter.pidbayesfilter.bayel, pidfilter.pidbayesfilter.baymu, pidfilter.pidbayesfilter.baypi, pidfilter.pidbayesfilter.bayka, pidfilter.pidbayesfilter.baypr); fPIDFilter = new PWGCF::PIDSelectionFilterAndAnalysis(pidsel, PWGCF::SelectionFilterAndAnalysis::kFilter); nReportedTracks = 0; @@ -181,7 +183,7 @@ struct TwoParticleCorrelationsSkimming { auto bc = collision.bc_as>(); auto colmask = filterRun2Collision(collision, bc); - LOGF(LOGTRACKCOLLISIONS, "Got mask 0x%lx", colmask); + LOGF(LOGTRACKCOLLISIONS, "Got mask 0x%16lx", colmask); if (colmask != 0UL) { skimmedcollision(collision.posZ(), bc.runNumber(), bc.timestamp(), colmask, fEventFilter->GetMultiplicities()); @@ -197,7 +199,7 @@ struct TwoParticleCorrelationsSkimming { } if (trkmask != 0UL and nReportedTracks < 1000) { if (nCollisionReportedTracks < 20) { - LOGF(LOGTRACKTRACKS, " Got track mask 0x%08lx and PID mask 0x%08lx", trkmask, pidmask); + LOGF(LOGTRACKTRACKS, " Got track mask 0x%016lx and PID mask 0x%016lx", trkmask, pidmask); LOGF(LOGTRACKTRACKS, " TPC clusters %d, Chi2 per TPC cluster %f, pT %f, eta %f, track type %d", track.tpcNClsFound(), track.tpcChi2NCl(), track.pt(), track.eta(), track.trackType()); nCollisionReportedTracks++; From 2597f260a1ed9747c1aaf8271c01743fa655ef11 Mon Sep 17 00:00:00 2001 From: Victor Date: Sat, 1 Oct 2022 13:26:04 +0200 Subject: [PATCH 12/20] Not replicating columns in the filtered table Also - adapted the filtering task; now filters cannot be applied to the skimming table because we are creating additional tables to be joined with it - extracting the armed index for a cut with variations which is applied to getting the corresponding multiplicity index for the multiplicities array column --- .../Core/EventSelectionFilterAndAnalysis.h | 2 ++ .../Core/SkimmingConfigurableCuts.cxx | 31 +++++++++++++++++++ .../Core/SkimmingConfigurableCuts.h | 4 +++ .../TwoParticleCorrelationsFiltered.h | 31 +++++++------------ .../TableProducer/skimmingconf.h | 8 ++--- .../twoParticleCorrelationsFiltering.cxx | 25 ++++++++------- 6 files changed, 66 insertions(+), 35 deletions(-) diff --git a/PWGCF/TwoParticleCorrelations/Core/EventSelectionFilterAndAnalysis.h b/PWGCF/TwoParticleCorrelations/Core/EventSelectionFilterAndAnalysis.h index 8159eabcb44..205a9997901 100644 --- a/PWGCF/TwoParticleCorrelations/Core/EventSelectionFilterAndAnalysis.h +++ b/PWGCF/TwoParticleCorrelations/Core/EventSelectionFilterAndAnalysis.h @@ -68,6 +68,8 @@ class EventSelectionFilterAndAnalysis : public SelectionFilterAndAnalysis template uint64_t Filter(CollisionToFilter const& col); std::vector GetMultiplicities(); + /// \brief Gets the index of the active multiplicity value within the multiplicities array + int getMultiplicityIndex() { return mMultiplicityClasses->getArmedIndex(); } private: void ConstructCutFromString(const TString&); diff --git a/PWGCF/TwoParticleCorrelations/Core/SkimmingConfigurableCuts.cxx b/PWGCF/TwoParticleCorrelations/Core/SkimmingConfigurableCuts.cxx index cf1bf1e720a..36f8601357f 100644 --- a/PWGCF/TwoParticleCorrelations/Core/SkimmingConfigurableCuts.cxx +++ b/PWGCF/TwoParticleCorrelations/Core/SkimmingConfigurableCuts.cxx @@ -807,6 +807,37 @@ int CutWithVariations::Length() return length; } +/// Virtual function. Return the index of the armed brick within this brick +/// \returns The index of the armed brick within this brick. Default -1 +template +int CutWithVariations::getArmedIndex() +{ + int index = -1; + if (this->mMode == this->kSELECTED) { + auto checkBrickList = [&index](auto& brklst) { + bool found = false; + for (int i = 0; not found and i < brklst.GetEntries(); ++i) { + index++; + std::vector tmp = ((CutBrick*)brklst.At(i))->IsArmed(); + for (bool iarmed : tmp) { + if (iarmed) { + found = true; + break; + } + } + } + return found; + }; + if (not checkBrickList(mDefaultBricks)) { + if (not checkBrickList(mVariationBricks)) { + LOGF(fatal, "CutWithVariations::getArmedIndex(). There should be at least one brick armed"); + return -1; + } + } + } + return index; +} + templateClassImp(o2::analysis::CutWithVariations); template class o2::analysis::PWGCF::CutWithVariations; template class o2::analysis::PWGCF::CutWithVariations; diff --git a/PWGCF/TwoParticleCorrelations/Core/SkimmingConfigurableCuts.h b/PWGCF/TwoParticleCorrelations/Core/SkimmingConfigurableCuts.h index 57d158f47e6..17176497ef4 100644 --- a/PWGCF/TwoParticleCorrelations/Core/SkimmingConfigurableCuts.h +++ b/PWGCF/TwoParticleCorrelations/Core/SkimmingConfigurableCuts.h @@ -59,6 +59,9 @@ class CutBrick : public TNamed /// The length is in brick units. The actual length is implementation dependent /// \returns Brick length in units of bricks virtual int Length() = 0; + /// Virtual function. Return the index of the armed brick within this brick + /// \returns The index of the armed brick within this brick. Default -1 + virtual int getArmedIndex() { return -1; } static CutBrick* constructBrick(const char* name, const char* regex, const std::set& allowed); static const char* mgImplementedbricks[]; @@ -241,6 +244,7 @@ class CutWithVariations : public CutBrick virtual std::vector IsArmed(); virtual std::vector Filter(const TValueToFilter&); virtual int Length(); + virtual int getArmedIndex(); private: void ConstructCutFromString(const TString&); diff --git a/PWGCF/TwoParticleCorrelations/DataModel/TwoParticleCorrelationsFiltered.h b/PWGCF/TwoParticleCorrelations/DataModel/TwoParticleCorrelationsFiltered.h index 9dec8d949a2..ac35f064808 100644 --- a/PWGCF/TwoParticleCorrelations/DataModel/TwoParticleCorrelationsFiltered.h +++ b/PWGCF/TwoParticleCorrelations/DataModel/TwoParticleCorrelationsFiltered.h @@ -22,36 +22,27 @@ namespace aod /* we have to change from int to bool when bool columns work properly */ namespace twopfilter { -DECLARE_SOA_COLUMN(TwoPCollisionCentMult, centmult, float); //! The centrality/multiplicity pecentile +DECLARE_SOA_COLUMN(TwoPCollisionAccepted, accepted, uint8_t); //! If the collision/event has been accepted or not +DECLARE_SOA_COLUMN(TwoPCollisionCentMult, centmult, float); //! The centrality/multiplicity pecentile +DECLARE_SOA_COLUMN(TwoPMCCollisionCentMult, mccentmult, float); //! The centrality/multiplicity pecentile } // namespace twopfilter DECLARE_SOA_TABLE(TwoPAcceptedCollisions, "AOD", "TWOPACCCOLL", //! Accepted reconstructed collisions/events filtered table - o2::soa::Index<>, - collision::PosZ, - twopfilter::TwoPCollisionCentMult); + twopfilter::TwoPCollisionCentMult, + twopfilter::TwoPCollisionAccepted); using TowPAcceptedCollision = TwoPAcceptedCollisions::iterator; DECLARE_SOA_TABLE(TwoPAcceptedGenCollisions, "AOD", "TWOPACCGENCOLL", //! Accepted generated collisions/events filtered table - o2::soa::Index<>, - mccollision::PosZ, - twopfilter::TwoPCollisionCentMult); + twopfilter::TwoPMCCollisionCentMult, + twopfilter::TwoPCollisionAccepted); using TwoPAcceptedGenCollision = TwoPAcceptedGenCollisions::iterator; namespace twopfilter { -DECLARE_SOA_INDEX_COLUMN(TwoPAcceptedCollision, collision); //! Reconstructed collision/event -DECLARE_SOA_INDEX_COLUMN(TwoPAcceptedGenCollision, mccollision); //! Generated collision/event -DECLARE_SOA_COLUMN(TwoPTrackacceptedAs, twoptrackacceptedas, uint8_t); //! Track accepted as type 0..255, even positive or particle, odd negative or antiparticle +DECLARE_SOA_COLUMN(TwoPTrackAcceptedAs, acceptedas, uint8_t); //! Track accepted as type 0..255, even positive, odd negative, < 0 not accepted +DECLARE_SOA_COLUMN(TwoPParticleAcceptedAs, mcacceptedas, uint8_t); //! Particle accepted as type 0..255, even positive, odd negative, < 0 not accepted } // namespace twopfilter DECLARE_SOA_TABLE(TwoPFilteredTracks, "AOD", "FILTEREDTRKS", //! The reconstructed tracks filtered table - twopfilter::TwoPAcceptedCollisionId, - twopfilter::TwoPTrackacceptedAs, - cfskim::Pt, - cfskim::Eta, - cfskim::Phi); + twopfilter::TwoPTrackAcceptedAs); DECLARE_SOA_TABLE(TwoPFilteredParticles, "AOD", "FILTEREDGENTRKS", //! The generated particles filtered table - twopfilter::TwoPAcceptedGenCollisionId, - twopfilter::TwoPTrackacceptedAs, - cfskim::Pt, - cfskim::Eta, - cfskim::Phi); + twopfilter::TwoPParticleAcceptedAs); } // namespace aod } // namespace o2 diff --git a/PWGCF/TwoParticleCorrelations/TableProducer/skimmingconf.h b/PWGCF/TwoParticleCorrelations/TableProducer/skimmingconf.h index a198e5c878a..4345128c6c7 100644 --- a/PWGCF/TwoParticleCorrelations/TableProducer/skimmingconf.h +++ b/PWGCF/TwoParticleCorrelations/TableProducer/skimmingconf.h @@ -8,8 +8,8 @@ // In applying this license CERN does not waive the privileges and immunities // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -#ifndef O2_ANALYSIS_DPTDPTSKIMCONF_H -#define O2_ANALYSIS_DPTDPTSKIMCONF_H +#ifndef O2_ANALYSIS_CFSKIMMINGCONF_H +#define O2_ANALYSIS_CFSKIMMINGCONF_H #include "Framework/AnalysisTask.h" #include "Framework/ASoAHelpers.h" @@ -29,7 +29,7 @@ struct : o2::framework::ConfigurableGroup { o2::framework::Configurable> xrofctpc{"trkflt_xrofctpc", {""}, "Min no of TPC crossed rows over findable clusters: first, default value, next, alternatives"}; o2::framework::Configurable> dcaxy{"trkflt_dcaxy", {""}, "Max DCAxy: first, default value, next, alternatives"}; o2::framework::Configurable> dcaz{"trkflt_dcaz", {""}, "Max DCAz: first, default value, next, alternatives"}; - o2::framework::Configurable> ptrange{"trkflt_pt", {"rg{0.2,10.0}"}, "pT range"}; + o2::framework::Configurable> ptrange{"trkflt_pt", {"rg{0.1,50.0}"}, "pT range"}; o2::framework::Configurable> etarange{"trkflt_eta", {"rg{-1.0,1.0}"}, "eta range"}; } trackfilter; @@ -57,4 +57,4 @@ struct : o2::framework::ConfigurableGroup { } pidbayesfilter; } pidfilter; -#endif // O2_ANALYSIS_DPTDPTSKIMCONF_H +#endif // O2_ANALYSIS_CFSKIMMINGCONF_H diff --git a/PWGCF/TwoParticleCorrelations/TableProducer/twoParticleCorrelationsFiltering.cxx b/PWGCF/TwoParticleCorrelations/TableProducer/twoParticleCorrelationsFiltering.cxx index b7972e29192..77d1a23d980 100644 --- a/PWGCF/TwoParticleCorrelations/TableProducer/twoParticleCorrelationsFiltering.cxx +++ b/PWGCF/TwoParticleCorrelations/TableProducer/twoParticleCorrelationsFiltering.cxx @@ -42,6 +42,8 @@ namespace o2::analysis::twopfilter PWGCF::EventSelectionFilterAndAnalysis* fCollisionFilter = nullptr; PWGCF::TrackSelectionFilterAndAnalysis* fTrackFilter = nullptr; PWGCF::PIDSelectionFilterAndAnalysis* fPIDFilter = nullptr; + +int fMultiplicityIndex = -1; //! the index to the multiplicity values array } // namespace o2::analysis::twopfilter using namespace o2::aod::cfskim; @@ -90,13 +92,14 @@ struct TwoParticleCorrelationsFilter { collisionmask = fCollisionFilter->getMask(); collisionmask_opt = fCollisionFilter->getOptMask(); collisionmask_forced = fCollisionFilter->getForcedMask(); + fMultiplicityIndex = fCollisionFilter->getMultiplicityIndex(); trackmask = fTrackFilter->getMask(); trackmask_opt = fTrackFilter->getOptMask(); trackmask_forced = fTrackFilter->getForcedMask(); pidmask = fPIDFilter->getMask(); pidmask_opt = fPIDFilter->getOptMask(); pidmask_forced = fPIDFilter->getForcedMask(); - LOGF(info, "TwoParticleCorrelationsFilter::init(), collision selection masks 0x%08lx, 0x%08lx, and 0x%08lx ", collisionmask, collisionmask_opt, collisionmask_forced); + LOGF(info, "TwoParticleCorrelationsFilter::init(), collision selection masks 0x%08lx, 0x%08lx, and 0x%08lx and multiplicity index %d", collisionmask, collisionmask_opt, collisionmask_forced, fMultiplicityIndex); LOGF(info, "TwoParticleCorrelationsFilter::init(), track selection masks 0x%08lx, 0x%08lx, and 0x%08lx ", trackmask, trackmask_opt, trackmask_forced); LOGF(info, "TwoParticleCorrelationsFilter::init(), PID selection masks 0x%08lx, 0x%08lx, and 0x%08lx ", pidmask, pidmask_opt, pidmask_forced); if (collisionmask == uint64_t(0) or trackmask == uint64_t(0)) { @@ -108,25 +111,25 @@ struct TwoParticleCorrelationsFilter { LOGF(info, "PID skimming signature: %s", fPIDFilter->getCutStringSignature().Data()); } - Filter onlyacceptedcolls = ((aod::cfskim::selflags & static_cast(collisionmask_forced)) == static_cast(collisionmask_forced)); - Filter onlyacceptedtracks = ((aod::cfskim::trackflags & static_cast(trackmask_forced)) == static_cast(trackmask_forced)); - - void processRun2(soa::Filtered::iterator const& collision, soa::Filtered const& tracks) + void processRun2(aod::CFCollision const& collision, aod::CFTracks const& tracks) { + using namespace twopfilter; LOGF(TWOPFILTERLOGCOLLISIONS, "Received collision with mask 0x%016lx and %ld tracks", collision.selflags(), tracks.size()); - /* for some reason we cannot apply this condition in the filter, it does not work */ - if ((collision.selflags() & collisionmask_opt) != 0UL) { - acceptedcollisions(collision.posZ(), collision.centmult()[0]); + if ((collision.selflags() & collisionmask_forced) == collisionmask_forced and (collision.selflags() & collisionmask_opt) != 0UL) { + acceptedcollisions(collision.centmult()[fMultiplicityIndex], uint8_t(true)); int nAcceptedTracks = 0; for (const auto& track : tracks) { - /* for some reason we cannot apply this condition in the filter, it does not work */ - if ((track.trackflags() & trackmask_opt) != 0UL) { - accepteddtracks(acceptedcollisions.lastIndex(), 0, track.pt(), track.eta(), track.phi()); + if ((track.trackflags() & trackmask_forced) == trackmask_forced and (track.trackflags() & trackmask_opt) != 0UL) { + accepteddtracks(0); // TODO: the kind of accepted track nAcceptedTracks++; + } else { + accepteddtracks(-1); } } LOGF(TWOPFILTERLOGCOLLISIONS, ">> Accepted collision with mask 0x%08lx and %d accepted tracks", collision.selflags(), nAcceptedTracks); + } else { + acceptedcollisions(collision.centmult()[fMultiplicityIndex], uint8_t(false)); } } PROCESS_SWITCH(TwoParticleCorrelationsFilter, processRun2, "Process Run 2 two particle correlations filtering", true); From f39aca2195b3e1cd04438756075b14f83bb6a0e8 Mon Sep 17 00:00:00 2001 From: Victor Date: Sun, 2 Oct 2022 18:51:55 +0200 Subject: [PATCH 13/20] Incorporated Magnetic Field polarity and track charge sign Both have been incorporated as additional bits in the collision and track masks The getting of the magnetic field has been also incorporated to the skimming task Now it is possible to select via 'analysis configuration' (mask) if both magnetic field polarities are required or only just one The track charge sign cannot be selected via 'analysis configuration' (mask). A dynamic column will be incorporated to extract it from the track mask --- .../Core/EventSelectionFilterAndAnalysis.cxx | 68 +++++++++++++++++-- .../Core/EventSelectionFilterAndAnalysis.h | 25 +++++-- .../Core/PIDSelectionFilterAndAnalysis.cxx | 7 +- .../Core/SelectionFilterAndAnalysis.cxx | 19 +++++- .../Core/SelectionFilterAndAnalysis.h | 6 +- .../Core/SkimmingConfigurableCuts.cxx | 6 +- .../Core/SkimmingConfigurableCuts.h | 6 +- .../Core/TrackSelectionFilterAndAnalysis.cxx | 37 ++++++++-- .../Core/TrackSelectionFilterAndAnalysis.h | 10 ++- .../TableProducer/skimmingconf.h | 1 + .../twoParticleCorrelationsFiltering.cxx | 44 +++++++----- .../twoParticleCorrelationsSkimming.cxx | 36 +++++++++- 12 files changed, 206 insertions(+), 59 deletions(-) diff --git a/PWGCF/TwoParticleCorrelations/Core/EventSelectionFilterAndAnalysis.cxx b/PWGCF/TwoParticleCorrelations/Core/EventSelectionFilterAndAnalysis.cxx index bc26b5840f2..71ec3108224 100644 --- a/PWGCF/TwoParticleCorrelations/Core/EventSelectionFilterAndAnalysis.cxx +++ b/PWGCF/TwoParticleCorrelations/Core/EventSelectionFilterAndAnalysis.cxx @@ -19,11 +19,13 @@ using namespace o2; using namespace o2::analysis::PWGCF; using namespace boost; -EventSelectionConfigurable::EventSelectionConfigurable(std::vector multsel, +EventSelectionConfigurable::EventSelectionConfigurable(std::vector bfieldsel, + std::vector multsel, std::vector trigsel, std::vector zvtxsel, std::vector pileuprej) - : mMultSel(""), + : mBFiledSel(""), + mMultSel(""), mTriggerSel(""), mZVertexSel(""), mPileUpRejection("") @@ -58,6 +60,20 @@ EventSelectionConfigurable::EventSelectionConfigurable(std::vector } return TString(""); }; + /* b-field is a bit specific */ + { + TString bfield = "bfield{"; + bool first = true; + for (auto& pol : bfieldsel) { + if (not first) { + bfield += ','; + } + bfield += pol; + first = false; + } + bfield += '}'; + mBFiledSel = bfield; + } mMultSel = storeCutString(multsel, "centmult"); mTriggerSel = storeCutString(trigsel, "trigger"); mZVertexSel = storeCutString(zvtxsel, "zvtx"); @@ -72,6 +88,7 @@ const char* multiplicityEstimators[nNoOfMultiplicityEstimators] = {"V0M", "CL0", /// \brief Default constructor EventSelectionFilterAndAnalysis::EventSelectionFilterAndAnalysis() : SelectionFilterAndAnalysis(), + mBFieldSelection{}, mMultiplicityClasses(nullptr), mTriggerSelection(nullptr), mZVertex(nullptr), @@ -85,6 +102,7 @@ EventSelectionFilterAndAnalysis::EventSelectionFilterAndAnalysis() /// \brief Constructor from regular expression EventSelectionFilterAndAnalysis::EventSelectionFilterAndAnalysis(const TString& cutstr, selmodes mode) : SelectionFilterAndAnalysis("", mode), + mBFieldSelection{}, mMultiplicityClasses(nullptr), mTriggerSelection(nullptr), mZVertex(nullptr), @@ -99,6 +117,7 @@ EventSelectionFilterAndAnalysis::EventSelectionFilterAndAnalysis(const TString& /// \brief Constructor from the event selection configurable EventSelectionFilterAndAnalysis::EventSelectionFilterAndAnalysis(const EventSelectionConfigurable& evtsel, selmodes mode) : SelectionFilterAndAnalysis("", mode), + mBFieldSelection{}, mMultiplicityClasses(nullptr), mTriggerSelection(nullptr), mZVertex(nullptr), @@ -120,6 +139,7 @@ EventSelectionFilterAndAnalysis::EventSelectionFilterAndAnalysis(const EventSele } } }; + appendCut(evtsel.mBFiledSel); appendCut(evtsel.mMultSel); appendCut(evtsel.mTriggerSel); appendCut(evtsel.mZVertexSel); @@ -147,6 +167,9 @@ int EventSelectionFilterAndAnalysis::CalculateMaskLength() } }; + for (auto brick : mBFieldSelection) { + length += brick->Length(); + } addLength(mMultiplicityClasses); addLength(mTriggerSelection); addLength(mZVertex); @@ -263,7 +286,33 @@ void EventSelectionFilterAndAnalysis::ConstructCutFromString(const TString& cuts } brickvar = CutBrick::constructBrick(m[1].str().c_str(), m[2].str().c_str(), allowed); }; - if (m[1].str() == "centmult") { + /* b-field requires speciat treatment */ + auto storeBFieldCut = [&m](auto& brickvector) { + LOGF(info, "Captured %s with %s", m[1].str().c_str(), m[2].str().c_str()); + auto storeBFPolarity = [&brickvector](auto regex) { + auto addBFieldBrick = [&brickvector](auto name, auto regex, bool arm) { + std::set allowed = {"lim", "th"}; + CutBrick* brick = CutBrick::constructBrick(name, regex, allowed); + brick->Arm(arm); + brickvector.push_back(brick); + }; + if (TString(regex).Contains("positive")) { + addBFieldBrick("bfp", "th{0}", TString(regex).Contains("-yes")); + } else if (TString(regex).Contains("negative")) { + addBFieldBrick("bfn", "lim{0}", TString(regex).Contains("-yes")); + } else { + LOGF(fatal, "storeBFPolarity(). Unknown polarity %s", regex); + } + }; + TObjArray* toks = TString(m[2].str()).Tokenize(","); + for (int i = 0; i < toks->GetEntries(); ++i) { + storeBFPolarity(toks->At(i)->GetName()); + } + delete toks; + }; + if (m[1].str() == "bfield") { + storeBFieldCut(mBFieldSelection); + } else if (m[1].str() == "centmult") { storeFloatCut(mMultiplicityClasses); InitializeMultiplicityFilter(); } else if (m[1].str() == "mtrigg") { @@ -287,7 +336,7 @@ void EventSelectionFilterAndAnalysis::StoreArmedMask() uint64_t optMask = 0UL; uint64_t forcedMask = 0UL; mArmedMask = 0UL; - mOptArmedMask = 0UL; + mOptArmedMask.clear(); mForcedArmedMask = 0UL; int bit = 0; @@ -306,6 +355,12 @@ void EventSelectionFilterAndAnalysis::StoreArmedMask() } }; + optMask = 0UL; + for (auto brick : mBFieldSelection) { + armedBrick(brick, true); + } + mOptArmedMask.push_back(optMask); + optMask = 0UL; if (mMultiplicityClasses != nullptr) { if (mAlternateMultiplicityEstimatorIndex.size() > 0) { /* we have alternative estimators so our brick is of kind cwv */ @@ -331,6 +386,8 @@ void EventSelectionFilterAndAnalysis::StoreArmedMask() armedBrick(mMultiplicityClasses, true); } } + mOptArmedMask.push_back(optMask); + optMask = 0UL; if (mTriggerSelection != nullptr) { } if (mZVertex != nullptr) { @@ -338,8 +395,7 @@ void EventSelectionFilterAndAnalysis::StoreArmedMask() } if (mPileUpRejection != nullptr) { } - LOGF(info, "EventSelectionFilterAndAnalysis::StoreArmedMask(), masks 0x%08lx, 0x%08lx, 0x%08lx", armedMask, optMask, forcedMask); + LOGF(info, "EventSelectionFilterAndAnalysis::StoreArmedMask(), masks 0x%016lx, %s, 0x%016lx", armedMask, printOptionalMasks().Data(), forcedMask); mArmedMask = armedMask; - mOptArmedMask = optMask; mForcedArmedMask = forcedMask; } diff --git a/PWGCF/TwoParticleCorrelations/Core/EventSelectionFilterAndAnalysis.h b/PWGCF/TwoParticleCorrelations/Core/EventSelectionFilterAndAnalysis.h index 205a9997901..0f77a62a4af 100644 --- a/PWGCF/TwoParticleCorrelations/Core/EventSelectionFilterAndAnalysis.h +++ b/PWGCF/TwoParticleCorrelations/Core/EventSelectionFilterAndAnalysis.h @@ -17,6 +17,7 @@ #include #include +#include "Framework/Logger.h" #include "SkimmingConfigurableCuts.h" #include "SelectionFilterAndAnalysis.h" @@ -35,19 +36,22 @@ class EventSelectionConfigurable friend class EventSelectionFilterAndAnalysis; public: - EventSelectionConfigurable(std::string multsel = "", + EventSelectionConfigurable(std::string bfieldsel = "", + std::string multsel = "", std::string trigsel = "", std::string zvtxsel = "", std::string pileuprej = "") - : mMultSel{multsel}, mTriggerSel{trigsel}, mZVertexSel{zvtxsel}, mPileUpRejection{pileuprej} + : mBFiledSel(bfieldsel), mMultSel{multsel}, mTriggerSel{trigsel}, mZVertexSel{zvtxsel}, mPileUpRejection{pileuprej} { } - EventSelectionConfigurable(std::vector multsel, + EventSelectionConfigurable(std::vector bfieldsel, + std::vector multsel, std::vector trigsel, std::vector zvtxsel, std::vector pileuprej); private: + std::string mBFiledSel = ""; //! the magnetic field selection cuts std::string mMultSel = ""; //! the multiplicity selection cuts std::string mTriggerSel = ""; //! the trigger selection cuts std::string mZVertexSel = ""; //! the z vertex selection cuts @@ -66,7 +70,7 @@ class EventSelectionFilterAndAnalysis : public SelectionFilterAndAnalysis EventSelectionFilterAndAnalysis(const EventSelectionConfigurable&, selmodes); template - uint64_t Filter(CollisionToFilter const& col); + uint64_t Filter(CollisionToFilter const& col, int bfield); std::vector GetMultiplicities(); /// \brief Gets the index of the active multiplicity value within the multiplicities array int getMultiplicityIndex() { return mMultiplicityClasses->getArmedIndex(); } @@ -77,7 +81,8 @@ class EventSelectionFilterAndAnalysis : public SelectionFilterAndAnalysis int CalculateMaskLength() override; virtual void StoreArmedMask() override; - CutBrick* mMultiplicityClasses; //! the multiplicity default classes cuts + std::vector*> mBFieldSelection; //! the magnetic field selection cuts + CutBrick* mMultiplicityClasses; //! the multiplicity classes cuts CutBrick* mTriggerSelection; //! the trigger selection cuts CutBrick* mZVertex; //! the z vertex selection cuts CutBrick* mPileUpRejection; //! the pile-up rejection criteria @@ -90,7 +95,7 @@ class EventSelectionFilterAndAnalysis : public SelectionFilterAndAnalysis /// \brief Fills the filter cuts mask template -inline uint64_t EventSelectionFilterAndAnalysis::Filter(CollisionToFilter const& col) +inline uint64_t EventSelectionFilterAndAnalysis::Filter(CollisionToFilter const& col, int bfield) { /* store the collision multiplicities for the different estimators */ /* TODO: we need to adapt this to the Run 3 scenario */ @@ -118,6 +123,14 @@ inline uint64_t EventSelectionFilterAndAnalysis::Filter(CollisionToFilter const& /* we require the collision be accepted by the whole set of filters */ bool acceptcollision = true; + if (mBFieldSelection.size() > 0) { + bool oneatleast = false; + for (auto brick : mBFieldSelection) { + bool acc = filterBrickValue(brick, bfield); + oneatleast = oneatleast || acc; + } + acceptcollision = acceptcollision && oneatleast; + } if (mMultiplicityClasses != nullptr) { if (mAlternateMultiplicityEstimatorIndex.size() > 0) { bool atleastonealternative = false; diff --git a/PWGCF/TwoParticleCorrelations/Core/PIDSelectionFilterAndAnalysis.cxx b/PWGCF/TwoParticleCorrelations/Core/PIDSelectionFilterAndAnalysis.cxx index 985ab3bc2c8..1148268e836 100644 --- a/PWGCF/TwoParticleCorrelations/Core/PIDSelectionFilterAndAnalysis.cxx +++ b/PWGCF/TwoParticleCorrelations/Core/PIDSelectionFilterAndAnalysis.cxx @@ -309,7 +309,7 @@ void PIDSelectionFilterAndAnalysis::StoreArmedMask() uint64_t optMask = 0UL; uint64_t forcedMask = 0UL; mArmedMask = 0UL; - mOptArmedMask = 0UL; + mOptArmedMask.clear(); mForcedArmedMask = 0UL; int bit = 0; auto armedList = [&](auto bricklst) { @@ -330,15 +330,14 @@ void PIDSelectionFilterAndAnalysis::StoreArmedMask() } }; for (auto brick : bricklst) { - armedBrick(brick, true); + armedBrick(brick, false); } }; armedList(mCloseNsigmasTPC); armedList(mCloseNsigmasTOF); armedList(mBayesProbability); - LOGF(info, "PIDSelectionFilterAndAnalysis::StoreArmedMask(), masks 0x%08lx, 0x%08lx, 0x%08lx", armedMask, optMask, forcedMask); + LOGF(info, "PIDSelectionFilterAndAnalysis::StoreArmedMask(), masks 0x%016lx, %s, 0x%016lx", armedMask, printOptionalMasks().Data(), forcedMask); mArmedMask = armedMask; - mOptArmedMask = optMask; mForcedArmedMask = forcedMask; } diff --git a/PWGCF/TwoParticleCorrelations/Core/SelectionFilterAndAnalysis.cxx b/PWGCF/TwoParticleCorrelations/Core/SelectionFilterAndAnalysis.cxx index ed7f0c5b17e..55a08c758ce 100644 --- a/PWGCF/TwoParticleCorrelations/Core/SelectionFilterAndAnalysis.cxx +++ b/PWGCF/TwoParticleCorrelations/Core/SelectionFilterAndAnalysis.cxx @@ -33,7 +33,7 @@ SelectionFilterAndAnalysis::SelectionFilterAndAnalysis() mMaskLength(0), mSelectedMask(0UL), mArmedMask(0UL), - mOptArmedMask(0UL), + mOptArmedMask{}, mForcedArmedMask(0UL) { } @@ -46,7 +46,22 @@ SelectionFilterAndAnalysis::SelectionFilterAndAnalysis(const TString& name, selm mMaskLength(0), mSelectedMask(0UL), mArmedMask(0UL), - mOptArmedMask(0UL), + mOptArmedMask{}, mForcedArmedMask(0UL) { } + +TString SelectionFilterAndAnalysis::printOptionalMasks() const +{ + TString str = "("; + bool first = true; + for (auto option : mOptArmedMask) { + if (not first) { + str += ", "; + } + first = false; + str += TString::Format("0x%016lx", option); + } + str += ")"; + return str; +} diff --git a/PWGCF/TwoParticleCorrelations/Core/SelectionFilterAndAnalysis.h b/PWGCF/TwoParticleCorrelations/Core/SelectionFilterAndAnalysis.h index 1ac20df0a7d..ab6fd2be627 100644 --- a/PWGCF/TwoParticleCorrelations/Core/SelectionFilterAndAnalysis.h +++ b/PWGCF/TwoParticleCorrelations/Core/SelectionFilterAndAnalysis.h @@ -45,7 +45,8 @@ class SelectionFilterAndAnalysis : public TNamed /// \return the armed optional mask /// A clear example of the optional part mask is the mask of the multiplicity classes /// where only one of the available in the whole mask will be flagged - uint64_t getOptMask() { return mOptArmedMask; } + std::vector& getOptMask() { return mOptArmedMask; } + TString printOptionalMasks() const; /// \brief get the valid (armed) mandatory part mask associated to the configuration /// \return the armed optional mask /// A clear example of the mandatory part mask is the mask of the zvertex and their @@ -64,7 +65,8 @@ class SelectionFilterAndAnalysis : public TNamed int mMaskLength = 0; /// the length of the mask needed to filter the selection cuts uint64_t mSelectedMask = 0UL; /// the selection mask for the current passed collision uint64_t mArmedMask = 0UL; /// the complete armed mask identifying the applicable selection cuts - uint64_t mOptArmedMask = 0UL; /// the armed mask for options of the applicable selection cuts + std::vector mOptArmedMask = {}; /// the list of armed masks for options of the applicable selection cuts + /// all of them have to have at least one option active uint64_t mForcedArmedMask = 0UL; /// the mandatory armed mask of the applicable selection cuts ClassDefNV(SelectionFilterAndAnalysis, 1) diff --git a/PWGCF/TwoParticleCorrelations/Core/SkimmingConfigurableCuts.cxx b/PWGCF/TwoParticleCorrelations/Core/SkimmingConfigurableCuts.cxx index 36f8601357f..60b60ed8e9e 100644 --- a/PWGCF/TwoParticleCorrelations/Core/SkimmingConfigurableCuts.cxx +++ b/PWGCF/TwoParticleCorrelations/Core/SkimmingConfigurableCuts.cxx @@ -246,7 +246,7 @@ template std::vector CutBrickThreshold::Filter(const TValueToFilter& value) { std::vector res; - if (mThreshold <= value) { + if (mThreshold < value) { this->mState = this->kACTIVE; res.push_back(true); } else { @@ -340,7 +340,7 @@ template std::vector CutBrickRange::Filter(const TValueToFilter& value) { std::vector res; - if ((mLow <= value) and (value < mHigh)) { + if ((mLow < value) and (value < mHigh)) { this->mState = this->kACTIVE; res.push_back(true); } else { @@ -434,7 +434,7 @@ template std::vector CutBrickExtToRange::Filter(const TValueToFilter& value) { std::vector res; - if ((value < mLow) or (mHigh <= value)) { + if ((value < mLow) or (mHigh < value)) { this->mState = this->kACTIVE; res.push_back(true); } else { diff --git a/PWGCF/TwoParticleCorrelations/Core/SkimmingConfigurableCuts.h b/PWGCF/TwoParticleCorrelations/Core/SkimmingConfigurableCuts.h index 17176497ef4..e9a91635053 100644 --- a/PWGCF/TwoParticleCorrelations/Core/SkimmingConfigurableCuts.h +++ b/PWGCF/TwoParticleCorrelations/Core/SkimmingConfigurableCuts.h @@ -128,9 +128,9 @@ class CutBrickThreshold : public CutBrick CutBrickThreshold(const CutBrickThreshold&) = delete; CutBrickThreshold& operator=(const CutBrickThreshold&) = delete; - virtual std::vector IsArmed(); - virtual std::vector Filter(const TValueToFilter&); - virtual int Length() { return 1; } + virtual std::vector IsArmed() override; + virtual std::vector Filter(const TValueToFilter&) override; + virtual int Length() override { return 1; } private: void ConstructCutFromString(const TString&); diff --git a/PWGCF/TwoParticleCorrelations/Core/TrackSelectionFilterAndAnalysis.cxx b/PWGCF/TwoParticleCorrelations/Core/TrackSelectionFilterAndAnalysis.cxx index 15f283aba2b..5b0c929d19b 100644 --- a/PWGCF/TwoParticleCorrelations/Core/TrackSelectionFilterAndAnalysis.cxx +++ b/PWGCF/TwoParticleCorrelations/Core/TrackSelectionFilterAndAnalysis.cxx @@ -113,7 +113,8 @@ TrackSelectionFilterAndAnalysis::TrackSelectionFilterAndAnalysis() mMaxDcaXY(nullptr), mMaxDcaZ(nullptr) { - /* we own the track types cuts objects */ + /* we own the track sign and types cuts objects */ + mTrackSign.SetOwner(true); mTrackTypes.SetOwner(true); /* at least we initialize by default pT and eta cuts */ mPtRange = CutBrick::constructBrick("pT", "rg{0.2,10}", std::set{"rg"}); @@ -132,7 +133,8 @@ TrackSelectionFilterAndAnalysis::TrackSelectionFilterAndAnalysis(const TString& mMaxDcaXY(nullptr), mMaxDcaZ(nullptr) { - /* we own the track types cuts objects */ + /* we own the track sign and types cuts objects */ + mTrackSign.SetOwner(true); mTrackTypes.SetOwner(true); /* at least we initialize by default pT and eta cuts */ mPtRange = CutBrick::constructBrick("pT", "rg{0.1,50}", std::set{"rg"}); @@ -155,7 +157,8 @@ TrackSelectionFilterAndAnalysis::TrackSelectionFilterAndAnalysis(const TrackSele mPtRange(nullptr), mEtaRange(nullptr) { - /* we own the track types cuts objects */ + /* we own the track sign and types cuts objects */ + mTrackSign.SetOwner(true); mTrackTypes.SetOwner(true); TString cutString = "tracksel{" + trcksel.mTrackTypes; @@ -209,6 +212,9 @@ TrackSelectionFilterAndAnalysis::TrackSelectionFilterAndAnalysis(const TrackSele int TrackSelectionFilterAndAnalysis::CalculateMaskLength() { int length = 0; + for (int i = 0; i < mTrackSign.GetEntries(); ++i) { + length += ((CutBrick*)mTrackSign.At(i))->Length(); + } for (int i = 0; i < mTrackTypes.GetEntries(); ++i) { length += ((SpecialCutBrick*)mTrackTypes.At(i))->Length(); } @@ -278,6 +284,18 @@ void TrackSelectionFilterAndAnalysis::ConstructCutFromString(const TString& cuts SetName("TrackSelectionFilterAndAnalysisCuts"); SetTitle(cutstr.Data()); + /* let's introduce the charge sign bricks into the chain */ + { + auto addChargeBrick = [this](auto name, auto regex) { + std::set allowed = {"lim", "th"}; + CutBrick* brick = CutBrick::constructBrick(name, regex, allowed); + brick->Arm(true); + mTrackSign.Add(brick); + }; + addChargeBrick("chp", "th{0}"); + addChargeBrick("chn", "lim{0}"); + } + /* let's split the handling of track types and of its characteristics */ /* let's handle the track types */ { @@ -382,7 +400,7 @@ void TrackSelectionFilterAndAnalysis::StoreArmedMask() uint64_t optMask = 0UL; uint64_t forcedMask = 0UL; mArmedMask = 0UL; - mOptArmedMask = 0UL; + mOptArmedMask.clear(); mForcedArmedMask = 0UL; int bit = 0; @@ -401,9 +419,17 @@ void TrackSelectionFilterAndAnalysis::StoreArmedMask() } }; + optMask = 0UL; + for (int i = 0; i < mTrackSign.GetEntries(); ++i) { + armedBrick((CutBrick*)mTrackSign.At(i), true); + } + mOptArmedMask.push_back(optMask); + optMask = 0UL; for (int i = 0; i < mTrackTypes.GetEntries(); ++i) { armedBrick((TrackSelectionBrick*)mTrackTypes.At(i), true); } + mOptArmedMask.push_back(optMask); + optMask = 0UL; if (mNClustersTPC != nullptr) { armedBrick(mNClustersTPC); } @@ -429,8 +455,7 @@ void TrackSelectionFilterAndAnalysis::StoreArmedMask() armedBrick(mMaxDcaZ); } /* for the time being the pT and eta bricks dont go to the mask */ - LOGF(info, "TrackSelectionFilterAndAnalysis::StoreArmedMask(), masks 0x%08lx, 0x%08lx, 0x%08lx", armedMask, optMask, forcedMask); + LOGF(info, "TrackSelectionFilterAndAnalysis::StoreArmedMask(), masks 0x%016lx, %s, 0x%016lx", armedMask, printOptionalMasks().Data(), forcedMask); mArmedMask = armedMask; - mOptArmedMask = optMask; mForcedArmedMask = forcedMask; } diff --git a/PWGCF/TwoParticleCorrelations/Core/TrackSelectionFilterAndAnalysis.h b/PWGCF/TwoParticleCorrelations/Core/TrackSelectionFilterAndAnalysis.h index ca8526ffea7..82f4c5e20f4 100644 --- a/PWGCF/TwoParticleCorrelations/Core/TrackSelectionFilterAndAnalysis.h +++ b/PWGCF/TwoParticleCorrelations/Core/TrackSelectionFilterAndAnalysis.h @@ -108,6 +108,7 @@ class TrackSelectionFilterAndAnalysis : public SelectionFilterAndAnalysis int CalculateMaskLength(); void StoreArmedMask(); + TList mTrackSign; /// the track charge sign list TList mTrackTypes; /// the track types to select list CutBrick* mNClustersTPC; //! the number of TPC clusters cuts CutBrick* mNCrossedRowsTPC; //! the number of TPC crossed rows cuts @@ -127,12 +128,6 @@ class TrackSelectionFilterAndAnalysis : public SelectionFilterAndAnalysis template uint64_t TrackSelectionFilterAndAnalysis::Filter(TrackToFilter const& track) { - /* limit for the current implementation */ - int length = CalculateMaskLength(); - if (length > 64) { - LOGF(fatal, "TrackSelectionFilterAndAnalysis not ready for filter mask of %d bits. Just 64 available for the time being"); - } - uint64_t selectedMask = 0UL; int bit = 0; @@ -163,6 +158,9 @@ uint64_t TrackSelectionFilterAndAnalysis::Filter(TrackToFilter const& track) return false; }; + for (int i = 0; i < mTrackSign.GetEntries(); ++i) { + filterBrickValue((CutBrick*)mTrackSign.At(i), track.sign()); + } for (int i = 0; i < mTrackTypes.GetEntries(); ++i) { filterTrackType((TrackSelectionBrick*)mTrackTypes.At(i), track); } diff --git a/PWGCF/TwoParticleCorrelations/TableProducer/skimmingconf.h b/PWGCF/TwoParticleCorrelations/TableProducer/skimmingconf.h index 4345128c6c7..e0b2d26fdb8 100644 --- a/PWGCF/TwoParticleCorrelations/TableProducer/skimmingconf.h +++ b/PWGCF/TwoParticleCorrelations/TableProducer/skimmingconf.h @@ -15,6 +15,7 @@ #include "Framework/ASoAHelpers.h" struct : o2::framework::ConfigurableGroup { + o2::framework::Configurable> bfield{"evtflt_bfield", {"positive-yes", "negative-yes"}, "B filed polarity cut"}; o2::framework::Configurable> zvtxsel{"evtflt_zvtx", {"rg{-7.0,7.0}-yes", "rg{-10.0,10.0}-no", "rg{-3.0,3.0}-no"}, "Z vertex cut: first, default value, next, alternatives"}; o2::framework::Configurable> centmultsel{"evtflt_centmult", {"mrg{V0M,0,5,10,20,30,40,50,60,70,80}-yes", "mrg{CL1,0,5,10,20,30,40,50,60,70,80}-no"}, "Centrality/Multiplicity cut:: first; default, next, alternatives"}; } eventfilter; diff --git a/PWGCF/TwoParticleCorrelations/TableProducer/twoParticleCorrelationsFiltering.cxx b/PWGCF/TwoParticleCorrelations/TableProducer/twoParticleCorrelationsFiltering.cxx index 77d1a23d980..ad23bc2af26 100644 --- a/PWGCF/TwoParticleCorrelations/TableProducer/twoParticleCorrelationsFiltering.cxx +++ b/PWGCF/TwoParticleCorrelations/TableProducer/twoParticleCorrelationsFiltering.cxx @@ -39,6 +39,16 @@ namespace o2::analysis::twopfilter #define TWOPFILTERLOGCOLLISIONS info #define TWOPFILTERLOGTRACKS info +uint64_t collisionmask = 0UL; +std::vector collisionmask_opt; +uint64_t collisionmask_forced = 0UL; +uint64_t trackmask = 0UL; +std::vector trackmask_opt; +uint64_t trackmask_forced = 0UL; +uint64_t pidmask = 0UL; +std::vector pidmask_opt; +uint64_t pidmask_forced = 0UL; + PWGCF::EventSelectionFilterAndAnalysis* fCollisionFilter = nullptr; PWGCF::TrackSelectionFilterAndAnalysis* fTrackFilter = nullptr; PWGCF::PIDSelectionFilterAndAnalysis* fPIDFilter = nullptr; @@ -59,16 +69,6 @@ struct TwoParticleCorrelationsFilter { int nReportedTracks; // HistogramRegistry historeg; - uint64_t collisionmask = 0UL; - uint64_t collisionmask_opt = 0UL; - uint64_t collisionmask_forced = 0UL; - uint64_t trackmask = 0UL; - uint64_t trackmask_opt = 0UL; - uint64_t trackmask_forced = 0UL; - uint64_t pidmask = 0UL; - uint64_t pidmask_opt = 0UL; - uint64_t pidmask_forced = 0UL; - void init(InitContext const&) { using namespace twopfilter; @@ -76,7 +76,7 @@ struct TwoParticleCorrelationsFilter { LOGF(info, "TwoParticleCorrelationsFilter::init()"); /* collision filtering configuration */ - PWGCF::EventSelectionConfigurable eventsel(eventfilter.centmultsel, {}, eventfilter.zvtxsel, {}); + PWGCF::EventSelectionConfigurable eventsel(eventfilter.bfield, eventfilter.centmultsel, {}, eventfilter.zvtxsel, {}); fCollisionFilter = new PWGCF::EventSelectionFilterAndAnalysis(eventsel, PWGCF::SelectionFilterAndAnalysis::kAnalysis); /* track filtering configuration */ @@ -86,7 +86,7 @@ struct TwoParticleCorrelationsFilter { PWGCF::PIDSelectionConfigurable pidsel(pidfilter.pidtpcfilter.tpcel, pidfilter.pidtpcfilter.tpcmu, pidfilter.pidtpcfilter.tpcpi, pidfilter.pidtpcfilter.tpcka, pidfilter.pidtpcfilter.tpcpr, pidfilter.pidtoffilter.tpcel, pidfilter.pidtoffilter.tpcmu, pidfilter.pidtoffilter.tpcpi, pidfilter.pidtoffilter.tpcka, pidfilter.pidtoffilter.tpcpr, pidfilter.pidbayesfilter.bayel, pidfilter.pidbayesfilter.baymu, pidfilter.pidbayesfilter.baypi, pidfilter.pidbayesfilter.bayka, pidfilter.pidbayesfilter.baypr); - fPIDFilter = new PWGCF::PIDSelectionFilterAndAnalysis(pidsel, PWGCF::SelectionFilterAndAnalysis::kFilter); + fPIDFilter = new PWGCF::PIDSelectionFilterAndAnalysis(pidsel, PWGCF::SelectionFilterAndAnalysis::kAnalysis); nReportedTracks = 0; collisionmask = fCollisionFilter->getMask(); @@ -99,9 +99,9 @@ struct TwoParticleCorrelationsFilter { pidmask = fPIDFilter->getMask(); pidmask_opt = fPIDFilter->getOptMask(); pidmask_forced = fPIDFilter->getForcedMask(); - LOGF(info, "TwoParticleCorrelationsFilter::init(), collision selection masks 0x%08lx, 0x%08lx, and 0x%08lx and multiplicity index %d", collisionmask, collisionmask_opt, collisionmask_forced, fMultiplicityIndex); - LOGF(info, "TwoParticleCorrelationsFilter::init(), track selection masks 0x%08lx, 0x%08lx, and 0x%08lx ", trackmask, trackmask_opt, trackmask_forced); - LOGF(info, "TwoParticleCorrelationsFilter::init(), PID selection masks 0x%08lx, 0x%08lx, and 0x%08lx ", pidmask, pidmask_opt, pidmask_forced); + LOGF(info, "TwoParticleCorrelationsFilter::init(), collision selection masks 0x%016lx, %s, and 0x%016lx and multiplicity index %d", collisionmask, fCollisionFilter->printOptionalMasks().Data(), collisionmask_forced, fMultiplicityIndex); + LOGF(info, "TwoParticleCorrelationsFilter::init(), track selection masks 0x%016lx, %s, and 0x%016lx ", trackmask, fTrackFilter->printOptionalMasks().Data(), trackmask_forced); + LOGF(info, "TwoParticleCorrelationsFilter::init(), PID selection masks 0x%016lx, %s, and 0x%016lx ", pidmask, fPIDFilter->printOptionalMasks().Data(), pidmask_forced); if (collisionmask == uint64_t(0) or trackmask == uint64_t(0)) { LOGF(fatal, "TwoParticleCorrelationsFilter::init() null masks, selecting everything!!!"); } @@ -115,19 +115,27 @@ struct TwoParticleCorrelationsFilter { { using namespace twopfilter; LOGF(TWOPFILTERLOGCOLLISIONS, "Received collision with mask 0x%016lx and %ld tracks", collision.selflags(), tracks.size()); + auto passOptions = [](auto options, auto mask) { + bool all = true; + for (auto option : options) { + all = all && ((option & mask) != 0UL); + } + return all; + }; - if ((collision.selflags() & collisionmask_forced) == collisionmask_forced and (collision.selflags() & collisionmask_opt) != 0UL) { + if ((collision.selflags() & collisionmask_forced) == collisionmask_forced and passOptions(collisionmask_opt, collision.selflags())) { + LOGF(TWOPFILTERLOGCOLLISIONS, ">> Accepted collision with mask 0x%016lx and %ld unfiltered tracks", collision.selflags(), tracks.size()); acceptedcollisions(collision.centmult()[fMultiplicityIndex], uint8_t(true)); int nAcceptedTracks = 0; for (const auto& track : tracks) { - if ((track.trackflags() & trackmask_forced) == trackmask_forced and (track.trackflags() & trackmask_opt) != 0UL) { + if ((track.trackflags() & trackmask_forced) == trackmask_forced and passOptions(trackmask_opt, track.trackflags())) { accepteddtracks(0); // TODO: the kind of accepted track nAcceptedTracks++; } else { accepteddtracks(-1); } } - LOGF(TWOPFILTERLOGCOLLISIONS, ">> Accepted collision with mask 0x%08lx and %d accepted tracks", collision.selflags(), nAcceptedTracks); + LOGF(TWOPFILTERLOGCOLLISIONS, ">> Accepted collision with mask 0x%016lx and %d accepted tracks", collision.selflags(), nAcceptedTracks); } else { acceptedcollisions(collision.centmult()[fMultiplicityIndex], uint8_t(false)); } diff --git a/PWGCF/TwoParticleCorrelations/TableProducer/twoParticleCorrelationsSkimming.cxx b/PWGCF/TwoParticleCorrelations/TableProducer/twoParticleCorrelationsSkimming.cxx index 833f9c21aa3..19774142d55 100644 --- a/PWGCF/TwoParticleCorrelations/TableProducer/twoParticleCorrelationsSkimming.cxx +++ b/PWGCF/TwoParticleCorrelations/TableProducer/twoParticleCorrelationsSkimming.cxx @@ -16,11 +16,12 @@ #include "Common/DataModel/Centrality.h" #include "Common/DataModel/PIDResponse.h" #include "PWGCF/TwoParticleCorrelations/DataModel/TwoParticleCorrelationsSkimmed.h" -#include "PWGCF/TwoParticleCorrelations/Core/SkimmingConfigurableCuts.h" #include "PWGCF/TwoParticleCorrelations/Core/EventSelectionFilterAndAnalysis.h" #include "PWGCF/TwoParticleCorrelations/Core/TrackSelectionFilterAndAnalysis.h" #include "PWGCF/TwoParticleCorrelations/Core/PIDSelectionFilterAndAnalysis.h" #include "Framework/runDataProcessing.h" +#include "DataFormatsParameters/GRPObject.h" +#include using namespace o2; using namespace o2::framework; @@ -96,11 +97,30 @@ struct TwoParticleCorrelationsSkimming { Produces skimmedgencollision; Produces skimmedparticles; + Service ccdb; + #include "skimmingconf.h" int nReportedTracks; + int runNumber = 0; + int bfield = 0; HistogramRegistry historeg; + int getMagneticField(std::string ccdbpath, uint64_t timestamp) + { + // TODO done only once (and not per run). Will be replaced by CCDBConfigurable + static o2::parameters::GRPObject* grpo = nullptr; + if (grpo == nullptr) { + grpo = ccdb->getForTimeStamp("GLO/GRP/GRP", timestamp); + if (grpo == nullptr) { + LOGF(fatal, "GRP object not found for timestamp %llu", timestamp); + return 0; + } + LOGF(info, "Retrieved GRP for timestamp %llu with magnetic field of %d kG", timestamp, grpo->getNominalL3Field()); + } + return grpo->getNominalL3Field(); + } + void init(InitContext const&) { using namespace cfskim; @@ -108,7 +128,7 @@ struct TwoParticleCorrelationsSkimming { LOGF(info, "DptDptSkimTask::init()"); /* collision filtering configuration */ - PWGCF::EventSelectionConfigurable eventsel(eventfilter.centmultsel, {}, eventfilter.zvtxsel, {}); + PWGCF::EventSelectionConfigurable eventsel(eventfilter.bfield, eventfilter.centmultsel, {}, eventfilter.zvtxsel, {}); fEventFilter = new PWGCF::EventSelectionFilterAndAnalysis(eventsel, PWGCF::SelectionFilterAndAnalysis::kFilter); /* track filtering configuration */ @@ -128,6 +148,11 @@ struct TwoParticleCorrelationsSkimming { historeg.add("EventCuts", "EventCuts", {HistType::kTH1F, {{aod::run2::kTRDHEE + 1, 0, aod::run2::kTRDHEE + 1}}}); setEventCutsLabels(historeg.get(HIST("EventCuts"))); + + /* initialize access to the CCDB */ + ccdb->setURL("http://alice-ccdb.cern.ch"); + ccdb->setCaching(true); + ccdb->setLocalObjectValidityChecking(); } template @@ -168,8 +193,13 @@ struct TwoParticleCorrelationsSkimming { reportEventCuts(historeg.get(HIST("EventCuts")), eventcuts); // CONFIGURABLE EVENT SELECTION + /* update magnetic field if needed */ + if (bcinfo.runNumber() != runNumber) { + bfield = getMagneticField("GLO/GRP/GRP", bcinfo.timestamp()); + runNumber = bcinfo.runNumber(); + } if (accepted) { - return fEventFilter->Filter(collision); + return fEventFilter->Filter(collision, bfield); } else { return 0UL; } From ce2a90d6f4dd6ef78a06c3109069dc29862feeab Mon Sep 17 00:00:00 2001 From: Victor Date: Sun, 2 Oct 2022 19:06:20 +0200 Subject: [PATCH 14/20] Fix clang formatting --- .../Core/SelectionFilterAndAnalysis.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/PWGCF/TwoParticleCorrelations/Core/SelectionFilterAndAnalysis.h b/PWGCF/TwoParticleCorrelations/Core/SelectionFilterAndAnalysis.h index ab6fd2be627..f3680d188f4 100644 --- a/PWGCF/TwoParticleCorrelations/Core/SelectionFilterAndAnalysis.h +++ b/PWGCF/TwoParticleCorrelations/Core/SelectionFilterAndAnalysis.h @@ -60,14 +60,14 @@ class SelectionFilterAndAnalysis : public TNamed virtual void StoreArmedMask() = 0; protected: - selmodes mMode = kFilter; /// the operating mode of the selection instance - TString mCutStringSignature; /// the signature of the cut string, i.e. without the alternative selection tags - int mMaskLength = 0; /// the length of the mask needed to filter the selection cuts - uint64_t mSelectedMask = 0UL; /// the selection mask for the current passed collision - uint64_t mArmedMask = 0UL; /// the complete armed mask identifying the applicable selection cuts + selmodes mMode = kFilter; /// the operating mode of the selection instance + TString mCutStringSignature; /// the signature of the cut string, i.e. without the alternative selection tags + int mMaskLength = 0; /// the length of the mask needed to filter the selection cuts + uint64_t mSelectedMask = 0UL; /// the selection mask for the current passed collision + uint64_t mArmedMask = 0UL; /// the complete armed mask identifying the applicable selection cuts std::vector mOptArmedMask = {}; /// the list of armed masks for options of the applicable selection cuts /// all of them have to have at least one option active - uint64_t mForcedArmedMask = 0UL; /// the mandatory armed mask of the applicable selection cuts + uint64_t mForcedArmedMask = 0UL; /// the mandatory armed mask of the applicable selection cuts ClassDefNV(SelectionFilterAndAnalysis, 1) }; From 749fd728875a52bd2345cc1620477ff974e90ff7 Mon Sep 17 00:00:00 2001 From: Victor Date: Mon, 3 Oct 2022 11:37:32 +0200 Subject: [PATCH 15/20] Replace `#include "Framework/Logger.h"` by `#include ` According to today's WP4+WP14 meeting --- .../Core/EventSelectionFilterAndAnalysis.h | 2 +- .../Core/SkimmingConfigurableCuts.cxx | 6 +++--- .../Core/TrackSelectionFilterAndAnalysis.cxx | 4 ++-- .../Core/TrackSelectionFilterAndAnalysis.h | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/PWGCF/TwoParticleCorrelations/Core/EventSelectionFilterAndAnalysis.h b/PWGCF/TwoParticleCorrelations/Core/EventSelectionFilterAndAnalysis.h index 0f77a62a4af..6c0bbb2169b 100644 --- a/PWGCF/TwoParticleCorrelations/Core/EventSelectionFilterAndAnalysis.h +++ b/PWGCF/TwoParticleCorrelations/Core/EventSelectionFilterAndAnalysis.h @@ -17,7 +17,7 @@ #include #include -#include "Framework/Logger.h" +#include #include "SkimmingConfigurableCuts.h" #include "SelectionFilterAndAnalysis.h" diff --git a/PWGCF/TwoParticleCorrelations/Core/SkimmingConfigurableCuts.cxx b/PWGCF/TwoParticleCorrelations/Core/SkimmingConfigurableCuts.cxx index 60b60ed8e9e..44fae2d1308 100644 --- a/PWGCF/TwoParticleCorrelations/Core/SkimmingConfigurableCuts.cxx +++ b/PWGCF/TwoParticleCorrelations/Core/SkimmingConfigurableCuts.cxx @@ -12,7 +12,7 @@ #include #include -#include "Framework/Logger.h" +#include #include "PWGCF/TwoParticleCorrelations/Core/SkimmingConfigurableCuts.h" using namespace o2; @@ -32,14 +32,14 @@ CutBrick* CutBrick::constructBrick(const char* n CutBrick* thebrick = nullptr; bool found = false; - for (auto bname : allowed) { + for (auto& bname : allowed) { if (TString(regex).BeginsWith(bname)) { found = true; break; } } if (not found) { - ::Fatal("CutBrick* CutBrick::constructBrick", "Wrong RE: %s, trying to construct a not allowed basic cut brick", regex); + LOGF(fatal, "CutBrick* CutBrick::constructBrick", "Wrong RE: %s, trying to construct a not allowed basic cut brick", regex); } TString brickregex = TString(name) + "{" + TString(regex) + "}"; diff --git a/PWGCF/TwoParticleCorrelations/Core/TrackSelectionFilterAndAnalysis.cxx b/PWGCF/TwoParticleCorrelations/Core/TrackSelectionFilterAndAnalysis.cxx index 5b0c929d19b..4b5708fdc90 100644 --- a/PWGCF/TwoParticleCorrelations/Core/TrackSelectionFilterAndAnalysis.cxx +++ b/PWGCF/TwoParticleCorrelations/Core/TrackSelectionFilterAndAnalysis.cxx @@ -12,7 +12,7 @@ #include #include -#include "Framework/Logger.h" +#include #include "TrackSelectionFilterAndAnalysis.h" using namespace o2; @@ -279,7 +279,7 @@ void TrackSelectionFilterAndAnalysis::ConstructCutFromString(const TString& cuts bool res = regex_search(in, m, cutregex); if (not res or m.empty() or (m.size() > 3)) { - Fatal("TrackSelectionFilterAndAnalysis::::ConstructCutFromString", "Wrong RE: %s, try tracksel{ttype{FB32,FB96};ncls{th{70}},nxr{cwv{th{70},th{80}}}} for instance", cutstr.Data()); + LOGF(fatal, "TrackSelectionFilterAndAnalysis::::ConstructCutFromString", "Wrong RE: %s, try tracksel{ttype{FB32,FB96};ncls{th{70}},nxr{cwv{th{70},th{80}}}} for instance", cutstr.Data()); } SetName("TrackSelectionFilterAndAnalysisCuts"); SetTitle(cutstr.Data()); diff --git a/PWGCF/TwoParticleCorrelations/Core/TrackSelectionFilterAndAnalysis.h b/PWGCF/TwoParticleCorrelations/Core/TrackSelectionFilterAndAnalysis.h index 82f4c5e20f4..3c322d7fa57 100644 --- a/PWGCF/TwoParticleCorrelations/Core/TrackSelectionFilterAndAnalysis.h +++ b/PWGCF/TwoParticleCorrelations/Core/TrackSelectionFilterAndAnalysis.h @@ -17,7 +17,7 @@ #include #include -#include "Framework/Logger.h" +#include #include "SkimmingConfigurableCuts.h" #include "SelectionFilterAndAnalysis.h" From 494c213726b764955b95f3d8fa5256549c8628f0 Mon Sep 17 00:00:00 2001 From: Victor Date: Tue, 4 Oct 2022 10:55:37 +0200 Subject: [PATCH 16/20] Fix typo in MC table name --- .../DataModel/TwoParticleCorrelationsSkimmed.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PWGCF/TwoParticleCorrelations/DataModel/TwoParticleCorrelationsSkimmed.h b/PWGCF/TwoParticleCorrelations/DataModel/TwoParticleCorrelationsSkimmed.h index 669da02c148..27f9a80e417 100644 --- a/PWGCF/TwoParticleCorrelations/DataModel/TwoParticleCorrelationsSkimmed.h +++ b/PWGCF/TwoParticleCorrelations/DataModel/TwoParticleCorrelationsSkimmed.h @@ -86,7 +86,7 @@ DECLARE_SOA_INDEX_COLUMN(CFMCParticle, mcparticle); DECLARE_SOA_TABLE(CFMCCollisionLbls, "AOD", "CFMCCOLLISONLBL", cfskim::CFMCCollisionId, mccollisionlabel::McMask); -DECLARE_SOA_TABLE(CFMCTrakLabels, "AOD", "CFMCTRACKLABEL", +DECLARE_SOA_TABLE(CFMCTrackLabels, "AOD", "CFMCTRACKLABEL", cfskim::CFMCParticleId, mctracklabel::McMask); } // namespace aod From 75aabf49af3a33fbebf2e954d9d89ef7de53cb72 Mon Sep 17 00:00:00 2001 From: Victor Date: Tue, 4 Oct 2022 10:56:26 +0200 Subject: [PATCH 17/20] Introduction of the function based cut bricks --- .../Core/SkimmingConfigurableCuts.cxx | 327 ++++++++++++++---- .../Core/SkimmingConfigurableCuts.h | 200 ++++++++++- .../Core/TwoPartCorrLinkDef.h | 12 +- 3 files changed, 470 insertions(+), 69 deletions(-) diff --git a/PWGCF/TwoParticleCorrelations/Core/SkimmingConfigurableCuts.cxx b/PWGCF/TwoParticleCorrelations/Core/SkimmingConfigurableCuts.cxx index 44fae2d1308..8aff0bedb67 100644 --- a/PWGCF/TwoParticleCorrelations/Core/SkimmingConfigurableCuts.cxx +++ b/PWGCF/TwoParticleCorrelations/Core/SkimmingConfigurableCuts.cxx @@ -22,7 +22,7 @@ using namespace o2::analysis::PWGCF; /// If more are implemented the list must be expanded and the /// corresponding brick construction implemented template -const char* CutBrick::mgImplementedbricks[] = {"lim", "th", "rg", "xrg", "mrg", "cwv"}; +const char* CutBrick::mgImplementedbricks[] = {"lim", "fnlim", "th", "fnth", "rg", "fnrg", "xrg", "fnxrg", "mrg", "cwv"}; /////////////////////////////////////////////////////////////////////////////////////// template @@ -45,12 +45,20 @@ CutBrick* CutBrick::constructBrick(const char* n if (TString(regex).BeginsWith("lim")) { thebrick = new CutBrickLimit(brickregex); + } else if (TString(regex).BeginsWith("fnlim")) { + thebrick = new CutBrickFnLimit(brickregex); } else if (TString(regex).BeginsWith("th")) { thebrick = new CutBrickThreshold(brickregex); + } else if (TString(regex).BeginsWith("fnth")) { + thebrick = new CutBrickFnThreshold(brickregex); } else if (TString(regex).BeginsWith("rg")) { thebrick = new CutBrickRange(brickregex); + } else if (TString(regex).BeginsWith("fnrg")) { + thebrick = new CutBrickFnRange(brickregex); } else if (TString(regex).BeginsWith("xrg")) { thebrick = new CutBrickExtToRange(brickregex); + } else if (TString(regex).BeginsWith("fnxrg")) { + thebrick = new CutBrickFnExtToRange(brickregex); } else if (TString(regex).BeginsWith("mrg")) { thebrick = new CutBrickSelectorMultipleRanges(brickregex); } else if (TString(regex).BeginsWith("cwv")) { @@ -150,26 +158,71 @@ std::vector CutBrickLimit::IsArmed() return res; } -/// \brief Filter the passed value to update the brick status accordingly -/// \param value The value to filter -/// \return true if the value passed the cut false otherwise +templateClassImp(CutBrickLimit); +template class o2::analysis::PWGCF::CutBrickLimit; +template class o2::analysis::PWGCF::CutBrickLimit; + +/////////////////////////////////////////////////////////////////////////////////////// +/// Default constructor template -std::vector CutBrickLimit::Filter(const TValueToFilter& value) +CutBrickFnLimit::CutBrickFnLimit() + : CutBrickLimit(), + mFunction{} { - std::vector res; - if (value < mLimit) { - this->mState = this->kACTIVE; - res.push_back(true); +} + +/// Named constructor +/// \param name The name of the brick +/// \param fn The function which will provide limit value +template +CutBrickFnLimit::CutBrickFnLimit(const char* name, const TF1& fn) + : CutBrickLimit(), + mFunction(fn) +{ + this->SetName(name); +} + +/// \brief Cut string constructor +/// \param cutstr The cuts string +template +CutBrickFnLimit::CutBrickFnLimit(const TString& cutstr) + : CutBrickLimit(), + mFunction{} +{ + ConstructCutFromString(cutstr); +} + +/// \brief Construct the cut from a cut string +/// \param cutstr The cut string +/// The cut string should have the structure +/// name{fnlim{function}} +/// If the cut string is correctly parsed the cut is correctly built +/// if not a fatal exception is rised +template +void CutBrickFnLimit::ConstructCutFromString(const TString& cutstr) +{ + LOGF(info, "Cut string: %s", cutstr.Data()); + + std::regex cutregex("^(\\w+)\\{fnlim\\{([\\w\\-\\*\\/\\+\\()\\.]+)}}$", std::regex_constants::ECMAScript | std::regex_constants::icase); + std::string in(cutstr.Data()); + std::smatch m; + + std::regex_search(in, m, cutregex); + if (m.empty() or (m.size() < 3)) { + Fatal("CutBrickFnLimit::ConstructCutFromString", "Wrong RE: %s, use pT{fnlim{2.0*sin(x)/x}} for instance", cutstr.Data()); } else { - this->mState = this->kPASSIVE; - res.push_back(false); + this->SetName(m[1].str().c_str()); + this->SetTitle(cutstr.Data()); + mFunction = TF1(m[1].str().c_str(), m[2].str().c_str(), 0, 1, TF1::EAddToList::kNo); + if (not mFunction.IsValid()) { + Fatal("CutBrickFnLimit::ConstructCutFromString", "Wrong function expression: %s, use pT{fnlim{2.0*sin(x)/x}} for instance", cutstr.Data()); + } } - return res; } -templateClassImp(CutBrickLimit); -template class o2::analysis::PWGCF::CutBrickLimit; -template class o2::analysis::PWGCF::CutBrickLimit; +templateClassImp(CutBrickFnLimit); +template class o2::analysis::PWGCF::CutBrickFnLimit; +template class o2::analysis::PWGCF::CutBrickFnLimit; /////////////////////////////////////////////////////////////////////////////////////// /// Default constructor @@ -239,26 +292,71 @@ std::vector CutBrickThreshold::IsArmed() return res; } -/// \brief Filter the passed value to update the brick status accordingly -/// \param value The value to filter -/// \return true if the value passed the cut false otherwise +templateClassImp(CutBrickThreshold); +template class o2::analysis::PWGCF::CutBrickThreshold; +template class o2::analysis::PWGCF::CutBrickThreshold; + +/////////////////////////////////////////////////////////////////////////////////////// +/// Default constructor template -std::vector CutBrickThreshold::Filter(const TValueToFilter& value) +CutBrickFnThreshold::CutBrickFnThreshold() + : CutBrickThreshold(), + mFunction{} { - std::vector res; - if (mThreshold < value) { - this->mState = this->kACTIVE; - res.push_back(true); +} + +/// Named constructor +/// \param name The name of the brick +/// \param fn The function which will provide the threshold value +template +CutBrickFnThreshold::CutBrickFnThreshold(const char* name, const TF1& fn) + : CutBrickThreshold(), + mFunction(fn) +{ + this->SetName(name); +} + +/// \brief Cut string constructor +/// \param cutstr The cuts string +template +CutBrickFnThreshold::CutBrickFnThreshold(const TString& cutstr) + : CutBrickThreshold(), + mFunction{} +{ + ConstructCutFromString(cutstr); +} + +/// \brief Construct the cut from a cut string +/// \param cutstr The cut string +/// The cut string should have the structure +/// name{fnth{function}} +/// If the cut string is correctly parsed the cut is correctly built +/// if not a fatal exception is rised +template +void CutBrickFnThreshold::ConstructCutFromString(const TString& cutstr) +{ + LOGF(info, "Cut string: %s", cutstr.Data()); + + std::regex cutregex("^(\\w+)\\{fnth\\{([\\w\\-\\*\\/\\+\\()\\.]+)}}$", std::regex_constants::ECMAScript | std::regex_constants::icase); + std::string in(cutstr.Data()); + std::smatch m; + + std::regex_search(in, m, cutregex); + if (m.empty() or (m.size() < 3)) { + Fatal("CutBrickFnThreshold::ConstructCutFromString", "Wrong RE: %s, use pT{fnth{2.0*sin(x)/x}} for instance", cutstr.Data()); } else { - this->mState = this->kPASSIVE; - res.push_back(false); + this->SetName(m[1].str().c_str()); + this->SetTitle(cutstr.Data()); + mFunction = TF1(m[1].str().c_str(), m[2].str().c_str(), 0, 1, TF1::EAddToList::kNo); + if (not mFunction.IsValid()) { + Fatal("CutBrickFnThreshold::ConstructCutFromString", "Wrong function expression: %s, use pT{fnth{2.0*sin(x)/x}} for instance", cutstr.Data()); + } } - return res; } -templateClassImp(CutBrickThreshold); -template class o2::analysis::PWGCF::CutBrickThreshold; -template class o2::analysis::PWGCF::CutBrickThreshold; +templateClassImp(CutBrickFnThreshold); +template class o2::analysis::PWGCF::CutBrickFnThreshold; +template class o2::analysis::PWGCF::CutBrickFnThreshold; /////////////////////////////////////////////////////////////////////////////////////// /// Default constructor @@ -266,7 +364,7 @@ template CutBrickRange::CutBrickRange() : CutBrick(), mLow(0), - mHigh(0) + mUp(0) { } @@ -278,7 +376,7 @@ template CutBrickRange::CutBrickRange(const char* name, const TValueToFilter& low, const TValueToFilter& high) : CutBrick(name, TString::Format("%s{rg{%f,%f}}", name, float(low), float(high))), mLow(low), - mHigh(high) + mUp(high) { } @@ -288,7 +386,7 @@ template CutBrickRange::CutBrickRange(const TString& cutstr) : CutBrick(), mLow(0), - mHigh(0) + mUp(0) { ConstructCutFromString(cutstr); } @@ -315,7 +413,7 @@ void CutBrickRange::ConstructCutFromString(const TString& cutstr this->SetName(m[1].str().c_str()); this->SetTitle(cutstr.Data()); mLow = TValueToFilter(std::stod(m[2])); - mHigh = TValueToFilter(std::stod(m[3])); + mUp = TValueToFilter(std::stod(m[3])); } } @@ -333,26 +431,76 @@ std::vector CutBrickRange::IsArmed() return res; } -/// \brief Filter the passed value to update the brick status accordingly -/// \param value The value to filter -/// \return true if the value passed the cut false otherwise +templateClassImp(CutBrickRange); +template class o2::analysis::PWGCF::CutBrickRange; +template class o2::analysis::PWGCF::CutBrickRange; + +/////////////////////////////////////////////////////////////////////////////////////// +/// Default constructor template -std::vector CutBrickRange::Filter(const TValueToFilter& value) +CutBrickFnRange::CutBrickFnRange() + : CutBrickRange(), + mLowFunction{}, + mUpFunction{} { - std::vector res; - if ((mLow < value) and (value < mHigh)) { - this->mState = this->kACTIVE; - res.push_back(true); +} + +/// Named constructor +/// \param name The name of the brick +/// \param lowfn The function which will provide the low value for the cut range +/// \param upfn The function which will provide the upper value for the cut range +template +CutBrickFnRange::CutBrickFnRange(const char* name, const TF1& lowfn, const TF1& upfn) + : CutBrickRange(), + mLowFunction{lowfn}, + mUpFunction{upfn} +{ + this->SetName(name); +} + +/// \brief Cut string constructor +/// \param cutstr The cuts string +template +CutBrickFnRange::CutBrickFnRange(const TString& cutstr) + : CutBrickRange(), + mLowFunction{}, + mUpFunction{} +{ + ConstructCutFromString(cutstr); +} + +/// \brief Construct the cut from a cut string +/// \param cutstr The cut string +/// The cut string should have the structure +/// name{fnrg{lowfn,highfn}} +/// If the cut string is correctly parsed the cut is correctly built +/// if not a fatal exception is rised +template +void CutBrickFnRange::ConstructCutFromString(const TString& cutstr) +{ + LOGF(info, "Cut string: %s", cutstr.Data()); + + std::regex cutregex("^(\\w+)\\{fnrg\\{([\\w\\-\\*\\/\\+\\()\\.]+),([\\w\\-\\*\\/\\+\\()\\.]+)}}$", std::regex_constants::ECMAScript | std::regex_constants::icase); + std::string in(cutstr.Data()); + std::smatch m; + + std::regex_search(in, m, cutregex); + if (m.empty() or (m.size() < 4)) { + Fatal("CutBrickFnRange::ConstructCutFromString", "Wrong RE: %s, use pT{fnrg{2.0*sin(x)/x}} for instance", cutstr.Data()); } else { - this->mState = this->kPASSIVE; - res.push_back(false); + this->SetName(m[1].str().c_str()); + this->SetTitle(cutstr.Data()); + mLowFunction = TF1(TString::Format("%s_low", m[1].str().c_str()), m[2].str().c_str(), 0, 1, TF1::EAddToList::kNo); + mUpFunction = TF1(TString::Format("%s_up", m[1].str().c_str()), m[3].str().c_str(), 0, 1, TF1::EAddToList::kNo); + if (not mLowFunction.IsValid() or not mUpFunction.IsValid()) { + Fatal("CutBrickFnRange::ConstructCutFromString", "Wrong function expression: %s, use pT{fnrg{2.0*sin(x)/x}} for instance", cutstr.Data()); + } } - return res; } -templateClassImp(CutBrickRange); -template class o2::analysis::PWGCF::CutBrickRange; -template class o2::analysis::PWGCF::CutBrickRange; +templateClassImp(CutBrickFnRange); +template class o2::analysis::PWGCF::CutBrickFnRange; +template class o2::analysis::PWGCF::CutBrickFnRange; /////////////////////////////////////////////////////////////////////////////////////// /// Default constructor @@ -360,7 +508,7 @@ template CutBrickExtToRange::CutBrickExtToRange() : CutBrick(), mLow(0), - mHigh(0) + mUp(0) { } @@ -372,7 +520,7 @@ template CutBrickExtToRange::CutBrickExtToRange(const char* name, const TValueToFilter& low, const TValueToFilter& high) : CutBrick(name, TString::Format("%s{xrg{%f,%f}}", name, float(low), float(high))), mLow(low), - mHigh(high) + mUp(high) { } @@ -382,7 +530,7 @@ template CutBrickExtToRange::CutBrickExtToRange(const TString& cutstr) : CutBrick(), mLow(0), - mHigh(0) + mUp(0) { ConstructCutFromString(cutstr); } @@ -409,7 +557,7 @@ void CutBrickExtToRange::ConstructCutFromString(const TString& c this->SetName(m[1].str().c_str()); this->SetTitle(cutstr.Data()); mLow = TValueToFilter(std::stod(m[2])); - mHigh = TValueToFilter(std::stod(m[3])); + mUp = TValueToFilter(std::stod(m[3])); } } @@ -427,26 +575,75 @@ std::vector CutBrickExtToRange::IsArmed() return res; } -/// \brief Filter the passed value to update the brick status accordingly -/// \param value The value to filter -/// \return true if the value passed the cut false otherwise +templateClassImp(CutBrickExtToRange); +template class o2::analysis::PWGCF::CutBrickExtToRange; +template class o2::analysis::PWGCF::CutBrickExtToRange; + +/////////////////////////////////////////////////////////////////////////////////////// +/// Default constructor template -std::vector CutBrickExtToRange::Filter(const TValueToFilter& value) +CutBrickFnExtToRange::CutBrickFnExtToRange() + : CutBrickExtToRange(), + mLowFunction{}, + mUpFunction{} { - std::vector res; - if ((value < mLow) or (mHigh < value)) { - this->mState = this->kACTIVE; - res.push_back(true); +} + +/// Named constructor +/// \param name The name of the brick +/// \param lowfn The function which will provide the low value for the cut excluded range +/// \param upfn The function which will provide the upper value for the cut excluded range +template +CutBrickFnExtToRange::CutBrickFnExtToRange(const char* name, const TF1& lowfn, const TF1& upfn) + : CutBrickExtToRange(), + mLowFunction{lowfn}, + mUpFunction{upfn} +{ +} + +/// \brief Cut string constructor +/// \param cutstr The cuts string +template +CutBrickFnExtToRange::CutBrickFnExtToRange(const TString& cutstr) + : CutBrickExtToRange(), + mLowFunction{}, + mUpFunction{} +{ + ConstructCutFromString(cutstr); +} + +/// \brief Construct the cut from a cut string +/// \param cutstr The cut string +/// The cut string should have the structure +/// name{fnxrg{low,high}} +/// If the cut string is correctly parsed the cut is correctly built +/// if not a fatal exception is rised +template +void CutBrickFnExtToRange::ConstructCutFromString(const TString& cutstr) +{ + LOGF(info, "Cut string: %s", cutstr.Data()); + + std::regex cutregex("^(\\w+)\\{fnxrg\\{([\\w\\-\\*\\/\\+\\()\\.]+),([\\w\\-\\*\\/\\+\\()\\.]+)}}$", std::regex_constants::ECMAScript | std::regex_constants::icase); + std::string in(cutstr.Data()); + std::smatch m; + + std::regex_search(in, m, cutregex); + if (m.empty() or (m.size() < 4)) { + Fatal("CutBrickFnExtToRange::ConstructCutFromString", "Wrong RE: %s, use pT{fnxrg{2.0*sin(x)/x}} for instance", cutstr.Data()); } else { - this->mState = this->kPASSIVE; - res.push_back(false); + this->SetName(m[1].str().c_str()); + this->SetTitle(cutstr.Data()); + mLowFunction = TF1(TString::Format("%s_low", m[1].str().c_str()), m[2].str().c_str(), 0, 1, TF1::EAddToList::kNo); + mUpFunction = TF1(TString::Format("%s_up", m[1].str().c_str()), m[3].str().c_str(), 0, 1, TF1::EAddToList::kNo); + if (not mLowFunction.IsValid() or not mUpFunction.IsValid()) { + Fatal("CutBrickFnExtToRange::ConstructCutFromString", "Wrong function expression: %s, use pT{fnxrg{2.0*sin(x)/x}} for instance", cutstr.Data()); + } } - return res; } -templateClassImp(CutBrickExtToRange); -template class o2::analysis::PWGCF::CutBrickExtToRange; -template class o2::analysis::PWGCF::CutBrickExtToRange; +templateClassImp(CutBrickFnExtToRange); +template class o2::analysis::PWGCF::CutBrickFnExtToRange; +template class o2::analysis::PWGCF::CutBrickFnExtToRange; /////////////////////////////////////////////////////////////////////////////////////// /// Default constructor diff --git a/PWGCF/TwoParticleCorrelations/Core/SkimmingConfigurableCuts.h b/PWGCF/TwoParticleCorrelations/Core/SkimmingConfigurableCuts.h index e9a91635053..dc90065c0a8 100644 --- a/PWGCF/TwoParticleCorrelations/Core/SkimmingConfigurableCuts.h +++ b/PWGCF/TwoParticleCorrelations/Core/SkimmingConfigurableCuts.h @@ -17,11 +17,13 @@ #include #include #include +#include #include #include #include #include +#include #include "Framework/DataTypes.h" namespace o2 @@ -68,6 +70,12 @@ class CutBrick : public TNamed /// Set the status of the cut significative (or not) for the selection chain void Arm(bool doit = true) { doit ? mMode = kSELECTED : mMode = kUNSELECTED; } + /// Setting the value of independent variable for cuts with function levels + /// The default behavior is to raise a fatal exception + virtual void setIndependentFnVar(float) + { + LOGF(fatal, "CutBrick::setIndependentFnVar(). The brick you are using %s does not accept setting the independent variable value"); + } protected: /// \enum BrickStatus @@ -110,10 +118,56 @@ class CutBrickLimit : public CutBrick private: void ConstructCutFromString(const TString&); + protected: TValueToFilter mLimit; ///< the limiting upper value + private: ClassDef(CutBrickLimit, 1); }; +/// \brief Filter the passed value to update the brick status accordingly +/// \param value The value to filter +/// \return true if the value passed the cut false otherwise +template +inline std::vector CutBrickLimit::Filter(const TValueToFilter& value) +{ + std::vector res; + if (value < mLimit) { + this->mState = this->kACTIVE; + res.push_back(true); + } else { + this->mState = this->kPASSIVE; + res.push_back(false); + } + return res; +} + +/// \class CutBrickFnLimit +/// \brief Class which implements a function based limiting cut brick. +/// The brick will be active if the filtered value is below the limit +template +class CutBrickFnLimit : public CutBrickLimit +{ + public: + CutBrickFnLimit(); + CutBrickFnLimit(const char*, const TF1&); + CutBrickFnLimit(const TString&); + virtual ~CutBrickFnLimit() override = default; + CutBrickFnLimit(const CutBrickFnLimit&) = delete; + CutBrickFnLimit& operator=(const CutBrickFnLimit&) = delete; + + /// sets the value of the limit according the passed variable value + virtual void setIndependentFnVar(float x) override + { + this->mLimit = TValueToFilter(mFunction.Eval(x)); + } + + private: + void ConstructCutFromString(const TString&); + + TF1 mFunction; ///< the function for evaluating the limit value + ClassDef(CutBrickFnLimit, 1); +}; + /// \class CutBrickThreshold /// \brief Class which implements a threshold cut brick. /// The brick will be active if the filtered value is above the threshold @@ -135,10 +189,56 @@ class CutBrickThreshold : public CutBrick private: void ConstructCutFromString(const TString&); + protected: TValueToFilter mThreshold; ///< the threshold value + private: ClassDef(CutBrickThreshold, 1); }; +/// \brief Filter the passed value to update the brick status accordingly +/// \param value The value to filter +/// \return true if the value passed the cut false otherwise +template +inline std::vector CutBrickThreshold::Filter(const TValueToFilter& value) +{ + std::vector res; + if (mThreshold < value) { + this->mState = this->kACTIVE; + res.push_back(true); + } else { + this->mState = this->kPASSIVE; + res.push_back(false); + } + return res; +} + +/// \class CutBrickFnThreshold +/// \brief Class which implements a function based threshold cut brick. +/// The brick will be active if the filtered value is above the threshold +template +class CutBrickFnThreshold : public CutBrickThreshold +{ + public: + CutBrickFnThreshold(); + CutBrickFnThreshold(const char*, const TF1&); + CutBrickFnThreshold(const TString&); + virtual ~CutBrickFnThreshold() override = default; + CutBrickFnThreshold(const CutBrickFnThreshold&) = delete; + CutBrickFnThreshold& operator=(const CutBrickFnThreshold&) = delete; + + /// sets the value of the threshold according the passed variable value + virtual void setIndependentFnVar(float x) override + { + this->mThreshold = TValueToFilter(mFunction.Eval(x)); + } + + private: + void ConstructCutFromString(const TString&); + + TF1 mFunction; ///< the function for evaluate the threshold value + ClassDef(CutBrickFnThreshold, 1); +}; + /// \class CutBrickRange /// \brief Class which implements a range cut brick. /// The brick will be active if the filtered value is within the range @@ -160,11 +260,59 @@ class CutBrickRange : public CutBrick private: void ConstructCutFromString(const TString&); + protected: TValueToFilter mLow; ///< the lower value of the range - TValueToFilter mHigh; ///< the upper value of the range + TValueToFilter mUp; ///< the upper value of the range + private: ClassDef(CutBrickRange, 1); }; +/// \brief Filter the passed value to update the brick status accordingly +/// \param value The value to filter +/// \return true if the value passed the cut false otherwise +template +std::vector CutBrickRange::Filter(const TValueToFilter& value) +{ + std::vector res; + if ((mLow < value) and (value < mUp)) { + this->mState = this->kACTIVE; + res.push_back(true); + } else { + this->mState = this->kPASSIVE; + res.push_back(false); + } + return res; +} + +/// \class CutBrickFnRange +/// \brief Class which implements a function based range cut brick. +/// The brick will be active if the filtered value is within the range +template +class CutBrickFnRange : public CutBrickRange +{ + public: + CutBrickFnRange(); + CutBrickFnRange(const char*, const TF1&, const TF1&); + CutBrickFnRange(const TString&); + virtual ~CutBrickFnRange() override = default; + CutBrickFnRange(const CutBrickFnRange&) = delete; + CutBrickFnRange& operator=(const CutBrickFnRange&) = delete; + + /// sets the value of the limits according the passed variable value + virtual void setIndependentFnVar(float x) override + { + this->mLow = TValueToFilter(mLowFunction.Eval(x)); + this->mUp = TValueToFilter(mUpFunction.Eval(x)); + } + + private: + void ConstructCutFromString(const TString&); + + TF1 mLowFunction; ///< the function for evaluating the low limit value + TF1 mUpFunction; ///< the function for evaluating the upper limit value + ClassDef(CutBrickFnRange, 1); +}; + /// \class CutBrickExtToRange /// \brief Class which implements an external to range cut brick. /// The brick will be active if the filtered value is outside the range @@ -186,11 +334,59 @@ class CutBrickExtToRange : public CutBrick private: void ConstructCutFromString(const TString&); + protected: TValueToFilter mLow; ///< the lower value of the range - TValueToFilter mHigh; ///< the upper value of the range + TValueToFilter mUp; ///< the upper value of the range + private: ClassDef(CutBrickExtToRange, 1); }; +/// \brief Filter the passed value to update the brick status accordingly +/// \param value The value to filter +/// \return true if the value passed the cut false otherwise +template +std::vector CutBrickExtToRange::Filter(const TValueToFilter& value) +{ + std::vector res; + if ((value < mLow) or (mUp < value)) { + this->mState = this->kACTIVE; + res.push_back(true); + } else { + this->mState = this->kPASSIVE; + res.push_back(false); + } + return res; +} + +/// \class CutBrickExtToRange +/// \brief Class which implements an external to function base range cut brick. +/// The brick will be active if the filtered value is outside the range +template +class CutBrickFnExtToRange : public CutBrickExtToRange +{ + public: + CutBrickFnExtToRange(); + CutBrickFnExtToRange(const char*, const TF1&, const TF1&); + CutBrickFnExtToRange(const TString&); + virtual ~CutBrickFnExtToRange() override = default; + CutBrickFnExtToRange(const CutBrickFnExtToRange&) = delete; + CutBrickFnExtToRange& operator=(const CutBrickFnExtToRange&) = delete; + + /// sets the value of the limits according the passed variable value + virtual void setIndependentFnVar(float x) override + { + this->mLow = TValueToFilter(mLowFunction.Eval(x)); + this->mUp = TValueToFilter(mUpFunction.Eval(x)); + } + + private: + void ConstructCutFromString(const TString&); + + TF1 mLowFunction; ///< the function for evaluating the low limit value + TF1 mUpFunction; ///< the function for evaluating the upper limit value + ClassDef(CutBrickFnExtToRange, 1); +}; + /// \class CutBrickSelectorMultipleRanges /// \brief Class which implements a string as selector an multiple ranges /// The brick will be active if the filtered value is inside any of the multiple ranges diff --git a/PWGCF/TwoParticleCorrelations/Core/TwoPartCorrLinkDef.h b/PWGCF/TwoParticleCorrelations/Core/TwoPartCorrLinkDef.h index 4fa46994eda..642cc2162fb 100644 --- a/PWGCF/TwoParticleCorrelations/Core/TwoPartCorrLinkDef.h +++ b/PWGCF/TwoParticleCorrelations/Core/TwoPartCorrLinkDef.h @@ -17,12 +17,20 @@ #pragma link C++ class o2::analysis::PWGCF::CutBrick < int> + ; #pragma link C++ class o2::analysis::PWGCF::CutBrickLimit < float> + ; #pragma link C++ class o2::analysis::PWGCF::CutBrickLimit < int> + ; +#pragma link C++ class o2::analysis::PWGCF::CutBrickFnLimit < float> + ; +#pragma link C++ class o2::analysis::PWGCF::CutBrickFnLimit < int> + ; #pragma link C++ class o2::analysis::PWGCF::CutBrickThreshold < float> + ; #pragma link C++ class o2::analysis::PWGCF::CutBrickThreshold < int> + ; +#pragma link C++ class o2::analysis::PWGCF::CutBrickFnThreshold < float> + ; +#pragma link C++ class o2::analysis::PWGCF::CutBrickFnThreshold < int> + ; #pragma link C++ class o2::analysis::PWGCF::CutBrickExtToRange < float> + ; -#pragma link C++ class o2::analysis::PWGCF::CutBrickRange < int> + ; -#pragma link C++ class o2::analysis::PWGCF::CutBrickRange < float> + ; #pragma link C++ class o2::analysis::PWGCF::CutBrickExtToRange < int> + ; +#pragma link C++ class o2::analysis::PWGCF::CutBrickFnExtToRange < float> + ; +#pragma link C++ class o2::analysis::PWGCF::CutBrickFnExtToRange < int> + ; +#pragma link C++ class o2::analysis::PWGCF::CutBrickRange < float> + ; +#pragma link C++ class o2::analysis::PWGCF::CutBrickRange < int> + ; +#pragma link C++ class o2::analysis::PWGCF::CutBrickFnRange < float> + ; +#pragma link C++ class o2::analysis::PWGCF::CutBrickFnRange < int> + ; #pragma link C++ class o2::analysis::PWGCF::CutBrickSelectorMultipleRanges < float> + ; #pragma link C++ class o2::analysis::PWGCF::CutBrickSelectorMultipleRanges < int> + ; #pragma link C++ class o2::analysis::PWGCF::CutWithVariations < float> + ; From d7155ad9835c8583a8532308e6f09113176cc2db Mon Sep 17 00:00:00 2001 From: ALICE Action Bot Date: Tue, 4 Oct 2022 09:00:03 +0000 Subject: [PATCH 18/20] Please consider the following formatting changes --- .../Core/SkimmingConfigurableCuts.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/PWGCF/TwoParticleCorrelations/Core/SkimmingConfigurableCuts.h b/PWGCF/TwoParticleCorrelations/Core/SkimmingConfigurableCuts.h index dc90065c0a8..b0f591f11dd 100644 --- a/PWGCF/TwoParticleCorrelations/Core/SkimmingConfigurableCuts.h +++ b/PWGCF/TwoParticleCorrelations/Core/SkimmingConfigurableCuts.h @@ -261,8 +261,8 @@ class CutBrickRange : public CutBrick void ConstructCutFromString(const TString&); protected: - TValueToFilter mLow; ///< the lower value of the range - TValueToFilter mUp; ///< the upper value of the range + TValueToFilter mLow; ///< the lower value of the range + TValueToFilter mUp; ///< the upper value of the range private: ClassDef(CutBrickRange, 1); }; @@ -335,8 +335,8 @@ class CutBrickExtToRange : public CutBrick void ConstructCutFromString(const TString&); protected: - TValueToFilter mLow; ///< the lower value of the range - TValueToFilter mUp; ///< the upper value of the range + TValueToFilter mLow; ///< the lower value of the range + TValueToFilter mUp; ///< the upper value of the range private: ClassDef(CutBrickExtToRange, 1); }; From c595f9e49af6aad4cbaf86efe8473b15113a612e Mon Sep 17 00:00:00 2001 From: Victor Date: Sat, 8 Oct 2022 01:29:18 +0200 Subject: [PATCH 19/20] Advanced pile-up rejection based on multiplicity correlators --- .../Core/EventSelectionFilterAndAnalysis.cxx | 236 +++++++++++------- .../Core/EventSelectionFilterAndAnalysis.h | 207 +++++++++------ .../Core/SkimmingConfigurableCuts.cxx | 82 +++--- .../Core/SkimmingConfigurableCuts.h | 1 + .../Core/TwoPartCorrLinkDef.h | 3 + .../TableProducer/skimmingconf.h | 5 +- .../twoParticleCorrelationsSkimming.cxx | 13 +- 7 files changed, 342 insertions(+), 205 deletions(-) diff --git a/PWGCF/TwoParticleCorrelations/Core/EventSelectionFilterAndAnalysis.cxx b/PWGCF/TwoParticleCorrelations/Core/EventSelectionFilterAndAnalysis.cxx index 71ec3108224..d348d3dd5e0 100644 --- a/PWGCF/TwoParticleCorrelations/Core/EventSelectionFilterAndAnalysis.cxx +++ b/PWGCF/TwoParticleCorrelations/Core/EventSelectionFilterAndAnalysis.cxx @@ -77,13 +77,15 @@ EventSelectionConfigurable::EventSelectionConfigurable(std::vector mMultSel = storeCutString(multsel, "centmult"); mTriggerSel = storeCutString(trigsel, "trigger"); mZVertexSel = storeCutString(zvtxsel, "zvtx"); - mPileUpRejection = storeCutString(pileuprej, "pileup"); + mPileUpRejection = storeCutString(pileuprej, "pileuprej"); } ClassImp(EventSelectionFilterAndAnalysis); const int nNoOfMultiplicityEstimators = 3; const char* multiplicityEstimators[nNoOfMultiplicityEstimators] = {"V0M", "CL0", "CL1"}; +const int nNoOfPileUpCorrelators = 3; +const char* multiplicityCorrelators[nNoOfPileUpCorrelators] = {"V0M_TPCOUT", "V0M_TRKLETS", "V0M_TPCCLSTS"}; /// \brief Default constructor EventSelectionFilterAndAnalysis::EventSelectionFilterAndAnalysis() @@ -92,10 +94,7 @@ EventSelectionFilterAndAnalysis::EventSelectionFilterAndAnalysis() mMultiplicityClasses(nullptr), mTriggerSelection(nullptr), mZVertex(nullptr), - mPileUpRejection(nullptr), - mMultiplicities{}, - mDefaultMultiplicityEstimatorIndex(-1), - mAlternateMultiplicityEstimatorIndex{} + mPileUpRejection(nullptr) { } @@ -106,10 +105,7 @@ EventSelectionFilterAndAnalysis::EventSelectionFilterAndAnalysis(const TString& mMultiplicityClasses(nullptr), mTriggerSelection(nullptr), mZVertex(nullptr), - mPileUpRejection(nullptr), - mMultiplicities{}, - mDefaultMultiplicityEstimatorIndex(-1), - mAlternateMultiplicityEstimatorIndex{} + mPileUpRejection(nullptr) { ConstructCutFromString(cutstr); } @@ -121,10 +117,7 @@ EventSelectionFilterAndAnalysis::EventSelectionFilterAndAnalysis(const EventSele mMultiplicityClasses(nullptr), mTriggerSelection(nullptr), mZVertex(nullptr), - mPileUpRejection(nullptr), - mMultiplicities{}, - mDefaultMultiplicityEstimatorIndex(-1), - mAlternateMultiplicityEstimatorIndex{} + mPileUpRejection(nullptr) { TString cutString = "eventsel{"; bool first = true; @@ -178,63 +171,116 @@ int EventSelectionFilterAndAnalysis::CalculateMaskLength() return length; } -void EventSelectionFilterAndAnalysis::InitializeMultiplicityFilter() +void EventSelectionFilterAndAnalysis::MultiplicityBrick::initialize() { /* initialize the storage of multiplicities from the differente estimators */ for (int i = 0; i < nNoOfMultiplicityEstimators; ++i) { - mMultiplicities.push_back(-1); + mValues.push_back(-1); } /* now initialize the filter machinery */ - if (mMultiplicityClasses != nullptr) { - if (mMultiplicityClasses->IsA() != CutWithVariations::Class()) { - /* no alternative estimators, just the default */ - LOGF(info, "Searching for default multiplicity estimator %s", mMultiplicityClasses->GetName()); - for (int i = 0; i < nNoOfMultiplicityEstimators; ++i) { - LOGF(info, "Checking multiplicity estimator %s", multiplicityEstimators[i]); - if (strcmp(multiplicityEstimators[i], mMultiplicityClasses->GetName()) == 0) { - mDefaultMultiplicityEstimatorIndex = i; - break; - } - } - if (mDefaultMultiplicityEstimatorIndex < 0) { - LOGF(fatal, "EventSelectionFilterAndAnalysis::InitializeMultiplicityFilter() default multiplicity class estimator not implemented"); + if (mBrick->IsA() != CutWithVariations::Class()) { + /* no alternative estimators, just the default */ + LOGF(info, "Searching for default multiplicity estimator %s", mBrick->GetName()); + for (int i = 0; i < nNoOfMultiplicityEstimators; ++i) { + LOGF(info, "Checking multiplicity estimator %s", multiplicityEstimators[i]); + if (strcmp(multiplicityEstimators[i], mBrick->GetName()) == 0) { + mDefaultEstimatorIndex = i; + break; } - } else { - /* we have alternative estimators our brick is of kind cwv */ - /* first the default */ - TList& deflst = dynamic_cast*>(mMultiplicityClasses)->getDefaultBricks(); - if (deflst.GetEntries() > 1) { - LOGF(fatal, "EventSelectionFilterAndAnalysis::InitializeMultiplicityFilter() expected only one default multiplicity class estimator"); + } + if (mDefaultEstimatorIndex < 0) { + LOGF(fatal, "EventSelectionFilterAndAnalysis::InitializeMultiplicityFilter() default multiplicity class estimator not implemented"); + } + } else { + /* we have alternative estimators our brick is of kind cwv */ + /* first the default */ + TList& deflst = dynamic_cast*>(mBrick)->getDefaultBricks(); + if (deflst.GetEntries() > 1) { + LOGF(fatal, "EventSelectionFilterAndAnalysis::InitializeMultiplicityFilter() expected only one default multiplicity class estimator"); + } + LOGF(info, "Searching for default multiplicity estimator %s", deflst.At(0)->GetName()); + for (int i = 0; i < nNoOfMultiplicityEstimators; ++i) { + LOGF(info, "Checking multiplicity estimator %s", multiplicityEstimators[i]); + if (strcmp(multiplicityEstimators[i], deflst.At(0)->GetName()) == 0) { + mDefaultEstimatorIndex = i; + break; } - LOGF(info, "Searching for default multiplicity estimator %s", deflst.At(0)->GetName()); + } + if (mDefaultEstimatorIndex < 0) { + LOGF(fatal, "EventSelectionFilterAndAnalysis::InitializeMultiplicityFilter() default multiplicity class estimator not implemented"); + } + /* and now the variants */ + TList& varlst = dynamic_cast*>(mBrick)->getVariantBricks(); + for (int ivar = 0; ivar < varlst.GetEntries(); ++ivar) { + LOGF(info, "Searching for variant multiplicity estimator %s", varlst.At(ivar)->GetName()); for (int i = 0; i < nNoOfMultiplicityEstimators; ++i) { LOGF(info, "Checking multiplicity estimator %s", multiplicityEstimators[i]); - if (strcmp(multiplicityEstimators[i], deflst.At(0)->GetName()) == 0) { - mDefaultMultiplicityEstimatorIndex = i; + if (strcmp(multiplicityEstimators[i], varlst.At(ivar)->GetName()) == 0) { + mAlternateEstimatorIndex.push_back(i); break; } } - if (mDefaultMultiplicityEstimatorIndex < 0) { - LOGF(fatal, "EventSelectionFilterAndAnalysis::InitializeMultiplicityFilter() default multiplicity class estimator not implemented"); + } + if (mAlternateEstimatorIndex.size() != (uint)(varlst.GetEntries())) { + LOGF(fatal, "EventSelectionFilterAndAnalysis::InitializeMultiplicityFilter() variant multiplicity class estimators not all implemented"); + } + } +} + +void EventSelectionFilterAndAnalysis::PileUpRejBrick::initialize() +{ + /* initialize the storage of multiplicities from the differente pile-up correlator estimators */ + for (int i = 0; i < nNoOfPileUpCorrelators; ++i) { + mValues.push_back(-1); + mIndepVar.push_back(-1); + } + /* now initialize the filter machinery */ + if (mBrick->IsA() != CutWithVariations::Class()) { + /* no alternative estimators, just the default */ + LOGF(info, "Searching for default pile-up correlator estimator %s", mBrick->GetName()); + for (int i = 0; i < nNoOfPileUpCorrelators; ++i) { + LOGF(info, "Checking pile-up correlator estimator %s", multiplicityCorrelators[i]); + if (strcmp(multiplicityCorrelators[i], mBrick->GetName()) == 0) { + mDefaultEstimatorIndex = i; + break; } - /* and now the variants */ - TList& varlst = dynamic_cast*>(mMultiplicityClasses)->getVariantBricks(); - for (int ivar = 0; ivar < varlst.GetEntries(); ++ivar) { - LOGF(info, "Searching for variant multiplicity estimator %s", varlst.At(ivar)->GetName()); - for (int i = 0; i < nNoOfMultiplicityEstimators; ++i) { - LOGF(info, "Checking multiplicity estimator %s", multiplicityEstimators[i]); - if (strcmp(multiplicityEstimators[i], varlst.At(ivar)->GetName()) == 0) { - mAlternateMultiplicityEstimatorIndex.push_back(i); - break; - } - } + } + if (mDefaultEstimatorIndex < 0) { + LOGF(fatal, "EventSelectionFilterAndAnalysis::InitializeMultiplicityFilter() default pile-up correlator estimator not implemented"); + } + } else { + /* we have alternative estimators our brick is of kind cwv */ + /* first the default */ + TList& deflst = dynamic_cast*>(mBrick)->getDefaultBricks(); + if (deflst.GetEntries() > 1) { + LOGF(fatal, "EventSelectionFilterAndAnalysis::InitializeMultiplicityFilter() expected only one default multiplicity class estimator"); + } + LOGF(info, "Searching for default pile-up correlator estimator %s", deflst.At(0)->GetName()); + for (int i = 0; i < nNoOfPileUpCorrelators; ++i) { + LOGF(info, "Checking pile-up correlator estimator %s", multiplicityCorrelators[i]); + if (strcmp(multiplicityCorrelators[i], deflst.At(0)->GetName()) == 0) { + mDefaultEstimatorIndex = i; + break; } - if (mAlternateMultiplicityEstimatorIndex.size() != (uint)(varlst.GetEntries())) { - LOGF(fatal, "EventSelectionFilterAndAnalysis::InitializeMultiplicityFilter() variant multiplicity class estimators not all implemented"); + } + if (mDefaultEstimatorIndex < 0) { + LOGF(fatal, "EventSelectionFilterAndAnalysis::InitializeMultiplicityFilter() default pile-up correlator estimator not implemented"); + } + /* and now the variants */ + TList& varlst = dynamic_cast*>(mBrick)->getVariantBricks(); + for (int ivar = 0; ivar < varlst.GetEntries(); ++ivar) { + LOGF(info, "Searching for variant pile-up correlator estimator %s", varlst.At(ivar)->GetName()); + for (int i = 0; i < nNoOfPileUpCorrelators; ++i) { + LOGF(info, "Checking pile-up correlator estimator %s", multiplicityCorrelators[i]); + if (strcmp(multiplicityCorrelators[i], varlst.At(ivar)->GetName()) == 0) { + mAlternateEstimatorIndex.push_back(i); + break; + } } } - } else { - LOGF(fatal, "EventSelectionFilterAndAnalysis::InitializeMultiplicityFilter expected a multiplicity filter but it is not there"); + if (mAlternateEstimatorIndex.size() != (uint)(varlst.GetEntries())) { + LOGF(fatal, "EventSelectionFilterAndAnalysis::InitializeMultiplicityFilter() variant pile-up correlator estimators not all implemented"); + } } } @@ -242,13 +288,13 @@ void EventSelectionFilterAndAnalysis::ConstructCutFromString(const TString& cuts { LOGF(info, "Cut string: %s", cutstr); /* let's catch the first level */ - regex cutregex("^eventsel\\{?(\\w+\\{[\\w\\d.,:{}-]+})*}$", regex_constants::ECMAScript | regex_constants::icase); + regex cutregex("^eventsel\\{?(\\w+\\{[\\w\\d.,:{}=\\-\\+\\*\\/]+})*}$", regex_constants::ECMAScript | regex_constants::icase); std::string in(cutstr.Data()); smatch m; bool res = regex_search(in, m, cutregex); if (not res or m.empty() or (m.size() > 2)) { - Fatal("EventSelectionFilterAndAnalysis::::ConstructCutFromString", "Wrong RE: %s, try tracksel{ttype{FB32,FB96};ncls{th{70}},nxr{cwv{th{70},th{80}}}} for instance", cutstr.Data()); + LOGF(fatal, "EventSelectionFilterAndAnalysis::ConstructCutFromString", "Wrong RE: %s, try eventsel{bfield{positive-yes,negative-yes},zvtx{cwv{rg{-7.0,7.0}-yes:rg{-10.0,10.0}-no,rg{-3.0,3.0}-no}}} for instance", cutstr.Data()); } this->SetName("EventSelectionFilterAndAnalysisCuts"); this->SetTitle(cutstr.Data()); @@ -258,7 +304,7 @@ void EventSelectionFilterAndAnalysis::ConstructCutFromString(const TString& cuts LOGF(info, "Captured %s", m[1].str().c_str()); TString lev2str = m[1].str(); while (lev2str.Length() != 0) { - std::set allowed = {"lim", "th", "rg", "xrg", "cwv", "mrg"}; + std::set allowed = {"lim", "th", "rg", "xrg", "fnlim", "fnth", "fnrg", "fnxrg", "cwv", "mrg"}; lev2str.Remove(TString::kLeading, ' '); lev2str.Remove(TString::kLeading, ','); lev2str.Remove(TString::kLeading, ' '); @@ -313,14 +359,17 @@ void EventSelectionFilterAndAnalysis::ConstructCutFromString(const TString& cuts if (m[1].str() == "bfield") { storeBFieldCut(mBFieldSelection); } else if (m[1].str() == "centmult") { - storeFloatCut(mMultiplicityClasses); - InitializeMultiplicityFilter(); + mMultiplicityClasses = new MultiplicityBrick(); + storeFloatCut(mMultiplicityClasses->mBrick); + mMultiplicityClasses->initialize(); } else if (m[1].str() == "mtrigg") { storeIntCut(mTriggerSelection); } else if (m[1].str() == "zvtx") { storeFloatCut(mZVertex); - } else if (m[1].str() == "pileup") { - storeIntCut(mPileUpRejection); + } else if (m[1].str() == "pileuprej") { + mPileUpRejection = new PileUpRejBrick(); + storeFloatCut(mPileUpRejection->mBrick); + mPileUpRejection->initialize(); } /* removing the already handled event characteristics cut */ lev2str.Remove(0, m[0].length()); @@ -329,6 +378,46 @@ void EventSelectionFilterAndAnalysis::ConstructCutFromString(const TString& cuts mMaskLength = CalculateMaskLength(); } +/// +void EventSelectionFilterAndAnalysis::ComplexBrickHelper::armedBrick(uint64_t& armedmask, uint64_t& optmask, uint64_t& forcedmask, int& bit) +{ + auto armedBrick = [&](auto brick, bool opt = false) { + std::vector res = brick->IsArmed(); + for (auto b : res) { + if (b) { + SETBIT(armedmask, bit); + if (opt) { + SETBIT(optmask, bit); + } else { + SETBIT(forcedmask, bit); + } + } + bit++; + } + }; + + if (mAlternateEstimatorIndex.size() > 0) { + /* we have alternative estimators so our brick is of kind cwv */ + if (mBrick->IsA() != CutWithVariations::Class()) { + LOGF(fatal, "EventSelectionFilterAndAnalysis::Filter() expected class with variations cut but it is not there"); + } + /* first the default */ + TList& deflst = dynamic_cast*>(mBrick)->getDefaultBricks(); + if (deflst.GetEntries() > 1) { + LOGF(fatal, "EventSelectionFilterAndAnalysis::Filter() expected only one default multiplicity class estimator"); + } + armedBrick((CutBrick*)deflst.At(0), true); + /* and now the variants */ + TList& varlst = dynamic_cast*>(mBrick)->getVariantBricks(); + for (int i = 0; i < varlst.GetEntries(); ++i) { + armedBrick((CutBrick*)varlst.At(i), true); + } + } else { + /* no alternative estimators, just the default */ + armedBrick(mBrick, true); + } +} + /// \brief Fills the filter cuts mask void EventSelectionFilterAndAnalysis::StoreArmedMask() { @@ -362,29 +451,7 @@ void EventSelectionFilterAndAnalysis::StoreArmedMask() mOptArmedMask.push_back(optMask); optMask = 0UL; if (mMultiplicityClasses != nullptr) { - if (mAlternateMultiplicityEstimatorIndex.size() > 0) { - /* we have alternative estimators so our brick is of kind cwv */ - if (mMultiplicityClasses->IsA() != CutWithVariations::Class()) { - LOGF(fatal, "EventSelectionFilterAndAnalysis::Filter() expected class with variations cut but it is not there"); - } - /* first the default */ - TList& deflst = dynamic_cast*>(mMultiplicityClasses)->getDefaultBricks(); - if (deflst.GetEntries() > 1) { - LOGF(fatal, "EventSelectionFilterAndAnalysis::Filter() expected only one default multiplicity class estimator"); - } - armedBrick((CutBrick*)deflst.At(0), true); - /* and now the variants */ - TList& varlst = dynamic_cast*>(mMultiplicityClasses)->getVariantBricks(); - for (int i = 0; i < varlst.GetEntries(); ++i) { - if (varlst.At(i)->IsA() != CutBrickSelectorMultipleRanges::Class()) { - LOGF(fatal, "EventSelectionFilterAndAnalysis::Filter, expected a multirange selector"); - } - armedBrick((CutBrick*)varlst.At(i), true); - } - } else { - /* no alternative estimators, just the default */ - armedBrick(mMultiplicityClasses, true); - } + mMultiplicityClasses->armedBrick(armedMask, optMask, forcedMask, bit); } mOptArmedMask.push_back(optMask); optMask = 0UL; @@ -394,6 +461,7 @@ void EventSelectionFilterAndAnalysis::StoreArmedMask() armedBrick(mZVertex); } if (mPileUpRejection != nullptr) { + mPileUpRejection->armedBrick(armedMask, optMask, forcedMask, bit); } LOGF(info, "EventSelectionFilterAndAnalysis::StoreArmedMask(), masks 0x%016lx, %s, 0x%016lx", armedMask, printOptionalMasks().Data(), forcedMask); mArmedMask = armedMask; diff --git a/PWGCF/TwoParticleCorrelations/Core/EventSelectionFilterAndAnalysis.h b/PWGCF/TwoParticleCorrelations/Core/EventSelectionFilterAndAnalysis.h index 6c0bbb2169b..ac436015159 100644 --- a/PWGCF/TwoParticleCorrelations/Core/EventSelectionFilterAndAnalysis.h +++ b/PWGCF/TwoParticleCorrelations/Core/EventSelectionFilterAndAnalysis.h @@ -69,105 +69,170 @@ class EventSelectionFilterAndAnalysis : public SelectionFilterAndAnalysis EventSelectionFilterAndAnalysis(const TString&, selmodes); EventSelectionFilterAndAnalysis(const EventSelectionConfigurable&, selmodes); - template - uint64_t Filter(CollisionToFilter const& col, int bfield); - std::vector GetMultiplicities(); + template + uint64_t Filter(CollisionToFilter const& col, AssociatedTracks const& trks, int bfield); + std::vector GetMultiplicities() { return (mMultiplicityClasses != nullptr) ? mMultiplicityClasses->GetMultiplicities() : std::vector{}; } /// \brief Gets the index of the active multiplicity value within the multiplicities array - int getMultiplicityIndex() { return mMultiplicityClasses->getArmedIndex(); } + int getMultiplicityIndex() { return (mMultiplicityClasses != nullptr) ? mMultiplicityClasses->GetArmedIndex() : -1; } private: + struct ComplexBrickHelper { + CutBrick* mBrick = nullptr; + int mDefaultEstimatorIndex = -1; + std::vector mAlternateEstimatorIndex = std::vector{}; + std::vector mValues = std::vector{}; + int Length() { return mBrick->Length(); } + virtual void initialize() = 0; + virtual bool Filter(uint64_t& mask, int& bit, CutBrick* brick, int index) = 0; + bool Filter(uint64_t& mask, int& bit); + void armedBrick(uint64_t&, uint64_t&, uint64_t&, int&); + }; + struct MultiplicityBrick : public ComplexBrickHelper { + virtual void initialize(); + std::vector GetMultiplicities(); + int GetArmedIndex() { return mBrick->getArmedIndex(); } + virtual bool Filter(uint64_t& mask, int& bit, CutBrick* brick, int index); + }; + struct PileUpRejBrick : public ComplexBrickHelper { + virtual void initialize(); + std::vector mIndepVar = std::vector{}; + virtual bool Filter(uint64_t& mask, int& bit, CutBrick* brick, int index); + }; + + static bool filterBrickValue(uint64_t& mask, int& bit, CutBrick* brick, float value); void ConstructCutFromString(const TString&); - void InitializeMultiplicityFilter(); + template + void StoreMultiplicities(CollisionToFilter const&, AssociatedTracks const&); int CalculateMaskLength() override; virtual void StoreArmedMask() override; std::vector*> mBFieldSelection; //! the magnetic field selection cuts - CutBrick* mMultiplicityClasses; //! the multiplicity classes cuts + MultiplicityBrick* mMultiplicityClasses; //! the multiplicity classes cuts CutBrick* mTriggerSelection; //! the trigger selection cuts CutBrick* mZVertex; //! the z vertex selection cuts - CutBrick* mPileUpRejection; //! the pile-up rejection criteria - std::vector mMultiplicities; // the collision multiplicities from the different implemented estimators - int mDefaultMultiplicityEstimatorIndex; // the default estimator index on the collision multiplicities array - std::vector mAlternateMultiplicityEstimatorIndex; // the vector of alternate estimators index on the collision multiplicities array + PileUpRejBrick* mPileUpRejection; //! the pile-up rejection criteria ClassDef(EventSelectionFilterAndAnalysis, 1) }; -/// \brief Fills the filter cuts mask -template -inline uint64_t EventSelectionFilterAndAnalysis::Filter(CollisionToFilter const& col, int bfield) +/// \brief Stores the different multiplicities needed for proper collision filtering +/// TODO: perhaps in a next iteration check if some storage can be removed +template +inline void EventSelectionFilterAndAnalysis::StoreMultiplicities(CollisionToFilter const& col, AssociatedTracks const& tracks) { /* store the collision multiplicities for the different estimators */ /* TODO: we need to adapt this to the Run 3 scenario */ /* this is hard coded with the estimator index declaration */ - mMultiplicities[0] = col.centRun2V0M(); - mMultiplicities[1] = col.centRun2CL0(); - mMultiplicities[2] = col.centRun2CL1(); + mMultiplicityClasses->mValues[0] = col.centRun2V0M(); + mMultiplicityClasses->mValues[1] = col.centRun2CL0(); + mMultiplicityClasses->mValues[2] = col.centRun2CL1(); + + int ntracksTPCout = 0; + int nTPCClusters = 0; // no TPC clusters available at collision level for the time being + + /* number of tracks with TPCout */ + /* we require tracks with pT > 0.15 and |eta| < 0.8 and additionally the TPCout flag */ + /* for the time being there is not TPCout flag, we just consider hasTPC */ + for (auto track : tracks) { + if (track.pt() > 0.15 and abs(track.eta()) < 0.8 and track.hasTPC()) { + ntracksTPCout++; + } + } + /* store the collision multiplicities for the different pile-up correlator estimators */ + /* TODO: we need to adapt this to the Run 3 scenario */ + /* this is hard coded with the pile-up correlator estimator index declaration */ + mPileUpRejection->mValues[0] = col.centRun2V0M(); + mPileUpRejection->mIndepVar[0] = ntracksTPCout; + mPileUpRejection->mValues[1] = col.centRun2V0M(); + mPileUpRejection->mIndepVar[1] = col.multTracklets(); + mPileUpRejection->mValues[2] = col.centRun2V0M(); + mPileUpRejection->mIndepVar[0] = nTPCClusters; +} + +inline bool EventSelectionFilterAndAnalysis::filterBrickValue(uint64_t& mask, int& bit, CutBrick* brick, float value) +{ + bool atleastone = false; + std::vector res = brick->Filter(value); + for (auto b : res) { + if (b) { + atleastone = true; + SETBIT(mask, bit); + } + bit++; + } + return atleastone; +}; + +inline bool EventSelectionFilterAndAnalysis::ComplexBrickHelper::Filter(uint64_t& mask, int& bit) +{ + bool acceptcollision = true; + if (mAlternateEstimatorIndex.size() > 0) { + bool atleastonealternative = false; + /* if (mBrick->IsA() != CutWithVariations::Class()) { + LOGF(fatal, "EventSelectionFilterAndAnalysis::Filter() expected class with variations cut but it is not there"); + } */ + /* first the default */ + TList& deflst = dynamic_cast*>(mBrick)->getDefaultBricks(); + bool acc = Filter(mask, bit, (CutBrick*)deflst.At(0), mDefaultEstimatorIndex); + atleastonealternative = atleastonealternative || acc; + /* and now the variants */ + TList& varlst = dynamic_cast*>(mBrick)->getVariantBricks(); + for (int i = 0; i < varlst.GetEntries(); ++i) { + bool acc = Filter(mask, bit, (CutBrick*)varlst.At(i), mAlternateEstimatorIndex[i]); + atleastonealternative = atleastonealternative || acc; + } + acceptcollision = acceptcollision && atleastonealternative; + } else { + /* no alternative estimators, just the default */ + bool acc = Filter(mask, bit, mBrick, mDefaultEstimatorIndex); + acceptcollision = acceptcollision && acc; + } + return acceptcollision; +} + +inline bool EventSelectionFilterAndAnalysis::MultiplicityBrick::Filter(uint64_t& mask, int& bit, CutBrick* brick, int index) +{ + return filterBrickValue(mask, bit, brick, mValues[index]); +} + +inline bool EventSelectionFilterAndAnalysis::PileUpRejBrick::Filter(uint64_t& mask, int& bit, CutBrick* brick, int index) +{ + brick->setIndependentFnVar(mIndepVar[index]); + return filterBrickValue(mask, bit, brick, mValues[index]); +} +/// \brief Fills the filter cuts mask +template +inline uint64_t EventSelectionFilterAndAnalysis::Filter(CollisionToFilter const& col, const AssociatedTracks& trks, int bfield) +{ + StoreMultiplicities(col, trks); uint64_t selectedMask = 0UL; mSelectedMask = 0UL; int bit = 0; - auto filterBrickValue = [&](auto brick, auto value) { - bool atleastone = false; - std::vector res = brick->Filter(value); - for (auto b : res) { - if (b) { - atleastone = true; - SETBIT(selectedMask, bit); - } - bit++; - } - return atleastone; - }; - /* we require the collision be accepted by the whole set of filters */ bool acceptcollision = true; if (mBFieldSelection.size() > 0) { bool oneatleast = false; for (auto brick : mBFieldSelection) { - bool acc = filterBrickValue(brick, bfield); + bool acc = filterBrickValue(selectedMask, bit, brick, bfield); oneatleast = oneatleast || acc; } acceptcollision = acceptcollision && oneatleast; } if (mMultiplicityClasses != nullptr) { - if (mAlternateMultiplicityEstimatorIndex.size() > 0) { - bool atleastonealternative = false; - /* we have alternative estimators so our brick is of kind cwv */ - if (mMultiplicityClasses->IsA() != CutWithVariations::Class()) { - LOGF(fatal, "EventSelectionFilterAndAnalysis::Filter() expected class with variations cut but it is not there"); - } - /* first the default */ - TList& deflst = dynamic_cast*>(mMultiplicityClasses)->getDefaultBricks(); - if (deflst.GetEntries() > 1) { - LOGF(fatal, "EventSelectionFilterAndAnalysis::Filter() expected only one default multiplicity class estimator"); - } - bool acc = filterBrickValue((CutBrick*)deflst.At(0), mMultiplicities[mDefaultMultiplicityEstimatorIndex]); - atleastonealternative = atleastonealternative || acc; - /* and now the variants */ - TList& varlst = dynamic_cast*>(mMultiplicityClasses)->getVariantBricks(); - for (int i = 0; i < varlst.GetEntries(); ++i) { - if (varlst.At(i)->IsA() != CutBrickSelectorMultipleRanges::Class()) { - LOGF(fatal, "EventSelectionFilterAndAnalysis::Filter, expected a multirange selector"); - } - bool acc = filterBrickValue((CutBrick*)varlst.At(i), mMultiplicities[mAlternateMultiplicityEstimatorIndex[i]]); - atleastonealternative = atleastonealternative || acc; - } - acceptcollision = acceptcollision && atleastonealternative; - } else { - /* no alternative estimators, just the default */ - bool acc = filterBrickValue(mMultiplicityClasses, mMultiplicities[mDefaultMultiplicityEstimatorIndex]); - acceptcollision = acceptcollision && acc; - } + bool acc = mMultiplicityClasses->ComplexBrickHelper::Filter(selectedMask, bit); + acceptcollision = acceptcollision && acc; } if (mTriggerSelection != nullptr) { } if (mZVertex != nullptr) { - bool acc = filterBrickValue(mZVertex, col.posZ()); + bool acc = filterBrickValue(selectedMask, bit, mZVertex, col.posZ()); acceptcollision = acceptcollision && acc; } if (mPileUpRejection != nullptr) { + bool acc = mPileUpRejection->ComplexBrickHelper::Filter(selectedMask, bit); + acceptcollision = acceptcollision && acc; } LOGF(debug, "EventSelectionFilterAndAnalysis::Filter(), %s collision", acceptcollision ? "accepted" : "rejected"); if (acceptcollision) { @@ -177,23 +242,21 @@ inline uint64_t EventSelectionFilterAndAnalysis::Filter(CollisionToFilter const& } /// \brief Fills the filter cuts mask -inline std::vector EventSelectionFilterAndAnalysis::GetMultiplicities() +inline std::vector EventSelectionFilterAndAnalysis::MultiplicityBrick::GetMultiplicities() { std::vector res; - if (mMultiplicityClasses != nullptr) { - if (mAlternateMultiplicityEstimatorIndex.size() > 0) { - /* first the default */ - res.push_back(mMultiplicities[mDefaultMultiplicityEstimatorIndex]); - /* and now the variants */ - TList& varlst = dynamic_cast*>(mMultiplicityClasses)->getVariantBricks(); - for (int i = 0; i < varlst.GetEntries(); ++i) { - res.push_back(mMultiplicities[mAlternateMultiplicityEstimatorIndex[i]]); - } - } else { - /* no alternative estimators, just the default */ - res.push_back(mMultiplicities[mDefaultMultiplicityEstimatorIndex]); + if (mAlternateEstimatorIndex.size() > 0) { + /* first the default */ + res.push_back(mValues[mDefaultEstimatorIndex]); + /* and now the variants */ + TList& varlst = dynamic_cast*>(mBrick)->getVariantBricks(); + for (int i = 0; i < varlst.GetEntries(); ++i) { + res.push_back(mValues[mAlternateEstimatorIndex[i]]); } + } else { + /* no alternative estimators, just the default */ + res.push_back(mValues[mDefaultEstimatorIndex]); } return res; } diff --git a/PWGCF/TwoParticleCorrelations/Core/SkimmingConfigurableCuts.cxx b/PWGCF/TwoParticleCorrelations/Core/SkimmingConfigurableCuts.cxx index 8aff0bedb67..c7e9e04f05d 100644 --- a/PWGCF/TwoParticleCorrelations/Core/SkimmingConfigurableCuts.cxx +++ b/PWGCF/TwoParticleCorrelations/Core/SkimmingConfigurableCuts.cxx @@ -64,7 +64,7 @@ CutBrick* CutBrick::constructBrick(const char* n } else if (TString(regex).BeginsWith("cwv")) { thebrick = new CutWithVariations(brickregex); } else { - ::Fatal("CutBrick* CutBrick::constructBrick", "Wrong RE: %s, trying to construct an unknown basic cut brick", regex); + LOGF(fatal, "CutBrick* CutBrick::constructBrick", "Wrong RE: %s, trying to construct an unknown basic cut brick", regex); } return thebrick; } @@ -136,7 +136,7 @@ void CutBrickLimit::ConstructCutFromString(const TString& cutstr std::regex_search(in, m, cutregex); if (m.empty() or (m.size() < 3)) { - Fatal("CutBrickLimit::ConstructCutFromString", "Wrong RE: %s, use pT{lim{2.0}} for instance", cutstr.Data()); + LOGF(fatal, "CutBrickLimit::ConstructCutFromString", "Wrong RE: %s, use pT{lim{2.0}} for instance", cutstr.Data()); } else { this->SetName(m[1].str().c_str()); this->SetTitle(cutstr.Data()); @@ -203,19 +203,19 @@ void CutBrickFnLimit::ConstructCutFromString(const TString& cuts { LOGF(info, "Cut string: %s", cutstr.Data()); - std::regex cutregex("^(\\w+)\\{fnlim\\{([\\w\\-\\*\\/\\+\\()\\.]+)}}$", std::regex_constants::ECMAScript | std::regex_constants::icase); + std::regex cutregex("^(\\w+)\\{fnlim\\{(\\w+)=([\\w\\-\\*\\/\\+\\()\\.]+)}}$", std::regex_constants::ECMAScript | std::regex_constants::icase); std::string in(cutstr.Data()); std::smatch m; std::regex_search(in, m, cutregex); - if (m.empty() or (m.size() < 3)) { - Fatal("CutBrickFnLimit::ConstructCutFromString", "Wrong RE: %s, use pT{fnlim{2.0*sin(x)/x}} for instance", cutstr.Data()); + if (m.empty() or (m.size() < 4)) { + LOGF(fatal, "CutBrickFnLimit::ConstructCutFromString", "Wrong RE: %s, use pT{fnlim{myfn=2.0*sin(x)/x}} for instance", cutstr.Data()); } else { - this->SetName(m[1].str().c_str()); + this->SetName(m[2].str().c_str()); this->SetTitle(cutstr.Data()); - mFunction = TF1(m[1].str().c_str(), m[2].str().c_str(), 0, 1, TF1::EAddToList::kNo); + mFunction = TF1(m[1].str().c_str(), m[3].str().c_str(), 0, 1, TF1::EAddToList::kNo); if (not mFunction.IsValid()) { - Fatal("CutBrickFnLimit::ConstructCutFromString", "Wrong function expression: %s, use pT{fnlim{2.0*sin(x)/x}} for instance", cutstr.Data()); + LOGF(fatal, "CutBrickFnLimit::ConstructCutFromString", "Wrong function expression: %s, use pT{fnlim{myfn=2.0*sin(x)/x}} for instance", cutstr.Data()); } } } @@ -270,7 +270,7 @@ void CutBrickThreshold::ConstructCutFromString(const TString& cu std::regex_search(in, m, cutregex); if (m.empty() or (m.size() < 3)) { - Fatal("CutBrickThreshold::ConstructCutFromString", "Wrong RE: %s, use pT{th{0.2}} for instance", cutstr.Data()); + LOGF(fatal, "CutBrickThreshold::ConstructCutFromString", "Wrong RE: %s, use pT{th{0.2}} for instance", cutstr.Data()); } else { this->SetName(m[1].str().c_str()); this->SetTitle(cutstr.Data()); @@ -337,19 +337,19 @@ void CutBrickFnThreshold::ConstructCutFromString(const TString& { LOGF(info, "Cut string: %s", cutstr.Data()); - std::regex cutregex("^(\\w+)\\{fnth\\{([\\w\\-\\*\\/\\+\\()\\.]+)}}$", std::regex_constants::ECMAScript | std::regex_constants::icase); + std::regex cutregex("^(\\w+)\\{fnth\\{(\\w+)=([\\w\\-\\*\\/\\+\\()\\.]+)}}$", std::regex_constants::ECMAScript | std::regex_constants::icase); std::string in(cutstr.Data()); std::smatch m; std::regex_search(in, m, cutregex); - if (m.empty() or (m.size() < 3)) { - Fatal("CutBrickFnThreshold::ConstructCutFromString", "Wrong RE: %s, use pT{fnth{2.0*sin(x)/x}} for instance", cutstr.Data()); + if (m.empty() or (m.size() < 4)) { + LOGF(fatal, "CutBrickFnThreshold::ConstructCutFromString", "Wrong RE: %s, use pT{fnth{myfn=2.0*sin(x)/x}} for instance", cutstr.Data()); } else { - this->SetName(m[1].str().c_str()); + this->SetName(m[2].str().c_str()); this->SetTitle(cutstr.Data()); - mFunction = TF1(m[1].str().c_str(), m[2].str().c_str(), 0, 1, TF1::EAddToList::kNo); + mFunction = TF1(m[1].str().c_str(), m[3].str().c_str(), 0, 1, TF1::EAddToList::kNo); if (not mFunction.IsValid()) { - Fatal("CutBrickFnThreshold::ConstructCutFromString", "Wrong function expression: %s, use pT{fnth{2.0*sin(x)/x}} for instance", cutstr.Data()); + LOGF(fatal, "CutBrickFnThreshold::ConstructCutFromString", "Wrong function expression: %s, use pT{fnth{myfn=2.0*sin(x)/x}} for instance", cutstr.Data()); } } } @@ -408,7 +408,7 @@ void CutBrickRange::ConstructCutFromString(const TString& cutstr std::regex_search(in, m, cutregex); if (m.empty() or (m.size() < 4)) { - Fatal("CutBrickRange::ConstructCutFromString", "Wrong RE: %s, use pT{rg{0.2,2.0}} for instance", cutstr.Data()); + LOGF(fatal, "CutBrickRange::ConstructCutFromString", "Wrong RE: %s, use pT{rg{0.2,2.0}} for instance", cutstr.Data()); } else { this->SetName(m[1].str().c_str()); this->SetTitle(cutstr.Data()); @@ -480,20 +480,20 @@ void CutBrickFnRange::ConstructCutFromString(const TString& cuts { LOGF(info, "Cut string: %s", cutstr.Data()); - std::regex cutregex("^(\\w+)\\{fnrg\\{([\\w\\-\\*\\/\\+\\()\\.]+),([\\w\\-\\*\\/\\+\\()\\.]+)}}$", std::regex_constants::ECMAScript | std::regex_constants::icase); + std::regex cutregex("^(\\w+)\\{fnrg\\{(\\w+)=([\\w\\-\\*\\/\\+\\()\\.]+),([\\w\\-\\*\\/\\+\\()\\.]+)}}$", std::regex_constants::ECMAScript | std::regex_constants::icase); std::string in(cutstr.Data()); std::smatch m; std::regex_search(in, m, cutregex); - if (m.empty() or (m.size() < 4)) { - Fatal("CutBrickFnRange::ConstructCutFromString", "Wrong RE: %s, use pT{fnrg{2.0*sin(x)/x}} for instance", cutstr.Data()); + if (m.empty() or (m.size() < 5)) { + LOGF(fatal, "CutBrickFnRange::ConstructCutFromString", "Wrong RE: %s, use pT{fnrg{myfn=2.0*sin(x)/x}} for instance", cutstr.Data()); } else { - this->SetName(m[1].str().c_str()); + this->SetName(m[2].str().c_str()); this->SetTitle(cutstr.Data()); - mLowFunction = TF1(TString::Format("%s_low", m[1].str().c_str()), m[2].str().c_str(), 0, 1, TF1::EAddToList::kNo); - mUpFunction = TF1(TString::Format("%s_up", m[1].str().c_str()), m[3].str().c_str(), 0, 1, TF1::EAddToList::kNo); + mLowFunction = TF1(TString::Format("%s_low", m[1].str().c_str()), m[3].str().c_str(), 0, 1, TF1::EAddToList::kNo); + mUpFunction = TF1(TString::Format("%s_up", m[1].str().c_str()), m[4].str().c_str(), 0, 1, TF1::EAddToList::kNo); if (not mLowFunction.IsValid() or not mUpFunction.IsValid()) { - Fatal("CutBrickFnRange::ConstructCutFromString", "Wrong function expression: %s, use pT{fnrg{2.0*sin(x)/x}} for instance", cutstr.Data()); + LOGF(fatal, "CutBrickFnRange::ConstructCutFromString", "Wrong function expression: %s, use pT{fnrg{myfn=2.0*sin(x)/x}} for instance", cutstr.Data()); } } } @@ -552,7 +552,7 @@ void CutBrickExtToRange::ConstructCutFromString(const TString& c std::regex_search(in, m, cutregex); if (m.empty() or (m.size() < 4)) { - Fatal("CutBrickExtToRange::ConstructCutFromString", "Wrong RE: %s, use minv{xrg{0.02,0.04}} for instance", cutstr.Data()); + LOGF(fatal, "CutBrickExtToRange::ConstructCutFromString", "Wrong RE: %s, use minv{xrg{0.02,0.04}} for instance", cutstr.Data()); } else { this->SetName(m[1].str().c_str()); this->SetTitle(cutstr.Data()); @@ -623,20 +623,20 @@ void CutBrickFnExtToRange::ConstructCutFromString(const TString& { LOGF(info, "Cut string: %s", cutstr.Data()); - std::regex cutregex("^(\\w+)\\{fnxrg\\{([\\w\\-\\*\\/\\+\\()\\.]+),([\\w\\-\\*\\/\\+\\()\\.]+)}}$", std::regex_constants::ECMAScript | std::regex_constants::icase); + std::regex cutregex("^(\\w+)\\{fnxrg\\{(\\w+)=([\\w\\-\\*\\/\\+\\()\\.]+),([\\w\\-\\*\\/\\+\\()\\.]+)}}$", std::regex_constants::ECMAScript | std::regex_constants::icase); std::string in(cutstr.Data()); std::smatch m; std::regex_search(in, m, cutregex); - if (m.empty() or (m.size() < 4)) { - Fatal("CutBrickFnExtToRange::ConstructCutFromString", "Wrong RE: %s, use pT{fnxrg{2.0*sin(x)/x}} for instance", cutstr.Data()); + if (m.empty() or (m.size() < 5)) { + LOGF(fatal, "CutBrickFnExtToRange::ConstructCutFromString", "Wrong RE: %s, use pT{fnxrg{myfn=2.0*sin(x)/x}} for instance", cutstr.Data()); } else { - this->SetName(m[1].str().c_str()); + this->SetName(m[2].str().c_str()); this->SetTitle(cutstr.Data()); - mLowFunction = TF1(TString::Format("%s_low", m[1].str().c_str()), m[2].str().c_str(), 0, 1, TF1::EAddToList::kNo); - mUpFunction = TF1(TString::Format("%s_up", m[1].str().c_str()), m[3].str().c_str(), 0, 1, TF1::EAddToList::kNo); + mLowFunction = TF1(TString::Format("%s_low", m[1].str().c_str()), m[3].str().c_str(), 0, 1, TF1::EAddToList::kNo); + mUpFunction = TF1(TString::Format("%s_up", m[1].str().c_str()), m[4].str().c_str(), 0, 1, TF1::EAddToList::kNo); if (not mLowFunction.IsValid() or not mUpFunction.IsValid()) { - Fatal("CutBrickFnExtToRange::ConstructCutFromString", "Wrong function expression: %s, use pT{fnxrg{2.0*sin(x)/x}} for instance", cutstr.Data()); + LOGF(fatal, "CutBrickFnExtToRange::ConstructCutFromString", "Wrong function expression: %s, use pT{fnxrg{myfn=2.0*sin(x)/x}} for instance", cutstr.Data()); } } } @@ -704,7 +704,7 @@ void CutBrickSelectorMultipleRanges::ConstructCutFromString(cons bool res = std::regex_search(in, m, cutregex); if (not res or m.empty() or (m.size() < 5)) { - Fatal("CutBrickSelectorMultipleRanges::ConstructCutFromString", "Wrong RE: %s, use centmult{mrg{V0M,0,5,10,20,30,40,50,60,70,80}} for instance", cutstr.Data()); + LOGF(fatal, "CutBrickSelectorMultipleRanges::ConstructCutFromString", "Wrong RE: %s, use centmult{mrg{V0M,0,5,10,20,30,40,50,60,70,80}} for instance", cutstr.Data()); } else { this->SetName(m[2].str().c_str()); this->SetTitle(cutstr.Data()); @@ -822,13 +822,13 @@ void CutWithVariations::ConstructCutFromString(const TString& cu /* let's catch the first level */ LOGF(info, "Cut with variations: cut string: %s", cutstr.Data()); - std::regex cutregex("^(\\w+)\\{cwv\\{([\\w\\d.,:{}-]+)}}$", std::regex_constants::ECMAScript | std::regex_constants::icase); + std::regex cutregex("^(\\w+)\\{cwv\\{([\\w\\d.,:{}=\\-\\+\\*\\/]+)}}$", std::regex_constants::ECMAScript | std::regex_constants::icase); std::string in(cutstr.Data()); std::smatch m; bool res = std::regex_search(in, m, cutregex); if (not res or m.empty() or (m.size() < 3)) { - Fatal("CutWithVariations::ConstructCutFromString", "Wrong RE: %s, use pT{cwv{rg{0.2,10.0}}} for instance", cutstr.Data()); + LOGF(fatal, "CutWithVariations::ConstructCutFromString", "Wrong RE: %s, use pT{cwv{rg{0.2,10.0}}} for instance", cutstr.Data()); } this->SetName(m[1].str().c_str()); this->SetTitle(cutstr.Data()); @@ -836,17 +836,17 @@ void CutWithVariations::ConstructCutFromString(const TString& cu /* let's split default and variations */ TObjArray* lev1toks = TString(m[2]).Tokenize(":"); if (lev1toks->GetEntries() > 2) { - Fatal("CutWithVariations::ConstructCutFromString", "Wrong RE: %s, use pT{cwv{rg{0.2,10.0}}} for instance", cutstr.Data()); + LOGF(fatal, "CutWithVariations::ConstructCutFromString", "Wrong RE: %s, use pT{cwv{rg{0.2,10.0}}} for instance", cutstr.Data()); } bool atleastonearmed = false; auto addCuts = [&](TList& cutlist, std::string cuttxt, bool reqflag) { std::smatch m; while (cuttxt.length() > 0) { - std::set allowed = {"lim", "th", "rg", "xrg", "mrg"}; - std::regex cutregex("(\\w+\\{[\\w.,-]+}(?:-(?:no|yes))*)"); + std::set allowed = {"lim", "th", "rg", "xrg", "mrg", "fnlim", "fnth", "fnrg", "fnxrg"}; + std::regex cutregex("(\\w+\\{[\\w.,=\\-\\+\\*\\/]+}(?:-(?:no|yes))*)"); bool res = regex_search(cuttxt, m, cutregex); if (not res or m.empty() or m.size() != 2) { - Fatal("CutWithVariations::ConstructCutFromString", "Cut with variations malformed RE %s", cuttxt.c_str()); + LOGF(fatal, "CutWithVariations::ConstructCutFromString", "Cut with variations malformed RE %s", cuttxt.c_str()); } TString brickre = m[1].str().c_str(); bool isarmed = brickre.EndsWith("-yes"); @@ -855,7 +855,7 @@ void CutWithVariations::ConstructCutFromString(const TString& cu } else if (brickre.EndsWith("-no")) { brickre.Remove(brickre.Index("-no"), strlen("-no")); } else if (reqflag) { - Fatal("CutWithVariations::ConstructCutFromString", "Wrong RE: %s, alternatives not correctly flagged", cuttxt.c_str()); + LOGF(fatal, "CutWithVariations::ConstructCutFromString", "Wrong RE: %s, alternatives not correctly flagged", cuttxt.c_str()); } CutBrick* brick = CutBrick::constructBrick(this->GetName(), brickre, allowed); brick->Arm(isarmed); @@ -870,7 +870,7 @@ void CutWithVariations::ConstructCutFromString(const TString& cu addCuts(mDefaultBricks, lev1toks->At(0)->GetName(), true); if (mDefaultBricks.GetEntries() > 1) { /* TODO: several default options for track type and for track pid selection */ - Fatal("CutWithVariations::ConstructCutFromString", "Wrong RE: %s, several defaults only for trktype or trkpid pending of implementation", cutstr.Data()); + LOGF(fatal, "CutWithVariations::ConstructCutFromString", "Wrong RE: %s, several defaults only for trktype or trkpid pending of implementation", cutstr.Data()); } } /* let's now handle the variations if any */ @@ -1085,7 +1085,7 @@ TrackSelectionBrick::TrackSelectionBrick(const TString& regex) : SpecialCutBrick } else if (name.EqualTo("FB64")) { constructFB64LHC2011(); } else { - ::Fatal("TrackSelectionBrick::TrackSelectionBrick", "Wrong RE: %s, trying to construct an unknown track type selector", regex.Data()); + LOGF(fatal, "TrackSelectionBrick::TrackSelectionBrick", "Wrong RE: %s, trying to construct an unknown track type selector", regex.Data()); } this->Arm(armed); } diff --git a/PWGCF/TwoParticleCorrelations/Core/SkimmingConfigurableCuts.h b/PWGCF/TwoParticleCorrelations/Core/SkimmingConfigurableCuts.h index b0f591f11dd..37819214e63 100644 --- a/PWGCF/TwoParticleCorrelations/Core/SkimmingConfigurableCuts.h +++ b/PWGCF/TwoParticleCorrelations/Core/SkimmingConfigurableCuts.h @@ -628,4 +628,5 @@ class TrackSelectionBrick : public SpecialCutBrick } // namespace PWGCF } // namespace analysis } // namespace o2 + #endif // SKIMMING_CONFIGURABLE_CUTS_CLASSES_H diff --git a/PWGCF/TwoParticleCorrelations/Core/TwoPartCorrLinkDef.h b/PWGCF/TwoParticleCorrelations/Core/TwoPartCorrLinkDef.h index 642cc2162fb..9620d0d392d 100644 --- a/PWGCF/TwoParticleCorrelations/Core/TwoPartCorrLinkDef.h +++ b/PWGCF/TwoParticleCorrelations/Core/TwoPartCorrLinkDef.h @@ -43,4 +43,7 @@ #pragma link C++ class o2::analysis::PWGCF::PIDSelectionConfigurable + ; #pragma link C++ class o2::analysis::PWGCF::PIDSelectionFilterAndAnalysis + ; #pragma link C++ class o2::analysis::PWGCF::EventSelectionConfigurable + ; +#pragma link C++ class o2::analysis::PWGCF::EventSelectionFilterAndAnalysis::ComplexBrickHelper + ; +#pragma link C++ class o2::analysis::PWGCF::EventSelectionFilterAndAnalysis::MultiplicityBrick + ; +#pragma link C++ class o2::analysis::PWGCF::EventSelectionFilterAndAnalysis::PileUpRejBrick + ; #pragma link C++ class o2::analysis::PWGCF::EventSelectionFilterAndAnalysis + ; diff --git a/PWGCF/TwoParticleCorrelations/TableProducer/skimmingconf.h b/PWGCF/TwoParticleCorrelations/TableProducer/skimmingconf.h index e0b2d26fdb8..cad3f8b12fe 100644 --- a/PWGCF/TwoParticleCorrelations/TableProducer/skimmingconf.h +++ b/PWGCF/TwoParticleCorrelations/TableProducer/skimmingconf.h @@ -15,9 +15,10 @@ #include "Framework/ASoAHelpers.h" struct : o2::framework::ConfigurableGroup { - o2::framework::Configurable> bfield{"evtflt_bfield", {"positive-yes", "negative-yes"}, "B filed polarity cut"}; + o2::framework::Configurable> bfield{"evtflt_bfield", {"positive-yes", "negative-yes"}, "B filed polarity cut: both 'yes' default, anything else alternative"}; o2::framework::Configurable> zvtxsel{"evtflt_zvtx", {"rg{-7.0,7.0}-yes", "rg{-10.0,10.0}-no", "rg{-3.0,3.0}-no"}, "Z vertex cut: first, default value, next, alternatives"}; - o2::framework::Configurable> centmultsel{"evtflt_centmult", {"mrg{V0M,0,5,10,20,30,40,50,60,70,80}-yes", "mrg{CL1,0,5,10,20,30,40,50,60,70,80}-no"}, "Centrality/Multiplicity cut:: first; default, next, alternatives"}; + o2::framework::Configurable> centmultsel{"evtflt_centmult", {"mrg{V0M,0,5,10,20,30,40,50,60,70,80}-yes", "mrg{CL1,0,5,10,20,30,40,50,60,70,80}-no"}, "Centrality/Multiplicity cut: first, default, next, alternatives"}; + o2::framework::Configurable> pileuprej{"evtflt_pileuprej", {"fnrg{V0M_TPCOUT=-0.5+3.7*x-0.14*x*x, 0.5-3.7*x+0.14*x*x}-yes", "fnrg{V0M_TRKLETS=-0.5+3.7*x-0.14*x*x, 0.5-3.7*x+0.14*x*x}-no"}, "Advanced pile-up rejection cut: first, default, next, alternatives"}; } eventfilter; struct : o2::framework::ConfigurableGroup { diff --git a/PWGCF/TwoParticleCorrelations/TableProducer/twoParticleCorrelationsSkimming.cxx b/PWGCF/TwoParticleCorrelations/TableProducer/twoParticleCorrelationsSkimming.cxx index 19774142d55..3f8d40e8f90 100644 --- a/PWGCF/TwoParticleCorrelations/TableProducer/twoParticleCorrelationsSkimming.cxx +++ b/PWGCF/TwoParticleCorrelations/TableProducer/twoParticleCorrelationsSkimming.cxx @@ -14,6 +14,7 @@ #include "Framework/ASoAHelpers.h" #include "Common/DataModel/TrackSelectionTables.h" #include "Common/DataModel/Centrality.h" +#include "Common/DataModel/Multiplicity.h" #include "Common/DataModel/PIDResponse.h" #include "PWGCF/TwoParticleCorrelations/DataModel/TwoParticleCorrelationsSkimmed.h" #include "PWGCF/TwoParticleCorrelations/Core/EventSelectionFilterAndAnalysis.h" @@ -128,7 +129,7 @@ struct TwoParticleCorrelationsSkimming { LOGF(info, "DptDptSkimTask::init()"); /* collision filtering configuration */ - PWGCF::EventSelectionConfigurable eventsel(eventfilter.bfield, eventfilter.centmultsel, {}, eventfilter.zvtxsel, {}); + PWGCF::EventSelectionConfigurable eventsel(eventfilter.bfield, eventfilter.centmultsel, {}, eventfilter.zvtxsel, eventfilter.pileuprej); fEventFilter = new PWGCF::EventSelectionFilterAndAnalysis(eventsel, PWGCF::SelectionFilterAndAnalysis::kFilter); /* track filtering configuration */ @@ -155,8 +156,8 @@ struct TwoParticleCorrelationsSkimming { ccdb->setLocalObjectValidityChecking(); } - template - uint64_t filterRun2Collision(Coll const& collision, BcInfo const& bcinfo) + template + uint64_t filterRun2Collision(Coll const& collision, AssociatedTracks const& tracks, BcInfo const& bcinfo) { using namespace aod::run2; using namespace aod::collision; @@ -199,20 +200,20 @@ struct TwoParticleCorrelationsSkimming { runNumber = bcinfo.runNumber(); } if (accepted) { - return fEventFilter->Filter(collision, bfield); + return fEventFilter->Filter(collision, tracks, bfield); } else { return 0UL; } } - void processRun2(soa::Join::iterator const& collision, + void processRun2(soa::Join::iterator const& collision, soa::Join const&, soa::Join const& tracks) { /* for the time being this will apply only to Run 1+2 converted data */ LOGF(LOGTRACKCOLLISIONS, "Got a new collision with zvtx %.2f and V0M %.2f, CL0 %.2f, CL1 %.2f", collision.posZ(), collision.centRun2V0M(), collision.centRun2CL0(), collision.centRun2CL1()); auto bc = collision.bc_as>(); - auto colmask = filterRun2Collision(collision, bc); + auto colmask = filterRun2Collision(collision, tracks, bc); LOGF(LOGTRACKCOLLISIONS, "Got mask 0x%16lx", colmask); if (colmask != 0UL) { From e16045506f71eddfd4afecdf9c47ac3a4e1f768d Mon Sep 17 00:00:00 2001 From: ALICE Action Bot Date: Fri, 7 Oct 2022 23:31:13 +0000 Subject: [PATCH 20/20] Please consider the following formatting changes --- .../Core/EventSelectionFilterAndAnalysis.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/PWGCF/TwoParticleCorrelations/Core/EventSelectionFilterAndAnalysis.h b/PWGCF/TwoParticleCorrelations/Core/EventSelectionFilterAndAnalysis.h index ac436015159..d8b805e86de 100644 --- a/PWGCF/TwoParticleCorrelations/Core/EventSelectionFilterAndAnalysis.h +++ b/PWGCF/TwoParticleCorrelations/Core/EventSelectionFilterAndAnalysis.h @@ -106,11 +106,11 @@ class EventSelectionFilterAndAnalysis : public SelectionFilterAndAnalysis int CalculateMaskLength() override; virtual void StoreArmedMask() override; - std::vector*> mBFieldSelection; //! the magnetic field selection cuts - MultiplicityBrick* mMultiplicityClasses; //! the multiplicity classes cuts - CutBrick* mTriggerSelection; //! the trigger selection cuts - CutBrick* mZVertex; //! the z vertex selection cuts - PileUpRejBrick* mPileUpRejection; //! the pile-up rejection criteria + std::vector*> mBFieldSelection; //! the magnetic field selection cuts + MultiplicityBrick* mMultiplicityClasses; //! the multiplicity classes cuts + CutBrick* mTriggerSelection; //! the trigger selection cuts + CutBrick* mZVertex; //! the z vertex selection cuts + PileUpRejBrick* mPileUpRejection; //! the pile-up rejection criteria ClassDef(EventSelectionFilterAndAnalysis, 1) };