mxlib
c++ tools for analyzing astronomical data and other tasks by Jared R. Males. [git repo]
signalWindows.hpp
Go to the documentation of this file.
1 /** \file signalWindows.hpp
2  * \brief Procedures to calculate window functions for signal processing
3  *
4  * \author Jared R. Males (jaredmales@gmail.com)
5  *
6  * \ingroup signal_processing_files
7  *
8  */
9 
10 //***********************************************************************//
11 // Copyright 2015 - 2020 Jared R. Males (jaredmales@gmail.com)
12 //
13 // This file is part of mxlib.
14 //
15 // mxlib is free software: you can redistribute it and/or modify
16 // it under the terms of the GNU General Public License as published by
17 // the Free Software Foundation, either version 3 of the License, or
18 // (at your option) any later version.
19 //
20 // mxlib is distributed in the hope that it will be useful,
21 // but WITHOUT ANY WARRANTY; without even the implied warranty of
22 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 // GNU General Public License for more details.
24 //
25 // You should have received a copy of the GNU General Public License
26 // along with mxlib. If not, see <http://www.gnu.org/licenses/>.
27 //***********************************************************************//
28 
29 #ifndef signalWindows_hpp
30 #define signalWindows_hpp
31 
32 #include <cmath>
33 #include "../math/constants.hpp"
34 
35 namespace mx
36 {
37 namespace sigproc
38 {
39 namespace window
40 {
41 
42 /// The Tukey Window
43 /**
44  * The width of the window is controlled by alpha. alpha = 0 is a square wave, alpha=1.0 is the Hann window.
45  *
46  * See https://en.wikipedia.org/wiki/Window_function
47  *
48  * \tparam realT a floating point type
49  *
50  * \ingroup signal_windows1D
51  */
52 template<typename realT>
53 void tukey( realT *filt, ///< [out] the pre-allocated array to hold the filter
54  int N, ///< [in] the size of the filter
55  realT alpha ///< [in] the width parameter
56  )
57 {
58  constexpr realT pi = math::pi<realT>();
59 
60  realT lim1 = alpha*(N-1.0)/2.0;
61  realT lim2 = (N-1.0)*(1.0-0.5*alpha);
62 
63  for(int ii=0; ii<N; ++ii)
64  {
65 
66  if(ii < lim1 && alpha > 0.)
67  {
68  filt[ii] = 0.5*(1.0 + cos(pi * ( 2.*(ii)/(alpha*(N-1)) - 1.0) ));
69  }
70  else if(ii > lim2 && alpha > 0.)
71  {
72  filt[ii] = 0.5*(1.0 + cos(pi * ( 2.*(ii)/(alpha*(N-1)) - 2./alpha + 1.0) ));
73  }
74  else
75  {
76  filt[ii] = 1.0;
77  }
78  }
79 }
80 
81 /// The Tukey Window
82 /**
83  * The width of the window is controlled by alpha. alpha = 0 is a square wave, alpha=1.0 is the Hann window.
84  *
85  * See https://en.wikipedia.org/wiki/Window_function
86  *
87  * \overload
88  *
89  * \tparam realT a floating point type
90  *
91  * \ingroup signal_windows1D
92  */
93 template<typename realT>
94 void tukey( std::vector<realT> & filt, ///< [out] the pre-allocated vector to hold the filter
95  realT alpha ///< [in] the width parameter
96  )
97 {
98  tukey(filt.data(), filt.size(), alpha);
99 }
100 
101 /// The generalized 2 parameter cosine Window
102 /** See https://en.wikipedia.org/wiki/Window_function
103  *
104  * \tparam realT a real floating point type
105  *
106  * \ingroup signal_windows1D
107  */
108 template<typename realT>
109 void genCosine( realT * filt, ///< [out] The pre-allocated vector which will store the filter
110  size_t N, ///< [in] the size of the filter vector
111  realT a0, ///< [in] parameter of the generalized cosine window
112  realT a1 ///< [in] parameter of the generalized cosine window
113  )
114 {
115  constexpr realT pi = math::pi<realT>();
116 
117  for( size_t n=0; n<N; ++n)
118  {
119  filt[n] = a0 - a1*cos(2*pi*n/N);
120  }
121 }
122 
123 /// The generalized 3 parameter cosine Window
124 /** See https://en.wikipedia.org/wiki/Window_function
125  *
126  * \tparam realT a real floating point type
127  *
128  * \ingroup signal_windows1D
129  */
130 template<typename realT>
131 void genCosine( realT * filt, ///< [out] The pre-allocated vector which will store the filter
132  size_t N, ///< [in] the size of the filter vector
133  realT a0, ///< [in] parameter of the generalized cosine window
134  realT a1, ///< [in] parameter of the generalized cosine window
135  realT a2 ///< [in] parameter of the generalized cosine window
136  )
137 {
138  constexpr realT pi = math::pi<realT>();
139 
140  for( size_t n=0; n<N; ++n)
141  {
142  filt[n] = a0 - a1*cos(2*pi*n/N) + a2*cos(4*pi*n/N);
143  }
144 }
145 
146 /// The generalized 4 parameter cosine Window
147 /** See https://en.wikipedia.org/wiki/Window_function
148  *
149  * \tparam realT a real floating point type
150  *
151  * \ingroup signal_windows1D
152  */
153 template<typename realT>
154 void genCosine( realT * filt, ///< [out] The pre-allocated vector which will store the filter
155  size_t N, ///< [in] the size of the filter vector
156  realT a0, ///< [in] parameter of the generalized cosine window
157  realT a1, ///< [in] parameter of the generalized cosine window
158  realT a2, ///< [in] parameter of the generalized cosine window
159  realT a3 ///< [in] parameter of the generalized cosine window
160  )
161 {
162  constexpr realT pi = math::pi<realT>();
163 
164  for( size_t n=0; n<N; ++n)
165  {
166  filt[n] = a0 - a1*cos(2*pi*n/N) + a2*cos(4*pi*n/N) - a3*cos(6*pi*n/N);
167  }
168 }
169 
170 /// The Hann Window
171 /**
172  * See https://en.wikipedia.org/wiki/Window_function
173  *
174  * \tparam realT a floating point type
175  *
176  * \ingroup signal_windows1D
177  */
178 template<typename realT>
179 void hann( realT *filt, ///< [out] the pre-allocated array to hold the filter
180  int N ///< [in] the size of the filter
181  )
182 {
183  genCosine<realT>(filt, N, 0.5, 0.5);
184 }
185 
186 /// The Hann Window
187 /**
188  * See https://en.wikipedia.org/wiki/Window_function
189  *
190  * \overload
191  *
192  * \tparam realT a floating point type
193  *
194  * \ingroup signal_windows1D
195  */
196 template<typename realT>
197 void hann( std::vector<realT> & filt /**< [out] the pre-allocated vector to hold the filter */)
198 {
199  hann(filt.data(), filt.size());
200 }
201 
202 /// The Hamming Window
203 /**
204  * See https://en.wikipedia.org/wiki/Window_function
205  *
206  * \tparam realT a floating point type
207  *
208  * \ingroup signal_windows1D
209  */
210 template<typename realT>
211 void hamming( realT *filt, ///< [out] the pre-allocated array to hold the filter
212  int N ///< [in] the size of the filter
213  )
214 {
215  genCosine<realT>(filt, N, 25.0/46.0, 1.0-25.0/46.0);
216 }
217 
218 /// The Hamming Window
219 /**
220  * See https://en.wikipedia.org/wiki/Window_function
221  *
222  * \overload
223  *
224  * \tparam realT a floating point type
225  *
226  * \ingroup signal_windows1D
227  */
228 template<typename realT>
229 void hamming( std::vector<realT> & filt /**< [out] the pre-allocated vector to hold the filter */)
230 {
231  hamming(filt.data(), filt.size());
232 }
233 
234 /// The Blackman Window
235 /** See https://en.wikipedia.org/wiki/Window_function
236  *
237  * \tparam realT a real floating point type
238  *
239  * \ingroup signal_windows1D
240  */
241 template<typename realT>
242 void blackman( realT * filt, ///< [out] The pre-allocated vector which will store the filter
243  size_t N ///< [in] the size of the filter vector
244  )
245 {
246  genCosine<realT>(filt, N, 0.42, 0.5, 0.08);
247 }
248 
249 /// The Blackman Window
250 /** See https://en.wikipedia.org/wiki/Window_function
251  *
252  * \overload
253  *
254  * \tparam realT a real floating point type
255  *
256  * \ingroup signal_windows1D
257  */
258 template<typename realT>
259 void blackman( std::vector<realT> & filt /**< [out] The pre-allocated vector which will store the filter */)
260 {
261  blackman(filt.data(), filt.size());
262 }
263 
264 /// The Exact Blackman Window
265 /** See https://en.wikipedia.org/wiki/Window_function
266  *
267  * \tparam realT a real floating point type
268  *
269  * \ingroup signal_windows1D
270  */
271 template<typename realT>
272 void exactBlackman( realT * filt, ///< [out] The pre-allocated vector which will store the filter
273  size_t N ///< [in] the size of the filter vector
274  )
275 {
276  genCosine<realT>(filt, N, 0.42659, 0.49656, 0.076849);
277 }
278 
279 /// The Exact Blackman Windwo
280 /** See https://en.wikipedia.org/wiki/Window_function
281  *
282  * \overload
283  *
284  * \tparam realT a real floating point type
285  */
286 template<typename realT>
287 void exactBlackman( std::vector<realT> & filt /**< [out] The pre-allocated vector which will store the filter */)
288 {
289  exactBlackman(filt.data(), filt.size());
290 }
291 
292 /// The Nuttal Window
293 /** See https://en.wikipedia.org/wiki/Window_function
294  *
295  * \tparam realT a real floating point type
296  *
297  * \ingroup signal_windows1D
298  */
299 template<typename realT>
300 void nuttal( realT * filt, ///< [out] The pre-allocated vector which will store the filter
301  size_t N ///< [in] the size of the filter vector
302  )
303 {
304  genCosine<realT>(filt, N, 0.355768, 0.487396, 0.144232, 0.012604);
305 }
306 
307 /// The Nuttal Window
308 /** See https://en.wikipedia.org/wiki/Window_function
309  *
310  * \overload
311  *
312  * \tparam realT a real floating point type
313  *
314  * \ingroup signal_windows1D
315  */
316 template<typename realT>
317 void nuttal( std::vector<realT> & filt /**< [out] The pre-allocated vector which will store the filter */)
318 {
319  nuttal(filt.data(), filt.size());
320 }
321 
322 /// The Blackman-Nuttal Windwo
323 /** See https://en.wikipedia.org/wiki/Window_function
324  *
325  * \tparam realT a real floating point type
326  *
327  * \ingroup signal_windows1D
328  */
329 template<typename realT>
330 void blackmanNuttal( realT * filt, ///< [out] The pre-allocated vector which will store the filter
331  size_t N ///< [in] the size of the filter vector
332  )
333 {
334  genCosine<realT>(filt, N, 0.3635819, 0.4891775, 0.1365995, 0.0106411 );
335 }
336 
337 /// The Blackman-Nuttal Windwo
338 /** See https://en.wikipedia.org/wiki/Window_function
339  *
340  * \overload
341  *
342  * \tparam realT a real floating point type
343  *
344  * \ingroup signal_windows1D
345  */
346 template<typename realT>
347 void blackmanNuttal( std::vector<realT> & filt /**< [out] The pre-allocated vector which will store the filter */)
348 {
349  blackmanNuttal(filt.data(), filt.size());
350 }
351 
352 /** \brief Create a 2-D Tukey window
353  *
354  * Function to create a 2-D Tukey window.
355  *
356  * The shape of the window is controlled by alpha. alpha = 0 is a cylinder, alpha=1.0 is the Hann window.
357  *
358  * See https://en.wikipedia.org/wiki/Window_function
359  *
360  * \ingroup signal_windows2D
361  */
362 template<typename realT>
363 void tukey2d( realT *filt, ///< [out] a pre-allocated array of size \p rows x \p cols (column major)
364  int rows, ///< [in] the number of rows in filt
365  int cols, ///< [in] the number of cols in filt
366  realT D, ///< [in] the diameter of the window
367  realT alpha, ///< [in] controls the window shape. 1.0 gives a Hann window, 0.0 gives a cylinder (a.k.a. no window)
368  realT xc, ///< [in] the desired x center of the window.
369  realT yc ///< [in] the desired y center of the window.
370  )
371 {
372 
373  int ii, jj;
374 
375  realT rad = 0.5*(D-1.0);
376 
377  realT pi = math::pi<realT>();
378 
379  for(int cc=0; cc<cols; ++cc)
380  {
381  realT y = ( (realT) cc) - yc;
382  for(int rr=0; rr<rows; ++rr)
383  {
384  realT x = ( (realT) rr) - xc;
385 
386  realT r = sqrt(x*x + y*y);
387 
388  //Following mxlib convention of including half pixels
389  if(r > rad + 0.5)
390  {
391  filt[cc*rows + rr] = 0.0;
392  }
393  else if(rad + r > (D-1)*(1-0.5*alpha) && alpha > 0.)
394  {
395  //Have to prevent going greater than N-1 due to half pixel inclusion.
396  realT dr = rad+r;
397  if(dr > D-1) dr = D-1;
398 
399  filt[cc*rows + rr] = 0.5*(1.0 + cos(pi * ( 2.*(dr)/(alpha*(D-1)) - 2./alpha + 1.0) ));
400  }
401  else
402  {
403  filt[cc*rows + rr] = 1.0;
404  }
405  }
406  }
407 }
408 
409 /** \brief Create a 2-D Tukey window
410  *
411  * Function to create a 2-D Tukey window.
412  *
413  * The shape of the window is controlled by alpha. alpha = 0 is a cylinder, alpha=1.0 is the Hann window.
414  *
415  * See https://en.wikipedia.org/wiki/Window_function
416  *
417  * \tparam arrT an Eigen-like array type
418  *
419  * \overload
420  *
421  * \ingroup signal_windows2D
422  */
423 template<typename arrT>
424 void tukey2d( arrT & filt, ///< [in.out] a pre-allocated array
425  typename arrT::Scalar D, ///< [in] the diameter of the window
426  typename arrT::Scalar alpha, ///< [in] controls the window shape. 1.0 gives a Hann window, 0.0 gives a cylinder (a.k.a. no window)
427  typename arrT::Scalar xc, ///< [in] the desired x center of the window.
428  typename arrT::Scalar yc ///< [in] the desired y center of the window.
429  )
430 {
431  tukey2d(filt.data(), filt.rows(), filt.cols(), D, alpha, xc, yc);
432 }
433 
434 /** \brief Create a 2-D Tukey window on an annulus
435  *
436  * Function to create a 2-D Tukey window on an annulus.
437  *
438  * The shape of the window is controlled by alpha. alpha = 0 is a cylinder, alpha=1.0 is the Hann window.
439  *
440  * See https://en.wikipedia.org/wiki/Window_function
441  *
442  * \tparam realT is a floating point type
443  *
444  * \ingroup signal_windows2D
445  */
446 template<typename realT>
447 void tukey2dAnnulus( realT *filt, ///< [out] a pre-allocated array of size \p rows x \p cols (column major)
448  int rows, ///< [in] the number of rows in filt
449  int cols, ///< [in] the number of cols in filt
450  realT D, ///< [in] the outer diameter of the window
451  realT eps, ///< [in] the ratio of inner diameter to the outer diameter
452  realT alpha, ///< [in] controls the window shape. 1.0 gives a Hann window, 0.0 gives a cylinder (a.k.a. no window)
453  realT xc, ///< [in] the desired x center of the window.
454  realT yc ///< [in] the desired y center of the window.
455  )
456 {
457  realT rad = 0.5*(D-1.0);
458 
459  int Z = (1-eps)*rad+1.0; //floor((1.0-eps)*(rad)) + 1.0;
460 
461  realT pi = math::pi<realT>();
462 
463  for(int cc=0; cc<cols; ++cc)
464  {
465  realT y = ( (realT) cc) - yc;
466  for(int rr=0; rr<rows; ++rr)
467  {
468  realT x = ( (realT) rr) - xc;
469 
470  realT r = sqrt(x*x + y*y);
471 
472  realT z = (r - eps*(rad));
473 
474  //Following mxlib convention of including half pixels
475  if(r > rad + 0.5 || r < eps*rad)
476  {
477  filt[cc*rows + rr] = 0.0;
478  }
479  else if(z <= 0.5*alpha*(Z-1) && alpha > 0)
480  {
481  filt[cc*rows + rr] = 0.5*(1.0 + cos(pi*(2.*z/(alpha*(Z-1)) -1.0) ));
482  }
483  else if(z > (Z-1)*(1.-0.5*alpha) && alpha > 0)
484  {
485  z = z*((Z-0.5)/Z); //Stretch a little to help with the half pixel
486  if(z > Z) z = Z-1;
487  filt[cc*rows + rr] = 0.5*(1.0 + cos(pi* ( 2.*(z)/(alpha*(Z-1)) - 2./alpha + 1.0) ));
488  }
489  else
490  {
491  filt[cc*rows + rr] = 1.0;
492  }
493  }
494  }
495 }
496 
497 /** \brief Create a 2-D Tukey window on an annulus
498  *
499  * Function to create a 2-D Tukey window on an annulus.
500  *
501  * The shape of the window is controlled by alpha. alpha = 0 is a cylinder, alpha=1.0 is the Hann window.
502  *
503  * See https://en.wikipedia.org/wiki/Window_function
504  *
505  * \overload
506  *
507  * \tparam realT is a floating point type
508  *
509  * \ingroup signal_windows2D
510  */
511 template<typename arrT>
512 void tukey2dAnnulus( arrT & filt, ///< [in,out] a pre-allocated array
513  typename arrT::Scalar D, ///< [in] the outer diameter of the window
514  typename arrT::Scalar eps, ///< [in] the ratio of inner diameter to the outer diameter
515  typename arrT::Scalar alpha, ///< [in] controls the window shape. 1.0 gives a Hann window, 0.0 gives a cylinder (a.k.a. no window)
516  typename arrT::Scalar xc, ///< [in] the desired x center of the window.
517  typename arrT::Scalar yc ///< [in] the desired y center of the window.
518  )
519 {
520  return tukey2dAnnulus(filt, filt.rows(), filt.cols(), D, eps, alpha, xc, yc);
521 }
522 
523 } //namespace window
524 } //namespace sigproc
525 } //namespace mx
526 
527 #endif // signalWindows_hpp
528 
constexpr T pi()
Get the value of pi.
Definition: constants.hpp:52
void hann(std::vector< realT > &filt)
The Hann Window.
void genCosine(realT *filt, size_t N, realT a0, realT a1, realT a2, realT a3)
The generalized 4 parameter cosine Window.
void blackman(std::vector< realT > &filt)
The Blackman Window.
void tukey(std::vector< realT > &filt, realT alpha)
The Tukey Window.
void hamming(std::vector< realT > &filt)
The Hamming Window.
void exactBlackman(realT *filt, size_t N)
The Exact Blackman Window.
void blackmanNuttal(std::vector< realT > &filt)
The Blackman-Nuttal Windwo.
void nuttal(std::vector< realT > &filt)
The Nuttal Window.
void tukey2d(arrT &filt, typename arrT::Scalar D, typename arrT::Scalar alpha, typename arrT::Scalar xc, typename arrT::Scalar yc)
Create a 2-D Tukey window.
void tukey2dAnnulus(arrT &filt, typename arrT::Scalar D, typename arrT::Scalar eps, typename arrT::Scalar alpha, typename arrT::Scalar xc, typename arrT::Scalar yc)
Create a 2-D Tukey window on an annulus.
The mxlib c++ namespace.
Definition: mxError.hpp:107