Skip to content

Commit f2719b5

Browse files
authored
DPL Analysis: add handlers for nested arrays in struct configurables (#5004)
1 parent 0931587 commit f2719b5

File tree

4 files changed

+76
-21
lines changed

4 files changed

+76
-21
lines changed

Analysis/Tutorials/include/Analysis/configurableCut.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ class configurableCut
3535
bool getOption() const;
3636

3737
void setBins(std::vector<float> bins_);
38-
auto getBins() const;
38+
std::vector<float> getBins() const;
3939

4040
private:
4141
float cut;

Analysis/Tutorials/src/configurableCut.cxx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ void configurableCut::setBins(std::vector<float> bins_)
5656
{
5757
bins = bins_;
5858
};
59-
auto configurableCut::getBins() const
59+
std::vector<float> configurableCut::getBins() const
6060
{
6161
return bins;
6262
};

Analysis/Tutorials/src/configurableObjects.cxx

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -21,30 +21,37 @@ using namespace o2::framework::expressions;
2121
/// This task demonstrates how to use configurable to wrap classes
2222
/// use it with supplied configuration: "configurableObject.json"
2323

24+
template <typename T>
25+
auto printArray(std::vector<T> const& vec)
26+
{
27+
std::stringstream ss;
28+
ss << "[";
29+
auto count = 0u;
30+
for (auto& entry : vec) {
31+
ss << entry;
32+
if (count < vec.size() - 1) {
33+
ss << ",";
34+
}
35+
++count;
36+
}
37+
ss << "]";
38+
return ss.str();
39+
}
40+
2441
struct ConfigurableObjectDemo {
2542
Configurable<configurableCut> cut{"cut", {0.5, 1, true}, "generic cut"};
2643
MutableConfigurable<configurableCut> mutable_cut{"mutable_cut", {1., 2, false}, "generic cut"};
2744

2845
// note that size is fixed by this declaration - externally supplied vector needs to be the same size!
29-
Configurable<std::vector<int>> array{"array", {1, 2, 3, 4, 5}, "generic array"};
46+
Configurable<std::vector<int>> array{"array", {0, 0, 0, 0, 0, 0, 0}, "generic array"};
3047

3148
void init(InitContext const&){};
3249
void process(aod::Collision const&, aod::Tracks const& tracks)
3350
{
3451
LOGF(INFO, "Cut1: %.3f; Cut2: %.3f", cut, mutable_cut);
52+
LOGF(INFO, "Cut1 bins: %s; Cut2 bins: %s", printArray(cut->getBins()), printArray(mutable_cut->getBins()));
3553
auto vec = (std::vector<int>)array;
36-
std::stringstream ss;
37-
ss << "[";
38-
auto count = 0u;
39-
for (auto& entry : vec) {
40-
ss << entry;
41-
if (count < vec.size() - 1) {
42-
ss << ",";
43-
}
44-
++count;
45-
}
46-
ss << "]";
47-
LOGF(INFO, "Array: %s", ss.str().c_str());
54+
LOGF(INFO, "Array: %s", printArray(vec).c_str());
4855
for (auto& track : tracks) {
4956
if (track.globalIndex() % 500 == 0) {
5057
std::string decision1;

Framework/Core/src/RootConfigParamHelpers.cxx

Lines changed: 54 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
#include "Framework/RootConfigParamHelpers.h"
1212
#include "Framework/ConfigParamSpec.h"
13+
#include "Framework/StringHelpers.h"
1314
#include <TClass.h>
1415
#include <TDataMember.h>
1516
#include <TDataType.h>
@@ -35,14 +36,14 @@ bool isString(TDataMember const& dm)
3536
// a generic looper of data members of a TClass; calling a callback
3637
// reused in various functions below
3738
void loopOverMembers(TClass* cl, void* obj,
38-
std::function<void(const TDataMember*, int, int)>&& callback)
39+
std::function<void(TDataMember*, int, int)>&& callback)
3940
{
4041
auto memberlist = cl->GetListOfDataMembers();
4142
for (int i = 0; i < memberlist->GetEntries(); ++i) {
4243
auto dm = (TDataMember*)memberlist->At(i);
4344

4445
auto isValidComplex = [dm]() {
45-
return isString(*dm) || dm->IsEnum();
46+
return isString(*dm) || dm->IsEnum() || dm->IsSTLContainer();
4647
};
4748

4849
// filter out static members for now
@@ -70,6 +71,20 @@ void loopOverMembers(TClass* cl, void* obj,
7071
}
7172
}
7273

74+
namespace
75+
{
76+
template <typename T>
77+
std::vector<T> extractVector(boost::property_tree::ptree const& tree)
78+
{
79+
std::vector<T> result(tree.size());
80+
auto count = 0u;
81+
for (auto& entry : tree) {
82+
result[count++] = entry.second.get_value<T>();
83+
}
84+
return result;
85+
}
86+
} // namespace
87+
7388
// construct name (in dependence on vector or scalar data and index)
7489
std::string getName(const TDataMember* dm, int index, int size)
7590
{
@@ -83,7 +98,7 @@ std::string getName(const TDataMember* dm, int index, int size)
8398

8499
void ptreeToMember(boost::property_tree::ptree const& value,
85100
char const* tname,
86-
TDataMember const* dm,
101+
TDataMember* dm,
87102
void* ptr)
88103
{
89104
auto dt = dm->GetDataType();
@@ -150,6 +165,23 @@ void ptreeToMember(boost::property_tree::ptree const& value,
150165
}
151166
}
152167
}
168+
if (dm->IsSTLContainer()) {
169+
auto type = dm->GetTypeName();
170+
switch (compile_time_hash(type)) {
171+
case compile_time_hash("vector<int>"):
172+
*static_cast<std::vector<int>*>(ptr) = extractVector<int>(value);
173+
return;
174+
case compile_time_hash("vector<float>"):
175+
*static_cast<std::vector<float>*>(ptr) = extractVector<float>(value);
176+
return;
177+
case compile_time_hash("vector<double>"):
178+
*static_cast<std::vector<double>*>(ptr) = extractVector<double>(value);
179+
return;
180+
case compile_time_hash("vector<bool>"):
181+
default:
182+
throw std::runtime_error("Not and int/float/double/bool vector");
183+
}
184+
}
153185
// if we get here none of the above worked
154186
if (strcmp(tname, "string") == 0 || strcmp(tname, "std::string")) {
155187
*(std::string*)ptr = value.get_value<std::string>();
@@ -158,7 +190,7 @@ void ptreeToMember(boost::property_tree::ptree const& value,
158190
}
159191

160192
// Convert a DataMember to a ConfigParamSpec
161-
ConfigParamSpec memberToConfigParamSpec(const char* tname, TDataMember const* dm, void* ptr)
193+
ConfigParamSpec memberToConfigParamSpec(const char* tname, TDataMember* dm, void* ptr)
162194
{
163195
auto dt = dm->GetDataType();
164196
if (dt != nullptr) {
@@ -210,6 +242,22 @@ ConfigParamSpec memberToConfigParamSpec(const char* tname, TDataMember const* dm
210242
}
211243
}
212244
}
245+
if (dm->IsSTLContainer()) {
246+
auto type = dm->GetTypeName();
247+
switch (compile_time_hash(type)) {
248+
case compile_time_hash("vector<int>"):
249+
return ConfigParamSpec{tname, VariantType::ArrayInt, *static_cast<std::vector<int>*>(ptr), {"No help"}};
250+
case compile_time_hash("vector<float>"):
251+
return ConfigParamSpec{tname, VariantType::ArrayFloat, *static_cast<std::vector<float>*>(ptr), {"No help"}};
252+
case compile_time_hash("vector<double>"):
253+
return ConfigParamSpec{tname, VariantType::ArrayDouble, *static_cast<std::vector<double>*>(ptr), {"No help"}};
254+
case compile_time_hash("vector<bool>"):
255+
throw std::runtime_error("bool vector not supported yet");
256+
// return ConfigParamSpec{tname, VariantType::ArrayBool, *static_cast<std::vector<bool>*>(ptr), {"No help"}};
257+
default:
258+
throw std::runtime_error("Not and int/float/double/bool vector");
259+
}
260+
}
213261
// if we get here none of the above worked
214262
if (strcmp(tname, "string") == 0 || strcmp(tname, "std::string")) {
215263
return ConfigParamSpec{tname, VariantType::String, *(std::string*)ptr, {"No help"}};
@@ -226,7 +274,7 @@ std::vector<ConfigParamSpec>
226274
{
227275
std::vector<ConfigParamSpec> specs;
228276

229-
auto toDataMember = [&mainKey, &specs, obj](const TDataMember* dm, int index, int size) {
277+
auto toDataMember = [&mainKey, &specs, obj](TDataMember* dm, int index, int size) {
230278
auto dt = dm->GetDataType();
231279
auto TS = dt ? dt->Size() : 0;
232280
char* ptr = ((char*)obj) + dm->GetOffset() + index * TS;
@@ -243,7 +291,7 @@ std::vector<ConfigParamSpec>
243291
/// using the values in the ptree to override, where appropriate.
244292
void RootConfigParamHelpers::fillFromPtree(TClass* cl, void* obj, boost::property_tree::ptree const& pt)
245293
{
246-
auto toDataMember = [obj, &pt](const TDataMember* dm, int index, int size) {
294+
auto toDataMember = [obj, &pt](TDataMember* dm, int index, int size) {
247295
auto dt = dm->GetDataType();
248296
auto TS = dt ? dt->Size() : 0;
249297
char* ptr = ((char*)obj) + dm->GetOffset() + index * TS;

0 commit comments

Comments
 (0)