/home/docs/checkouts/readthedocs.org/user_builds/ratpac/checkouts/latest/src/util/include/RAT/ROOTInterpolator.hh Source File

Ratpac-two: /home/docs/checkouts/readthedocs.org/user_builds/ratpac/checkouts/latest/src/util/include/RAT/ROOTInterpolator.hh Source File
Ratpac-two
ROOTInterpolator.hh
1 #ifndef __RAT_ROOTINTERPOLATOR_HH__
2 #define __RAT_ROOTINTERPOLATOR_HH__
3 
4 #include <TGraph.h>
5 
6 #include <RAT/Log.hh>
7 
8 namespace RAT {
9 
10 // A Interpolator class based on ROOT's TGraph. Adds more control over out-of-domain behaviors
12  public:
13  enum class kind_t {
14  kLinear,
15  kCubic,
16  };
17  enum class extrapolation_t {
18  kError, // no interpolation, throws an error instead
19  kExtrapolate, // extrapolate. Default behavior of TGraph::Eval
20  kClamp, // clamp to the nearest point
21  kConstant, // constant value
22  };
23  ROOTInterpolator() : fGraph(nullptr) {}
24  ROOTInterpolator(const TGraph& g, kind_t kind = kind_t::kLinear,
25  extrapolation_t extrapolation = extrapolation_t::kExtrapolate, double fillvalue = 0.0)
26  : fGraph(std::make_unique<TGraph>(g)), fKind(kind), fExtrapolation(extrapolation), fFillValue(fillvalue) {
27  prepareGraph();
28  }
29  ROOTInterpolator(TGraph&& graph, kind_t kind = kind_t::kLinear,
30  extrapolation_t extrapolation = extrapolation_t::kExtrapolate, double fillvalue = 0.0) noexcept
31  : fGraph(std::make_unique<TGraph>(std::move(graph))),
32  fKind(kind),
33  fExtrapolation(extrapolation),
34  fFillValue(fillvalue) {
35  prepareGraph();
36  }
37  ROOTInterpolator& operator=(const ROOTInterpolator& other) {
38  if (this != &other) {
39  fGraph = std::make_unique<TGraph>(*other.fGraph);
40  fMinX = other.fMinX;
41  fMaxX = other.fMaxX;
42  fKind = other.fKind;
43  fExtrapolation = other.fExtrapolation;
44  fFillValue = other.fFillValue;
45  }
46  return *this;
47  }
48  ROOTInterpolator& operator=(ROOTInterpolator&& other) noexcept {
49  if (this != &other) {
50  fGraph = std::move(other.fGraph);
51  fMinX = other.fMinX;
52  fMaxX = other.fMaxX;
53  fKind = other.fKind;
54  fExtrapolation = other.fExtrapolation;
55  fFillValue = other.fFillValue;
56  }
57  return *this;
58  }
59 
60  ROOTInterpolator(const std::vector<double>& x, const std::vector<double>& y, kind_t kind = kind_t::kLinear,
61  extrapolation_t extrapolation = extrapolation_t::kExtrapolate, double fillvalue = 0.0)
62  : fGraph(std::make_unique<TGraph>(x.size(), x.data(), y.data())),
63  fKind(kind),
64  fExtrapolation(extrapolation),
65  fFillValue(fillvalue) {
66  prepareGraph();
67  }
68 
69  void SetGraph(const TGraph& g) {
70  fGraph = std::make_unique<TGraph>(g);
71  prepareGraph();
72  }
73  void SetGraph(TGraph&& graph) noexcept {
74  fGraph = std::make_unique<TGraph>(std::move(graph));
75  prepareGraph();
76  }
77  void SetData(const std::vector<double>& x, const std::vector<double>& y) {
78  fGraph = std::make_unique<TGraph>(x.size(), x.data(), y.data());
79  prepareGraph();
80  }
81 
82  void SetFillValue(double fillValue) { fFillValue = fillValue; }
83  void SetKind(kind_t kind) { fKind = kind; }
84  void SetExtrapolation(extrapolation_t extrapolation) { fExtrapolation = extrapolation; }
85  double GetFillValue() const { return fFillValue; }
86  kind_t GetKind() const { return fKind; }
87  extrapolation_t GetExtrapolation() const { return fExtrapolation; }
88  const TGraph* GetGraph() const { return fGraph.get(); }
89 
90  double operator()(double xx) const {
91  if (!fGraph) {
92  Log::Die("Interpolator has no graph set.");
93  }
94  double result;
95  if (xx > fMinX && xx < fMaxX) {
96  switch (fKind) {
97  case kind_t::kLinear:
98  result = fGraph->Eval(xx);
99  break;
100  case kind_t::kCubic:
101  result = fGraph->Eval(xx, 0, "S");
102  break;
103  }
104  } else { // out of bound
105  switch (fExtrapolation) {
106  case extrapolation_t::kError:
107  Log::Die("Interpolator called with out-of-bound value: %f", xx);
108  break;
109  case extrapolation_t::kExtrapolate:
110  return fGraph->Eval(xx);
111  break;
112  case extrapolation_t::kClamp:
113  if (xx < fMinX) {
114  result = fGraph->Eval(fMinX);
115  } else {
116  result = fGraph->Eval(fMaxX);
117  }
118  break;
119  case extrapolation_t::kConstant:
120  result = fFillValue;
121  break;
122  }
123  }
124  return result;
125  }
126 
127  protected:
128  std::unique_ptr<TGraph> fGraph;
129  double fMinX, fMaxX;
130  kind_t fKind = kind_t::kLinear;
131  extrapolation_t fExtrapolation = extrapolation_t::kExtrapolate;
132  double fFillValue = 0.0;
133  void prepareGraph() {
134  if (!fGraph) {
135  Log::Die("Interpolator has no graph set.");
136  }
137  fGraph->Sort();
138  fMinX = fGraph->GetX()[0];
139  fMaxX = fGraph->GetX()[fGraph->GetN() - 1];
140  }
141 };
142 
143 } // namespace RAT
144 
145 #endif // __RAT_ROOTINTERPOLATOR_HH__
static void Die(std::string message, int return_code=1)
Definition: Log.cc:90
Definition: ROOTInterpolator.hh:11
Definition: CCCrossSecMessenger.hh:29