Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 20 additions & 1 deletion 21 Analysis/Tutorials/src/histogramRegistry.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,27 @@ struct ATask {
}
};

struct BTask {
/// Construct a registry object with direct declaration
HistogramRegistry registry{
"registry",
true,
{
{"eta", "#eta", {HistogramType::kTH1F, {{102, -2.01, 2.01}}}}, //
{"ptToPt", "#ptToPt", {HistogramType::kTH2F, {{100, -0.01, 10.01}, {100, -0.01, 10.01}}}} //
} //
};

void process(aod::Tracks const& tracks)
{
registry.fill<aod::track::Eta>("eta", tracks, aod::track::eta > 0.0f);
registry.fill<aod::track::Pt, aod::track::Pt>("ptToPt", tracks, aod::track::pt < 5.0f);
}
};

WorkflowSpec defineDataProcessing(ConfigContext const&)
{
return WorkflowSpec{
adaptAnalysisTask<ATask>("eta-and-phi-histograms")};
adaptAnalysisTask<ATask>("eta-and-phi-histograms"),
adaptAnalysisTask<BTask>("filtered-histograms")};
}
34 changes: 20 additions & 14 deletions 34 Framework/Core/include/Framework/AnalysisHelpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -460,6 +460,25 @@ struct Service {
}
};

template <typename T>
o2::soa::Filtered<T>* getTableFromFilter(const T& table, const expressions::Filter& filter)
{
auto schema = table.asArrowTable()->schema();
expressions::Operations ops = createOperations(filter);
gandiva::NodePtr tree = nullptr;
if (isSchemaCompatible(schema, ops)) {
tree = createExpressionTree(ops, schema);
} else {
throw std::runtime_error("Partition filter does not match declared table type");
}

if constexpr (soa::is_soa_filtered_t<std::decay_t<T>>::value) {
return new o2::soa::Filtered<T>{{table}, tree};
} else {
return new o2::soa::Filtered<T>{{table.asArrowTable()}, tree};
}
}

template <typename T>
struct Partition {
Partition(expressions::Node&& filter_) : filter{std::move(filter_)}
Expand All @@ -468,19 +487,7 @@ struct Partition {

void setTable(const T& table)
{
auto schema = table.asArrowTable()->schema();
expressions::Operations ops = createOperations(filter);
if (isSchemaCompatible(schema, ops)) {
mTree = createExpressionTree(ops, schema);
} else {
throw std::runtime_error("Partition filter does not match declared table type");
}

if constexpr (soa::is_soa_filtered_t<std::decay_t<T>>::value) {
mFiltered.reset(new o2::soa::Filtered<T>{{table}, mTree});
} else {
mFiltered.reset(new o2::soa::Filtered<T>{{table.asArrowTable()}, mTree});
}
mFiltered.reset(getTableFromFilter(table, filter));
}

template <typename... Ts>
Expand All @@ -505,7 +512,6 @@ struct Partition {
}

expressions::Filter filter;
gandiva::NodePtr mTree = nullptr;
std::unique_ptr<o2::soa::Filtered<T>> mFiltered = nullptr;

using filtered_iterator = typename o2::soa::Filtered<T>::iterator;
Expand Down
52 changes: 51 additions & 1 deletion 52 Framework/Core/include/Framework/HistogramRegistry.h
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,34 @@ std::unique_ptr<TH3> createTH3FromSpec(HistogramSpec const& spec)
return std::make_unique<T>(spec.name.data(), spec.readableName.data(), spec.config.axes[0].nBins, spec.config.axes[0].bins.data(), spec.config.axes[1].nBins, spec.config.axes[1].bins.data(), spec.config.axes[2].nBins, spec.config.axes[2].bins.data());
}

/// Helper functions to fill histograms with expressions
template <typename C1, typename C2, typename C3, typename T>
void fill(TH1* hist, const T& table, const o2::framework::expressions::Filter& filter)
{
auto filtered = o2::soa::Filtered<T>{{table.asArrowTable()}, o2::framework::expressions::createSelection(table.asArrowTable(), filter)};
for (auto& t : filtered) {
hist->Fill(*(static_cast<C1>(t).getIterator()), *(static_cast<C2>(t).getIterator()), *(static_cast<C3>(t).getIterator()));
}
}

template <typename C1, typename C2, typename T>
void fill(TH1* hist, const T& table, const o2::framework::expressions::Filter& filter)
{
auto filtered = o2::soa::Filtered<T>{{table.asArrowTable()}, o2::framework::expressions::createSelection(table.asArrowTable(), filter)};
for (auto& t : filtered) {
hist->Fill(*(static_cast<C1>(t).getIterator()), *(static_cast<C2>(t).getIterator()));
}
}

template <typename C, typename T>
void fill(TH1* hist, const T& table, const o2::framework::expressions::Filter& filter)
{
auto filtered = o2::soa::Filtered<T>{{table.asArrowTable()}, o2::framework::expressions::createSelection(table.asArrowTable(), filter)};
for (auto& t : filtered) {
hist->Fill(*(static_cast<C>(t).getIterator()));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It may be more efficient to use FillN method of ROOT histogram, that allows to fill it from an array

Copy link
Collaborator Author

@saganatt saganatt Sep 24, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, do I see well there is no FillN() for TH3?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure how it is implemented for dimensions > 1, I'll have to check. For 1-dimensional you can pass nullptr for the weights.

}
}

using HistogramCreationCallback = std::function<std::unique_ptr<TH1>(HistogramSpec const& spec)>;

// Wrapper to avoid multiple function definitinions error
Expand Down Expand Up @@ -278,7 +306,7 @@ class HistogramRegistry
return get(name);
}

