OPALX (Object Oriented Parallel Accelerator Library for Exascal) MINIorX
OPALX
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//
21
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
39extern Inform* gmsg;
40
41// The attributes of class OpalFilter.
42namespace {
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(
57 SIZE, "FILTER",
58 "The \"FILTER\" statement defines a 1 dimensional filter to be "
59 "applied on histogram."),
60 filter_m(0) {
62 "TYPE", "Specifies the type of filter.",
63 {"SAVITZKY-GOLAY", "FIXEDFFTLOWPASS", "RELATIVEFFTLOWPASS", "STENCIL"});
64
65 itsAttr[NFREQ] =
66 Attributes::makeReal("NFREQ", "Number of frequencies to use in fixedFFTLowPass filter", 9.);
67
68 itsAttr[THRESHOLD] = Attributes::makeReal(
69 "THRESHOLD", "Relative threshold for amplitude of frequencies in relativeFFTLowPass filter",
70 1.e-6);
71
73 "NPOINTS", "Number of points in Savitzky-Golay filter", NPOINTS_DEFAULT);
74
76 "NLEFT", "Number of points to the left in Savitzky-Golay filter", NLEFT_DEFAULT);
77
79 "NRIGHT", "Number of points to the right in Savitzky-Golay filter", NRIGHT_DEFAULT);
80
81 itsAttr[POLYORDER] = Attributes::makeReal(
82 "POLYORDER", "Polynomial order for local fit-function in Savitzky-Golay filter",
84
86
87 OpalFilter* defFilter = clone("UNNAMED_FILTER");
88 defFilter->builtin = true;
89
90 try {
91 defFilter->update();
92 OpalData::getInstance()->define(defFilter);
93 } catch (...) {
94 delete defFilter;
95 }
96}
97
98OpalFilter::OpalFilter(const std::string& name, OpalFilter* parent)
99 : Definition(name, parent), filter_m(0) {
100}
101
103 if (filter_m)
104 delete filter_m;
105}
106
108 // Can replace only by another WAKE.
109 return dynamic_cast<OpalFilter*>(object) != 0;
110}
111
112OpalFilter* OpalFilter::clone(const std::string& name) {
113 return new OpalFilter(name, this);
114}
115
117 update();
118}
119
120OpalFilter* OpalFilter::find(const std::string& name) {
121 OpalFilter* filter = dynamic_cast<OpalFilter*>(OpalData::getInstance()->find(name));
122
123 if (filter == 0) {
124 throw OpalException("OpalFilter::find()", "OpalFilter \"" + name + "\" not found.");
125 }
126 return filter;
127}
128
130 // Set default name.
131 if (getOpalName().empty())
132 setOpalName("UNNAMED_FILTER");
133}
134
136 if (filter_m == 0) {
137 *gmsg << "* ************* F I L T E R "
138 "************************************************************"
139 << endl;
140 *gmsg << "OpalFilter::initOpalFilterfunction " << endl;
141 *gmsg
142 << "* "
143 "**********************************************************************************"
144 << endl;
145
146 static const std::unordered_map<std::string, FilterType> stringFilterType_s = {
147 {"SAVITZKY-GOLAY", FilterType::SAVITZKYGOLAY},
148 {"FIXEDFFTLOWPASS", FilterType::FIXEDFFTLOWPASS},
149 {"RELATIVEFFTLOWPASS", FilterType::RELATIVEFFTLOWPASS},
150 {"STENCIL", FilterType::STENCIL}};
151
152 FilterType type = stringFilterType_s.at(Attributes::getString(itsAttr[TYPE]));
153 switch (type) {
155 int num_points = (int)(Attributes::getReal(itsAttr[NPOINTS]));
156 int num_points_left = (int)(Attributes::getReal(itsAttr[NLEFT]));
157 int num_points_right = (int)(Attributes::getReal(itsAttr[NRIGHT]));
158 int polynomial_order = std::abs((int)(Attributes::getReal(itsAttr[POLYORDER])));
159
160 Inform svg("Savitzky-Golay: ");
161 if (num_points_left < 0) {
162 svg << "Number of points to the left negative; using default (" << NLEFT_DEFAULT
163 << ");" << endl;
164 num_points_left = NLEFT_DEFAULT;
165 }
166 if (num_points_right < 0) {
167 svg << "Number of points to the right negative; using default ("
168 << 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 "
173 "the right plus 1; using default (NLEFT + NRIGHT + 1);"
174 << endl;
175 num_points = num_points_left + num_points_right + 1;
176 }
177 if (polynomial_order > num_points_left + num_points_right) {
178 svg << "Polynomial order bigger than sum of points to the left and to the "
179 "right; using default (NLEFT + NRIGHT);"
180 << endl;
181 polynomial_order = num_points_left + num_points_right;
182 }
183
185 num_points, num_points_left, num_points_right, polynomial_order);
186 break;
187 }
189 filter_m =
190 new FixedFFTLowPassFilter(std::abs((int)(Attributes::getReal(itsAttr[NFREQ]))));
191 break;
192 }
194 filter_m =
195 new RelativeFFTLowPassFilter(std::abs(Attributes::getReal(itsAttr[THRESHOLD])));
196 break;
197 }
198 case FilterType::STENCIL: {
199 filter_m = new StencilFilter();
200 break;
201 }
202 default: {
203 filter_m = 0;
204 *ippl::Info << "No filter attached" << endl;
205 break;
206 }
207 }
208 }
209}
210
211void OpalFilter::print(std::ostream& os) const {
212 os << "* ************* F I L T E R ********************************************************\n"
213 << "* FILTER " << getOpalName() << '\n'
214 << "* TYPE " << Attributes::getString(itsAttr[TYPE]) << '\n'
215 << "* NFREQ " << Attributes::getReal(itsAttr[NFREQ]) << '\n'
216 << "* THRESHOLD " << Attributes::getReal(itsAttr[THRESHOLD]) << '\n'
217 << "* NPOINTS " << Attributes::getReal(itsAttr[NPOINTS]) << '\n'
218 << "* NLEFT " << Attributes::getReal(itsAttr[NLEFT]) << '\n'
219 << "* NRIGHT " << Attributes::getReal(itsAttr[NRIGHT]) << '\n'
220 << "* POLYORDER " << Attributes::getReal(itsAttr[POLYORDER]) << '\n'
221 << "* ********************************************************************************** "
222 << std::endl;
223}
Inform * gmsg
Definition changes.cpp:7
@ SIZE
Definition IndexMap.cpp:173
#define NPOINTS_DEFAULT
#define NRIGHT_DEFAULT
#define NLEFT_DEFAULT
#define POLYORDER_DEFAULT
double getReal(const Attribute &attr)
Return real value.
Attribute makePredefinedString(const std::string &name, const std::string &help, const std::initializer_list< std::string > &predefinedStrings)
Make predefined string attribute.
Attribute makeReal(const std::string &name, const std::string &help)
Make real attribute.
std::string getString(const Attribute &attr)
Get string value.
Definition(int size, const char *name, const char *help)
Constructor for exemplars.
void registerOwnership(const AttributeHandler::OwnerType &itsClass) const
Definition Object.cpp:189
const std::string & getOpalName() const
Return object name.
Definition Object.cpp:308
Object(int size, const char *name, const char *help)
Constructor for exemplars.
Definition Object.cpp:354
void setOpalName(const std::string &name)
Set object name.
Definition Object.cpp:329
std::vector< Attribute > itsAttr
The object attributes.
Definition Object.h:216
bool builtin
Built-in flag.
Definition Object.h:233
Object * find(const std::string &name)
Find entry.
Definition OpalData.cpp:563
static OpalData * getInstance()
Definition OpalData.cpp:195
void define(Object *newObject)
Define a new object.
Definition OpalData.cpp:486
The base class for all OPAL exceptions.
void initOpalFilter()
virtual void execute()
Check the OpalFilter data.
virtual ~OpalFilter()
static OpalFilter * find(const std::string &name)
Find named FILTER.
Filter * filter_m
Definition OpalFilter.h:61
virtual bool canReplaceBy(Object *object)
Test if replacement is allowed.
virtual OpalFilter * clone(const std::string &name)
Make clone.
virtual void update()
Update the OpalFilter data.
OpalFilter()
Exemplar constructor.
void print(std::ostream &os) const
Print the object.