Skip to content

Commit ed327f8

Browse files
author
Michal Tichák
committed
helpers implemented
1 parent 2424063 commit ed327f8

File tree

7 files changed

+218
-64
lines changed

7 files changed

+218
-64
lines changed

Framework/include/QualityControl/Data.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020
#include <any>
2121
#include <concepts>
2222
#include <functional>
23-
#include <map>
2423
#include <memory>
2524
#include <optional>
2625
#include <string>

Framework/include/QualityControl/DataAdapters.h

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -28,13 +28,25 @@ Data createData(const std::map<std::string, std::shared_ptr<MonitorObject>>& moM
2828
Data createData(const QualityObjectsMapType& moMap);
2929

3030
template <typename Result, typename DataContainer>
31-
auto iterateMOsFilterByNameAndTransform(const DataGeneric<DataContainer>& data, std::string_view moName)
32-
{
33-
return data.template iterateByTypeFilterAndTransform<MonitorObject, Result>(
34-
[name = std::string{ moName }](const std::pair<std::string_view, const MonitorObject*>& pair) -> bool { return std::string_view{ pair.second->GetName() } == name; },
35-
[](const MonitorObject* ptr) -> const Result* { return dynamic_cast<const Result*>(ptr->getObject()); });
36-
}
31+
auto iterateMonitorObjects(const DataGeneric<DataContainer>& data, std::string_view moName);
32+
inline auto iterateMonitorObjects(const Data& data);
33+
inline auto iterateMonitorObjects(const Data& data, std::string_view taskName);
34+
35+
template <typename StoredType = MonitorObject>
36+
std::optional<std::reference_wrapper<const StoredType>> getMonitorObject(const Data& data, std::string_view objectName, std::string_view taskName);
37+
38+
// returns first occurence of MO with given name (possible name clash)
39+
template <typename StoredType = MonitorObject>
40+
std::optional<std::reference_wrapper<const StoredType>> getMonitorObject(const Data& data, std::string_view objectName);
41+
42+
inline auto iterateQualityObjects(const Data& data);
43+
44+
// returns first occurence of QO with given name (possible name clash)
45+
std::optional<std::reference_wrapper<const QualityObject>> getQualityObject(const Data& data, std::string_view objectName);
3746

3847
} // namespace o2::quality_control::core
3948