// @return the associated OutputSpec
/// @return the associated OutputSpec
OutputSpec const spec()
{
ConcreteDataMatcher matcher{"HIST", "\0", 0};
Expand Down Expand Up @@ -308,6 +336,28 @@ class HistogramRegistry
return folder;
}

/// fill the histogram with an expression
template <typename C1, typename C2, typename C3, typename T>
void fill(char const* const name, const T& table, const o2::framework::expressions::Filter& filter)
{
TH1* hist = get(name).get();
framework::fill<C1, C2, C3>(hist, table, filter);
}

template <typename C1, typename C2, typename T>
void fill(char const* const name, const T& table, const o2::framework::expressions::Filter& filter)
{
TH1* hist = get(name).get();
framework::fill<C1, C2>(hist, table, filter);
}

template <typename C, typename T>
void fill(char const* const name, const T& table, const o2::framework::expressions::Filter& filter)
{
TH1* hist = get(name).get();
framework::fill<C>(hist, table, filter);
}

/// lookup distance counter for benchmarking
mutable uint32_t lookup = 0;

Expand Down
55 changes: 49 additions & 6 deletions 55 Framework/Core/test/test_HistogramRegistry.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,12 @@
using namespace o2;
using namespace o2::framework;

namespace test
{
DECLARE_SOA_COLUMN_FULL(X, x, float, "x");
DECLARE_SOA_COLUMN_FULL(Y, y, float, "y");
} // namespace test

HistogramRegistry foo()
{
return {"r", true, {{"histo", "histo", {HistogramType::kTH1F, {{100, 0, 1}}}}}};
Expand All @@ -25,12 +31,14 @@ HistogramRegistry foo()
BOOST_AUTO_TEST_CASE(HistogramRegistryLookup)
{
/// Construct a registry object with direct declaration
HistogramRegistry registry{"registry", true, {
{"eta", "#Eta", {HistogramType::kTH1F, {{100, -2.0, 2.0}}}}, //
{"phi", "#Phi", {HistogramType::kTH1D, {{102, 0, 2 * M_PI}}}}, //
{"pt", "p_{T}", {HistogramType::kTH1D, {{1002, -0.01, 50.1}}}}, //
{"ptToPt", "#ptToPt", {HistogramType::kTH2F, {{100, -0.01, 10.01}, {100, -0.01, 10.01}}}} //
}};
HistogramRegistry registry{
"registry", true, {
{"eta", "#Eta", {HistogramType::kTH1F, {{100, -2.0, 2.0}}}}, //
{"phi", "#Phi", {HistogramType::kTH1D, {{102, 0, 2 * M_PI}}}}, //
{"pt", "p_{T}", {HistogramType::kTH1D, {{1002, -0.01, 50.1}}}}, //
{"ptToPt", "#ptToPt", {HistogramType::kTH2F, {{100, -0.01, 10.01}, {100, -0.01, 10.01}}}} //
} //
};

/// Get histograms by name
BOOST_REQUIRE_EQUAL(registry.get("eta")->GetNbinsX(), 100);
Expand All @@ -48,3 +56,38 @@ BOOST_AUTO_TEST_CASE(HistogramRegistryLookup)
auto histo2 = r.get("histo").get();
BOOST_REQUIRE_EQUAL(histo2->GetNbinsX(), 100);
}

BOOST_AUTO_TEST_CASE(HistogramRegistryExpressionFill)
{
TableBuilder builderA;
auto rowWriterA = builderA.persist<float, float>({"x", "y"});
rowWriterA(0, 0.0f, -2.0f);
rowWriterA(0, 1.0f, -4.0f);
rowWriterA(0, 2.0f, -1.0f);
rowWriterA(0, 3.0f, -5.0f);
rowWriterA(0, 4.0f, 0.0f);
rowWriterA(0, 5.0f, -9.0f);
rowWriterA(0, 6.0f, -7.0f);
rowWriterA(0, 7.0f, -4.0f);
auto tableA = builderA.finalize();
BOOST_REQUIRE_EQUAL(tableA->num_rows(), 8);
using TestA = o2::soa::Table<o2::soa::Index<>, test::X, test::Y>;
TestA tests{tableA};
BOOST_REQUIRE_EQUAL(8, tests.size());

/// Construct a registry object with direct declaration
HistogramRegistry registry{
"registry", true, {
{"x", "test x", {HistogramType::kTH1F, {{100, 0.0f, 10.0f}}}}, //
{"xy", "test xy", {HistogramType::kTH2F, {{100, -10.0f, 10.01f}, {100, -10.0f, 10.01f}}}} //
} //
};

/// Fill histogram with expression and table
registry.fill<test::X>("x", tests, test::x > 3.0f);
BOOST_CHECK_EQUAL(registry.get("x")->GetEntries(), 4);

/// Fill histogram with expression and table
registry.fill<test::X, test::Y>("xy", tests, test::x > 3.0f && test::y > -5.0f);
BOOST_CHECK_EQUAL(registry.get("xy")->GetEntries(), 2);
}
Morty Proxy This is a proxified and sanitized view of the page, visit original site.