|
| 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 | +} |
0 commit comments