diff --git a/PWGCF/TwoParticleCorrelations/Core/CMakeLists.txt b/PWGCF/TwoParticleCorrelations/Core/CMakeLists.txt index c1a9696cee7..91a202cf067 100644 --- a/PWGCF/TwoParticleCorrelations/Core/CMakeLists.txt +++ b/PWGCF/TwoParticleCorrelations/Core/CMakeLists.txt @@ -15,6 +15,7 @@ o2physics_add_library(TwoPartCorrCore TrackSelectionFilterAndAnalysis.cxx PIDSelectionFilterAndAnalysis.cxx EventSelectionFilterAndAnalysis.cxx + FilterAndAnalysisFramework.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore) o2physics_target_root_dictionary(TwoPartCorrCore @@ -23,4 +24,5 @@ o2physics_target_root_dictionary(TwoPartCorrCore TrackSelectionFilterAndAnalysis.h PIDSelectionFilterAndAnalysis.h EventSelectionFilterAndAnalysis.h + FilterAndAnalysisFramework.h LINKDEF TwoPartCorrLinkDef.h) diff --git a/PWGCF/TwoParticleCorrelations/Core/FilterAndAnalysisFramework.cxx b/PWGCF/TwoParticleCorrelations/Core/FilterAndAnalysisFramework.cxx new file mode 100644 index 00000000000..6d7be396a87 --- /dev/null +++ b/PWGCF/TwoParticleCorrelations/Core/FilterAndAnalysisFramework.cxx @@ -0,0 +1,189 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +#include +#include +#include +#include +#include +#include + +#include "FilterAndAnalysisFramework.h" + +using namespace o2; +using namespace o2::analysis::PWGCF; + +ClassImp(FilterAndAnalysisFramework); + +/// \brief Default constructor +FilterAndAnalysisFramework::FilterAndAnalysisFramework() + : TNamed(), + ccdburl(""), + ccdbpath(""), + filterdate(""), + forceupdate(false), + fTrackFilter(nullptr), + fEventFilter(nullptr), + fPIDFilter(nullptr), + _fTrackFilter(nullptr), + _fEventFilter(nullptr), + _fPIDFilter(nullptr) +{ +} + +/// \brief Named constructor for a concrete operating mode +void FilterAndAnalysisFramework::SetConfiguration(EventSelectionConfigurable& evtf, TrackSelectionConfigurable& trkf, PIDSelectionConfigurable& pidf, SelectionFilterAndAnalysis::selmodes mode) +{ + _fTrackFilter = new PWGCF::TrackSelectionFilterAndAnalysis(trkf, mode); + _fEventFilter = new PWGCF::EventSelectionFilterAndAnalysis(evtf, mode); + _fPIDFilter = new PWGCF::PIDSelectionFilterAndAnalysis(pidf, mode); +} + +void FilterAndAnalysisFramework::RegisterConfiguration() +{ + LOGF(info, "Registering configuration into CCDB for date %s", filterdate.data()); + + /* sanity checks */ + if (_fTrackFilter == nullptr || _fEventFilter == nullptr || _fPIDFilter == nullptr) { + LOGF(fatal, "Configuration not stored yet, please use SetConfiguration(evtf, trkf, pidf, mode), or configuration already registered"); + } + if (fTrackFilter != nullptr || fEventFilter != nullptr || fPIDFilter != nullptr) { + LOGF(fatal, "Configuration already registered"); + } + + TList* signatures = nullptr; + std::tm t{}; + /* we set noon for checking */ + std::istringstream ss(filterdate + "1200"); + /* let's extract the timestamp */ + ss >> std::get_time(&t, "%Y%m%d%H%M"); + if (ss.fail()) { + LOGF(fatal, "Wrong skimming filter date format. Please use YYYYMMDD"); + } + std::time_t time_stamp = mktime(&t); + /* and get it in ms */ + uint64_t timestamp = 1000 * time_stamp; + /* let's prepare the sot and eot */ + uint64_t sot = timestamp - (12 * 60 * 60 * 1000); /* the beginning of the day */ + uint64_t eot = timestamp + (12 * 60 * 60 * 1000 - 1000); /* one second before the end of the day */ + + /* get access to the CCDB */ + o2::ccdb::CcdbApi* ccdb = new o2::ccdb::CcdbApi(); + ccdb->init(ccdburl); + o2::ccdb::BasicCCDBManager* ccdbm = &o2::ccdb::BasicCCDBManager::instance(); + ccdbm->setFatalWhenNull(false); /* we need to check the availability of objects */ + ccdbm->setURL(ccdburl); + signatures = ccdbm->getForTimeStamp(ccdbpath, timestamp); + + auto storesignatures = [&]() { + TList* siglst = new TList(); + siglst->SetOwner(); + siglst->SetName("Skimming signatures"); + siglst->Add(new TObjString(_fEventFilter->getCutStringSignature().Data())); + siglst->Add(new TObjString(_fTrackFilter->getCutStringSignature().Data())); + siglst->Add(new TObjString(_fPIDFilter->getCutStringSignature().Data())); + std::map metadata = {{"FilterDate", filterdate}}; + ccdb->storeAsTFileAny(siglst, ccdbpath, metadata, sot, eot); + fEventFilter = _fEventFilter; + fTrackFilter = _fTrackFilter; + fPIDFilter = _fPIDFilter; + _fEventFilter = nullptr; + _fTrackFilter = nullptr; + _fPIDFilter = nullptr; + }; + + if (signatures != nullptr) { + /* signatures already stored in the CCDB, check if they match with the current configuration */ + auto domatch = [&signatures](int index, auto filter) { + return (strcmp(signatures->At(index)->GetName(), filter->getCutStringSignature().Data()) == 0); + }; + if (domatch(0, _fEventFilter) && domatch(1, _fTrackFilter) && domatch(2, _fPIDFilter)) { + /* signatures match so configuration already registered and available for skimming and/or analysis */ + LOGF(info, "Filter signatures already registered in the CCDB. You can proceed with the skimming and/or analysis"); + } else { + /* signatures don't match the version on the CCDB */ + if (forceupdate) { + /* forced update required so store the configuration signatures in the CCDB */ + LOGF(info, "Filter configuration signatures registered into the CCDB"); + storesignatures(); + } else { + /* no forced update required, inform the user */ + LOGF(error, "The filter configuration signatures for the requested date don't match the ones available at the CCDB"); + LOGF(error, "If the new filter configuration is registered the previous one will not be anylonger available"); + LOGF(error, "If you agree on that please invoke againg the registering with --forced=true"); + LOGF(error, "Nothing was done!!!"); + } + } + } else { + /* signatures not stored in the CCDB, let's store them */ + LOGF(info, "Filter configuration signatures registered into the CCDB"); + storesignatures(); + } +} + +void FilterAndAnalysisFramework::Init() +{ + LOGF(info, "Initializing filter configuration from date %s", filterdate.data()); + + /* sanity checks */ + if (_fTrackFilter == nullptr || _fEventFilter == nullptr || _fPIDFilter == nullptr) { + LOGF(fatal, "Configuration not stored yet, please use SetConfiguration(evtf, trkf, pidf, mode, force), or configuration already initalized"); + } + if (fTrackFilter != nullptr || fEventFilter != nullptr || fPIDFilter != nullptr) { + LOGF(fatal, "Configuration already initialized"); + } + + TList* signatures = nullptr; + std::tm t{}; + /* we set noon for checking */ + std::istringstream ss(filterdate + "1200"); + /* let's extract the timestamp */ + ss >> std::get_time(&t, "%Y%m%d%H%M"); + if (ss.fail()) { + LOGF(fatal, "Wrong skimming filter date format. Please use YYYYMMDD"); + } + std::time_t time_stamp = mktime(&t); + /* and get it in ms */ + uint64_t timestamp = 1000 * time_stamp; + + /* get access to the CCDB */ + o2::ccdb::BasicCCDBManager* ccdbm = &o2::ccdb::BasicCCDBManager::instance(); + ccdbm->setFatalWhenNull(false); /* we need to check the availability of objects */ + ccdbm->setURL(ccdburl); + signatures = ccdbm->getForTimeStamp(ccdbpath, timestamp); + + if (signatures != nullptr) { + /* signatures registered in the CCDB, check if they match with the current configuration */ + auto domatch = [&signatures](int index, auto filter) { + return (strcmp(signatures->At(index)->GetName(), filter->getCutStringSignature().Data()) == 0); + }; + if (domatch(0, _fEventFilter) && domatch(1, _fTrackFilter) && domatch(2, _fPIDFilter)) { + /* signatures match the configuration proceed with skimming and/or analysis */ + LOGF(info, "Filter signatures registered in the CCDB. Proceeding with the skimming and/or analysis"); + fEventFilter = _fEventFilter; + fTrackFilter = _fTrackFilter; + fPIDFilter = _fPIDFilter; + _fEventFilter = nullptr; + _fTrackFilter = nullptr; + _fPIDFilter = nullptr; + } else { + /* signatures don't match the version on the CCDB */ + LOGF(fatal, + "The stored configuration signatures don't match with the ones registered at the CCDB\n" + "\t\tEither you are trying to use a new filter configuration which is not registerd, please register it,\n" + "\t\tor you have changed the configuration for carrying your analysis, but it will not match the skimmed data,\n" + "\t\tplease do not modify the configuration, just the selection \"yes\" \"not\" flags."); + } + } else { + /* signatures not stored in the CCDB, abort! */ + LOGF(fatal, "Filter configuration signatures not stored in the CCDB!!! We cannot proceed!!!"); + } +} diff --git a/PWGCF/TwoParticleCorrelations/Core/FilterAndAnalysisFramework.h b/PWGCF/TwoParticleCorrelations/Core/FilterAndAnalysisFramework.h new file mode 100644 index 00000000000..fa3b7aaeb6e --- /dev/null +++ b/PWGCF/TwoParticleCorrelations/Core/FilterAndAnalysisFramework.h @@ -0,0 +1,122 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. +#ifndef PWGCF_TWOPARTICLECORRELATIONS_CORE_FILTERANDANALYSISFRAMEWORK_H_ +#define PWGCF_TWOPARTICLECORRELATIONS_CORE_FILTERANDANALYSISFRAMEWORK_H_ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "PWGCF/TwoParticleCorrelations/Core/EventSelectionFilterAndAnalysis.h" +#include "PWGCF/TwoParticleCorrelations/Core/TrackSelectionFilterAndAnalysis.h" +#include "PWGCF/TwoParticleCorrelations/Core/PIDSelectionFilterAndAnalysis.h" + +namespace o2 +{ +namespace analysis +{ +namespace PWGCF +{ + +/// \brief Base class for filter and selection once filetered +class FilterAndAnalysisFramework : public TNamed +{ + friend void registerConfiguration(FilterAndAnalysisFramework*); + + public: + FilterAndAnalysisFramework(); + FilterAndAnalysisFramework(std::string& url, std::string& path, std::string& date, bool force = false) + : ccdburl(url), ccdbpath(path), filterdate(date), forceupdate(force) {} + + void SetConfiguration(EventSelectionConfigurable&, TrackSelectionConfigurable&, PIDSelectionConfigurable&, SelectionFilterAndAnalysis::selmodes mode); + + protected: + void RegisterConfiguration(); + + public: + void Init(); + + /// \brief get the valid (armed) mask associated to the configuration of the different objects + /// \return the corresponding armed mask + uint64_t getCollisionMask() { return fEventFilter->getMask(); } + uint64_t getTrackMask() { return fTrackFilter->getMask(); } + uint64_t getPIDMask() { return fPIDFilter->getMask(); } + /// \brief get the valid (armed) optional part mask associated to the configuration of the different objects + /// \return the corresponding 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 + std::vector& getCollisionOptMask() { return fEventFilter->getOptMask(); } + std::vector& getTrackOptMask() { return fTrackFilter->getOptMask(); } + std::vector& getPIDOptMask() { return fPIDFilter->getOptMask(); } + /// \brief provides the optional part mask of the different objects in a printable shape + TString printCollisionOptionalMasks() const { return fEventFilter->printOptionalMasks(); } + TString printTrackOptionalMasks() const { return fTrackFilter->printOptionalMasks(); } + TString printPIDOptionalMasks() const { return fPIDFilter->printOptionalMasks(); } + /// \brief get the valid (armed) mandatory part mask associated to the configuration of the different objects + /// \return the corresponding armed forced mask + /// A clear example of the mandatory part mask is the mask of the zvertex and their + /// alternatives where only a concrete one is required to be flagged + uint64_t getCollisionForcedMask() { return fEventFilter->getForcedMask(); } + uint64_t getTrackForcedMask() { return fTrackFilter->getForcedMask(); } + uint64_t getPIDForcedMask() { return fPIDFilter->getForcedMask(); } + /// \brief filter the different objects + template + uint64_t FilterCollision(CollisionToFilter const& col, AssociatedTracks const& trks, int bfield) + { + return fEventFilter->Filter(col, trks, bfield); + } + template + uint64_t FilterTrack(TrackToFilter const& track) + { + return fTrackFilter->Filter(track); + } + template + uint64_t FilterTrackPID(TrackToFilter const& track) + { + return fPIDFilter->Filter(track); + } + /// \brief get the event multiplicities + std::vector GetCollisionMultiplicities() { return fEventFilter->GetMultiplicities(); } + /// \brief Gets the index of the active multiplicity value within the multiplicities array + int getCollisionMultiplicityIndex() { return fEventFilter->getMultiplicityIndex(); } + + /// \brief get the cut string signatures + const TString& getEventFilterCutStringSignature() { return fEventFilter->getCutStringSignature(); } + const TString& getTrackFilterCutStringSignature() { return fTrackFilter->getCutStringSignature(); } + const TString& getPIDFilterCutStringSignature() { return fPIDFilter->getCutStringSignature(); } + + private: + std::string ccdburl = ""; + std::string ccdbpath = ""; + std::string filterdate = ""; + bool forceupdate = false; + PWGCF::TrackSelectionFilterAndAnalysis* fTrackFilter = nullptr; /// the track filter + PWGCF::EventSelectionFilterAndAnalysis* fEventFilter = nullptr; /// the event filter + PWGCF::PIDSelectionFilterAndAnalysis* fPIDFilter = nullptr; /// the PID filter + PWGCF::TrackSelectionFilterAndAnalysis* _fTrackFilter = nullptr; /// the track filter temporal storage until initialized + PWGCF::EventSelectionFilterAndAnalysis* _fEventFilter = nullptr; /// the event filter temporal storage until initialized + PWGCF::PIDSelectionFilterAndAnalysis* _fPIDFilter = nullptr; /// the PID filter temporal storage until initialized + + ClassDefNV(FilterAndAnalysisFramework, 1) +}; + +extern void registerConfiguration(o2::analysis::PWGCF::FilterAndAnalysisFramework*); + +} // namespace PWGCF +} // namespace analysis +} // namespace o2 + +#endif // PWGCF_TWOPARTICLECORRELATIONS_CORE_FILTERANDANALYSISFRAMEWORK_H_ diff --git a/PWGCF/TwoParticleCorrelations/Core/TwoPartCorrLinkDef.h b/PWGCF/TwoParticleCorrelations/Core/TwoPartCorrLinkDef.h index 9620d0d392d..c6ff9c1ac28 100644 --- a/PWGCF/TwoParticleCorrelations/Core/TwoPartCorrLinkDef.h +++ b/PWGCF/TwoParticleCorrelations/Core/TwoPartCorrLinkDef.h @@ -8,6 +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 PWGCF_TWOPARTICLECORRELATIONS_CORE_TWOPARTCORRLINKDEF_H_ +#define PWGCF_TWOPARTICLECORRELATIONS_CORE_TWOPARTCORRLINKDEF_H_ #pragma link off all globals; #pragma link off all classes; @@ -47,3 +49,6 @@ #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 + ; +#pragma link C++ class o2::analysis::PWGCF::FilterAndAnalysisFramework + ; + +#endif // PWGCF_TWOPARTICLECORRELATIONS_CORE_TWOPARTCORRLINKDEF_H_ diff --git a/PWGCF/TwoParticleCorrelations/TableProducer/CMakeLists.txt b/PWGCF/TwoParticleCorrelations/TableProducer/CMakeLists.txt index 53721e68464..cb869a643d6 100644 --- a/PWGCF/TwoParticleCorrelations/TableProducer/CMakeLists.txt +++ b/PWGCF/TwoParticleCorrelations/TableProducer/CMakeLists.txt @@ -9,6 +9,11 @@ # granted to it by virtue of its status as an Intergovernmental Organization # or submit itself to any jurisdiction. +o2physics_add_dpl_workflow(twopartcorr-register-skim + SOURCES twoParticleCorrelationsRegisterSkimming.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::TwoPartCorrCore + COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(twopartcorr-skim SOURCES twoParticleCorrelationsSkimming.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::TwoPartCorrCore diff --git a/PWGCF/TwoParticleCorrelations/TableProducer/skimmingconf.h b/PWGCF/TwoParticleCorrelations/TableProducer/skimmingconf.h index 4ac9d40fbac..7ec84db86ed 100644 --- a/PWGCF/TwoParticleCorrelations/TableProducer/skimmingconf.h +++ b/PWGCF/TwoParticleCorrelations/TableProducer/skimmingconf.h @@ -8,9 +8,11 @@ // In applying this license CERN does not waive the privileges and immunities // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -#ifndef O2_ANALYSIS_CFSKIMMINGCONF_H -#define O2_ANALYSIS_CFSKIMMINGCONF_H +#ifndef PWGCF_TWOPARTICLECORRELATIONS_TABLEPRODUCER_SKIMMINGCONF_H_ +#define PWGCF_TWOPARTICLECORRELATIONS_TABLEPRODUCER_SKIMMINGCONF_H_ +#include +#include #include "Framework/AnalysisTask.h" #include "Framework/ASoAHelpers.h" @@ -61,4 +63,10 @@ struct : o2::framework::ConfigurableGroup { #endif } pidfilter; -#endif // O2_ANALYSIS_CFSKIMMINGCONF_H +struct : o2::framework::ConfigurableGroup { + o2::framework::Configurable ccdburl{"ccdburl", "http://ccdb-test.cern.ch:8080", "url of the skimming ccdb repository"}; + o2::framework::Configurable ccdbpath{"ccdbpath", "Users/v/victor/Skimming", "url of the skimming ccdb repository"}; + o2::framework::Configurable filterdate{"filterdate", "20221115", "the date for the skimming production with the current filter configuration"}; +} filterccdb; + +#endif // PWGCF_TWOPARTICLECORRELATIONS_TABLEPRODUCER_SKIMMINGCONF_H_ diff --git a/PWGCF/TwoParticleCorrelations/TableProducer/twoParticleCorrelationsFiltering.cxx b/PWGCF/TwoParticleCorrelations/TableProducer/twoParticleCorrelationsFiltering.cxx index 3182ff04d4f..34073387d82 100644 --- a/PWGCF/TwoParticleCorrelations/TableProducer/twoParticleCorrelationsFiltering.cxx +++ b/PWGCF/TwoParticleCorrelations/TableProducer/twoParticleCorrelationsFiltering.cxx @@ -9,10 +9,10 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. +#include + #include "Framework/AnalysisTask.h" -#include "PWGCF/TwoParticleCorrelations/Core/EventSelectionFilterAndAnalysis.h" -#include "PWGCF/TwoParticleCorrelations/Core/TrackSelectionFilterAndAnalysis.h" -#include "PWGCF/TwoParticleCorrelations/Core/PIDSelectionFilterAndAnalysis.h" +#include "PWGCF/TwoParticleCorrelations/Core/FilterAndAnalysisFramework.h" #include "PWGCF/TwoParticleCorrelations/DataModel/TwoParticleCorrelationsSkimmed.h" #include "PWGCF/TwoParticleCorrelations/DataModel/TwoParticleCorrelationsFiltered.h" #include "Framework/runDataProcessing.h" @@ -27,8 +27,6 @@ #include #include -#include - using namespace o2; using namespace o2::framework; using namespace o2::soa; @@ -50,9 +48,7 @@ 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; +PWGCF::FilterAndAnalysisFramework* fFilterFramework = nullptr; int fMultiplicityIndex = -1; //! the index to the multiplicity values array } // namespace o2::analysis::twopfilter @@ -65,7 +61,7 @@ struct TwoParticleCorrelationsFilter { Produces acceptedgencollisions; Produces acceptedgentracks; -#include "skimmingconf.h" +#include "PWGCF/TwoParticleCorrelations/TableProducer/skimmingconf.h" int nReportedTracks; // HistogramRegistry historeg; @@ -78,12 +74,9 @@ struct TwoParticleCorrelationsFilter { /* collision filtering configuration */ PWGCF::EventSelectionConfigurable eventsel(eventfilter.bfield, 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); #ifdef INCORPORATEBAYESIANPID 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, @@ -92,29 +85,30 @@ 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); #endif - fPIDFilter = new PWGCF::PIDSelectionFilterAndAnalysis(pidsel, PWGCF::SelectionFilterAndAnalysis::kAnalysis); - + fFilterFramework = new PWGCF::FilterAndAnalysisFramework(filterccdb.ccdburl.value, filterccdb.ccdbpath.value, filterccdb.filterdate.value); + fFilterFramework->SetConfiguration(eventsel, trksel, pidsel, PWGCF::SelectionFilterAndAnalysis::kAnalysis); + fFilterFramework->Init(); nReportedTracks = 0; - 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%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)) { + collisionmask = fFilterFramework->getCollisionMask(); + collisionmask_opt = fFilterFramework->getCollisionOptMask(); + collisionmask_forced = fFilterFramework->getCollisionForcedMask(); + fMultiplicityIndex = fFilterFramework->getCollisionMultiplicityIndex(); + trackmask = fFilterFramework->getTrackMask(); + trackmask_opt = fFilterFramework->getTrackOptMask(); + trackmask_forced = fFilterFramework->getTrackForcedMask(); + pidmask = fFilterFramework->getPIDMask(); + pidmask_opt = fFilterFramework->getPIDOptMask(); + pidmask_forced = fFilterFramework->getPIDForcedMask(); + LOGF(info, "TwoParticleCorrelationsFilter::init(), collision selection masks 0x%016lx, %s, and 0x%016lx and multiplicity index %d", collisionmask, fFilterFramework->printCollisionOptionalMasks().Data(), collisionmask_forced, fMultiplicityIndex); + LOGF(info, "TwoParticleCorrelationsFilter::init(), track selection masks 0x%016lx, %s, and 0x%016lx ", trackmask, fFilterFramework->printTrackOptionalMasks().Data(), trackmask_forced); + LOGF(info, "TwoParticleCorrelationsFilter::init(), PID selection masks 0x%016lx, %s, and 0x%016lx ", pidmask, fFilterFramework->printPIDOptionalMasks().Data(), pidmask_forced); + if (collisionmask == uint64_t(0) || 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()); + LOGF(info, "Collision skimming signature: %s", fFilterFramework->getEventFilterCutStringSignature().Data()); + LOGF(info, "Track skimming signature: %s", fFilterFramework->getTrackFilterCutStringSignature().Data()); + LOGF(info, "PID skimming signature: %s", fFilterFramework->getPIDFilterCutStringSignature().Data()); } void processRun2(aod::CFCollision const& collision, aod::CFTracks const& tracks) @@ -129,12 +123,12 @@ struct TwoParticleCorrelationsFilter { return all; }; - if ((collision.selflags() & collisionmask_forced) == collisionmask_forced and passOptions(collisionmask_opt, collision.selflags())) { + if ((collision.selflags() & collisionmask_forced) == collisionmask_forced && 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 passOptions(trackmask_opt, track.trackflags())) { + if ((track.trackflags() & trackmask_forced) == trackmask_forced && passOptions(trackmask_opt, track.trackflags())) { accepteddtracks(0); // TODO: the kind of accepted track nAcceptedTracks++; } else { diff --git a/PWGCF/TwoParticleCorrelations/TableProducer/twoParticleCorrelationsRegisterSkimming.cxx b/PWGCF/TwoParticleCorrelations/TableProducer/twoParticleCorrelationsRegisterSkimming.cxx new file mode 100644 index 00000000000..22cb9f721dc --- /dev/null +++ b/PWGCF/TwoParticleCorrelations/TableProducer/twoParticleCorrelationsRegisterSkimming.cxx @@ -0,0 +1,75 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +#include +#include "Framework/AnalysisTask.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/ASoAHelpers.h" +#include "PWGCF/TwoParticleCorrelations/Core/FilterAndAnalysisFramework.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; + +void o2::analysis::PWGCF::registerConfiguration(PWGCF::FilterAndAnalysisFramework* fFilterFramework) +{ + fFilterFramework->RegisterConfiguration(); +} + +struct TwoParticleCorrelationsRegisterSkimming { + bool registered = false; + PWGCF::FilterAndAnalysisFramework* fFilterFramework = nullptr; + +#include "PWGCF/TwoParticleCorrelations/TableProducer/skimmingconf.h" + + void init(InitContext const&) + { + + LOGF(info, "TwoParticleCorrelationsRegisterSkimming::init()"); + + /* collision filtering configuration */ + PWGCF::EventSelectionConfigurable eventsel(eventfilter.bfield, eventfilter.centmultsel, {}, eventfilter.zvtxsel, eventfilter.pileuprej); + /* 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); +#ifdef INCORPORATEBAYESIANPID + 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); +#else + 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); +#endif + + fFilterFramework = new PWGCF::FilterAndAnalysisFramework(filterccdb.ccdburl.value, filterccdb.ccdbpath.value, filterccdb.filterdate.value); + fFilterFramework->SetConfiguration(eventsel, trksel, pidsel, PWGCF::SelectionFilterAndAnalysis::kFilter); + registered = false; + } + + void process(aod::Collisions const&) + { + if (!registered) { + LOGF(info, "Registering filter configuration"); + PWGCF::registerConfiguration(fFilterFramework); + registered = true; + } + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + WorkflowSpec workflow{ + adaptAnalysisTask(cfgc)}; + return workflow; +} diff --git a/PWGCF/TwoParticleCorrelations/TableProducer/twoParticleCorrelationsSkimming.cxx b/PWGCF/TwoParticleCorrelations/TableProducer/twoParticleCorrelationsSkimming.cxx index 5935fefe07c..1e7306740ba 100644 --- a/PWGCF/TwoParticleCorrelations/TableProducer/twoParticleCorrelationsSkimming.cxx +++ b/PWGCF/TwoParticleCorrelations/TableProducer/twoParticleCorrelationsSkimming.cxx @@ -9,6 +9,7 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. +#include #include "Framework/AnalysisTask.h" #include "Framework/AnalysisDataModel.h" #include "Framework/ASoAHelpers.h" @@ -17,12 +18,9 @@ #include "Common/DataModel/Multiplicity.h" #include "Common/DataModel/PIDResponse.h" #include "PWGCF/TwoParticleCorrelations/DataModel/TwoParticleCorrelationsSkimmed.h" -#include "PWGCF/TwoParticleCorrelations/Core/EventSelectionFilterAndAnalysis.h" -#include "PWGCF/TwoParticleCorrelations/Core/TrackSelectionFilterAndAnalysis.h" -#include "PWGCF/TwoParticleCorrelations/Core/PIDSelectionFilterAndAnalysis.h" +#include "PWGCF/TwoParticleCorrelations/Core/FilterAndAnalysisFramework.h" #include "Framework/runDataProcessing.h" #include "DataFormatsParameters/GRPObject.h" -#include using namespace o2; using namespace o2::framework; @@ -43,9 +41,7 @@ using pidTables = soa::Join; #endif -PWGCF::TrackSelectionFilterAndAnalysis* fTrackFilter = nullptr; -PWGCF::EventSelectionFilterAndAnalysis* fEventFilter = nullptr; -PWGCF::PIDSelectionFilterAndAnalysis* fPIDFilter = nullptr; +PWGCF::FilterAndAnalysisFramework* fFilterFramework = nullptr; } // namespace o2::analysis::cfskim using namespace cfskim; @@ -104,7 +100,7 @@ struct TwoParticleCorrelationsSkimming { Service ccdb; -#include "skimmingconf.h" +#include "PWGCF/TwoParticleCorrelations/TableProducer/skimmingconf.h" int nReportedTracks; int runNumber = 0; @@ -116,7 +112,7 @@ struct TwoParticleCorrelationsSkimming { // 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); + grpo = ccdb->getForTimeStamp(ccdbpath, timestamp); if (grpo == nullptr) { LOGF(fatal, "GRP object not found for timestamp %llu", timestamp); return 0; @@ -134,12 +130,9 @@ struct TwoParticleCorrelationsSkimming { /* collision filtering configuration */ PWGCF::EventSelectionConfigurable eventsel(eventfilter.bfield, eventfilter.centmultsel, {}, eventfilter.zvtxsel, eventfilter.pileuprej); - 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); #ifdef INCORPORATEBAYESIANPID 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, @@ -148,13 +141,16 @@ struct TwoParticleCorrelationsSkimming { 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); #endif - fPIDFilter = new PWGCF::PIDSelectionFilterAndAnalysis(pidsel, PWGCF::SelectionFilterAndAnalysis::kFilter); + + fFilterFramework = new PWGCF::FilterAndAnalysisFramework(filterccdb.ccdburl.value, filterccdb.ccdbpath.value, filterccdb.filterdate.value); + fFilterFramework->SetConfiguration(eventsel, trksel, pidsel, PWGCF::SelectionFilterAndAnalysis::kFilter); + fFilterFramework->Init(); 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()); + LOGF(info, "Collision skimming signature: %s", fFilterFramework->getEventFilterCutStringSignature().Data()); + LOGF(info, "Track skimming signature: %s", fFilterFramework->getTrackFilterCutStringSignature().Data()); + LOGF(info, "PID skimming signature: %s", fFilterFramework->getPIDFilterCutStringSignature().Data()); historeg.add("EventCuts", "EventCuts", {HistType::kTH1F, {{aod::run2::kTRDHEE + 1, 0, aod::run2::kTRDHEE + 1}}}); setEventCutsLabels(historeg.get(HIST("EventCuts"))); @@ -176,27 +172,27 @@ struct TwoParticleCorrelationsSkimming { // NOT CONFIGURABLE EVENT SELECTION /* incomplete data acquisition */ - if (not TESTBIT(eventcuts, kIncompleteDAQ)) { + if (!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 + if (!TESTBIT(eventcuts, kPileupInMultBins) || + !TESTBIT(eventcuts, kTrackletsVsClusters) || + !TESTBIT(eventcuts, kPileUpMV) || + !TESTBIT(eventcuts, kTimeRangeCut) || + !TESTBIT(eventcuts, kTPCPileUp) || + TESTBIT(eventcuts, kIsPileupFromSPD) || TESTBIT(eventcuts, kIsV0PFPileup)) { accepted = false; } /* TPC issues*/ - if (TESTBIT(eventcuts, kIsTPCHVdip) or + if (TESTBIT(eventcuts, kIsTPCHVdip) || TESTBIT(eventcuts, kIsTPCLaserWarmUp)) { accepted = false; } /* vertex */ - if (not TESTBIT(eventcuts, kNonZeroNContribs) or + if (!TESTBIT(eventcuts, kNonZeroNContribs) || (((collision.flags() & Run2VertexerZ) == Run2VertexerZ) && collision.covZZ() < 0.25)) { accepted = false; } @@ -209,7 +205,7 @@ struct TwoParticleCorrelationsSkimming { runNumber = bcinfo.runNumber(); } if (accepted) { - return fEventFilter->Filter(collision, tracks, bfield); + return fFilterFramework->FilterCollision(collision, tracks, bfield); } else { return 0UL; } @@ -226,18 +222,18 @@ struct TwoParticleCorrelationsSkimming { LOGF(LOGTRACKCOLLISIONS, "Got mask 0x%16lx", colmask); if (colmask != 0UL) { - skimmedcollision(collision.posZ(), bc.runNumber(), bc.timestamp(), colmask, fEventFilter->GetMultiplicities()); + skimmedcollision(collision.posZ(), bc.runNumber(), bc.timestamp(), colmask, fFilterFramework->GetCollisionMultiplicities()); int nFilteredTracks = 0; int nCollisionReportedTracks = 0; for (auto const& track : tracks) { - auto trkmask = fTrackFilter->Filter(track); - auto pidmask = fPIDFilter->Filter(track); + auto trkmask = fFilterFramework->FilterTrack(track); + auto pidmask = fFilterFramework->FilterTrackPID(track); if (trkmask != 0UL) { skimmedtrack(skimmedcollision.lastIndex(), trkmask, track.pt(), track.eta(), track.phi()); skimmtrackpid(pidmask); nFilteredTracks++; } - if (trkmask != 0UL and nReportedTracks < 1000) { + if (trkmask != 0UL && nReportedTracks < 1000) { if (nCollisionReportedTracks < 20) { 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",