improved wording, make using namespace consistent, fixed missing section about 2d axes

This commit is contained in:
Hans Dembinski 2019-02-24 23:20:25 +01:00
parent ff97700470
commit 94c1563ae7
7 changed files with 46 additions and 38 deletions

View File

@ -2,7 +2,7 @@
Boost.Histogram is designed to make simple things simple, yet complex things possible. Correspondingly, this guides covers the basic usage first, and the advanced usage in later sections. For an alternative quick start guide, have a look at the [link histogram.getting_started Getting started] section.
[section Making a histogram]
[section Make a histogram]
A histogram consists of a [link histogram.concepts.storage storage] and a sequence of [link histogram.concepts.axis axis] objects. The storage represents a grid of cells of counters. The axis objects maps input values to indices, which are used to look up the cell. You don't normally have to worry about the storage, since the library provides a very good default. There are many interesting axis types to choose from, but for now let us stick to the most common axis, the [classref boost::histogram::axis::regular regular] axis. It represents equidistant intervals on the real line.
@ -24,7 +24,7 @@ When the axis types are known at compile-time, the histogram internally holds th
The factory function named [headerref boost/histogram/make_histogram.hpp make_histogram] uses the default storage type, which provides safe counting, is fast, and memory efficient. If you want to create a histogram with another storage type, use [headerref boost/histogram/make_histogram.hpp make_histogram_with]. To learn more about other storage types and how to create your own, have a look at the section [link histogram.guide.expert Advanced Usage].
[section Choosing an axis]
[section Choose an axis]
The library provides a number of useful axis types. Here is some advice when to use which.
@ -179,11 +179,11 @@ A growing axis can have under- and overflow bins, but these only count the speci
[endsect] [/ make a histogram]
[section Filling and accessing a histogram]
[section Fill a histogram and access cells]
A histogram has been created, now you want to insert tuples of possibly multi-dimensional and values of different types. This is done with the flexible [memberref boost::histogram::histogram::operator() histogram::operator()], which you typically use in a loop. It accepts `N` arguments or a `std::tuple` with `N` elements, where `N` is equal to the number of axes of the histogram. It finds the corresponding bin for the input and increments the bin counter by one.
A histogram has been created and now you want to insert values. This is done with the flexible [memberref boost::histogram::histogram::operator() histogram::operator()], which you typically use in a loop. It accepts `N` arguments or a `std::tuple` with `N` elements, where `N` is equal to the number of axes of the histogram. It finds the corresponding bin for the input and increments the bin counter by one.
After the histogram has been filled, use [memberref boost::histogram::histogram::at histogram::at] (in analogy to `std::vector::at`) to access the cell values. It accepts integer indices, one for each axis of the histogram. Example:
After the histogram has been filled, use [memberref boost::histogram::histogram::at histogram::at] (in analogy to `std::vector::at`) to access the cell values. It accepts integer indices, one for each axis of the histogram.
[import ../examples/guide_fill_histogram.cpp]
[guide_fill_histogram]
@ -197,14 +197,14 @@ When the weights come from a stochastic process, it is useful to keep track of t
[import ../examples/guide_fill_weighted_histogram.cpp]
[guide_fill_weighted_histogram]
When iterating over all cells, using [memberref boost::histogram::histogram::at histogram::at] can be inconvenient. The [funcref boost::histogram::indexed indexed] range generator is provided for this case, which is very convenient and /faster/ than naive for-loops:
When iterating over all cells, using [memberref boost::histogram::histogram::at histogram::at] can be inconvenient. The [funcref boost::histogram::indexed indexed] range generator is provided for this case, which is very convenient and /faster/ than naive for-loops.
[import ../examples/guide_indexed_access.cpp]
[guide_indexed_access]
[endsect]
[section Making a profile]
[section Make a profile]
Histograms from this library can do more than counting, they can hold arbitrary accumulators which accept samples. A histogram is called a /profile/, if it computes the means of the samples in each cell. Profiles can be generated with the factory function [funcref boost::histogram::make_profile make_profile].
@ -217,7 +217,7 @@ Weights and samples may be combined, if the histogram accumulators can handle we
[endsect]
[section Using operators]
[section Use operators]
The following operators are supported for pairs of histograms `+, -, *, /, ==, !=`. Histograms can also be multiplied and divided by a scalar. Only a subset of the arithmetic operators is available when the underlying cell value type only supports a subset.
@ -252,11 +252,11 @@ The library supports serialization via [@boost:/libs/serialization/index.html Bo
[endsect]
[section Algorithms]
[section Use algorithms]
The library was designed to work with algorithms from the C++ standard library. In addition, a support library of algorithms is included with common operations on histograms.
[section Using algorithms from the C++ standard library]
[section Algorithms from the C++ standard library]
The histogram class has standard random-access iterators which can be used with various algorithms from the standard library. Some things need to be kept in mind:
@ -274,7 +274,7 @@ It is easy to iterate over all histogram cells to compute the sum of cell values
[endsect]
[section Projections]
[section Projection]
Sometimes you want to remove some axes from a high-dimensional histogram and obtain the equivalent lower-dimensional version, that one gets by summing up the bin contents of the removed axes. This is called a /projection/. This is useful if you found out that there is no interesting structure along an axis, so it is not worth keeping that axis around, or if you want to visualize 1d or 2d projections of a high-dimensional histogram.
@ -285,7 +285,7 @@ The library provides the [funcref boost::histogram::algorithm::project] function
[endsect]
[section Reductions]
[section Reduction]
A projection removes an axis completely. Another way to obtain a smaller histogram which consume less memory is the [funcref boost::histogram::algorithm::reduce] function to /shrink/ and /rebin/ axes.
@ -331,13 +331,17 @@ How to make an axis completely from scratch is shown in the next example.
[import ../examples/guide_custom_minimal_axis.cpp]
[guide_custom_minimal_axis]
Such a minimal axis lacks many features provided by the builtin axis types, for example, one cannot iterate over this axis, but this functionality can be added as needed.
Such minimal axis types lack many features provided by the builtin axis types, for example, one cannot iterate over them, but this functionality can be added as needed.
[endsect]
[section Axis which accepts several arguments]
[section Axis with several arguments]
It is also possible to make
Multi-dimensional histograms usually have an orthogonal system of axes. Orthogonal means that each axis takes care of only one value and computes its local index independently of all the other axes and values. A checker-board is such an orthogonal grid in 2D.
There are other interesting grids which are not orthogonal, notably the honeycomb grid in 2D. In such a grid, each cell is hexagonal and even though the cells form a perfectly regular pattern, it is not possible to sort values into these cells using two orthogonal axes.
The library supports non-orthogonal grids by allowing axis type to accepts two or more arguments instead of one, if they are packed into a `std::tuple`. The following example demonstrates this.
[import ../examples/guide_custom_2d_axis.cpp]
[guide_custom_2d_axis]

View File

@ -14,7 +14,8 @@ int main() {
// axis which returns 1 if the input falls inside the unit circle and zero otherwise
struct circle_axis {
axis::index_type index(std::tuple<double, double> point) const {
// accepts a 2D point in form of a std::tuple
axis::index_type index(const std::tuple<double, double>& point) const {
const auto x = std::get<0>(point);
const auto y = std::get<1>(point);
return x * x + y * y <= 1.0;
@ -25,7 +26,7 @@ int main() {
auto h1 = make_histogram(circle_axis());
// call looks like for a histogram with N 1d axes if histogram has only one Nd axis
// fill looks normal for a histogram which has only one Nd-axis
h1(0, 0); // in
h1(0, -1); // in
h1(0, 1); // in
@ -34,15 +35,18 @@ int main() {
h1(1, 1); // out
h1(-1, -1); // out
// 2D histogram, but only 1D index
assert(h1.at(0) == 2); // out
assert(h1.at(1) == 5); // in
// other axes can be combined with a Nd-axis
auto h2 = make_histogram(circle_axis(), axis::category<std::string>({"red", "blue"}));
// pass arguments for first axis as std::tuple
// now we need to pass arguments for Nd-axis explicitly as std::tuple
h2(std::make_tuple(0, 0), "red");
h2(std::make_tuple(1, 1), "blue");
// 3D histogram, but only 2D index
assert(h2.at(0, 0) == 0); // out, red
assert(h2.at(0, 1) == 1); // out, blue
assert(h2.at(1, 0) == 1); // in, red

View File

@ -13,11 +13,11 @@
#include <cassert>
#include <sstream>
namespace bh = boost::histogram;
int main() {
auto a = bh::make_histogram(bh::axis::regular<>(3, -1.0, 1.0, "axis 0"),
bh::axis::integer<>(0, 2, "axis 1"));
using namespace boost::histogram;
auto a = make_histogram(axis::regular<>(3, -1.0, 1.0, "axis 0"),
axis::integer<>(0, 2, "axis 1"));
a(0.5, 1);
std::string buf; // to hold persistent representation

View File

@ -7,11 +7,9 @@
//[ guide_histogram_streaming
#include <boost/histogram.hpp>
#include <boost/histogram/axis/ostream.hpp>
#include <boost/histogram/ostream.hpp>
#include <cassert>
#include <iostream>
#include <memory>
#include <sstream>
#include <string>
@ -24,9 +22,10 @@ int main() {
axis::regular<double, tr::log>(2, 1.0, 10.0, "axis 1"),
axis::regular<double, tr::pow, use_default, axis::option::growth>(
tr::pow{1.5}, 2, 1.0, 10.0, "axis 2"),
axis::circular<double, axis::null_type>(4, 0.0, 360.0), // axis without metadata
axis::variable<double, use_default, axis::option::none, std::allocator<double>>(
{-1.0, 0.0, 1.0}, "axis 4"),
// axis without metadata
axis::circular<double, axis::null_type>(4, 0.0, 360.0),
// axis without under-/overflow bins
axis::variable<double, use_default, axis::option::none>({-1.0, 0.0, 1.0}, "axis 4"),
axis::category<>({2, 1, 3}, "axis 5"),
axis::category<std::string>({"red", "blue"}, "axis 6"),
axis::integer<>(-1, 1, "axis 7"));

View File

@ -14,13 +14,13 @@
const char* config = "4 1.0 2.0\n"
"5 3.0 4.0\n";
namespace bh = boost::histogram;
int main() {
using namespace boost::histogram;
// read axis config from a config file (mocked here with std::istringstream)
// and create vector of regular axes, the number of axis is not known at compile-time
std::istringstream is(config);
auto v1 = std::vector<bh::axis::regular<>>();
auto v1 = std::vector<axis::regular<>>();
while (is.good()) {
unsigned bins;
double start, stop;
@ -30,17 +30,17 @@ int main() {
// create histogram from iterator range
// (copying or moving the vector also works, move is shown below)
auto h1 = bh::make_histogram(v1.begin(), v1.end());
auto h1 = make_histogram(v1.begin(), v1.end());
assert(h1.rank() == v1.size());
// with a vector of axis::variant (polymorphic axis type that can hold any one of the
// template arguments at a time) the types and number of axis can vary at run-time
auto v2 = std::vector<bh::axis::variant<bh::axis::regular<>, bh::axis::integer<>>>();
v2.emplace_back(bh::axis::regular<>(100, -1.0, 1.0));
v2.emplace_back(bh::axis::integer<>(1, 7));
auto v2 = std::vector<axis::variant<axis::regular<>, axis::integer<>>>();
v2.emplace_back(axis::regular<>(100, -1.0, 1.0));
v2.emplace_back(axis::integer<>(1, 7));
// create dynamic histogram by moving the vector
auto h2 = bh::make_histogram(std::move(v2));
auto h2 = make_histogram(std::move(v2));
assert(h2.rank() == 2);
}

View File

@ -9,13 +9,12 @@
#include <boost/histogram.hpp>
#include <cassert>
namespace bh = boost::histogram;
int main() {
using namespace boost::histogram;
// create a 1d-histogram in default configuration which
// covers the real line from -1 to 1 in 100 bins
auto h = bh::make_histogram(bh::axis::regular<>(100, -1.0, 1.0));
auto h = make_histogram(axis::regular<>(100, -1.0, 1.0));
// rank is the number of axes
assert(h.rank() == 1);

View File

@ -7,6 +7,8 @@
#ifndef BOOST_HISTOGRAM_OSTREAM_HPP
#define BOOST_HISTOGRAM_OSTREAM_HPP
#include <boost/histogram/accumulators/ostream.hpp>
#include <boost/histogram/axis/ostream.hpp>
#include <boost/histogram/fwd.hpp>
#include <iosfwd>