Loading [MathJax]/extensions/tex2jax.js
mxlib
c++ tools for analyzing astronomical data and other tasks by Jared R. Males. [git repo]
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Modules Pages
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
35namespace mx
36{
37namespace sigproc
38{
39namespace 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 */
52template <typename realT>
53void 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 */
93template <typename realT>
94void 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 */
108template <typename realT>
109void 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 */
130template <typename realT>
131void 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 */
153template <typename realT>
154void 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 */
178template <typename realT>
179void 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 */
196template <typename realT>
197void 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 */
210template <typename realT>
211void 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 */
228template <typename realT>
229void 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 */
241template <typename realT>
242void 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 */
258template <typename realT>
259void 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 */
271template <typename realT>
272void 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 */
286template <typename realT>
287void 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 */
299template <typename realT>
300void 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 */
316template <typename realT>
317void 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 */
329template <typename realT>
330void 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 */
346template <typename realT>
347void 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 */
362template <typename realT>
364 realT *filt, ///< [out] a pre-allocated array of size \p rows x \p cols (column major)
365 int rows, ///< [in] the number of rows in filt
366 int cols, ///< [in] the number of cols in filt
367 realT D, ///< [in] the diameter of the window
368 realT alpha, ///< [in] controls the window shape. 1.0 gives a Hann window, 0.0 gives a cylinder (a.k.a. no window)
369 realT xc, ///< [in] the desired x center of the window.
370 realT yc ///< [in] the desired y center of the window.
371)
372{
373
374 int ii, jj;
375
376 realT rad = 0.5 * ( D - 1.0 );
377
378 realT pi = math::pi<realT>();
379
380 for( int cc = 0; cc < cols; ++cc )
381 {
382 realT y = ( (realT)cc ) - yc;
383 for( int rr = 0; rr < rows; ++rr )
384 {
385 realT x = ( (realT)rr ) - xc;
386
387 realT r = sqrt( x * x + y * y );
388
389 // Following mxlib convention of including half pixels
390 if( r > rad + 0.5 )
391 {
392 filt[cc * rows + rr] = 0.0;
393 }
394 else if( rad + r > ( D - 1 ) * ( 1 - 0.5 * alpha ) && alpha > 0. )
395 {
396 // Have to prevent going greater than N-1 due to half pixel inclusion.
397 realT dr = rad + r;
398 if( dr > D - 1 )
399 dr = D - 1;
400
401 filt[cc * rows + rr] =
402 0.5 * ( 1.0 + cos( pi * ( 2. * ( dr ) / ( alpha * ( D - 1 ) ) - 2. / alpha + 1.0 ) ) );
403 }
404 else
405 {
406 filt[cc * rows + rr] = 1.0;
407 }
408 }
409 }
410}
411
412/** \brief Create a 2-D Tukey window
413 *
414 * Function to create a 2-D Tukey window.
415 *
416 * The shape of the window is controlled by alpha. alpha = 0 is a cylinder, alpha=1.0 is the Hann window.
417 *
418 * See https://en.wikipedia.org/wiki/Window_function
419 *
420 * \tparam arrT an Eigen-like array type
421 *
422 * \overload
423 *
424 * \ingroup signal_windows2D
425 */
426template <typename arrT>
427void tukey2d( arrT &filt, ///< [in.out] a pre-allocated array
428 typename arrT::Scalar D, ///< [in] the diameter of the window
429 typename arrT::Scalar alpha, ///< [in] controls the window shape. 1.0 gives a Hann window, 0.0 gives a
430 ///< cylinder (a.k.a. no window)
431 typename arrT::Scalar xc, ///< [in] the desired x center of the window.
432 typename arrT::Scalar yc ///< [in] the desired y center of the window.
433 )
434{
435 tukey2d( filt.data(), filt.rows(), filt.cols(), D, alpha, xc, yc );
436}
437
438/** \brief Create a 2-D Tukey window on an annulus
439 *
440 * Function to create a 2-D Tukey window on an annulus.
441 *
442 * The shape of the window is controlled by alpha. alpha = 0 is a cylinder, alpha=1.0 is the Hann window.
443 *
444 * See https://en.wikipedia.org/wiki/Window_function
445 *
446 * \tparam realT is a floating point type
447 *
448 * \ingroup signal_windows2D
449 */
450template <typename realT>
452 realT *filt, ///< [out] a pre-allocated array of size \p rows x \p cols (column major)
453 int rows, ///< [in] the number of rows in filt
454 int cols, ///< [in] the number of cols in filt
455 realT D, ///< [in] the outer diameter of the window
456 realT eps, ///< [in] the ratio of inner diameter to the outer diameter
457 realT alpha, ///< [in] controls the window shape. 1.0 gives a Hann window, 0.0 gives a cylinder (a.k.a. no window)
458 realT xc, ///< [in] the desired x center of the window.
459 realT yc ///< [in] the desired y center of the window.
460)
461{
462 realT rad = 0.5 * ( D - 1.0 );
463
464 int Z = ( 1 - eps ) * rad + 1.0; // floor((1.0-eps)*(rad)) + 1.0;
465
466 realT pi = math::pi<realT>();
467
468 for( int cc = 0; cc < cols; ++cc )
469 {
470 realT y = ( (realT)cc ) - yc;
471 for( int rr = 0; rr < rows; ++rr )
472 {
473 realT x = ( (realT)rr ) - xc;
474
475 realT r = sqrt( x * x + y * y );
476
477 realT z = ( r - eps * ( rad ) );
478
479 // Following mxlib convention of including half pixels
480 if( r > rad + 0.5 || r < eps * rad )
481 {
482 filt[cc * rows + rr] = 0.0;
483 }
484 else if( z <= 0.5 * alpha * ( Z - 1 ) && alpha > 0 )
485 {
486 filt[cc * rows + rr] = 0.5 * ( 1.0 + cos( pi * ( 2. * z / ( alpha * ( Z - 1 ) ) - 1.0 ) ) );
487 }
488 else if( z > ( Z - 1 ) * ( 1. - 0.5 * alpha ) && alpha > 0 )
489 {
490 z = z * ( ( Z - 0.5 ) / Z ); // Stretch a little to help with the half pixel
491 if( z > Z )
492 z = Z - 1;
493 filt[cc * rows + rr] =
494 0.5 * ( 1.0 + cos( pi * ( 2. * ( z ) / ( alpha * ( Z - 1 ) ) - 2. / alpha + 1.0 ) ) );
495 }
496 else
497 {
498 filt[cc * rows + rr] = 1.0;
499 }
500 }
501 }
502}
503
504/** \brief Create a 2-D Tukey window on an annulus
505 *
506 * Function to create a 2-D Tukey window on an annulus.
507 *
508 * The shape of the window is controlled by alpha. alpha = 0 is a cylinder, alpha=1.0 is the Hann window.
509 *
510 * See https://en.wikipedia.org/wiki/Window_function
511 *
512 * \overload
513 *
514 * \tparam realT is a floating point type
515 *
516 * \ingroup signal_windows2D
517 */
518template <typename arrT>
519void tukey2dAnnulus( arrT &filt, ///< [in,out] a pre-allocated array
520 typename arrT::Scalar D, ///< [in] the outer diameter of the window
521 typename arrT::Scalar eps, ///< [in] the ratio of inner diameter to the outer diameter
522 typename arrT::Scalar alpha, ///< [in] controls the window shape. 1.0 gives a Hann window, 0.0
523 ///< gives a cylinder (a.k.a. no window)
524 typename arrT::Scalar xc, ///< [in] the desired x center of the window.
525 typename arrT::Scalar yc ///< [in] the desired y center of the window.
526)
527{
528 return tukey2dAnnulus( filt, filt.rows(), filt.cols(), D, eps, alpha, xc, yc );
529}
530
531/** \brief Create a 2-D Tukey window on a rectangle
532 *
533 * Function to create a 2-D Tukey window on a rectangle.
534 *
535 * The shape of the window is controlled by alpha. alpha = 0 is a rectangle window, alpha=1.0 is the Hann window.
536 *
537 * See https://en.wikipedia.org/wiki/Window_function
538 *
539 * \ingroup signal_windows2D
540 */
541template <typename realT>
543 realT *filt, ///< [out] a pre-allocated array of size \p rows x \p cols (column major)
544 int rows, ///< [in] the number of rows in filt
545 int cols, ///< [in] the number of cols in filt
546 realT W, ///< [in] the width of the window, corresponds to rows
547 realT H, ///< [in] the height of the window, corresponds to cols
548 realT alpha, ///< [in] controls the window shape. 1.0 gives a Hann window, 0.0 gives a cylinder (a.k.a. no window)
549 realT xc, ///< [in] the desired x center of the window.
550 realT yc ///< [in] the desired y center of the window.
551)
552{
553
554 int ii, jj;
555
556 realT W2 = 0.5 * ( W - 1.0 );
557 realT H2 = 0.5 * ( H - 1.0 );
558
559 realT pi = math::pi<realT>();
560
561 for( int cc = 0; cc < cols; ++cc )
562 {
563 realT y = fabs( ( (realT)cc ) - yc );
564
565 if( y > H2 + 0.5 )
566 {
567 for( int rr = 0; rr < rows; ++rr )
568 {
569 filt[cc * rows + rr] = 0;
570 }
571 continue;
572 }
573
574 for( int rr = 0; rr < rows; ++rr )
575 {
576 realT x = fabs( ( (realT)rr ) - xc );
577
578 if( x > W2 + 0.5 )
579 {
580 filt[cc * rows + rr] = 0;
581 continue;
582 }
583 else if( ( W2 + x > ( W - 1 ) * ( 1 - 0.5 * alpha ) ) && ( H2 + x > ( H - 1 ) * ( 1 - 0.5 * alpha ) ) &&
584 alpha > 0. )
585 {
586 // Have to prevent going greater than N-1 due to half pixel inclusion.
587 realT dx = W2 + x;
588 if( dx > W - 1 )
589 dx = W - 1;
590
591 realT dy = H2 + y;
592 if( dy > H - 1 )
593 dy = H - 1;
594
595 filt[cc * rows + rr] =
596 0.5 * ( 1.0 + cos( pi * ( 2. * ( dx ) / ( alpha * ( W - 1 ) ) - 2. / alpha + 1.0 ) ) );
597 filt[cc * rows + rr] *=
598 0.5 * ( 1.0 + cos( pi * ( 2. * ( dy ) / ( alpha * ( H - 1 ) ) - 2. / alpha + 1.0 ) ) );
599 }
600 else
601 {
602 filt[cc * rows + rr] = 1.0;
603 }
604 }
605 }
606}
607
608} // namespace window
609} // namespace sigproc
610} // namespace mx
611
612#endif // signalWindows_hpp
constexpr floatT six_fifths()
Return 6/5 in the specified precision.
void nuttal(realT *filt, size_t N)
The Nuttal Window.
void genCosine(realT *filt, size_t N, realT a0, realT a1)
The generalized 2 parameter cosine Window.
void tukey(realT *filt, int N, realT alpha)
The Tukey Window.
void blackmanNuttal(realT *filt, size_t N)
The Blackman-Nuttal Windwo.
void blackman(realT *filt, size_t N)
The Blackman Window.
void exactBlackman(realT *filt, size_t N)
The Exact Blackman Window.
void hamming(realT *filt, int N)
The Hamming Window.
void hann(realT *filt, int N)
The Hann Window.
void tukey2d(realT *filt, int rows, int cols, realT D, realT alpha, realT xc, realT yc)
Create a 2-D Tukey window.
void tukey2dAnnulus(realT *filt, int rows, int cols, realT D, realT eps, realT alpha, realT xc, realT yc)
Create a 2-D Tukey window on an annulus.
void tukey2dSquare(realT *filt, int rows, int cols, realT W, realT H, realT alpha, realT xc, realT yc)
Create a 2-D Tukey window on a rectangle.
The mxlib c++ namespace.
Definition mxError.hpp:106