49+
// Templates definitions
50+
#include "QualityControl/DataAdapters.inl"
51+
4052
#endif
Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
// Copyright 2025 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+
///
13+
/// \file DataAdapters.inl
14+
/// \author Michal Tichak
15+
///
16+
17+
#ifndef QC_CORE_DATA_ADAPTERS_IMPL_H
18+
#define QC_CORE_DATA_ADAPTERS_IMPL_H
19+
20+
#include <optional>
21+
#include <string_view>
22+
#include "QualityControl/Data.h"
23+
#include "QualityControl/MonitorObject.h"
24+
#include "QualityControl/QualityObject.h"
25+
26+
#ifdef QC_CORE_DATA_ADAPTERS_H
27+
#include "QualityControl/DataAdapters.h"
28+
#endif
29+
30+
namespace o2::quality_control::core
31+
{
32+
33+
namespace helpers
34+
{
35+
36+
}
37+
38+
template <typename Result, typename DataContainer>
39+
auto iterateMonitorObjects(const DataGeneric<DataContainer>& data, std::string_view moName)
40+
{
41+
return data.template iterateByTypeFilterAndTransform<MonitorObject, Result>(
42+
[name = std::string{ moName }](const std::pair<std::string_view, const MonitorObject*>& pair) -> bool { return std::string_view{ pair.second->GetName() } == name; },
43+
[](const MonitorObject* ptr) -> const Result* { return dynamic_cast<const Result*>(ptr->getObject()); });
44+
}
45+
46+
inline auto iterateMonitorObjects(const o2::quality_control::core::Data& data)
47+
{
48+
return data.iterateByType<o2::quality_control::core::MonitorObject>();
49+
}
50+
51+
inline auto iterateMonitorObjects(const Data& data, std::string_view taskName)
52+
{
53+
const auto filterMOByTaskName = [taskName](const auto& pair) {
54+
return pair.second->getTaskName() == taskName;
55+
};
56+
57+
return data.iterateByTypeAndFilter<MonitorObject>(filterMOByTaskName);
58+
}
59+
60+
namespace helpers
61+
{
62+
63+
template <typename StoredType, typename Filter>
64+
std::optional<std::reference_wrapper<const StoredType>> getMonitorObjectCommon(const Data& data, Filter&& filter)
65+
{
66+
if constexpr (std::same_as<StoredType, MonitorObject>) {
67+
for (const auto& mo : data.iterateByTypeAndFilter<o2::quality_control::core::MonitorObject>(filter)) {
68+
return { mo };
69+
}
70+
} else {
71+
const auto getInternalObject = [](const MonitorObject* ptr) -> const auto* {
72+
return dynamic_cast<const StoredType*>(ptr->getObject());
73+
};
74+
for (const auto& v : data.template iterateByTypeFilterAndTransform<MonitorObject, StoredType>(filter, getInternalObject)) {
75+
return { v };
76+
}
77+
}
78+
return std::nullopt;
79+
}
80+
81+
}; // namespace helpers
82+
83+
template <typename StoredType>
84+
std::optional<std::reference_wrapper<const StoredType>> getMonitorObject(const Data& data, std::string_view objectName, std::string_view taskName)
85+
{
86+
87+
const auto filterMOByNameAndTaskName = [objectName, taskName](const auto& pair) {
88+
return std::tuple{ std::string_view{ pair.second->GetName() }, pair.second->getTaskName() } == std::tuple{ objectName, taskName };
89+
};
90+
91+
return helpers::getMonitorObjectCommon<StoredType>(data, filterMOByNameAndTaskName);
92+
}
93+
94+
template <typename StoredType>
95+
std::optional<std::reference_wrapper<const StoredType>> getMonitorObject(const Data& data, std::string_view objectName)
96+
{
97+
const auto filterMOByName = [objectName](const auto& pair) {
98+
return std::string_view(pair.second->GetName()) == objectName;
99+
};
100+
101+
return helpers::getMonitorObjectCommon<StoredType>(data, filterMOByName);
102+
}
103+
104+
inline auto iterateQualityObjects(const Data& data)
105+
{
106+
return data.iterateByType<o2::quality_control::core::QualityObject>();
107+
}
108+
109+
} // namespace o2::quality_control::core
110+
111+
#endif

Framework/src/DataAdapters.cxx

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,4 +37,15 @@ Data createData(const QualityObjectsMapType& qoMap)
3737
return data;
3838
}
3939

40+
std::optional<std::reference_wrapper<const QualityObject>> getQualityObject(const Data& data, std::string_view objectName)
41+
{
42+
const auto filterQOByName = [objectName](const auto& pair) {
43+
return std::string_view(pair.second->GetName()) == objectName;
44+
};
45+
for (const auto& qo : data.iterateByTypeAndFilter<QualityObject>(filterQOByName)) {
46+
return { qo };
47+
}
48+
return std::nullopt;
49+
}
50+
4051
} // namespace o2::quality_control::core

Framework/test/testData.cxx

Lines changed: 75 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include <TH1.h>
1818
#include <boost/container/flat_map.hpp>
1919
#include <catch_amalgamated.hpp>
20+
#include "Framework/include/QualityControl/DataAdapters.inl"
2021
#include "Framework/include/QualityControl/MonitorObject.h"
2122
#include "QualityControl/Data.h"
2223
#include "QualityControl/DataAdapters.h"
@@ -85,13 +86,6 @@ TEST_CASE("Data - iterateByTypeAndFilter", "[Data]")
8586
REQUIRE(count == 1);
8687
}
8788

