Skip to content

Commit f7f5e91

Browse files
author
Michal Tichák
committed
[Framework] classes inherited from Reductor are now configurable
- field reductorParameters inside of dataSources is used - internally we use CustomParameters so json config has same format as extendedTaskParameters
1 parent ace19c2 commit f7f5e91

File tree

7 files changed

+235
-88
lines changed

7 files changed

+235
-88
lines changed

Framework/include/QualityControl/Reductor.h

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,17 @@
1616
#ifndef QUALITYCONTROL_REDUCTOR_H
1717
#define QUALITYCONTROL_REDUCTOR_H
1818

19+
#include "CustomParameters.h"
20+
1921
namespace o2::quality_control::postprocessing
2022
{
2123

2224
/// \brief An interface for storing columnar data into a TTree
2325
class Reductor
2426
{
27+
protected:
28+
core::CustomParameters mCustomParameters;
29+
2530
public:
2631
/// \brief Constructor
2732
Reductor() = default;
@@ -34,8 +39,10 @@ class Reductor
3439
/// \brief Branch leaf list getter
3540
/// \return A C string with a description of a branch format, formatted accordingly to the TTree interface
3641
virtual const char* getBranchLeafList() = 0;
42+
/// \brief setter for mCustomParameters
43+
void setCustomConfig(const core::CustomParameters& parameters) { mCustomParameters = parameters; };
3744
};
3845

3946
} // namespace o2::quality_control::postprocessing
4047

41-
#endif //QUALITYCONTROL_REDUCTOR_H
48+
#endif // QUALITYCONTROL_REDUCTOR_H

Framework/include/QualityControl/TrendingTaskConfig.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
#include <vector>
2121
#include <string>
22+
#include "CustomParameters.h"
2223
#include "QualityControl/PostProcessingConfig.h"
2324

2425
namespace o2::quality_control::postprocessing
@@ -56,6 +57,7 @@ struct TrendingTaskConfig : PostProcessingConfig {
5657
std::string path;
5758
std::string name;
5859
std::string reductorName;
60+
core::CustomParameters reductorParameters;
5961
std::string moduleName;
6062
};
6163

Framework/src/TrendingTask.cxx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,8 @@ void TrendingTask::configure(const boost::property_tree::ptree& config)
4848
// configuration
4949
mConfig = TrendingTaskConfig(getID(), config);
5050
for (const auto& source : mConfig.dataSources) {
51-
mReductors.emplace(source.name, root_class_factory::create<Reductor>(source.moduleName, source.reductorName));
51+
auto&& [emplaced, _] = mReductors.emplace(source.name, root_class_factory::create<Reductor>(source.moduleName, source.reductorName));
52+
emplaced->second->setCustomConfig(source.reductorParameters);
5253
}
5354
}
5455

Framework/src/TrendingTaskConfig.cxx

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,13 +58,23 @@ TrendingTaskConfig::TrendingTaskConfig(std::string id, const boost::property_tre
5858
plotConfig.get<int>("colorPalette", 0),
5959
graphs });
6060
}
61+
62+
const auto extractReductorParams = [](const boost::property_tree::ptree& dataSourceConfig) -> core::CustomParameters {
63+
core::CustomParameters result;
64+
if (const auto reductorParams = dataSourceConfig.get_child_optional("reductorParameters"); reductorParams.has_value()) {
65+
result.populateCustomParameters(reductorParams.value());
66+
}
67+
return result;
68+
};
69+
6170
for (const auto& dataSourceConfig : config.get_child("qc.postprocessing." + id + ".dataSources")) {
6271
if (const auto& sourceNames = dataSourceConfig.second.get_child_optional("names"); sourceNames.has_value()) {
6372
for (const auto& sourceName : sourceNames.value()) {
6473
dataSources.push_back({ dataSourceConfig.second.get<std::string>("type", "repository"),
6574
dataSourceConfig.second.get<std::string>("path"),
6675
sourceName.second.data(),
6776
dataSourceConfig.second.get<std::string>("reductorName"),
77+
extractReductorParams(dataSourceConfig.second),
6878
dataSourceConfig.second.get<std::string>("moduleName") });
6979
}
7080
} else if (!dataSourceConfig.second.get<std::string>("name").empty()) {
@@ -73,6 +83,7 @@ TrendingTaskConfig::TrendingTaskConfig(std::string id, const boost::property_tre
7383
dataSourceConfig.second.get<std::string>("path"),
7484
dataSourceConfig.second.get<std::string>("name"),
7585
dataSourceConfig.second.get<std::string>("reductorName"),
86+
extractReductorParams(dataSourceConfig.second),
7687
dataSourceConfig.second.get<std::string>("moduleName") });
7788
} else {
7889
throw std::runtime_error("No 'name' value or a 'names' vector in the path 'qc.postprocessing." + id + ".dataSources'");

Framework/test/testReductor.cxx

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
/// \author Piotr Konopka
1515
///
1616

17+
#include "QualityControl/CustomParameters.h"
1718
#include "QualityControl/Reductor.h"
1819
#include "QualityControl/ReductorTObject.h"
1920
#include "QualityControl/ReductorConditionAny.h"
@@ -23,6 +24,7 @@
2324
#include "QualityControl/ConditionAccess.h"
2425
#include <TH1I.h>
2526
#include <TTree.h>
27+
#include <boost/test/tools/old/interface.hpp>
2628

2729
#define BOOST_TEST_MODULE Reductor test
2830
#define BOOST_TEST_MAIN
@@ -172,4 +174,30 @@ BOOST_AUTO_TEST_CASE(test_ReductorAnyInterface)
172174
Double_t* integrals = tree->GetVal(0);
173175

174176
BOOST_CHECK_EQUAL(integrals[0], secret.Length());
175-
}
177+
}
178+
179+
BOOST_AUTO_TEST_CASE(test_ReductorConfigurable)
180+
{
181+
class ReductorTest : public Reductor
182+
{
183+
public:
184+
std::string value{};
185+
186+
virtual void* getBranchAddress()
187+
{
188+
return nullptr;
189+
}
190+
virtual const char* getBranchLeafList()
191+
{
192+
value = mCustomParameters.at("key");
193+
return value.c_str();
194+
}
195+
};
196+
197+
ReductorTest reductor;
198+
CustomParameters params;
199+
params.set("key", "value");
200+
Reductor& r = reductor;
201+
r.setCustomConfig(params);
202+
BOOST_REQUIRE_EQUAL(r.getBranchLeafList(), "value");
203+
}

