Skip to content

Commit 1bc5ff9

Browse files
authored
PWGCF: flow: add Run3ITSall7Layers option and a new run-by-run task (#8201)
1 parent d3a5567 commit 1bc5ff9

3 files changed

Lines changed: 234 additions & 9 deletions

File tree

PWGCF/Flow/Tasks/CMakeLists.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,11 @@ o2physics_add_dpl_workflow(flow-task
1919
PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::AnalysisCCDB O2Physics::GFWCore
2020
COMPONENT_NAME Analysis)
2121

22+
o2physics_add_dpl_workflow(flow-runbyrun
23+
SOURCES FlowRunbyRun.cxx
24+
PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::AnalysisCCDB O2Physics::GFWCore
25+
COMPONENT_NAME Analysis)
26+
2227
o2physics_add_dpl_workflow(flow-gfw-pbpb
2328
SOURCES FlowGFWPbPb.cxx
2429
PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::GFWCore

PWGCF/Flow/Tasks/FlowRunbyRun.cxx

Lines changed: 204 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,204 @@
1+
// Copyright 2019-2020 CERN and copyright holders of ALICE O2.
2+
// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
3+
// All rights not expressly granted are reserved.
4+
//
5+
// This software is distributed under the terms of the GNU General Public
6+
// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
7+
//
8+
// In applying this license CERN does not waive the privileges and immunities
9+
// granted to it by virtue of its status as an Intergovernmental Organization
10+
// or submit itself to any jurisdiction.
11+
//
12+
// code author: Zhiyong Lu (zhiyong.lu@cern.ch)
13+
// jira: PWGCF-254
14+
// Produce Run-by-Run QA plots and flow analysis for Run3
15+
16+
#include <CCDB/BasicCCDBManager.h>
17+
#include <cmath>
18+
#include <vector>
19+
#include <map>
20+
#include "Framework/runDataProcessing.h"
21+
#include "Framework/AnalysisTask.h"
22+
#include "Framework/ASoAHelpers.h"
23+
#include "Framework/RunningWorkflowInfo.h"
24+
#include "Framework/HistogramRegistry.h"
25+
26+
#include "Common/DataModel/EventSelection.h"
27+
#include "Common/Core/TrackSelection.h"
28+
#include "Common/DataModel/TrackSelectionTables.h"
29+
#include "Common/DataModel/Centrality.h"
30+
#include "Common/DataModel/Multiplicity.h"
31+
32+
#include "GFWPowerArray.h"
33+
#include "GFW.h"
34+
#include "GFWCumulant.h"
35+
#include "GFWWeights.h"
36+
#include "TList.h"
37+
#include <TProfile.h>
38+
#include <TRandom3.h>
39+
40+
using namespace o2;
41+
using namespace o2::framework;
42+
using namespace o2::framework::expressions;
43+
44+
#define O2_DEFINE_CONFIGURABLE(NAME, TYPE, DEFAULT, HELP) Configurable<TYPE> NAME{#NAME, DEFAULT, HELP};
45+
46+
struct FlowRunbyRun {
47+
48+
O2_DEFINE_CONFIGURABLE(cfgCutVertex, float, 10.0f, "Accepted z-vertex range")
49+
O2_DEFINE_CONFIGURABLE(cfgCutPtPOIMin, float, 0.2f, "Minimal pT for poi tracks")
50+
O2_DEFINE_CONFIGURABLE(cfgCutPtPOIMax, float, 10.0f, "Maximal pT for poi tracks")
51+
O2_DEFINE_CONFIGURABLE(cfgCutPtRefMin, float, 0.2f, "Minimal pT for ref tracks")
52+
O2_DEFINE_CONFIGURABLE(cfgCutPtRefMax, float, 3.0f, "Maximal pT for ref tracks")
53+
O2_DEFINE_CONFIGURABLE(cfgCutPtMin, float, 0.2f, "Minimal pT for all tracks")
54+
O2_DEFINE_CONFIGURABLE(cfgCutPtMax, float, 10.0f, "Maximal pT for all tracks")
55+
O2_DEFINE_CONFIGURABLE(cfgCutEta, float, 0.8f, "Eta range for tracks")
56+
O2_DEFINE_CONFIGURABLE(cfgCutChi2prTPCcls, float, 2.5, "Chi2 per TPC clusters")
57+
O2_DEFINE_CONFIGURABLE(cfgCutDCAz, float, 2.0f, "max DCA to vertex z")
58+
O2_DEFINE_CONFIGURABLE(cfgUseNch, bool, false, "Use Nch for flow observables")
59+
Configurable<std::vector<int>> cfgRunNumbers{"cfgRunNumbers", std::vector<int>{544095, 544098, 544116, 544121, 544122, 544123, 544124}, "Preconfigured run numbers"};
60+
61+
ConfigurableAxis axisVertex{"axisVertex", {20, -10, 10}, "vertex axis for histograms"};
62+
ConfigurableAxis axisPhi{"axisPhi", {60, 0.0, constants::math::TwoPI}, "phi axis for histograms"};
63+
ConfigurableAxis axisEta{"axisEta", {40, -1., 1.}, "eta axis for histograms"};
64+
ConfigurableAxis axisPt{"axisPt", {VARIABLE_WIDTH, 0.2, 0.25, 0.3, 0.35, 0.4, 0.45, 0.5, 0.55, 0.6, 0.65, 0.7, 0.75, 0.8, 0.85, 0.9, 0.95, 1, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 2, 2.2, 2.4, 2.6, 2.8, 3, 3.5, 4, 5, 6, 8, 10}, "pt axis for histograms"};
65+
ConfigurableAxis axisIndependent{"axisIndependent", {VARIABLE_WIDTH, 0, 5, 10, 20, 30, 40, 50, 60, 70, 80, 90}, "X axis for histograms"};
66+
67+
Filter collisionFilter = nabs(aod::collision::posZ) < cfgCutVertex;
68+
Filter trackFilter = ((requireGlobalTrackInFilter()) || (aod::track::isGlobalTrackSDD == (uint8_t) true)) && (nabs(aod::track::eta) < cfgCutEta) && (aod::track::pt > cfgCutPtMin) && (aod::track::pt < cfgCutPtMax) && (aod::track::tpcChi2NCl < cfgCutChi2prTPCcls) && (nabs(aod::track::dcaZ) < cfgCutDCAz);
69+
70+
// Connect to ccdb
71+
Service<ccdb::BasicCCDBManager> ccdb;
72+
Configurable<int64_t> nolaterthan{"ccdb-no-later-than", std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count(), "latest acceptable timestamp of creation for the object"};
73+
Configurable<std::string> url{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"};
74+
75+
// Define output
76+
HistogramRegistry registry{"registry"};
77+
78+
// define global variables
79+
GFW* fGFW = new GFW();
80+
std::vector<GFW::CorrConfig> corrconfigs;
81+
std::vector<int> RunNumbers; // vector of run numbers
82+
std::map<int, std::vector<std::shared_ptr<TH1>>> TH1sList; // map of histograms for all runs
83+
std::map<int, std::vector<std::shared_ptr<TProfile>>> ProfilesList; // map of profiles for all runs
84+
enum OutputTH1Names {
85+
// here are TProfiles for vn-pt correlations that are not implemented in GFW
86+
hPhi = 0,
87+
hEta,
88+
hVtxZ,
89+
hMult,
90+
hCent,
91+
kCount_TH1Names
92+
};
93+
enum OutputTProfileNames {
94+
c22 = 0,
95+
c22_gap10,
96+
kCount_TProfileNames
97+
};
98+
99+
using aodCollisions = soa::Filtered<soa::Join<aod::Collisions, aod::EvSels, aod::CentFT0Cs, aod::Mults>>;
100+
using aodTracks = soa::Filtered<soa::Join<aod::Tracks, aod::TrackSelection, aod::TracksExtra, aod::TracksDCA>>;
101+
102+
void init(InitContext const&)
103+
{
104+
ccdb->setURL(url.value);
105+
ccdb->setCaching(true);
106+
ccdb->setCreatedNotAfter(nolaterthan.value);
107+
108+
// Add output histograms to the registry
109+
std::vector<int> temp = cfgRunNumbers;
110+
RunNumbers = temp;
111+
for (auto& runNumber : RunNumbers) {
112+
CreateOutputObjectsForRun(runNumber);
113+
}
114+
115+
fGFW->AddRegion("full", -0.8, 0.8, 1, 1);
116+
fGFW->AddRegion("refN10", -0.8, -0.5, 1, 1);
117+
fGFW->AddRegion("refP10", 0.5, 0.8, 1, 1);
118+
corrconfigs.resize(kCount_TProfileNames);
119+
corrconfigs[c22] = fGFW->GetCorrelatorConfig("full {2 -2}", "ChFull22", kFALSE);
120+
corrconfigs[c22_gap10] = fGFW->GetCorrelatorConfig("refN10 {2} refP10 {-2}", "Ch10Gap22", kFALSE);
121+
fGFW->CreateRegions();
122+
}
123+
124+
template <char... chars>
125+
void FillProfile(const GFW::CorrConfig& corrconf, std::shared_ptr<TProfile> profile, const double& cent)
126+
{
127+
double dnx, val;
128+
dnx = fGFW->Calculate(corrconf, 0, kTRUE).real();
129+
if (dnx == 0)
130+
return;
131+
if (!corrconf.pTDif) {
132+
val = fGFW->Calculate(corrconf, 0, kFALSE).real() / dnx;
133+
if (TMath::Abs(val) < 1)
134+
profile->Fill(cent, val, dnx);
135+
return;
136+
}
137+
return;
138+
}
139+
140+
void CreateOutputObjectsForRun(int runNumber)
141+
{
142+
std::vector<std::shared_ptr<TH1>> histos(kCount_TH1Names);
143+
histos[hPhi] = registry.add<TH1>(Form("%d/hPhi", runNumber), "", {HistType::kTH1D, {axisPhi}});
144+
histos[hEta] = registry.add<TH1>(Form("%d/hEta", runNumber), "", {HistType::kTH1D, {axisEta}});
145+
histos[hVtxZ] = registry.add<TH1>(Form("%d/hVtxZ", runNumber), "", {HistType::kTH1D, {axisVertex}});
146+
histos[hMult] = registry.add<TH1>(Form("%d/hMult", runNumber), "", {HistType::kTH1D, {{3000, 0.5, 3000.5}}});
147+
histos[hCent] = registry.add<TH1>(Form("%d/hCent", runNumber), "", {HistType::kTH1D, {{90, 0, 90}}});
148+
TH1sList.insert(std::make_pair(runNumber, histos));
149+
150+
std::vector<std::shared_ptr<TProfile>> profiles(kCount_TProfileNames);
151+
profiles[c22] = registry.add<TProfile>(Form("%d/c22", runNumber), "", {HistType::kTProfile, {axisIndependent}});
152+
profiles[c22_gap10] = registry.add<TProfile>(Form("%d/c22_gap10", runNumber), "", {HistType::kTProfile, {axisIndependent}});
153+
ProfilesList.insert(std::make_pair(runNumber, profiles));
154+
}
155+
156+
void process(aodCollisions::iterator const& collision, aod::BCsWithTimestamps const&, aodTracks const& tracks)
157+
{
158+
if (!collision.sel8())
159+
return;
160+
if (tracks.size() < 1)
161+
return;
162+
// detect run number
163+
auto bc = collision.bc_as<aod::BCsWithTimestamps>();
164+
int runNumber = bc.runNumber();
165+
if (std::find(RunNumbers.begin(), RunNumbers.end(), runNumber) == RunNumbers.end()) {
166+
// if run number is not in the preconfigured list, create new output histograms for this run
167+
CreateOutputObjectsForRun(runNumber);
168+
RunNumbers.push_back(runNumber);
169+
}
170+
171+
if (TH1sList.find(runNumber) == TH1sList.end()) {
172+
LOGF(fatal, "RunNumber %d not found in TH1sList", runNumber);
173+
return;
174+
}
175+
176+
TH1sList[runNumber][hVtxZ]->Fill(collision.posZ());
177+
TH1sList[runNumber][hMult]->Fill(tracks.size());
178+
TH1sList[runNumber][hCent]->Fill(collision.centFT0C());
179+
180+
fGFW->Clear();
181+
const auto cent = collision.centFT0C();
182+
float weff = 1, wacc = 1;
183+
for (auto& track : tracks) {
184+
TH1sList[runNumber][hPhi]->Fill(track.phi());
185+
TH1sList[runNumber][hEta]->Fill(track.eta());
186+
bool WithinPtPOI = (cfgCutPtPOIMin < track.pt()) && (track.pt() < cfgCutPtPOIMax); // within POI pT range
187+
bool WithinPtRef = (cfgCutPtRefMin < track.pt()) && (track.pt() < cfgCutPtRefMax); // within RF pT range
188+
if (WithinPtRef) {
189+
fGFW->Fill(track.eta(), 1, track.phi(), wacc * weff, 1);
190+
}
191+
}
192+
193+
// Filling TProfile
194+
for (uint i = 0; i < kCount_TProfileNames; ++i) {
195+
FillProfile(corrconfigs[i], ProfilesList[runNumber][i], cent);
196+
}
197+
}
198+
};
199+
200+
WorkflowSpec defineDataProcessing(ConfigContext const& cfgc)
201+
{
202+
return WorkflowSpec{
203+
adaptAnalysisTask<FlowRunbyRun>(cfgc)};
204+
}

PWGCF/Flow/Tasks/FlowTask.cxx

Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424

2525
#include "Common/DataModel/EventSelection.h"
2626
#include "Common/Core/TrackSelection.h"
27+
#include "Common/Core/TrackSelectionDefaults.h"
2728
#include "Common/DataModel/TrackSelectionTables.h"
2829
#include "Common/DataModel/Centrality.h"
2930
#include "Common/DataModel/Multiplicity.h"
@@ -58,14 +59,16 @@ struct FlowTask {
5859
O2_DEFINE_CONFIGURABLE(cfgCutChi2prTPCcls, float, 2.5f, "max chi2 per TPC clusters")
5960
O2_DEFINE_CONFIGURABLE(cfgCutTPCclu, float, 70.0f, "minimum TPC clusters")
6061
O2_DEFINE_CONFIGURABLE(cfgCutDCAz, float, 2.0f, "max DCA to vertex z")
62+
O2_DEFINE_CONFIGURABLE(cfgTrkSelSwitch, bool, false, "switch for self-defined track selection")
63+
O2_DEFINE_CONFIGURABLE(cfgTrkSelRun3ITSMatch, bool, false, "GlobalTrackRun3ITSMatching::Run3ITSall7Layers selection")
64+
O2_DEFINE_CONFIGURABLE(cfgRejectionTPCsectorOverlap, bool, true, "rejection for TPC sector overlap")
6165
O2_DEFINE_CONFIGURABLE(cfgUseAdditionalEventCut, bool, false, "Use additional event cut on mult correlations")
6266
O2_DEFINE_CONFIGURABLE(cfgTriggerkTVXinTRD, bool, true, "TRD triggered")
6367
O2_DEFINE_CONFIGURABLE(cfgEvSelkNoSameBunchPileup, bool, true, "rejects collisions which are associated with the same found-by-T0 bunch crossing")
6468
O2_DEFINE_CONFIGURABLE(cfgEvSelkIsGoodZvtxFT0vsPV, bool, true, "removes collisions with large differences between z of PV by tracks and z of PV from FT0 A-C time difference, use this cut at low multiplicities with caution")
6569
O2_DEFINE_CONFIGURABLE(cfgEvSelkNoCollInTimeRangeStandard, bool, true, "no collisions in specified time range")
6670
O2_DEFINE_CONFIGURABLE(cfgEvSelMultCorrelation, bool, true, "Multiplicity correlation cut")
6771
O2_DEFINE_CONFIGURABLE(cfgEvSelV0AT0ACut, bool, true, "V0A T0A 5 sigma cut")
68-
O2_DEFINE_CONFIGURABLE(cfgUseAdditionalTrackCut, bool, false, "Use additional track cut on phi")
6972
O2_DEFINE_CONFIGURABLE(cfgGetInteractionRate, bool, false, "Get interaction rate from CCDB")
7073
O2_DEFINE_CONFIGURABLE(cfgUseInteractionRateCut, bool, false, "Use events with low interaction rate")
7174
O2_DEFINE_CONFIGURABLE(cfgCutIR, float, 50.0, "maximum interaction rate (kHz)")
@@ -141,9 +144,11 @@ struct FlowTask {
141144
using aodCollisions = soa::Filtered<soa::Join<aod::Collisions, aod::EvSels, aod::CentFT0Cs, aod::Mults>>;
142145
using aodTracks = soa::Filtered<soa::Join<aod::Tracks, aod::TrackSelection, aod::TracksExtra, aod::TracksDCA>>;
143146

144-
// Additional Event selection cuts - Copy from flowGenericFramework.cxx
147+
// Track selection
148+
TrackSelection myTrackSel;
145149
TF1* fPhiCutLow = nullptr;
146150
TF1* fPhiCutHigh = nullptr;
151+
// Additional Event selection cuts - Copy from flowGenericFramework.cxx
147152
TF1* fMultPVCutLow = nullptr;
148153
TF1* fMultPVCutHigh = nullptr;
149154
TF1* fMultCutLow = nullptr;
@@ -280,7 +285,7 @@ struct FlowTask {
280285
std::vector<std::string> UserDefineGFWCorr = cfgUserDefineGFWCorr;
281286
std::vector<std::string> UserDefineGFWName = cfgUserDefineGFWName;
282287
if (!UserDefineGFWCorr.empty() && !UserDefineGFWName.empty()) {
283-
for (auto i = 0; i < UserDefineGFWName.size(); i++) {
288+
for (uint i = 0; i < UserDefineGFWName.size(); i++) {
284289
oba->Add(new TNamed(UserDefineGFWName.at(i).c_str(), UserDefineGFWName.at(i).c_str()));
285290
}
286291
}
@@ -354,7 +359,7 @@ struct FlowTask {
354359
if (!UserDefineGFWCorr.empty() && !UserDefineGFWName.empty()) {
355360
LOGF(info, "User adding GFW CorrelatorConfig:");
356361
// attentaion: here we follow the index of cfgUserDefineGFWCorr
357-
for (auto i = 0; i < UserDefineGFWCorr.size(); i++) {
362+
for (uint i = 0; i < UserDefineGFWCorr.size(); i++) {
358363
if (i >= UserDefineGFWName.size()) {
359364
LOGF(fatal, "The names you provided are more than configurations. UserDefineGFWName.size(): %d > UserDefineGFWCorr.size(): %d", UserDefineGFWName.size(), UserDefineGFWCorr.size());
360365
break;
@@ -382,10 +387,17 @@ struct FlowTask {
382387
fT0AV0ASigma->SetParameters(463.4144, 6.796509e-02, -9.097136e-07, 7.971088e-12, -2.600581e-17);
383388
}
384389

385-
if (cfgUseAdditionalTrackCut) {
390+
if (cfgRejectionTPCsectorOverlap) {
386391
fPhiCutLow = new TF1("fPhiCutLow", "0.06/x+pi/18.0-0.06", 0, 100);
387392
fPhiCutHigh = new TF1("fPhiCutHigh", "0.1/x+pi/18.0+0.06", 0, 100);
388393
}
394+
395+
if (cfgTrkSelRun3ITSMatch) {
396+
myTrackSel = getGlobalTrackSelectionRun3ITSMatch(TrackSelection::GlobalTrackRun3ITSMatching::Run3ITSall7Layers, TrackSelection::GlobalTrackRun3DCAxyCut::Default);
397+
} else {
398+
myTrackSel = getGlobalTrackSelectionRun3ITSMatch(TrackSelection::GlobalTrackRun3ITSMatching::Run3ITSibAny, TrackSelection::GlobalTrackRun3DCAxyCut::Default);
399+
}
400+
myTrackSel.SetMinNClustersTPC(cfgCutTPCclu);
389401
}
390402

391403
template <char... chars>
@@ -570,11 +582,15 @@ struct FlowTask {
570582
template <typename TTrack>
571583
bool trackSelected(TTrack track)
572584
{
573-
return (track.tpcNClsFound() >= cfgCutTPCclu);
585+
if (cfgTrkSelSwitch) {
586+
return myTrackSel.IsSelected(track);
587+
} else {
588+
return (track.tpcNClsFound() >= cfgCutTPCclu);
589+
}
574590
}
575591

576592
template <typename TTrack>
577-
bool AdditionaltrackSelected(TTrack track, const int field)
593+
bool RejectionTPCoverlap(TTrack track, const int field)
578594
{
579595
double phimodn = track.phi();
580596
if (field < 0) // for negative polarity field
@@ -670,7 +686,7 @@ struct FlowTask {
670686
double sum_ptSquare_wSquare_WithinGap08 = 0., sum_pt_wSquare_WithinGap08 = 0.;
671687
int Magnetfield = 0;
672688
double NTracksCorrected = 0;
673-
if (cfgUseAdditionalTrackCut) {
689+
if (cfgRejectionTPCsectorOverlap) {
674690
// magnet field dependence cut
675691
Magnetfield = getMagneticField(bc.timestamp());
676692
}
@@ -681,7 +697,7 @@ struct FlowTask {
681697
for (auto& track : tracks) {
682698
if (!trackSelected(track))
683699
continue;
684-
if (cfgUseAdditionalTrackCut && !AdditionaltrackSelected(track, Magnetfield))
700+
if (cfgRejectionTPCsectorOverlap && !RejectionTPCoverlap(track, Magnetfield))
685701
continue;
686702
if (cfgOutputNUAWeights)
687703
fWeights->Fill(track.phi(), track.eta(), vtxz, track.pt(), cent, 0);

0 commit comments

Comments
 (0)