Tomographer  v5.0
Tomographer C++ Framework Documentation
pyhistogram.h
1 /* This file is part of the Tomographer project, which is distributed under the
2  * terms of the MIT license.
3  *
4  * The MIT License (MIT)
5  *
6  * Copyright (c) 2016 ETH Zurich, Institute for Theoretical Physics, Philippe Faist
7  * Copyright (c) 2017 Caltech, Institute for Quantum Information and Matter, Philippe Faist
8  *
9  * Permission is hereby granted, free of charge, to any person obtaining a copy
10  * of this software and associated documentation files (the "Software"), to deal
11  * in the Software without restriction, including without limitation the rights
12  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13  * copies of the Software, and to permit persons to whom the Software is
14  * furnished to do so, subject to the following conditions:
15  *
16  * The above copyright notice and this permission notice shall be included in
17  * all copies or substantial portions of the Software.
18  *
19  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25  * SOFTWARE.
26  */
27 
28 #ifndef PY_HISTOGRAM_H
29 #define PY_HISTOGRAM_H
30 
31 
32 #include <tomographerpy/common.h>
33 
34 #include <tomographer/histogram.h>
36 
37 
38 // namespace Tomographer { namespace Tools {
39 // template<>
40 // inline bool isFinite<py::float_>(py::object o)
41 // {
42 // auto numpy = py::module::import("numpy");
43 // return numpy.attr("isfinite")(o).cast<bool>();
44 // }
45 // } } // Tomographer::Tools
46 
47 
48 namespace tpy {
49 
52 
53 
54 
56 struct Histogram
57 {
58  Histogram(HistogramParams params_)
59  : params(params_),
60  bins(py::cast(Eigen::VectorXd::Zero(params_.num_bins))),
61  off_chart(py::cast(0.0))
62  {
63  }
64 
65  Histogram(tpy::RealType min, tpy::RealType max, Eigen::Index num_bins)
66  : params(min, max, num_bins),
67  bins(py::cast(Eigen::VectorXd::Zero(num_bins))),
68  off_chart(py::cast(0.0))
69  {
70  }
71 
72  template<typename Scalar, typename CountType>
74  : params(h.params),
75  bins(py::cast(h.bins)),
76  off_chart(py::cast(h.off_chart))
77  {
78  }
79 
80  // ### Apparently doesn't work, need to be more brutal:
81  // template<typename Scalar, typename CountType>
82  // inline operator Tomographer::Histogram<Scalar,CountType> ()
83  template<typename X>
84  inline operator X () const
85  {
86  typedef typename X::Scalar Scalar;
87  typedef typename X::CountType CountType;
88  return toCxxHistogram<Scalar,CountType>();
89  }
90 
91  template<typename Scalar, typename CountType>
92  inline Tomographer::Histogram<Scalar,CountType> toCxxHistogram() const
93  {
96  h.off_chart = off_chart.cast<CountType>();
97  return h;
98  }
99 
100  inline void set_bins(py::object newbins)
101  {
102  if (py::len(newbins.attr("shape")) != 1) {
103  throw py::type_error("Expected 1-D NumPy array for assignment to Histogram.bins");
104  }
105  if ((Eigen::Index)py::len(newbins) != params.num_bins) {
106  throw py::type_error(streamstr("Expected "<<params.num_bins<<" elements for assignment to Histogram.bins,"
107  " got "<<py::len(newbins)));
108  }
109  bins = newbins;
110  }
111  inline void set_off_chart(py::object o)
112  {
113  auto np = py::module::import("numpy");
114  if ( ! np.attr("isscalar")(o).cast<bool>() ) {
115  throw py::type_error("Expected scalar for assignment to Histogram.off_chart");
116  }
117  off_chart = o;
118  }
119 
120  inline void load(py::object x, py::object o)
121  {
122  set_bins(x);
123  set_off_chart(o);
124  }
125 
126  inline py::object normalization() const {
127  auto np = py::module::import("numpy");
128  // off_chart + binResolution() * sum(bins)
129  return np.attr("add")(off_chart, np.attr("multiply")(py::cast(params.binResolution()), bins.attr("sum")()));
130  }
131 
132  inline py::object totalCounts() const {
133  auto np = py::module::import("numpy");
134  // off_chart + sum(bins)
135  return np.attr("add")(off_chart, bins.attr("sum")());
136  }
137 
138  HistogramParams params;
139  py::object bins;
140  py::object off_chart;
141 
142  enum { HasErrorBars = 0 };
143 };
144 
145 
148 {
149  HistogramWithErrorBars(HistogramParams params_)
150  : Histogram(params_),
151  delta(py::cast(Eigen::VectorXd::Zero(params_.num_bins)))
152  {
153  }
154 
155  HistogramWithErrorBars(tpy::RealType min, tpy::RealType max, Eigen::Index num_bins)
156  : Histogram(min, max, num_bins),
157  delta(py::cast(Eigen::VectorXd::Zero(num_bins)))
158  {
159  }
160 
161  template<typename Scalar, typename CountType>
163  : Histogram(h),
164  delta(py::cast(h.delta))
165  {
166  }
167 
168  // ### Apparently doesn't work, need to be more brutal:
169  // template<typename Scalar, typename CountType>
170  // inline operator Tomographer::HistogramWithErrorBars<Scalar,CountType> ()
171  template<typename X>
172  inline operator X () const
173  {
174  typedef typename X::Scalar Scalar;
175  typedef typename X::CountType CountType;
176  return toCxxHistogram<Scalar,CountType>();
177  }
178 
179  template<typename Scalar, typename CountType>
180  inline Tomographer::HistogramWithErrorBars<Scalar,CountType> toCxxHistogram() const
181  {
185  h.off_chart = off_chart.cast<CountType>();
186  return h;
187  }
188 
189  inline void set_delta(py::object newdelta)
190  {
191  if (py::len(newdelta.attr("shape")) != 1) {
192  throw py::type_error("Expected 1-D NumPy array for assignment to HistogramWithErrorBars.delta");
193  }
194  if ((Eigen::Index)py::len(newdelta) != params.num_bins) {
195  throw py::type_error(streamstr("Expected "<<params.num_bins<<" elements for assignment to HistogramWithErrorBars.delta,"
196  " got "<<py::len(newdelta)));
197  }
198  delta = newdelta;
199  }
200 
201  inline void load(py::object x, py::object err, py::object o)
202  {
203  set_bins(x);
204  set_delta(err);
205  set_off_chart(o);
206  }
207 
208  py::object delta;
209 
210  enum { HasErrorBars = 1 };
211 };
212 
213 
214 
215 
216 } // namespace Py
217 
218 
219 #endif
Eigen::Array< CountType, Eigen::Dynamic, 1 > delta
The error bars associated with each histogram bin.
Definition: histogram.h:558
Tomographer::HistogramParams< RealType > HistogramParams
Histogram Params. See Tomographer::HistogramParams.
Definition: pyhistogram.h:51
Histogram class like Tomographer::Histogram, but with NumPy arrays storage.
Definition: pyhistogram.h:56
Scalar binResolution() const
Returns the width of a bin.
Definition: histogram.h:174
Stores a histogram along with error bars.
Definition: histogram.h:537
Params params
Parameters of this histogram (range and # of bins)
Definition: histogram.h:236
double RealType
Real type for template arguments (double)
Definition: common.h:88
A Histogram with real counts and error bars. See Tomographer::HistogramWithErrorBars.
Definition: pyhistogram.h:147
Eigen::Array< CountType, Eigen::Dynamic, 1 > bins
The counts for each bin.
Definition: histogram.h:238
CountType off_chart
The number of points that fell outside of the given range.
Definition: histogram.h:240
Stores a histogram.
Definition: histogram.h:213
Some C++ utilities, with a tad of C++11 tricks.
Definitions for Histogram Types.
#define streamstr(tokens)
Utility macro to format stream tokens to a std::string.
Definition: fmt.h:149
C++ Classes and Utilities for Python Modules.
Definition: common.h:85
Eigen::Index num_bins
Number of bins to split the range into.
Definition: histogram.h:95
internal::cast_return_type< Array< _Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols >, const CwiseUnaryOp< internal::scalar_cast_op< typename internal::traits< Array< _Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols > >::Scalar, NewType >, const Array< _Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols > > >::type cast() const