Skip to content

Commit 3fcaf1d

Browse files
davkksmaff92
authored andcommitted
[PWGCF/FemtoUniverse] Initial implementation of EfficiencyCalculator (AliceO2Group#9282)
1 parent 654fc68 commit 3fcaf1d

File tree

2 files changed

+319
-19
lines changed

2 files changed

+319
-19
lines changed
Lines changed: 242 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,242 @@
1+
// Copyright 2019-2022 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+
/// \file FemtoUniverseEfficiencyCalculator.h
13+
/// \brief Abstraction for calculating efficiency and applying corrections with the help of CCDB
14+
/// \author Dawid Karpiński, WUT Warsaw, dawid.karpinski@cern.ch
15+
16+
#ifndef PWGCF_FEMTOUNIVERSE_CORE_FEMTOUNIVERSEEFFICIENCYCALCULATOR_H_
17+
#define PWGCF_FEMTOUNIVERSE_CORE_FEMTOUNIVERSEEFFICIENCYCALCULATOR_H_
18+
19+
#include <vector>
20+
#include <memory>
21+
#include <map>
22+
#include <string>
23+
24+
#include "Framework/Configurable.h"
25+
#include "Framework/AnalysisHelpers.h"
26+
#include "Framework/CallbackService.h"
27+
#include "Framework/InitContext.h"
28+
#include "CCDB/BasicCCDBManager.h"
29+
#include "PWGCF/FemtoUniverse/DataModel/FemtoDerived.h"
30+
#include "FemtoUniverseParticleHisto.h"
31+
32+
namespace o2::analysis::femto_universe::efficiency
33+
{
34+
template <uint8_t T>
35+
concept isOneOrTwo = T == 1 || T == 2;
36+
37+
struct EfficiencyConfigurableGroup : ConfigurableGroup {
38+
Configurable<bool> confEfficiencyCalculate{"confEfficiencyCalculate", false, "Should calculate efficiency"};
39+
Configurable<bool> confEfficiencyApplyCorrections{"confEfficiencyApplyCorrections", false, "Should apply corrections from efficiency"};
40+
41+
Configurable<std::vector<std::string>> confCCDBLabels{"confCCDBLabels", std::vector<std::string>{"label1", "label2"}, "Labels for efficiency objects in CCDB"};
42+
43+
OutputObj<TH1F> hEfficiency1{"Efficiency part1"};
44+
OutputObj<TH1F> hEfficiency2{"Efficiency part2"};
45+
46+
// TODO: move to separate struct?
47+
Configurable<std::string> confCCDBUrl{"confCCDBUrl", "http://alice-ccdb.cern.ch", "CCDB URL to be used"};
48+
Configurable<std::string> confCCDBPath{"confCCDBPath", "", "CCDB base path to where to upload objects"};
49+
Configurable<int64_t> confCCDBTimestamp{"confCCDBTimestamp", -1, "Timestamp from which to query CCDB objects"};
50+
51+
// TODO: declare this in task directly?
52+
FemtoUniverseParticleHisto<aod::femtouniverseparticle::ParticleType::kMCTruthTrack, 1> hMCTruth1;
53+
FemtoUniverseParticleHisto<aod::femtouniverseparticle::ParticleType::kMCTruthTrack, 2> hMCTruth2;
54+
};
55+
56+
class EfficiencyCalculator
57+
{
58+
public:
59+
o2::ccdb::BasicCCDBManager& ccdb{o2::ccdb::BasicCCDBManager::instance()};
60+
61+
explicit EfficiencyCalculator(EfficiencyConfigurableGroup* config) : config(config) // o2-linter: disable=name/function-variable
62+
{
63+
}
64+
65+
auto init() -> void
66+
{
67+
ccdbApi.init(config->confCCDBUrl);
68+
ccdb.setURL(config->confCCDBUrl);
69+
ccdb.setLocalObjectValidityChecking();
70+
ccdb.setFatalWhenNull(false);
71+
72+
shouldCalculate = config->confEfficiencyCalculate;
73+
shouldApplyCorrections = config->confEfficiencyApplyCorrections;
74+
75+
ccdbFullPath = fmt::format("{}/{}", config->confCCDBPath.value, folderName);
76+
77+
if (config->confEfficiencyCalculate) {
78+
hOutput = {config->hEfficiency1.object, config->hEfficiency2.object};
79+
}
80+
81+
if (config->confEfficiencyApplyCorrections) {
82+
hLoaded = {
83+
loadEfficiencyFromCCDB<1>(config->confCCDBTimestamp),
84+
loadEfficiencyFromCCDB<2>(config->confCCDBTimestamp) //
85+
};
86+
}
87+
}
88+
89+
template <uint8_t N>
90+
requires isOneOrTwo<N>
91+
auto doMCTruth(auto particles) const -> void
92+
{
93+
for (const auto& particle : particles) {
94+
if constexpr (N == 1) {
95+
config->hMCTruth1.fillQA<false, false>(particle);
96+
} else if constexpr (N == 2) {
97+
config->hMCTruth2.fillQA<false, false>(particle);
98+
}
99+
}
100+
}
101+
102+
auto uploadOnStop(InitContext& ic) -> void
103+
{
104+
if (!shouldCalculate) {
105+
return;
106+
}
107+
108+
if (!shouldUploadOnStop) {
109+
shouldUploadOnStop = true;
110+
111+
auto& callbacks = ic.services().get<CallbackService>();
112+
callbacks.set<o2::framework::CallbackService::Id::Stop>([this]() {
113+
for (auto i = 0UL; i < hOutput.size(); i++) {
114+
const auto& output = hOutput[i];
115+
116+
if (isHistogramEmpty(output.get())) {
117+
LOGF(error, notify("Histogram %d is empty - save aborted"), i + 1);
118+
return;
119+
}
120+
LOGF(debug, notify("Found histogram %d: %s"), i + 1, output->GetTitle());
121+
122+
int64_t now = duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count();
123+
int64_t oneYear = 365LL * 24 * 60 * 60 * 1000;
124+
125+
if (ccdbApi.storeAsTFileAny(output.get(), ccdbFullPath, createMetadata(i), now, now + oneYear) == 0) {
126+
LOGF(info, notify("Histogram %d saved successfully"), i + 1);
127+
} else {
128+
LOGF(fatal, notify("Histogram %d save failed"), i + 1);
129+
}
130+
}
131+
});
132+
} else {
133+
LOGF(warn, notify("Uploading on stop callback is already set up"));
134+
}
135+
}
136+
137+
template <uint8_t N>
138+
requires isOneOrTwo<N>
139+
auto getWeight(auto const& particle) const -> float
140+
{
141+
auto weight = 1.0f;
142+
auto hEff = hLoaded[N - 1];
143+
144+
if (shouldApplyCorrections && hEff) {
145+
auto bin = hEff->FindBin(particle.pt());
146+
auto eff = hEff->GetBinContent(bin);
147+
weight /= eff > 0 ? eff : 1.0f;
148+
}
149+
150+
return weight;
151+
}
152+
153+
template <uint8_t N>
154+
requires isOneOrTwo<N>
155+
auto calculate(std::shared_ptr<TH1> truth, std::shared_ptr<TH1> reco) const
156+
{
157+
if (!shouldCalculate) {
158+
return;
159+
}
160+
161+
if (!truth || !reco) {
162+
LOGF(error, notify("MC Truth & MC Reco histograms cannot be null"));
163+
return;
164+
}
165+
166+
auto hEff = hOutput[N - 1];
167+
if (!hEff) {
168+
LOGF(error, notify("No OutputObj specified for particle %d histogram"), N);
169+
return;
170+
}
171+
172+
for (auto bin = 0; bin < hEff->GetNbinsX(); bin++) {
173+
auto denom = truth->GetBinContent(bin);
174+
hEff->SetBinContent(bin, denom == 0 ? 0 : reco->GetBinContent(bin) / denom);
175+
}
176+
}
177+
178+
private:
179+
static inline auto notify(const std::string& msg) -> const std::string
180+
{
181+
return fmt::format("[EFFICIENCY] {}", msg);
182+
}
183+
184+
static auto isHistogramEmpty(TH1* hist) -> bool
185+
{
186+
if (!hist) {
187+
return true;
188+
}
189+
190+
// check overflow bins as well
191+
for (auto idx = 0; idx <= hist->GetNbinsX() + 1; idx++) {
192+
if (hist->GetBinContent(idx) != 0) {
193+
return false;
194+
}
195+
}
196+
197+
return true;
198+
}
199+
200+
auto createMetadata(uint8_t partNo) const -> std::map<std::string, std::string>
201+
{
202+
if (config->confCCDBLabels->size() != 2) {
203+
LOGF(fatal, notify("CCDB labels configurable should be exactly of size 2"));
204+
}
205+
return std::map<std::string, std::string>{
206+
{"label", config->confCCDBLabels.value[partNo]} //
207+
};
208+
}
209+
210+
template <uint8_t N>
211+
requires isOneOrTwo<N>
212+
auto loadEfficiencyFromCCDB(int64_t timestamp) const -> TH1*
213+
{
214+
auto hEff = ccdb.getSpecific<TH1>(ccdbFullPath, timestamp, createMetadata(N - 1));
215+
if (!hEff || hEff->IsZombie()) {
216+
LOGF(error, notify("Could not load histogram from %s"), config->confCCDBPath.value);
217+
return nullptr;
218+
}
219+
220+
LOGF(info, notify("Histogram \"%s\" loaded from \"%s\""), hEff->GetTitle(), config->confCCDBPath.value);
221+
return hEff;
222+
}
223+
224+
EfficiencyConfigurableGroup* config{};
225+
226+
bool shouldUploadOnStop = false;
227+
bool shouldCalculate = false;
228+
bool shouldApplyCorrections = false;
229+
230+
std::array<std::shared_ptr<TH1>, 2> hOutput{};
231+
std::array<TH1*, 2> hLoaded{};
232+
233+
o2::ccdb::CcdbApi ccdbApi{};
234+
std::string ccdbFullPath{};
235+
236+
static constexpr std::string_view folderName{"Efficiency"};
237+
static constexpr std::array<std::string_view, 3> histSuffix{"", "_one", "_two"};
238+
};
239+
240+
} // namespace o2::analysis::femto_universe::efficiency
241+
242+
#endif // PWGCF_FEMTOUNIVERSE_CORE_FEMTOUNIVERSEEFFICIENCYCALCULATOR_H_

0 commit comments

Comments
 (0)