88-
struct Base {
89-
int v;
90-
};
91-
92-
struct Derived : public Base {
93-
};
94-
9589
TEST_CASE("Data - iterateByTypeFilterAndTransform", "[Data]")
9690
{
9791

@@ -119,53 +113,6 @@ TEST_CASE("Data - iterateByTypeFilterAndTransform", "[Data]")
119113
REQUIRE(count == 1);
120114
}
121115

122-
TEST_CASE("Data - Monitor adaptors MOs", "[Data]")
123-
{
124-
auto* h1 = new TH1F("th11", "th11", 100, 0, 99);
125-
std::shared_ptr<MonitorObject> mo1 = std::make_shared<MonitorObject>(h1, "taskname", "class1", "TST");
126-
127-
auto* h2 = new TH1F("th12", "th12", 100, 0, 99);
128-
std::shared_ptr<MonitorObject> mo2 = std::make_shared<MonitorObject>(h2, "taskname", "class2", "TST");
129-
130-
std::map<std::string, std::shared_ptr<MonitorObject>> map;
131-
map.emplace(mo1->getFullName(), mo1);
132-
map.emplace(mo2->getFullName(), mo2);
133-
134-
auto data = createData(map);
135-
136-
REQUIRE(data.size() == 2);
137-
138-
auto filteredHistos = iterateMOsFilterByNameAndTransform<TH1F>(data, "th11");
139-
REQUIRE(!filteredHistos.empty());
140-
size_t count{};
141-
for (const auto& histo1d : filteredHistos) {
142-
REQUIRE(std::string_view{ histo1d.GetName() } == "th11");
143-
++count;
144-
}
145-
REQUIRE(count == 1);
146-
}
147-
148-
TEST_CASE("Data - Monitor adaptors QOs", "[Data]")
149-
{
150-
QualityObjectsMapType qoMap;
151-
qoMap["1"] = std::make_shared<QualityObject>(Quality::Good, "1");
152-
qoMap["2"] = std::make_shared<QualityObject>(Quality::Good, "2");
153-
154-
auto data = createData(qoMap);
155-
156-
REQUIRE(data.size() == 2);
157-
158-
auto filteredObjects = data.iterateByType<QualityObject>();
159-
REQUIRE(!filteredObjects.empty());
160-
size_t count{};
161-
for (const auto& qo : filteredObjects) {
162-
const auto& name = qo.getName();
163-
REQUIRE((name == "1" || name == "2"));
164-
++count;
165-
}
166-
REQUIRE(count == 2);
167-
}
168-
169116
TEST_CASE("Data - raw pointers", "[Data]")
170117
{
171118
Data data;
@@ -279,6 +226,79 @@ TEMPLATE_TEST_CASE("Data - inserting and iterating MOs", "[.Data-benchmark]", st
279226
data.insert(mo->getFullName(), mo);
280227
}
281228

282-
REQUIRE(iterateMOsFilterByNameAndTransform<TH1F>(data, "notimportantname").empty());
229+
REQUIRE(iterateMonitorObjects<TH1F>(data, "notimportantname").empty());
283230
};
284231
}
232+
233+
TEST_CASE("Data adapters - helper functions")
234+
{
235+
236+
Data data;
237+
{
238+
for (size_t i{}; i != 10; ++i) {
239+
const auto iStr = std::to_string(i);
240+
const auto thName = std::string("TH1F_") + iStr;
241+
const auto moName = "testMO_" + iStr;
242+
auto* h = new TH1F(thName.c_str(), thName.c_str(), 100, 0, 99);
243+
data.insert(moName, std::make_shared<MonitorObject>(h, "taskname_" + iStr, "class1", "TST"));
244+
}
245+
246+
auto* h = new TH1F("TH1F_duplicate", "TH1F_duplicate", 100, 0, 99);
247+
data.insert("testMO_duplicate", std::make_shared<MonitorObject>(h, "taskname_8", "class1", "TST"));
248+
249+
data.insert("testQO_1", std::make_shared<QualityObject>(Quality::Good, "QO_1"));
250+
data.insert("testQO_2", std::make_shared<QualityObject>(Quality::Good, "QO_2"));
251+
}
252+
253+
REQUIRE(data.size() == 13);
254+
255+
SECTION("getMonitorObject")
256+
{
257+
const auto moOpt = getMonitorObject(data, "TH1F_1");
258+
REQUIRE(moOpt.has_value());
259+
REQUIRE(std::string_view(moOpt.value().get().GetName()) == "TH1F_1");
260+
const auto th1Opt = getMonitorObject<TH1F>(data, "TH1F_8");
261+
REQUIRE(th1Opt.has_value());
262+
REQUIRE(std::string_view(th1Opt.value().get().GetName()) == "TH1F_8");
263+
264+
const auto moSpecificOpt = getMonitorObject(data, "TH1F_duplicate", "taskname_8");
265+
REQUIRE(moSpecificOpt.has_value());
266+
REQUIRE(moSpecificOpt.value().get().GetName() == std::string_view{ "TH1F_duplicate" });
267+
REQUIRE(moSpecificOpt.value().get().getTaskName() == std::string_view{ "taskname_8" });
268+
const auto th1SpecificOpt = getMonitorObject<TH1F>(data, "TH1F_duplicate", "taskname_8");
269+
REQUIRE(th1SpecificOpt.has_value());
270+
REQUIRE(th1SpecificOpt.value().get().GetName() == std::string_view{ "TH1F_duplicate" });
271+
REQUIRE(!getMonitorObject<nonexistent>(data, "TH1F_duplicate", "taskname_8").has_value());
272+
}
273+
274+
SECTION("iterateMonitorObjects")
275+
{
276+
size_t count{};
277+
for (auto& mo : iterateMonitorObjects(data)) {
278+
++count;
279+
}
280+
REQUIRE(count == 11);
281+
282+
count = 0;
283+
for (auto& mo : iterateMonitorObjects(data, "taskname_8")) {
284+
++count;
285+
}
286+
REQUIRE(count == 2);
287+
}
288+
289+
SECTION("getQualityObject")
290+
{
291+
const auto qoOpt = getQualityObject(data, "QO_1");
292+
REQUIRE(qoOpt.has_value());
293+
REQUIRE(std::string_view{ qoOpt.value().get().GetName() } == "QO_1");
294+
}
295+
296+
SECTION("iterateQualityObjects")
297+
{
298+
size_t count{};
299+
for (const auto& qo : iterateQualityObjects(data)) {
300+
++count;
301+
}
302+
REQUIRE(count == 2);
303+
}
304+
}

