new and updated examples for user guide (#210)

* new accmulator examples for user guide
* new weighted profile example
* minor corrections to other examples
This commit is contained in:
Hans Dembinski 2019-09-10 23:19:27 +02:00 committed by GitHub
parent 35a93a8c81
commit 14f36ea932
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 219 additions and 89 deletions

View File

@ -228,7 +228,10 @@ Profiles can be generated with the factory function [funcref boost::histogram::m
Just like [funcref boost::histogram::weight weight()], [funcref boost::histogram::sample sample()] is a marker function. It must be the first or last argument.
Weights and samples may be combined, if the histogram accumulators can handle weights. When both [funcref boost::histogram::weight weight()] and [funcref boost::histogram::sample sample()] appear in [memberref boost::histogram::histogram::operator() histogram::operator()], they can be in any order with respect to other, but they must be the first and/or last arguments. To make a profile which can compute weighted means use the [funcref boost::histogram::make_weighted_profile make_weighted_profile] factory function.
Weights and samples may be combined, if the histogram accumulators can handle weights. When both [funcref boost::histogram::weight weight()] and [funcref boost::histogram::sample sample()] appear in [memberref boost::histogram::histogram::operator() histogram::operator()], they can be in any order with respect to other, but they must be the first or last arguments. To make a profile which can compute weighted means use the [funcref boost::histogram::make_weighted_profile make_weighted_profile] factory function.
[import ../examples/guide_fill_weighted_profile.cpp]
[guide_fill_weighted_profile]
[endsect]
@ -401,8 +404,17 @@ The library provides several accumulators:
Users can easily write their own accumulators and plug them into the histogram, if they adhere to the [link histogram.concepts.Accumulator [*Accumulator] concept].
[import ../examples/guide_custom_accumulators.cpp]
[guide_custom_accumulators]
The first example shows how to make and use a histogram that uses one of the the builtin accumulators.
[import ../examples/guide_custom_accumulators_1.cpp]
[guide_custom_accumulators_1]
The second example shows how to use a simple user-generated accumulator.
[import ../examples/guide_custom_accumulators_2.cpp]
[guide_custom_accumulators_2]
The third example shows how to use to make an accumulator that accepts multiple samples at once. Here, we make an accumulator that accepts two samples and computes the mean for each. This is more convenient and more efficient than filling two identical profiles, because the cell lookup has to be done only once.
[import ../examples/guide_custom_accumulators_3.cpp]
[guide_custom_accumulators_3]
[endsect]

View File

@ -28,13 +28,16 @@ alias cxx14 :
[ run guide_axis_with_transform.cpp ]
[ run guide_axis_with_uoflow_off.cpp ]
[ run guide_custom_2d_axis.cpp ]
[ run guide_custom_accumulators.cpp ]
[ run guide_custom_accumulators_1.cpp ]
[ run guide_custom_accumulators_2.cpp ]
[ run guide_custom_accumulators_3.cpp ]
[ run guide_custom_minimal_axis.cpp ]
[ run guide_custom_modified_axis.cpp ]
[ run guide_custom_storage.cpp ]
[ run guide_fill_histogram.cpp ]
[ run guide_fill_weighted_histogram.cpp ]
[ run guide_fill_profile.cpp ]
[ run guide_fill_weighted_histogram.cpp ]
[ run guide_fill_weighted_profile.cpp ]
[ run guide_histogram_operators.cpp ]
[ run guide_histogram_reduction.cpp ]
[ run guide_histogram_projection.cpp ]

View File

@ -1,69 +0,0 @@
// Copyright 2018 Hans Dembinski
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt
// or copy at http://www.boost.org/LICENSE_1_0.txt)
//[ guide_custom_accumulators
#include <array>
#include <boost/format.hpp>
#include <boost/histogram.hpp>
#include <boost/histogram/accumulators/mean.hpp>
#include <iostream>
int main() {
using namespace boost::histogram;
const auto axis = axis::regular<>(3, 0.0, 1.0);
// Create a 1D-profile, which computes the mean of samples in each bin. The
// factory function `make_profile` is provided by the library as a shorthand.
auto h1 = make_histogram_with(dense_storage<accumulators::mean<>>(), axis);
// Argument of `sample` is passed to accumulator.
h1(0.0, sample(2)); // sample 2 goes to first bin
h1(0.1, sample(2)); // sample 2 goes to first bin
h1(0.4, sample(3)); // sample 3 goes to second bin
h1(0.5, sample(4)); // sample 4 goes to second bin
std::ostringstream os1;
for (auto&& x : indexed(h1)) {
// Accumulators usually have methods to access their state. Use the arrow
// operator to access them. Here, `count()` gives the number of samples,
// `value()` the mean, and `variance()` the variance estimate of the mean.
os1 << boost::format("%i count %i mean %.1f variance %.1f\n") % x.index() %
x->count() % x->value() % x->variance();
}
std::cout << os1.str() << std::flush;
assert(os1.str() == "0 count 2 mean 2.0 variance 0.0\n"
"1 count 2 mean 3.5 variance 0.5\n"
"2 count 0 mean 0.0 variance 0.0\n");
// Let's make a custom accumulator, which tracks the maximum of the samples. It must
// have a call operator that accepts the argument of the `sample` function. The return
// value of the call operator is ignored.
struct max {
void operator()(double x) {
if (x > value) value = x;
}
double value = 0; // value is initialized to zero
};
// Create a histogram that uses the custom accumulator.
auto h2 = make_histogram_with(dense_storage<max>(), axis);
h2(0.0, sample(2)); // sample 2 goes to first bin
h2(0.1, sample(2.5)); // sample 2.5 goes to first bin
h2(0.4, sample(3)); // sample 3 goes to second bin
h2(0.5, sample(4)); // sample 4 goes to second bin
std::ostringstream os2;
for (auto&& x : indexed(h2)) {
os2 << boost::format("%i value %.1f\n") % x.index() % x->value;
}
std::cout << os2.str() << std::flush;
assert(os2.str() == "0 value 2.5\n"
"1 value 4.0\n"
"2 value 0.0\n");
}
//]

View File

@ -0,0 +1,43 @@
// Copyright 2018 Hans Dembinski
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt
// or copy at http://www.boost.org/LICENSE_1_0.txt)
//[ guide_custom_accumulators_1
#include <boost/format.hpp>
#include <boost/histogram.hpp>
#include <cassert>
#include <iostream>
#include <sstream>
int main() {
using namespace boost::histogram;
using mean = accumulators::mean<>;
// Create a 1D-profile, which computes the mean of samples in each bin.
auto h = make_histogram_with(dense_storage<mean>(), axis::integer<>(0, 2));
// The factory function `make_profile` is provided as a shorthand for this, so this is
// equivalent to the previous line: auto h = make_profile(axis::integer<>(0, 2));
// An argument marked as `sample` is passed to the accumulator.
h(0, sample(1)); // sample goes to first cell
h(0, sample(2)); // sample goes to first cell
h(1, sample(3)); // sample goes to second cell
h(1, sample(4)); // sample goes to second cell
std::ostringstream os;
for (auto&& x : indexed(h)) {
// Accumulators usually have methods to access their state. Use the arrow
// operator to access them. Here, `count()` gives the number of samples,
// `value()` the mean, and `variance()` the variance estimate of the mean.
os << boost::format("index %i count %i mean %.1f variance %.1f\n") % x.index() %
x->count() % x->value() % x->variance();
}
std::cout << os.str() << std::flush;
assert(os.str() == "index 0 count 2 mean 1.5 variance 0.5\n"
"index 1 count 2 mean 3.5 variance 0.5\n");
}
//]

View File

@ -0,0 +1,44 @@
// Copyright 2018 Hans Dembinski
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt
// or copy at http://www.boost.org/LICENSE_1_0.txt)
//[ guide_custom_accumulators_2
#include <boost/format.hpp>
#include <boost/histogram.hpp>
#include <cassert>
#include <iostream>
#include <sstream>
int main() {
using namespace boost::histogram;
// Make a custom accumulator, which tracks the maximum of the samples.
// It must have a call operator that accepts the argument of the `sample` function.
struct maximum {
// return value is ignored, so we use void
void operator()(double x) {
if (x > value) value = x;
}
double value = 0; // value is initialized to zero
};
// Create 1D histogram that uses the custom accumulator.
auto h = make_histogram_with(dense_storage<maximum>(), axis::integer<>(0, 2));
h(0, sample(1.0)); // sample goes to first cell
h(0, sample(2.0)); // sample goes to first cell
h(1, sample(3.0)); // sample goes to second cell
h(1, sample(4.0)); // sample goes to second cell
std::ostringstream os;
for (auto&& x : indexed(h)) {
os << boost::format("index %i maximum %.1f\n") % x.index() % x->value;
}
std::cout << os.str() << std::flush;
assert(os.str() == "index 0 maximum 2.0\n"
"index 1 maximum 4.0\n");
}
//]

View File

@ -0,0 +1,45 @@
// Copyright 2019 Hans Dembinski
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt
// or copy at http://www.boost.org/LICENSE_1_0.txt)
//[ guide_custom_accumulators_3
#include <boost/format.hpp>
#include <boost/histogram.hpp>
#include <iostream>
#include <sstream>
int main() {
using namespace boost::histogram;
// Make a accumulator which accepts two samples and computes the mean of each.
struct multi_mean {
accumulators::mean<> mean_x, mean_y;
void operator()(double x, double y) {
mean_x(x);
mean_y(y);
}
};
// Note: There are more efficient implementations of this accumulator.
// Create a 1D histogram that uses the custom accumulator.
auto h = make_histogram_with(dense_storage<multi_mean>(), axis::integer<>(0, 2));
h(0, sample(1, 2)); // samples go to first cell
h(0, sample(3, 4)); // samples go to first cell
h(1, sample(5, 6)); // samples go to second cell
h(1, sample(7, 8)); // samples go to second cell
std::ostringstream os;
for (auto&& x : indexed(h)) {
os << boost::format("index %i mean_x %.1f mean_y %.1f\n") % x.index() %
x->mean_x.value() % x->mean_y.value();
}
std::cout << os.str() << std::flush;
assert(os.str() == "index 0 mean_x 2.0 mean_y 3.0\n"
"index 1 mean_x 6.0 mean_y 7.0\n");
}
//]

View File

@ -11,25 +11,25 @@
#include <cassert>
#include <iostream>
#include <sstream>
#include <utility>
#include <tuple>
int main() {
using namespace boost::histogram;
// make a profile, it computes the mean of the samples in each histogram cell
auto h = make_profile(axis::regular<>(3, 0.0, 1.0));
auto h = make_profile(axis::integer<>(0, 3));
// mean is computed from the values marked with the sample() helper function
h(0.10, sample(2.5)); // 2.5 goes to bin 0
h(0.25, sample(3.5)); // 3.5 goes to bin 0
h(0.45, sample(1.2)); // 1.2 goes to bin 1
h(sample(3.4), 0.51); // 3.4 goes to bin 1, sample be at the front
h(0, sample(1)); // sample goes to cell 0
h(0, sample(2)); // sample goes to cell 0
h(1, sample(3)); // sample goes to cell 1
h(sample(4), 1); // sample goes to cell 1; sample can be first or last argument
// fills from tuples are also supported, 1.3 and 1.9 go to bin 2
auto xs1 = std::make_tuple(0.81, sample(1.3));
auto xs2 = std::make_tuple(0.86, sample(1.9));
h(xs1);
h(xs2);
// fills from tuples are also supported, 5 and 6 go to cell 2
auto a = std::make_tuple(2, sample(5));
auto b = std::make_tuple(sample(6), 2);
h(a);
h(b);
// builtin accumulators have methods to access their state
std::ostringstream os;
@ -40,14 +40,14 @@ int main() {
const auto n = x->count(); // how many samples are in this bin
const auto vl = x->value(); // mean value
const auto vr = x->variance(); // estimated variance of the mean value
os << boost::format("bin %i count %i value %.1f variance %.1f\n") % i % n % vl % vr;
os << boost::format("index %i count %i value %.1f variance %.1f\n") % i % n % vl % vr;
}
std::cout << os.str() << std::flush;
assert(os.str() == "bin 0 count 2 value 3.0 variance 0.5\n"
"bin 1 count 2 value 2.3 variance 2.4\n"
"bin 2 count 2 value 1.6 variance 0.2\n");
assert(os.str() == "index 0 count 2 value 1.5 variance 0.5\n"
"index 1 count 2 value 3.5 variance 0.5\n"
"index 2 count 2 value 5.5 variance 0.5\n");
}
//]

View File

@ -7,6 +7,7 @@
//[ guide_fill_weighted_histogram
#include <boost/histogram.hpp>
#include <cassert>
int main() {
using namespace boost::histogram;

View File

@ -0,0 +1,51 @@
// Copyright 2019 Hans Dembinski
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt
// or copy at http://www.boost.org/LICENSE_1_0.txt)
//[ guide_fill_weighted_profile
#include <boost/format.hpp>
#include <boost/histogram.hpp>
#include <cassert>
#include <iostream>
#include <sstream>
int main() {
using namespace boost::histogram;
using namespace boost::histogram::literals; // _c suffix creates compile-time numbers
// make 2D weighted profile
auto h = make_weighted_profile(axis::integer<>(0, 2), axis::integer<>(0, 2));
// The mean is computed from the values marked with the sample() helper function.
// Weights can be passed as well. The `sample` and `weight` arguments can appear in any
// order, but they must be the first or last arguments.
h(0, 0, sample(1)); // sample goes to cell (0, 0); weight is 1
h(0, 0, sample(2), weight(3)); // sample goes to cell (0, 0); weight is 3
h(1, 0, sample(3)); // sample goes to cell (1, 0); weight is 1
h(1, 0, sample(4)); // sample goes to cell (1, 0); weight is 1
h(0, 1, sample(5)); // sample goes to cell (1, 0); weight is 1
h(0, 1, sample(6)); // sample goes to cell (1, 0); weight is 1
h(1, 1, weight(4), sample(7)); // sample goes to cell (1, 1); weight is 4
h(weight(5), sample(8), 1, 1); // sample goes to cell (1, 1); weight is 5
std::ostringstream os;
for (auto&& x : indexed(h)) {
const auto i = x.index(0_c);
const auto j = x.index(1_c);
const auto m = x->value(); // weighted mean
const auto v = x->variance(); // estimated variance of weighted mean
os << boost::format("index %i,%i mean %.1f variance %.1f\n") % i % j % m % v;
}
std::cout << os.str() << std::flush;
assert(os.str() == "index 0,0 mean 1.8 variance 0.5\n"
"index 1,0 mean 3.5 variance 0.5\n"
"index 0,1 mean 5.5 variance 0.5\n"
"index 1,1 mean 7.6 variance 0.5\n");
}
//]