Belle II Software  release-05-02-19
tools.h
1 /**************************************************************************
2  * BASF2 (Belle Analysis Framework 2) *
3  * Copyright(C) 2020 - Belle II Collaboration *
4  * *
5  * Author: The Belle II Collaboration *
6  * Contributors: Radek Zlebcik *
7  * *
8  * This software is provided "as is" without any warranty. *
9  **************************************************************************/
10 
11 #pragma once
12 
13 #include <vector>
14 #include <iostream>
15 #include <cstdlib>
16 #include <TString.h>
17 #include <TRandom.h>
18 
19 #include <Eigen/Dense>
20 
21 //If compiled within BASF2
22 #ifdef _PACKAGE_
23 #include <framework/logging/Logger.h>
24 #else
25 #ifndef B2FATAL
26 #define B2FATAL(arg) { std::cout << arg << std::endl; std::exit(1);}
27 #define B2ASSERT(str, cond) { if((cond) == false) {std::cout << __FILE__ <<", line "<<__LINE__ << std::endl << "" << #cond << " failed" << std::endl; std::exit(1);} }
28 #endif
29 #endif
30 
31 
32 
33 
34 namespace Belle2 {
40  inline TString rn() {return Form("%d", gRandom->Integer(1000000000)); }
42 
44  inline std::vector<std::vector<double>> merge(std::vector<std::vector<std::vector<double>>> toMerge)
45  {
46  std::vector<std::vector<double>> allVecs;
47  for (const auto& v : toMerge)
48  allVecs.insert(allVecs.end(), v.begin(), v.end());
49  return allVecs;
50  }
51 
52 
54  inline Eigen::VectorXd vec2vec(std::vector<double> vec)
55  {
56  Eigen::VectorXd v(vec.size());
57  for (unsigned i = 0; i < vec.size(); ++i) {
58  v[i] = vec[i];
59  }
60  return v;
61  }
62 
64  inline std::vector<double> vec2vec(Eigen::VectorXd v)
65  {
66  std::vector<double> vNew(v.rows());
67  for (int i = 0; i < v.rows(); ++i)
68  vNew[i] = v(i);
69  return vNew;
70  }
71 
72 
73 
75  inline Eigen::MatrixXd vecs2mat(std::vector<std::vector<double>> vecs)
76  {
77  Eigen::MatrixXd m(vecs[0].size(), vecs.size());
78  for (unsigned i = 0; i < vecs[0].size(); ++i)
79  for (unsigned j = 0; j < vecs.size(); ++j) {
80  m(i, j) = vecs[j][i];
81  }
82  return m;
83  }
84 
86  inline std::vector<double> getRangeLin(int nVals, double xMin, double xMax)
87  {
88  B2ASSERT("At least one value in the spline required", nVals >= 1);
89  if (nVals == 1) return {};
90  std::vector<double> v(nVals);
91  for (int i = 0; i < nVals; ++i)
92  v[i] = xMin + i * (xMax - xMin) / (nVals - 1);
93  return v;
94  }
95 
97  inline std::vector<double> getRangeZero(int nVals, double xMin, double xMax)
98  {
99  B2ASSERT("At least one value in the spline required", nVals >= 1);
100  if (nVals == 1) return {};
101  std::vector<double> v(nVals - 1);
102  for (int i = 1; i < nVals; ++i)
103  v[i - 1] = xMin + i * (xMax - xMin) / (nVals);
104  return v;
105  }
106 
107 
109  inline std::vector<double> slice(std::vector<double> v, unsigned ind, unsigned n)
110  {
111  std::vector<double> vNew;
112  for (unsigned i = ind; i < ind + n && i < v.size(); ++i)
113  vNew.push_back(v[i]);
114  return vNew;
115  }
116 
118  inline double eval(const std::vector<double>& spl, const std::vector<double>& vals, double x)
119  {
120  int order = -1;
121  if (spl.size() == 0)
122  order = 0;
123  else if (spl.size() == vals.size() - 1)
124  order = 0;
125  else if (spl.size() == vals.size())
126  order = 1;
127  else {
128  B2FATAL("Unknown order of spline");
129  }
130  B2ASSERT("Spline order should be zero or one", order == 0 || order == 1);
131 
132  if (order == 1) {
133  B2ASSERT("Linear spline only meaningful for two or more nodes", spl.size() >= 2);
134  B2ASSERT("As nodes as values in lin. spline", spl.size() == vals.size());
135 
136  if (x <= spl[0]) return vals[0];
137  if (x >= spl.back()) return vals.back();
138 
139  // binary search for position
140  int i1 = lower_bound(spl.begin(), spl.end(), x) - spl.begin() - 1;
141 
142  if (!(spl[i1] <= x && x <= spl[i1 + 1])) {
143  B2FATAL("Wrong place founded : " << spl[i1] << " " << x << " " << spl[i1 + 1]);
144  }
145 
146  // Linear interpolation between neighbouring nodes
147  double v = ((spl[i1 + 1] - x) * vals[i1] + (x - spl[i1]) * vals[i1 + 1]) / (spl[i1 + 1] - spl[i1]);
148  return v;
149  } else if (order == 0) { //zero order polynomial
150  B2ASSERT("#values vs #nodes in zero-order spline", spl.size() + 1 == vals.size());
151  if (vals.size() == 1) {
152  return vals[0];
153  } else {
154  double res = vals[0]; //by default value from lowest node
155  for (unsigned i = 0; i < spl.size(); ++i) {
156  if (spl[i] <= x) res = vals[i + 1];
157  else break;
158  }
159  return res;
160  }
161  }
162  return -99;
163  }
164 
165 
168  struct Spline {
169  std::vector<double> nodes;
170  std::vector<double> vals;
171  std::vector<double> errs;
172 
174  double val(double x) const {return eval(nodes, vals, x);}
175 
177  double err(double x) const {return eval(nodes, errs, x);}
178 
180  double center() const
181  {
182  if (nodes.size() == 0) //dummy situation
183  return 0;
184  else if (nodes.size() % 2 == 1)
185  return nodes[nodes.size() / 2];
186  else
187  return (nodes[nodes.size() / 2 - 1] + nodes[nodes.size() / 2]) / 2;
188  }
189 
191  void print(TString tag = "")
192  {
193  std::cout << tag << " : nodes: ";
194  for (auto n : nodes) {
195  std::cout << n << " ";
196  }
197  std::cout << std::endl;
198  std::cout << tag << " : vals: ";
199  for (auto n : vals) {
200  std::cout << n << " ";
201  }
202  std::cout << std::endl;
203 
204  std::cout << tag << " : errs: ";
205  for (auto n : errs) {
206  std::cout << n << " ";
207  }
208  std::cout << std::endl;
209  }
210 
211  Spline() : nodes{}, vals{0}, errs{0} {}
212 
213  };
214 
215 
217 }
218 
Belle2::Spline::nodes
std::vector< double > nodes
vector of spline nodes
Definition: tools.h:169
Belle2::Spline::err
double err(double x) const
get error of spline at point x
Definition: tools.h:177
Belle2::getRangeZero
std::vector< double > getRangeZero(int nVals, double xMin, double xMax)
Equidistant range between xMin and xMax for spline of the zero order.
Definition: tools.h:97
Belle2::vec2vec
Eigen::VectorXd vec2vec(std::vector< double > vec)
std vector -> ROOT vector
Definition: tools.h:54
Belle2::merge
std::vector< std::vector< double > > merge(std::vector< std::vector< std::vector< double >>> toMerge)
merge { vector<double> a, vector<double> b} into {a, b}
Definition: tools.h:44
Belle2::Spline
Spline structure for zero-order & linear splines.
Definition: tools.h:168
Belle2
Abstract base class for different kinds of events.
Definition: MillepedeAlgorithm.h:19
Belle2::Spline::print
void print(TString tag="")
print the spline
Definition: tools.h:191
Belle2::Spline::vals
std::vector< double > vals
vector of spline values
Definition: tools.h:170
Belle2::Spline::val
double val(double x) const
get value of spline at point x
Definition: tools.h:174
Belle2::eval
double eval(const std::vector< double > &spl, const std::vector< double > &vals, double x)
Evaluate spline (zero order or first order) in point x.
Definition: tools.h:118
Belle2::vecs2mat
Eigen::MatrixXd vecs2mat(std::vector< std::vector< double >> vecs)
merge columns (from std::vectors) into ROOT matrix
Definition: tools.h:75
Belle2::slice
std::vector< Atom > slice(std::vector< Atom > vec, int s, int e)
Slice the vector to contain only elements with indexes s .. e (included)
Definition: Splitter.h:89
Belle2::Spline::errs
std::vector< double > errs
vector of spline errors
Definition: tools.h:171
Belle2::rn
TString rn()
Get random string.
Definition: tools.h:41
Belle2::Spline::center
double center() const
Get center of the spline domain.
Definition: tools.h:180
Belle2::getRangeLin
std::vector< double > getRangeLin(int nVals, double xMin, double xMax)
Equidistant range between xMin and xMax for spline of the first order.
Definition: tools.h:86