|
14 | 14 | #include "Acts/Utilities/Logger.hpp" |
15 | 15 | #include "Acts/Utilities/RangeXD.hpp" |
16 | 16 |
|
| 17 | +#include <cmath> |
| 18 | +#include <random> |
17 | 19 | #include <sstream> |
18 | 20 | #include <type_traits> |
19 | 21 | #include <unordered_map> |
@@ -58,39 +60,26 @@ static py::array_t<double> copyBins(const Hist& h, ValueFn fn) { |
58 | 60 |
|
59 | 61 | template <std::size_t Dim> |
60 | 62 | static void bindHistogram(py::module_& m) { |
61 | | - using H = Acts::Experimental::Histogram<Dim>; |
62 | | - py::class_<H>(m, ("Histogram" + std::to_string(Dim)).c_str()) |
63 | | - .def(py::init<std::string, std::string, std::array<AxisVariant, Dim>>(), |
64 | | - "name"_a, "title"_a, "axes"_a) |
| 63 | + using H = Histogram<Dim>; |
| 64 | + py::classh<H>(m, ("Histogram" + std::to_string(Dim)).c_str()) |
65 | 65 | .def_property_readonly("name", &H::name) |
66 | 66 | .def_property_readonly("title", &H::title) |
67 | 67 | .def_property_readonly("rank", [](const H&) { return Dim; }) |
68 | | - .def("histogram", &H::histogram, |
69 | | - py::return_value_policy::reference_internal) |
70 | | - .def( |
71 | | - "fill", [](H& h, std::array<double, Dim> vals) { h.fill(vals); }, |
72 | | - "vals"_a); |
| 68 | + .def_property_readonly("histogram", &H::histogram, |
| 69 | + py::return_value_policy::reference_internal); |
73 | 70 | } |
74 | 71 |
|
75 | 72 | template <std::size_t Dim> |
76 | 73 | static void bindEfficiency(py::module_& m) { |
77 | | - using E = Acts::Experimental::Efficiency<Dim>; |
78 | | - py::class_<E>(m, ("Efficiency" + std::to_string(Dim)).c_str()) |
79 | | - .def(py::init<std::string, std::string, std::array<AxisVariant, Dim>>(), |
80 | | - "name"_a, "title"_a, "axes"_a) |
| 74 | + using E = Efficiency<Dim>; |
| 75 | + py::classh<E>(m, ("Efficiency" + std::to_string(Dim)).c_str()) |
81 | 76 | .def_property_readonly("name", &E::name) |
82 | 77 | .def_property_readonly("title", &E::title) |
83 | 78 | .def_property_readonly("rank", [](const E&) { return Dim; }) |
84 | | - .def("accepted", &E::acceptedHistogram, |
85 | | - py::return_value_policy::reference_internal) |
86 | | - .def("total", &E::totalHistogram, |
87 | | - py::return_value_policy::reference_internal) |
88 | | - .def( |
89 | | - "fill", |
90 | | - [](E& e, std::array<double, Dim> vals, bool accepted) { |
91 | | - e.fill(vals, accepted); |
92 | | - }, |
93 | | - "vals"_a, "accepted"_a); |
| 79 | + .def_property_readonly("accepted", &E::acceptedHistogram, |
| 80 | + py::return_value_policy::reference_internal) |
| 81 | + .def_property_readonly("total", &E::totalHistogram, |
| 82 | + py::return_value_policy::reference_internal); |
94 | 83 | } |
95 | 84 |
|
96 | 85 | /// @brief This adds the classes from Core/Utilities to the python module |
@@ -296,17 +285,6 @@ void addUtilities(py::module_& m) { |
296 | 285 | { |
297 | 286 | // Single axis type covering regular, variable, and log axes |
298 | 287 | py::class_<AxisVariant>(m, "Axis") |
299 | | - .def( |
300 | | - py::init([](unsigned int n, double lo, double hi, |
301 | | - std::string label) { |
302 | | - return AxisVariant{BoostRegularAxis{n, lo, hi, std::move(label)}}; |
303 | | - }), |
304 | | - "nbins"_a, "lo"_a, "hi"_a, "label"_a = "") |
305 | | - .def(py::init([](std::vector<double> edges, std::string label) { |
306 | | - return AxisVariant{BoostVariableAxis{edges.begin(), edges.end(), |
307 | | - std::move(label)}}; |
308 | | - }), |
309 | | - "edges"_a, "label"_a = "") |
310 | 288 | .def_property_readonly("size", &AxisVariant::size) |
311 | 289 | .def_property_readonly( |
312 | 290 | "label", |
@@ -336,40 +314,78 @@ void addUtilities(py::module_& m) { |
336 | 314 | return h.axis(i); |
337 | 315 | }, |
338 | 316 | "i"_a) |
| 317 | + .def("counts", |
| 318 | + [](const BoostProfileHist& h) { |
| 319 | + return copyBins(h, [](auto& x) { |
| 320 | + return static_cast<double>((*x).count()); |
| 321 | + }); |
| 322 | + }) |
339 | 323 | .def("means", |
340 | 324 | [](const BoostProfileHist& h) { |
341 | 325 | return copyBins(h, [](auto& x) { return (*x).value(); }); |
342 | 326 | }) |
343 | | - .def("variances", [](const BoostProfileHist& h) { |
344 | | - return copyBins(h, [](auto& x) { return (*x).variance(); }); |
| 327 | + .def("sum_of_deltas_squared", [](const BoostProfileHist& h) { |
| 328 | + return copyBins(h, [](auto& x) { |
| 329 | + const auto n = (*x).count(); |
| 330 | + return n > 1.0 ? (*x).variance() * (n - 1.0) : 0.0; |
| 331 | + }); |
345 | 332 | }); |
346 | 333 |
|
347 | 334 | bindHistogram<1>(m); |
348 | 335 | bindHistogram<2>(m); |
349 | 336 | bindHistogram<3>(m); |
350 | 337 |
|
351 | 338 | { |
352 | | - using H = ProfileHistogram<1>; |
353 | | - py::class_<H>(m, "ProfileHistogram1") |
354 | | - .def(py::init<std::string, std::string, std::array<AxisVariant, 1>, |
355 | | - std::string>(), |
356 | | - "name"_a, "title"_a, "axes"_a, "sampleAxisTitle"_a) |
357 | | - .def_property_readonly("name", &H::name) |
358 | | - .def_property_readonly("title", &H::title) |
359 | | - .def_property_readonly("rank", [](const H&) { return 1u; }) |
360 | | - .def_property_readonly("sampleAxisTitle", &H::sampleAxisTitle) |
361 | | - .def("histogram", &H::histogram, |
362 | | - py::return_value_policy::reference_internal) |
363 | | - .def( |
364 | | - "fill", |
365 | | - [](H& h, std::array<double, 1> vals, double sample) { |
366 | | - h.fill(vals, sample); |
367 | | - }, |
368 | | - "vals"_a, "sample"_a); |
| 339 | + using P = ProfileHistogram<1>; |
| 340 | + py::classh<P>(m, "ProfileHistogram1") |
| 341 | + .def_property_readonly("name", &P::name) |
| 342 | + .def_property_readonly("title", &P::title) |
| 343 | + .def_property_readonly("rank", [](const P&) { return 1u; }) |
| 344 | + .def_property_readonly("sampleAxisTitle", &P::sampleAxisTitle) |
| 345 | + .def_property_readonly("histogram", &P::histogram, |
| 346 | + py::return_value_policy::reference_internal); |
369 | 347 | } |
370 | 348 |
|
371 | 349 | bindEfficiency<1>(m); |
372 | 350 | bindEfficiency<2>(m); |
| 351 | + |
| 352 | + // Demo factory functions for testing and examples — not public API |
| 353 | + m.def("_demo_histogram1", []() -> Histogram1 { |
| 354 | + BoostRegularAxis ax(10, 0.0, 10.0, "x [a.u.]"); |
| 355 | + Histogram1 h("demo", "Demo Histogram", {AxisVariant(ax)}); |
| 356 | + std::mt19937 rng(42); |
| 357 | + std::uniform_real_distribution<double> x(0.0, 10.0); |
| 358 | + for (int i = 0; i < 1000; ++i) { |
| 359 | + h.fill({x(rng)}); |
| 360 | + } |
| 361 | + return h; |
| 362 | + }); |
| 363 | + |
| 364 | + m.def("_demo_profile1", []() -> ProfileHistogram1 { |
| 365 | + BoostRegularAxis ax(10, 0.0, 10.0, "x [a.u.]"); |
| 366 | + ProfileHistogram1 h("demo", "Demo Profile", {AxisVariant(ax)}, "y [a.u.]"); |
| 367 | + std::mt19937 rng(42); |
| 368 | + std::uniform_real_distribution<double> x(0.0, 10.0); |
| 369 | + std::normal_distribution<double> noise(0.0, 0.1); |
| 370 | + for (int i = 0; i < 1000; ++i) { |
| 371 | + double xi = x(rng); |
| 372 | + h.fill({xi}, std::sin(xi) + noise(rng)); |
| 373 | + } |
| 374 | + return h; |
| 375 | + }); |
| 376 | + |
| 377 | + m.def("_demo_efficiency1", []() -> Efficiency1 { |
| 378 | + BoostRegularAxis ax(10, 0.0, 10.0, "x [a.u.]"); |
| 379 | + Efficiency1 h("demo", "Demo Efficiency", {AxisVariant(ax)}); |
| 380 | + std::mt19937 rng(42); |
| 381 | + std::uniform_real_distribution<double> x(0.0, 10.0); |
| 382 | + for (int i = 0; i < 1000; ++i) { |
| 383 | + double xi = x(rng); |
| 384 | + std::bernoulli_distribution accepted(1.0 - std::exp(-xi)); |
| 385 | + h.fill({xi}, accepted(rng)); |
| 386 | + } |
| 387 | + return h; |
| 388 | + }); |
373 | 389 | } |
374 | 390 | } |
375 | 391 |
|
|
0 commit comments