Framework/test/testTrendingTask.cxx

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
/// \author Piotr Konopka
1515
///
1616

17+
#include "Framework/include/QualityControl/Reductor.h"
1718
#include "QualityControl/TrendingTask.h"
1819
#include "QualityControl/DatabaseFactory.h"
1920
#include "QualityControl/MonitorObject.h"
@@ -51,6 +52,25 @@ struct CleanupAtDestruction {
5152
std::function<void()> mCallback = nullptr;
5253
};
5354

55+
// https://stackoverflow.com/questions/424104/can-i-access-private-members-from-outside-the-class-without-using-friends
56+
template <typename Accessor, typename Accessor::type Member>
57+
struct DeclareGlobalGet {
58+
friend typename Accessor::type get(Accessor) { return Member; }
59+
};
60+
61+
struct TrendingTaskReductorAccessor {
62+
using type = std::unordered_map<std::string, std::unique_ptr<Reductor>> TrendingTask::*;
63+
friend type get(TrendingTaskReductorAccessor);
64+
};
65+
66+
struct ReductorConfigAccessor {
67+
using type = CustomParameters Reductor::*;
68+
friend type get(ReductorConfigAccessor);
69+
};
70+
71+
template struct DeclareGlobalGet<TrendingTaskReductorAccessor, &TrendingTask::mReductors>;
72+
template struct DeclareGlobalGet<ReductorConfigAccessor, &Reductor::mCustomParameters>;
73+
5474
TEST_CASE("test_trending_task")
5575
{
5676
const std::string pid = std::to_string(getpid());
@@ -88,6 +108,13 @@ TEST_CASE("test_trending_task")
88108
taskName + R"json(",
89109
"name": "testHistoTrending",
90110
"reductorName": "o2::quality_control_modules::common::TH1Reductor",
111+
"reductorParameters": {
112+
"default": {
113+
"default": {
114+
"key":"value"
115+
}
116+
}
117+
},
91118
"moduleName": "QcCommon"
92119
},
93120
{
@@ -146,6 +173,20 @@ TEST_CASE("test_trending_task")
146173
task.setObjectsManager(objectManager);
147174
REQUIRE_NOTHROW(task.configure(config));
148175

176+
{
177+
auto& reductors = task.*get(TrendingTaskReductorAccessor());
178+
size_t foundCount{};
179+
for (const auto& reductor : reductors) {
180+
auto& config = (*reductor.second.get()).*get(ReductorConfigAccessor());
181+
if (auto found = config.find("key"); found != config.end()) {
182+
if (found->second == "value") {
183+
foundCount++;
184+
}
185+
}
186+
}
187+
REQUIRE(foundCount == 1);
188+
}
189+
149190
// test initialize()
150191
REQUIRE_NOTHROW(task.initialize({ TriggerType::UserOrControl, true, { 0, "NONE", "", "", "qc" }, 1 }, services));
151192
REQUIRE(objectManager->getNumberPublishedObjects() == 1);

0 commit comments

Comments
 (0)