OPAL (Object Oriented Parallel Accelerator Library)  2024.1
OPAL
OpalFilter.cpp
Go to the documentation of this file.
1 //
2 // Class OpalFilter
3 // The class for the Filter Object.
4 // A FILTER definition is used to define a filter which can be applied
5 // to a 1D histogram in order to get rid of noise.
6 //
7 // Copyright (c) 2008 - 2022, Christof Metzger-Kraus
8 // All rights reserved
9 //
10 // This file is part of OPAL.
11 //
12 // OPAL is free software: you can redistribute it and/or modify
13 // it under the terms of the GNU General Public License as published by
14 // the Free Software Foundation, either version 3 of the License, or
15 // (at your option) any later version.
16 //
17 // You should have received a copy of the GNU General Public License
18 // along with OPAL. If not, see <https://www.gnu.org/licenses/>.
19 //
20 #include "Utilities/OpalFilter.h"
21 
24 #include "Attributes/Attributes.h"
25 #include "Filters/Filters.h"
26 #include "Physics/Physics.h"
28 
29 #include "Utility/IpplInfo.h"
30 
31 #include <cmath>
32 #include <unordered_map>
33 
34 #define NPOINTS_DEFAULT 129
35 #define NLEFT_DEFAULT 64
36 #define NRIGHT_DEFAULT 64
37 #define POLYORDER_DEFAULT 1
38 
39 extern Inform *gmsg;
40 
41 // The attributes of class OpalFilter.
42 namespace {
43  enum {
44  TYPE, // The type of filter
45  NFREQ, // Number of frequencies in fixedFFTLowPass filter
46  THRESHOLD, // Relative threshold for amplitude of frequency in relativeFFTLowPass
47  NPOINTS, // Number of points in Savitzky-Golay filter
48  NLEFT, // Number of points to the left in S-G filter
49  NRIGHT, // Number of points to the right in S-G filter
50  POLYORDER, // Polynomial order in S-G Filter
51  SIZE
52  };
53 }
54 
56  Definition(SIZE, "FILTER",
57  "The \"FILTER\" statement defines a 1 dimensional filter to be "
58  "applied on histogram."),
59  filter_m(0) {
61  ("TYPE", "Specifies the type of filter.",
62  {"SAVITZKY-GOLAY", "FIXEDFFTLOWPASS", "RELATIVEFFTLOWPASS", "STENCIL"});
63 
65  ("NFREQ", "Number of frequencies to use in fixedFFTLowPass filter", 9.);
66 
67  itsAttr[THRESHOLD] = Attributes::makeReal
68  ("THRESHOLD", "Relative threshold for amplitude of frequencies in relativeFFTLowPass filter", 1.e-6);
69 
70  itsAttr[NPOINTS] = Attributes::makeReal
71  ("NPOINTS", "Number of points in Savitzky-Golay filter", NPOINTS_DEFAULT);
72 
73  itsAttr[NLEFT] = Attributes::makeReal
74  ("NLEFT", "Number of points to the left in Savitzky-Golay filter", NLEFT_DEFAULT);
75 
76  itsAttr[NRIGHT] = Attributes::makeReal
77  ("NRIGHT", "Number of points to the right in Savitzky-Golay filter", NRIGHT_DEFAULT);
78 
79  itsAttr[POLYORDER] = Attributes::makeReal
80  ("POLYORDER", "Polynomial order for local fit-function in Savitzky-Golay filter", POLYORDER_DEFAULT);
81 
83 
84  OpalFilter* defFilter = clone("UNNAMED_FILTER");
85  defFilter->builtin = true;
86 
87  try {
88  defFilter->update();
89  OpalData::getInstance()->define(defFilter);
90  } catch(...) {
91  delete defFilter;
92  }
93 }
94 
95 
96 OpalFilter::OpalFilter(const std::string& name, OpalFilter* parent):
97  Definition(name, parent),
98  filter_m(0)
99 {}
100 
101 
103  if (filter_m)
104  delete filter_m;
105 }
106 
107 
109  // Can replace only by another WAKE.
110  return dynamic_cast<OpalFilter*>(object) != 0;
111 }
112 
113 
114 OpalFilter *OpalFilter::clone(const std::string& name) {
115  return new OpalFilter(name, this);
116 }
117 
118 
120  update();
121 }
122 
123 
124 OpalFilter* OpalFilter::find(const std::string& name) {
125  OpalFilter* filter = dynamic_cast<OpalFilter*>(OpalData::getInstance()->find(name));
126 
127  if (filter == 0) {
128  throw OpalException("OpalFilter::find()",
129  "OpalFilter \"" + name + "\" not found.");
130  }
131  return filter;
132 }
133 
134 
136  // Set default name.
137  if (getOpalName().empty()) setOpalName("UNNAMED_FILTER");
138 }
139 
140 
142  if (filter_m == 0) {
143  *gmsg << "* ************* F I L T E R ************************************************************" << endl;
144  *gmsg << "OpalFilter::initOpalFilterfunction " << endl;
145  *gmsg << "* **********************************************************************************" << endl;
146 
147  static const std::unordered_map<std::string, FilterType> stringFilterType_s = {
148  {"SAVITZKY-GOLAY", FilterType::SAVITZKYGOLAY},
149  {"FIXEDFFTLOWPASS", FilterType::FIXEDFFTLOWPASS},
150  {"RELATIVEFFTLOWPASS", FilterType::RELATIVEFFTLOWPASS},
151  {"STENCIL", FilterType::STENCIL}
152  };
153 
154  FilterType type = stringFilterType_s.at(Attributes::getString(itsAttr[TYPE]));
155  switch (type) {
157  int num_points = (int)(Attributes::getReal(itsAttr[NPOINTS]));
158  int num_points_left = (int)(Attributes::getReal(itsAttr[NLEFT]));
159  int num_points_right = (int)(Attributes::getReal(itsAttr[NRIGHT]));
160  int polynomial_order = std::abs((int)(Attributes::getReal(itsAttr[POLYORDER])));
161 
162  Inform svg("Savitzky-Golay: ");
163  if (num_points_left < 0) {
164  svg << "Number of points to the left negative; using default (" << NLEFT_DEFAULT << ");" << endl;
165  num_points_left = NLEFT_DEFAULT;
166  }
167  if (num_points_right < 0) {
168  svg << "Number of points to the right negative; using default (" << NRIGHT_DEFAULT << ");" << endl;
169  num_points_right = NRIGHT_DEFAULT;
170  }
171  if (num_points < num_points_left + num_points_right) {
172  svg << "Total number of points small than sum of the ones to the left and to the right plus 1; using default (NLEFT + NRIGHT + 1);" << endl;
173  num_points = num_points_left + num_points_right + 1;
174  }
175  if (polynomial_order > num_points_left + num_points_right) {
176  svg << "Polynomial order bigger than sum of points to the left and to the right; using default (NLEFT + NRIGHT);" << endl;
177  polynomial_order = num_points_left + num_points_right;
178  }
179 
180  filter_m = new SavitzkyGolayFilter(num_points, num_points_left, num_points_right, polynomial_order);
181  break;
182  }
185  break;
186  }
189  break;
190  }
191  case FilterType::STENCIL: {
192  filter_m = new StencilFilter();
193  break;
194  }
195  default: {
196  filter_m = 0;
197  INFOMSG("No filter attached" << endl);
198  break;
199  }
200  }
201  }
202 }
203 
204 void OpalFilter::print(std::ostream& os) const {
205  os << "* ************* F I L T E R ********************************************************\n"
206  << "* FILTER " << getOpalName() << '\n'
207  << "* TYPE " << Attributes::getString(itsAttr[TYPE]) << '\n'
208  << "* NFREQ " << Attributes::getReal(itsAttr[NFREQ]) << '\n'
209  << "* THRESHOLD " << Attributes::getReal(itsAttr[THRESHOLD]) << '\n'
210  << "* NPOINTS " << Attributes::getReal(itsAttr[NPOINTS]) << '\n'
211  << "* NLEFT " << Attributes::getReal(itsAttr[NLEFT]) << '\n'
212  << "* NRIGHT " << Attributes::getReal(itsAttr[NRIGHT]) << '\n'
213  << "* POLYORDER " << Attributes::getReal(itsAttr[POLYORDER]) << '\n'
214  << "* ********************************************************************************** " << std::endl;
215 }
Attribute makeReal(const std::string &name, const std::string &help)
Make real attribute.
Definition: Attributes.cpp:240
static OpalData * getInstance()
Definition: OpalData.cpp:196
bool builtin
Built-in flag.
Definition: Object.h:233
void print(std::ostream &os) const
Print the object.
Definition: OpalFilter.cpp:204
virtual ~OpalFilter()
Definition: OpalFilter.cpp:102
void setOpalName(const std::string &name)
Set object name.
Definition: Object.cpp:331
The base class for all OPAL objects.
Definition: Object.h:48
std::string getString(const Attribute &attr)
Get string value.
Definition: Attributes.cpp:343
PETE_TUTree< FnAbs, typename T::PETE_Expr_t > abs(const PETE_Expr< T > &l)
static OpalFilter * find(const std::string &name)
Find named FILTER.
Definition: OpalFilter.cpp:124
void define(Object *newObject)
Define a new object.
Definition: OpalData.cpp:489
virtual void execute()
Check the OpalFilter data.
Definition: OpalFilter.cpp:119
#define NLEFT_DEFAULT
Definition: OpalFilter.cpp:35
#define INFOMSG(msg)
Definition: IpplInfo.h:348
Inform & endl(Inform &inf)
Definition: Inform.cpp:42
virtual OpalFilter * clone(const std::string &name)
Make clone.
Definition: OpalFilter.cpp:114
#define NPOINTS_DEFAULT
Definition: OpalFilter.cpp:34
Filter * filter_m
Definition: OpalFilter.h:61
#define NRIGHT_DEFAULT
Definition: OpalFilter.cpp:36
void registerOwnership(const AttributeHandler::OwnerType &itsClass) const
Definition: Object.cpp:191
The base class for all OPAL exceptions.
Definition: OpalException.h:28
Attribute makePredefinedString(const std::string &name, const std::string &help, const std::initializer_list< std::string > &predefinedStrings)
Make predefined string attribute.
Definition: Attributes.cpp:409
Definition: Inform.h:42
OpalFilter()
Exemplar constructor.
Definition: OpalFilter.cpp:55
virtual void update()
Update the OpalFilter data.
Definition: OpalFilter.cpp:135
const std::string & getOpalName() const
Return object name.
Definition: Object.cpp:310
std::vector< Attribute > itsAttr
The object attributes.
Definition: Object.h:216
void initOpalFilter()
Definition: OpalFilter.cpp:141
const std::string name
double getReal(const Attribute &attr)
Return real value.
Definition: Attributes.cpp:252
virtual bool canReplaceBy(Object *object)
Test if replacement is allowed.
Definition: OpalFilter.cpp:108
The base class for all OPAL definitions.
Definition: Definition.h:30
Object * find(const std::string &name)
Find entry.
Definition: OpalData.cpp:571
constexpr double e
The value of .
Definition: Physics.h:39
#define POLYORDER_DEFAULT
Definition: OpalFilter.cpp:37
SDDS1 &description type
Definition: test.stat:4
Inform * gmsg
Definition: Main.cpp:70