Tomographer  v5.4
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 tpy {
39 
47 
48 
49 
51 class Histogram
52 {
53 public:
54  Histogram(HistogramParams params_)
55  : params(params_),
56  bins(py::cast(Eigen::VectorXd::Zero(params_.num_bins))),
57  off_chart(py::cast(0.0))
58  {
59  }
60 
61  Histogram(tpy::RealScalar min, tpy::RealScalar max, Eigen::Index num_bins)
62  : params(min, max, num_bins),
63  bins(py::cast(Eigen::VectorXd::Zero(num_bins))),
64  off_chart(py::cast(0.0))
65  {
66  }
67 
68  template<typename Scalar, typename CountType>
70  : params(h.params),
71  bins(py::cast(h.bins)),
72  off_chart(py::cast(h.off_chart))
73  {
74  }
75 
76  // ### Apparently doesn't work, need to be more brutal:
77  // template<typename Scalar, typename CountType>
78  // inline operator Tomographer::Histogram<Scalar,CountType> ()
79  template<typename X>
80  inline operator X () const
81  {
82  typedef typename X::Scalar Scalar;
83  typedef typename X::CountType CountType;
84  return toCxxHistogram<Scalar,CountType>();
85  }
86 
87  template<typename Scalar, typename CountType>
88  inline Tomographer::Histogram<Scalar,CountType> toCxxHistogram() const
89  {
92  h.off_chart = off_chart.cast<CountType>();
93  return h;
94  }
95 
96  inline void set_bins(py::object newbins)
97  {
98  if (py::len(newbins.attr("shape")) != 1) {
99  throw py::value_error("Expected 1-D NumPy array for assignment to Histogram.bins");
100  }
101  if ((Eigen::Index)py::len(newbins) != params.num_bins) {
102  throw py::value_error(streamstr("Expected "<<params.num_bins<<" elements for assignment to Histogram.bins,"
103  " got "<<py::len(newbins)));
104  }
105  bins = newbins;
106  }
107  inline void set_off_chart(py::object o)
108  {
109  auto np = py::module::import("numpy");
110  if ( ! np.attr("isscalar")(o).cast<bool>() ) {
111  throw py::value_error("Expected scalar for assignment to Histogram.off_chart");
112  }
113  off_chart = o;
114  }
115 
116  inline void load(py::object x, py::object o)
117  {
118  set_bins(x);
119  set_off_chart(o);
120  }
121 
122  inline py::object normalization() const {
123  auto np = py::module::import("numpy");
124  // off_chart + binResolution() * sum(bins)
125  return np.attr("add")(off_chart, np.attr("multiply")(py::cast(params.binResolution()), bins.attr("sum")()));
126  }
127 
128  inline py::object totalCounts() const {
129  auto np = py::module::import("numpy");
130  // off_chart + sum(bins)
131  return np.attr("add")(off_chart, bins.attr("sum")());
132  }
133 
134  HistogramParams params;
135  py::object bins;
136  py::object off_chart;
137 
138  enum { HasErrorBars = 0 };
139 };
140 
141 
144 {
145 public:
146  HistogramWithErrorBars(HistogramParams params_)
147  : Histogram(params_),
148  delta(py::cast(Eigen::VectorXd::Zero(params_.num_bins)))
149  {
150  }
151 
152  HistogramWithErrorBars(tpy::RealScalar min, tpy::RealScalar max, Eigen::Index num_bins)
153  : Histogram(min, max, num_bins),
154  delta(py::cast(Eigen::VectorXd::Zero(num_bins)))
155  {
156  }
157 
158  template<typename Scalar, typename CountType>
160  : Histogram(h),
161  delta(py::cast(h.delta))
162  {
163  }
164 
165  // ### Apparently doesn't work, need to be more brutal:
166  // template<typename Scalar, typename CountType>
167  // inline operator Tomographer::HistogramWithErrorBars<Scalar,CountType> ()
168  template<typename X>
169  inline operator X () const
170  {
171  typedef typename X::Scalar Scalar;
172  typedef typename X::CountType CountType;
173  return toCxxHistogram<Scalar,CountType>();
174  }
175 
176  template<typename Scalar, typename CountType>
177  inline Tomographer::HistogramWithErrorBars<Scalar,CountType> toCxxHistogram() const
178  {
182  h.off_chart = off_chart.cast<CountType>();
183  return h;
184  }
185 
186  inline void set_delta(py::object newdelta)
187  {
188  if (py::len(newdelta.attr("shape")) != 1) {
189  throw py::value_error("Expected 1-D NumPy array for assignment to HistogramWithErrorBars.delta");
190  }
191  if ((Eigen::Index)py::len(newdelta) != params.num_bins) {
192  throw py::value_error(streamstr("Expected " << params.num_bins << " elements for assignment to "
193  "HistogramWithErrorBars.delta, got " << py::len(newdelta)));
194  }
195  delta = newdelta;
196  }
197 
198  inline void load(py::object x, py::object err, py::object o)
199  {
200  set_bins(x);
201  set_delta(err);
202  set_off_chart(o);
203  }
204 
205  py::object delta;
206 
207  enum { HasErrorBars = 1 };
208 };
209 
210 
211 
212 
213 } // namespace Py
214 
215 
216 #endif
Eigen::Array< CountType, Eigen::Dynamic, 1 > delta
The error bars associated with each histogram bin.
Definition: histogram.h:587
Tomographer::HistogramParams< RealScalar > HistogramParams
Histogram Params. See Tomographer::HistogramParams.
Definition: pyhistogram.h:46
Scalar binResolution() const
Returns the width of a bin.
Definition: histogram.h:179
Stores a histogram along with error bars.
Definition: histogram.h:566
Params params
Parameters of this histogram (range and # of bins)
Definition: histogram.h:253
Histogram class like Tomographer::Histogram, but with NumPy arrays storage.
Definition: pyhistogram.h:51
Eigen::Array< CountType, Eigen::Dynamic, 1 > bins
The counts for each bin.
Definition: histogram.h:255
CountType off_chart
The number of points that fell outside of the given range.
Definition: histogram.h:257
Stores a histogram.
Definition: histogram.h:230
Some C++ utilities, with a tad of C++11 tricks.
double RealScalar
Real type for general calculation precisions (density matrix elements, log-likelihood value calculati...
Definition: common.h:92
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:89
A Histogram with real counts and error bars. See Tomographer::HistogramWithErrorBars.
Definition: pyhistogram.h:143
Eigen::Index num_bins
Number of bins to split the range into.
Definition: histogram.h:100
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