Modules/Skeleton/src/SkeletonAggregator.cxx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
#include "Skeleton/SkeletonAggregator.h"
1818
#include "QualityControl/QcInfoLogger.h"
19+
#include "QualityControl/DataAdapters.h"
1920

2021
using namespace std;
2122
using namespace o2::quality_control::core;
@@ -42,7 +43,7 @@ std::map<std::string, Quality> SkeletonAggregator::aggregate(const o2::quality_c
4243

4344
// we return the worse quality of all the objects we receive
4445
Quality current = Quality::Good;
45-
for (const auto& qo : data.iterateByType<QualityObject>()) {
46+
for (const auto& qo : iterateQualityObjects(data)) {
4647
ILOG(Info, Devel) << "Object: " << qo << ENDM;
4748
if (qo.getQuality().isWorseThan(current)) {
4849
current = qo.getQuality();

Modules/Skeleton/src/SkeletonCheck.cxx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ Quality SkeletonCheck::check(const quality_control::core::Data& data)
5858
// and you can get your custom parameters:
5959
ILOG(Debug, Devel) << "custom param physics.pp.myOwnKey1 : " << mCustomParameters.atOrDefaultValue("myOwnKey1", "default_value", "physics", "pp") << ENDM;
6060

61-
for (const auto& h : iterateMOsFilterByNameAndTransform<TH1>(data, "example")) {
61+
for (const auto& h : iterateMonitorObjects<TH1>(data, "example")) {
6262
// unless we find issues, we assume the quality is good
6363
result = Quality::Good;
6464

0 commit comments

Comments
 (0)