mxlib
c++ tools for analyzing astronomical data and other tasks by Jared R. Males. [git repo]
psdFilter.hpp
Go to the documentation of this file.
1 /** \file psdFilter.hpp
2  * \brief Declares and defines a class for filtering with PSDs
3  * \ingroup signal_processing_files
4  * \author Jared R. Males (jaredmales@gmail.com)
5  *
6  */
7 
8 //***********************************************************************//
9 // Copyright 2015, 2016, 2017, 2018, 2019, 2020 Jared R. Males (jaredmales@gmail.com)
10 //
11 // This file is part of mxlib.
12 //
13 // mxlib is free software: you can redistribute it and/or modify
14 // it under the terms of the GNU General Public License as published by
15 // the Free Software Foundation, either version 3 of the License, or
16 // (at your option) any later version.
17 //
18 // mxlib is distributed in the hope that it will be useful,
19 // but WITHOUT ANY WARRANTY; without even the implied warranty of
20 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 // GNU General Public License for more details.
22 //
23 // You should have received a copy of the GNU General Public License
24 // along with mxlib. If not, see <http://www.gnu.org/licenses/>.
25 //***********************************************************************//
26 
27 #ifndef psdFilter_hpp
28 #define psdFilter_hpp
29 
30 #include <vector>
31 #include <complex>
32 #include <Eigen/Dense>
33 
34 #include "../mxError.hpp"
35 #include "../math/fft/fft.hpp"
36 #include "../improc/eigenCube.hpp"
37 
38 namespace mx
39 {
40 namespace sigproc
41 {
42 
43 
44 namespace psdFilterTypes
45 {
46 
47 ///Types for different ranks in psdFilter
48 template<typename realT, size_t rank>
49 struct arrayT;
50 
51 template<typename realT>
52 struct arrayT<realT, 1>
53 {
54  typedef std::vector<realT> realArrayT;
55  typedef std::vector<realT>* realArrayMapT;
56  typedef std::vector<std::complex<realT>> complexArrayT;
57 
58  static void clear( realArrayT & arr)
59  {
60  arr.clear();
61  }
62 
63  static void clear( complexArrayT & arr)
64  {
65  arr.clear();
66  }
67 
68 };
69 
70 template<typename realT>
71 struct arrayT<realT, 2>
72 {
73  typedef Eigen::Array<realT, Eigen::Dynamic, Eigen::Dynamic> realArrayT;
74  typedef Eigen::Map<Eigen::Array<realT, Eigen::Dynamic, Eigen::Dynamic>> realArrayMapT;
75 
76  typedef Eigen::Array<std::complex<realT>,Eigen::Dynamic, Eigen::Dynamic> complexArrayT;
77 
78  static void clear( realArrayT & arr)
79  {
80  arr.resize(0,0);
81  }
82 
83  static void clear( complexArrayT & arr)
84  {
85  arr.resize(0,0);
86  }
87 };
88 
89 template<typename realT>
90 struct arrayT<realT, 3>
91 {
92  typedef improc::eigenCube<realT> realArrayT;
93  typedef improc::eigenCube<realT>* realArrayMapT;
94  typedef improc::eigenCube<std::complex<realT>> complexArrayT;
95 
96  static void clear( realArrayT & arr)
97  {
98  arr.resize(0,0,0);
99  }
100 
101  static void clear( complexArrayT & arr)
102  {
103  arr.resize(0,0,0);
104  }
105 };
106 
107 }
108 
109 //Forward declaration
110 template<typename _realT, size_t rank, int cuda = 0>
111 class psdFilter;
112 
113 /** \defgroup psd_filter PSD Filter
114  * \brief Filtering with a PSD to generate correlated noise.
115  *
116  * \ingroup psds
117  */
118 
119 /// A class for filtering noise with PSDs
120 /** The square-root of the PSD is maintained by this class, either as a pointer to an external array or using internally allocated memory (which will be
121  * de-allocated on destruction).
122  *
123  * PSD Requirements:
124  * - the PSD must be in FFT storage order form. That means including negative frequencies reversed from the end of the array.
125  * - the PSD used for this needs to be normalized properly, \ref psds "according to the mxlib standard", to produce filtered noise with the correct statistics.
126  *
127  *
128  * Array type varies based on rank.
129  * - For rank==1, the array type is std::vector<realT>
130  * - for rank==2, the array type is Eigen::Array<realT, -1, -1>
131  * - for rank==3, the array type is mx::improc::eigenCube<realT>
132  * and likewise for the complex types.
133  *
134  * \tparam _realT real floating type
135  * \tparam _rank the rank, or dimension, of the PSD
136  *
137  * \ingroup psd_filter
138  *
139  * \todo once fftT has a plan interface with pointers for working memory, use it.
140  *
141  * \test Scenario: compiling psdFilter. \ref tests_sigproc_psdFilter_compile "[test doc]"
142  */
143 template<typename _realT, size_t _rank>
144 class psdFilter<_realT, _rank, 0>
145 {
146 public:
147 
148  typedef _realT realT; ///< Real floating point type
149  typedef std::complex<_realT> complexT; ///< Complex floating point type.
150 
151  static const size_t rank = _rank;
152 
153  typedef typename psdFilterTypes::arrayT<realT,rank>::realArrayT realArrayT; ///< std::vector for rank==1, Eigen::Array for rank==2, eigenCube for rank==3.
154  typedef typename psdFilterTypes::arrayT<realT,rank>::realArrayMapT realArrayMapT; ///< std::vector for rank==1, Eigen::Map for rank==2, eigenCube for rank==3.
155  typedef typename psdFilterTypes::arrayT<realT,rank>::complexArrayT complexArrayT; ///< std::vector for rank==1, Eigen::Array for rank==2, eigenCube for rank==3.
156 
157 
158 protected:
159 
160  int m_rows {0}; ///< The number of rows in the filter, and the required number of rows in the noise array.
161  int m_cols {0}; ///< The number of columns in the filter, and the required number of columns in the noise array.
162  int m_planes {0}; ///< Then number of planes in the filter.
163 
164  realT m_dFreq1 {1.0}; ///< The frequency scaling of the x-dimension. Used to scale the output.
165  realT m_dFreq2 {1.0}; ///< The frequency scaling of the y-dimension. Used to scale the output.
166  realT m_dFreq3 {1.0}; ///< The frequency scaling of the z-dimension. Used to scale the output.
167 
168  realArrayT * m_psdSqrt {nullptr}; ///< Pointer to the real array containing the square root of the PSD.
169  bool m_owner {false}; ///< Flag indicates whether or not m_psdSqrt was allocated by this instance, and so must be deallocated.
170 
171  mutable complexArrayT m_ftWork; ///< Working memory for the FFT. Declared mutable so it can be accessed in the const filter method.
172 
173  math::fft::fftT< complexT, complexT,rank,0> m_fft_fwd; ///< FFT object for the forward transform.
174  math::fft::fftT< complexT, complexT,rank,0> m_fft_back; ///< FFT object for the backward transfsorm.
175 
176 public:
177 
178  ///C'tor.
179  /**
180  * \test Verify compilation and initialization of the 3 ranks for psdFilter. \ref tests_sigproc_psdFilter_compile "[test doc]"
181  */
183 
184  ///Destructor
186 
187 protected:
188 
189  ///Set the sqaure-root of the PSD to be a pointer to an array containing the square root of the properly normalized PSD.
190  /** This does not allocate _npsdSqrt, it merely points to the specified array, which remains your responsibility for deallocation, etc.
191  *
192  * See the discussion of PSD normalization above.
193  *
194  * This private version handles the actual setting of m_psdSqrt, which is rank independent.
195  *
196  * \returns 0 on success
197  * \returns -1 on error
198  *
199  * \test Verify compilation and initialization of the 3 ranks for psdFilter. \ref tests_sigproc_psdFilter_compile "[test doc]"
200  */
201  int psdSqrt( realArrayT * npsdSqrt /**< [in] a pointer to an array containing the square root of the PSD. */ );
202 
203  /// Set the sqaure-root of the PSD.
204  /** This allocates _npsdSqrt and fills it with the values in the array.
205  *
206  * See the discussion of PSD normalization above.
207  *
208  * This private version handles the actual setting of m_psdSqrt, which is rank independent.
209  *
210  * \returns 0 on success
211  * \returns -1 on error
212  *
213  * \test Verify compilation and initialization of the 3 ranks for psdFilter. \ref tests_sigproc_psdFilter_compile "[test doc]"
214  */
215  int psdSqrt( const realArrayT & npsdSqrt /**< [in] an array containing the square root of the PSD. */ );
216 
217  ///Set the size of the filter.
218  /** Handles allocation of the m_ftWork array and fftw planning.
219  *
220  * Requires m_psdSqrt to be set first. This is called by the psdSqrt() and psd() methods.
221  *
222  * This version compiles when rank==1
223  *
224  * \test Verify compilation and initialization of the 3 ranks for psdFilter. \ref tests_sigproc_psdFilter_compile "[test doc]"
225  */
226  template<size_t crank=rank>
227  int setSize(typename std::enable_if<crank==1>::type* = 0 );
228 
229  ///Set the size of the filter.
230  /** Handles allocation of the m_ftWork array and fftw planning.
231  *
232  * Requires m_psdSqrt to be set first. This is called by the psdSqrt() and psd() methods.
233  *
234  * This version compiles when rank==2
235  *
236  * \test Verify compilation and initialization of the 3 ranks for psdFilter. \ref tests_sigproc_psdFilter_compile "[test doc]"
237  */
238  template<size_t crank=rank>
239  int setSize(typename std::enable_if<crank==2>::type* = 0 );
240 
241  ///Set the size of the filter.
242  /** Handles allocation of the m_ftWork array and fftw planning.
243  *
244  * Requires m_psdSqrt to be set first. This is called by the psdSqrt() and psd() methods.
245  *
246  * This version compiles when rank==3
247  *
248  * \test Verify compilation and initialization of the 3 ranks for psdFilter. \ref tests_sigproc_psdFilter_compile "[test doc]"
249  */
250  template<size_t crank=rank>
251  int setSize(typename std::enable_if<crank==3>::type* = 0 );
252 
253 public:
254 
255  ///Get the number of rows in the filter
256  /**
257  * \returns the current value of m_rows.
258  *
259  * \test Verify compilation and initialization of the 3 ranks for psdFilter. \ref tests_sigproc_psdFilter_compile "[test doc]"
260  */
261  int rows();
262 
263  ///Get the number of columns in the filter
264  /**
265  * \returns the current value of m_cols.
266  *
267  * \test Verify compilation and initialization of the 3 ranks for psdFilter. \ref tests_sigproc_psdFilter_compile "[test doc]"
268  */
269  int cols();
270 
271  ///Get the number of planes in the filter
272  /**
273  * \returns the current value of m_planes.
274  *
275  * \test Verify compilation and initialization of the 3 ranks for psdFilter. \ref tests_sigproc_psdFilter_compile "[test doc]"
276  */
277  int planes();
278 
279  ///Set the sqaure-root of the PSD to be a pointer to an array containing the square root of the properly normalized PSD.
280  /** This does not allocate _npsdSqrt, it merely points to the specified array, which remains your responsibility for deallocation, etc.
281  *
282  * See the discussion of PSD normalization above.
283  *
284  * This version compiles when rank==1
285  *
286  * \returns 0 on success
287  * \returns -1 on error
288  *
289  * \test Verify compilation and initialization of the 3 ranks for psdFilter. \ref tests_sigproc_psdFilter_compile "[test doc]"
290  */
291  template<size_t crank = rank>
292  int psdSqrt( realArrayT * npsdSqrt, ///< [in] a pointer to an array containing the square root of the PSD.
293  realT df, ///< [in] the frequency spacing
294  typename std::enable_if<crank==1>::type* = 0
295  );
296 
297  ///Set the square-root of the PSD to be a pointer to an array containing the square root of the properly normalized PSD.
298  /** This does not allocate _npsdSqrt, it merely points to the specified array, which remains your responsibility for deallocation, etc.
299  *
300  * See the discussion of PSD normalization above.
301  *
302  * This version compiles when rank==2
303  *
304  * \returns 0 on success
305  * \returns -1 on error
306  *
307  * \test Verify compilation and initialization of the 3 ranks for psdFilter. \ref tests_sigproc_psdFilter_compile "[test doc]"
308  */
309  template<size_t crank = rank>
310  int psdSqrt( realArrayT * npsdSqrt, ///< [in] a pointer to an array containing the square root of the PSD.
311  realT dk1, ///< [in] the frequency spacing along dimension 1
312  realT dk2, ///< [in] the frequency spacing along dimension 2
313  typename std::enable_if<crank==2>::type* = 0
314  );
315 
316  ///Set the sqaure-root of the PSD to be a pointer to an array containing the square root of the properly normalized PSD.
317  /** This does not allocate _npsdSqrt, it merely points to the specified array, which remains your responsibility for deallocation, etc.
318  *
319  * See the discussion of PSD normalization above.
320  *
321  * This version compiles when rank==3
322  *
323  * \returns 0 on success
324  * \returns -1 on error
325  *
326  * \test Verify compilation and initialization of the 3 ranks for psdFilter. \ref tests_sigproc_psdFilter_compile "[test doc]"
327  */
328  template<size_t crank = rank>
329  int psdSqrt( realArrayT * npsdSqrt, ///< [in] a pointer to an array containing the square root of the PSD.
330  realT dk1, ///< [in] the frequency spacing along dimension 1
331  realT dk2, ///< [in] the frequency spacing along dimension 2
332  realT df, ///< [in] the frequency spacing along dimension 3
333  typename std::enable_if<crank==3>::type* = 0
334  );
335 
336  /// Set the sqaure-root of the PSD.
337  /** This allocates _npsdSqrt and fills it with th evalues in the array.
338  *
339  * See the discussion of PSD normalization above.
340  *
341  * This version compiles when rank==1
342  *
343  * \returns 0 on success
344  * \returns -1 on error
345  *
346  * \test Verify compilation and initialization of the 3 ranks for psdFilter. \ref tests_sigproc_psdFilter_compile "[test doc]"
347  */
348  template<size_t crank = rank>
349  int psdSqrt( const realArrayT & npsdSqrt, ///< [in] an array containing the square root of the PSD.
350  realT df, ///< [in] the frequency spacing
351  typename std::enable_if<crank==1>::type* = 0
352  );
353 
354  ///Set the sqaure-root of the PSD.
355  /** This allocates _npsdSqrt and fills it with th evalues in the array.
356  *
357  * See the discussion of PSD normalization above.
358  *
359  * This version compiles when rank==2
360  *
361  * \returns 0 on success
362  * \returns -1 on error
363  *
364  * \test Verify compilation and initialization of the 3 ranks for psdFilter. \ref tests_sigproc_psdFilter_compile "[test doc]"
365  */
366  template<size_t crank = rank>
367  int psdSqrt( const realArrayT & npsdSqrt, ///< [in] an array containing the square root of the PSD.
368  realT dk1, ///< [in] the frequency spacing along dimension 1
369  realT dk2, ///< [in] the frequency spacing along dimension 2
370  typename std::enable_if<crank==2>::type* = 0
371  );
372 
373  ///Set the sqaure-root of the PSD.
374  /** This allocates _npsdSqrt and fills it with th evalues in the array.
375  *
376  * See the discussion of PSD normalization above.
377  *
378  * This version compiles when rank==3
379  *
380  * \returns 0 on success
381  * \returns -1 on error
382  *
383  * \test Verify compilation and initialization of the 3 ranks for psdFilter. \ref tests_sigproc_psdFilter_compile "[test doc]"
384  */
385  template<size_t crank = rank>
386  int psdSqrt( const realArrayT & npsdSqrt, ///< [in] an array containing the square root of the PSD.
387  realT dk1, ///< [in] the frequency spacing along dimension 1
388  realT dk2, ///< [in] the frequency spacing along dimension 2
389  realT df, ///< [in] the frequency spacing along dimension 3
390  typename std::enable_if<crank==3>::type* = 0
391  );
392 
393  ///Set the sqaure-root of the PSD from the PSD.
394  /** This allocates _npsdSqrt and fills it with the square root of the values in the array.
395  *
396  * See the discussion of PSD normalization above.
397  *
398  * This version compiles when rank==1
399  *
400  * \returns 0 on success
401  * \returns -1 on error
402  *
403  * \test Verify compilation and initialization of the 3 ranks for psdFilter. \ref tests_sigproc_psdFilter_compile "[test doc]"
404  */
405  template<size_t crank=rank>
406  int psd( const realArrayT & npsd, ///< [in] an array containing the PSD
407  const realT df, ///< [in] the frequency spacing
408  typename std::enable_if<crank==1>::type* = 0
409  );
410 
411  ///Set the sqaure-root of the PSD from the PSD.
412  /** This allocates _npsdSqrt and fills it with the square root of the values in the array.
413  *
414  * See the discussion of PSD normalization above.
415  *
416  * This version compiles when rank==2
417  *
418  * \returns 0 on success
419  * \returns -1 on error
420  *
421  * \test Verify compilation and initialization of the 3 ranks for psdFilter. \ref tests_sigproc_psdFilter_compile "[test doc]"
422  */
423  template<size_t crank=rank>
424  int psd( const realArrayT & npsd, ///< [in] an array containing the PSD
425  const realT dk1, ///< [in] the frequency spacing along dimension 1
426  const realT dk2, ///< [in] the frequency spacing along dimension 2
427  typename std::enable_if<crank==2>::type* = 0
428  );
429 
430  ///Set the sqaure-root of the PSD from the PSD.
431  /** This allocates _npsdSqrt and fills it with the square root of the values in the array.
432  *
433  * See the discussion of PSD normalization above.
434  *
435  * This version compiles when rank==3
436  *
437  * \returns 0 on success
438  * \returns -1 on error
439  *
440  * \test Verify compilation and initialization of the 3 ranks for psdFilter. \ref tests_sigproc_psdFilter_compile "[test doc]"
441  */
442  template<size_t crank=rank>
443  int psd( const realArrayT & npsd, ///< [in] an array containing the PSD
444  const realT dk1, ///< [in] the frequency spacing along dimension 1
445  const realT dk2, ///< [in] the frequency spacing along dimension 2
446  const realT df, ///< [in] the frequency spacing along dimension 3
447  typename std::enable_if<crank==3>::type* = 0
448  );
449 
450  ///De-allocate all working memory and reset to initial state.
451  /**
452  *
453  * \test Verify compilation and initialization of the 3 ranks for psdFilter. \ref tests_sigproc_psdFilter_compile "[test doc]"
454  */
455  void clear();
456 
457 
458  ///Apply the filter.
459  /**
460  * This version compiles when rank==1
461  *
462  * \returns 0 on success
463  * \returns -1 on error
464  *
465  * \test Verify filtering and noise normalization. \ref tests_sigproc_psdFilter_filter "[test doc]"
466  */
467  template<size_t crank=rank>
468  int filter( realArrayT & noise, ///< [in.out] the noise field of size rows() X cols(), which is filtered in-place.
469  realArrayT * noiseIm = nullptr, ///< [out] [optional] an array to fill with the imaginary output of the filter, allowing 2-for-1 calculation.
470  typename std::enable_if<crank==1>::type* = 0
471  ) const;
472 
473  ///Apply the filter.
474  /**
475  * This version compiles when rank==2
476  *
477  * \returns 0 on success
478  * \returns -1 on error
479  *
480  * \test Verify filtering and noise normalization. \ref tests_sigproc_psdFilter_filter "[test doc]"
481  */
482  template<size_t crank=rank>
483  int filter( realArrayT & noise, ///< [in.out] the noise field of size rows() X cols(), which is filtered in-place.
484  realArrayT * noiseIm = nullptr, ///< [out] [optional] an array to fill with the imaginary output of the filter, allowing 2-for-1 calculation.
485  typename std::enable_if<crank==2>::type* = 0
486  ) const;
487 
488  ///Apply the filter.
489  /**
490  * This version compiles when rank==2
491  *
492  * \returns 0 on success
493  * \returns -1 on error
494  *
495  */
496  template<size_t crank=rank>
497  int filter( realArrayMapT noise, ///< [in.out] the noise field of size rows() X cols(), which is filtered in-place.
498  realArrayT * noiseIm = nullptr, ///< [out] [optional] an array to fill with the imaginary output of the filter, allowing 2-for-1 calculation.
499  typename std::enable_if<crank==2>::type* = 0
500  ) const;
501 
502  ///Apply the filter.
503  /**
504  * This version compiles when rank==3
505  *
506  * \returns 0 on success
507  * \returns -1 on error
508  *
509  * \test Verify filtering and noise normalization. \ref tests_sigproc_psdFilter_filter "[test doc]"
510  */
511  template<size_t crank=rank>
512  int filter( realArrayT & noise, ///< [in.out] the noise field of size rows() X cols(), which is filtered in-place.
513  realArrayT * noiseIm = nullptr, ///< [out] [optional] an array to fill with the imaginary output of the filter, allowing 2-for-1 calculation.
514  typename std::enable_if<crank==3>::type* = 0
515  ) const;
516 
517  ///Apply the filter.
518  /**
519  * \returns 0 on success
520  * \returns -1 on error
521  *
522  * \test Verify filtering and noise normalization. \ref tests_sigproc_psdFilter_filter "[test doc]"
523  */
524  int operator()( realArrayT & noise /**< [in.out] the noise field of size rows() X cols(), which is filtered in-place. */ ) const;
525 
526  ///Apply the filter.
527  /**
528  * \overload
529  *
530  * \returns 0 on success
531  * \returns -1 on error
532  *
533  * \test Verify filtering and noise normalization. \ref tests_sigproc_psdFilter_filter "[test doc]"
534  */
535  int operator()( realArrayMapT noise /**< [in.out] the noise field of size rows() X cols(), which is filtered in-place. */ ) const;
536 
537  ///Apply the filter.
538  /**
539  * \returns 0 on success
540  * \returns -1 on error
541  *
542  * \test Verify filtering and noise normalization. \ref tests_sigproc_psdFilter_filter "[test doc]"
543  */
544  int operator()( realArrayT & noise, ///< [in.out] the noise field of size rows() X cols(), which is filtered in-place.
545  realArrayT & noiseIm ///< [out] [optional] an array to fill with the imaginary output of the filter, allowing 2-for-1 calculation.
546  ) const;
547 };
548 
549 template<typename realT, size_t rank>
550 psdFilter<realT,rank>::psdFilter()
551 {
552 }
553 
554 template<typename realT, size_t rank>
555 psdFilter<realT,rank>::~psdFilter()
556 {
557  if(m_psdSqrt && m_owner)
558  {
559  delete m_psdSqrt;
560  }
561 }
562 
563 template<typename realT, size_t rank>
564 int psdFilter<realT,rank>::psdSqrt( realArrayT * npsdSqrt )
565 {
566  if(m_psdSqrt && m_owner)
567  {
568  delete m_psdSqrt;
569  }
570 
571  m_psdSqrt = npsdSqrt;
572  m_owner = false;
573 
574  setSize();
575 
576  return 0;
577 }
578 
579 template<typename realT, size_t rank>
580 int psdFilter<realT,rank>::psdSqrt( const realArrayT & npsdSqrt )
581 {
582  if(m_psdSqrt && m_owner)
583  {
584  delete m_psdSqrt;
585  }
586 
587  m_psdSqrt = new realArrayT;
588 
589  (*m_psdSqrt) = npsdSqrt;
590  m_owner = true;
591 
592  setSize();
593 
594  return 0;
595 }
596 
597 template<typename realT, size_t rank>
598 template<size_t crank>
599 int psdFilter<realT,rank>::setSize(typename std::enable_if<crank==1>::type* )
600 {
601  if( m_psdSqrt == 0)
602  {
603  mxError("psdFilter", MXE_PARAMNOTSET, "m_psdSqrt has not been set yet, is still NULL.");
604  return -1;
605  }
606 
607  if( m_rows == m_psdSqrt->size() )
608  {
609  return 0;
610  }
611 
612  m_rows = m_psdSqrt->size();
613  m_cols = 1;
614  m_planes = 1;
615 
616  m_ftWork.resize(m_rows);
617 
618  m_fft_fwd.plan(m_rows, MXFFT_FORWARD, true);
619 
620  m_fft_back.plan(m_rows, MXFFT_BACKWARD, true);
621 
622  return 0;
623 }
624 
625 template<typename realT, size_t rank>
626 template<size_t crank>
627 int psdFilter<realT,rank>::setSize(typename std::enable_if<crank==2>::type* )
628 {
629  if( m_psdSqrt == 0)
630  {
631  mxError("psdFilter", MXE_PARAMNOTSET, "m_psdSqrt has not been set yet, is still NULL.");
632  return -1;
633  }
634 
635  if( m_rows == m_psdSqrt->rows() && m_cols == m_psdSqrt->cols())
636  {
637  return 0;
638  }
639 
640  m_rows = m_psdSqrt->rows();
641  m_cols = m_psdSqrt->cols();
642  m_planes = 1;
643 
644  m_ftWork.resize(m_rows, m_cols);
645 
646  m_fft_fwd.plan(m_rows, m_cols, MXFFT_FORWARD, true);
647 
648  m_fft_back.plan(m_rows, m_cols, MXFFT_BACKWARD, true);
649 
650  return 0;
651 }
652 
653 template<typename realT, size_t rank>
654 template<size_t crank>
655 int psdFilter<realT,rank>::setSize(typename std::enable_if<crank==3>::type* )
656 {
657  if( m_psdSqrt == 0)
658  {
659  mxError("psdFilter", MXE_PARAMNOTSET, "m_psdSqrt has not been set yet, is still NULL.");
660  return -1;
661  }
662 
663  if( m_rows == m_psdSqrt->rows() && m_cols == m_psdSqrt->cols() && m_planes == m_psdSqrt->planes())
664  {
665  return 0;
666  }
667 
668  m_rows = m_psdSqrt->rows();
669  m_cols = m_psdSqrt->cols();
670  m_planes = m_psdSqrt->planes();
671 
672  m_ftWork.resize(m_rows, m_cols, m_planes);
673 
674  m_fft_fwd.plan(m_planes, m_rows, m_cols, MXFFT_FORWARD, true);
675 
676  m_fft_back.plan(m_planes, m_rows, m_cols, MXFFT_BACKWARD, true);
677 
678  return 0;
679 }
680 
681 template<typename realT, size_t rank>
682 int psdFilter<realT,rank>::rows()
683 {
684  return m_rows;
685 }
686 
687 template<typename realT, size_t rank>
688 int psdFilter<realT,rank>::cols()
689 {
690  return m_cols;
691 }
692 
693 template<typename realT, size_t rank>
694 int psdFilter<realT,rank>::planes()
695 {
696  return m_planes;
697 }
698 
699 template<typename realT, size_t rank>
700 template<size_t crank>
701 int psdFilter<realT,rank>::psdSqrt( realArrayT * npsdSqrt,
702  realT df,
703  typename std::enable_if<crank==1>::type*
704  )
705 {
706  m_dFreq1 = df;
707  return psdSqrt(npsdSqrt);
708 }
709 
710 template<typename realT, size_t rank>
711 template<size_t crank>
712 int psdFilter<realT,rank>::psdSqrt( realArrayT * npsdSqrt,
713  realT dk1,
714  realT dk2,
715  typename std::enable_if<crank==2>::type*
716  )
717 {
718  m_dFreq1 = dk1;
719  m_dFreq2 = dk2;
720  return psdSqrt(npsdSqrt);
721 }
722 
723 template<typename realT, size_t rank>
724 template<size_t crank>
725 int psdFilter<realT,rank>::psdSqrt( realArrayT * npsdSqrt,
726  realT dk1,
727  realT dk2,
728  realT df,
729  typename std::enable_if<crank==3>::type*
730  )
731 {
732  m_dFreq1 = dk1;
733  m_dFreq2 = dk2;
734  m_dFreq3 = df;
735  return psdSqrt(npsdSqrt);
736 }
737 
738 template<typename realT, size_t rank>
739 template<size_t crank>
740 int psdFilter<realT,rank>::psdSqrt( const realArrayT & npsdSqrt,
741  realT df,
742  typename std::enable_if<crank==1>::type*
743  )
744 {
745  m_dFreq1 = df;
746  return psdSqrt(npsdSqrt);
747 }
748 
749 template<typename realT, size_t rank>
750 template<size_t crank>
751 int psdFilter<realT,rank>::psdSqrt( const realArrayT & npsdSqrt,
752  realT dk1,
753  realT dk2,
754  typename std::enable_if<crank==2>::type*
755  )
756 {
757  m_dFreq1 = dk1;
758  m_dFreq2 = dk2;
759  return psdSqrt(npsdSqrt);
760 }
761 
762 template<typename realT, size_t rank>
763 template<size_t crank>
764 int psdFilter<realT,rank>::psdSqrt( const realArrayT & npsdSqrt,
765  realT dk1,
766  realT dk2,
767  realT df,
768  typename std::enable_if<crank==3>::type*
769  )
770 {
771  m_dFreq1 = dk1;
772  m_dFreq2 = dk2;
773  m_dFreq3 = df;
774  return psdSqrt(npsdSqrt);
775 }
776 
777 template<typename realT, size_t rank>
778 template<size_t crank>
779 int psdFilter<realT,rank>::psd( const realArrayT & npsd,
780  const realT df1,
781  typename std::enable_if<crank==1>::type*
782  )
783 {
784  if(m_psdSqrt && m_owner)
785  {
786  delete m_psdSqrt;
787  }
788 
789  m_psdSqrt = new realArrayT;
790 
791  //Vector
792  m_psdSqrt->resize(npsd.size());
793  for(size_t n=0;n<npsd.size();++n) (*m_psdSqrt)[n] = sqrt(npsd[n]);
794 
795  m_owner = true;
796 
797  m_dFreq1 = df1;
798 
799  setSize();
800 
801  return 0;
802 }
803 
804 template<typename realT, size_t rank>
805 template<size_t crank>
806 int psdFilter<realT,rank>::psd( const realArrayT & npsd,
807  const realT dk1,
808  const realT dk2,
809  typename std::enable_if<crank==2>::type*
810  )
811 {
812  if(m_psdSqrt && m_owner)
813  {
814  delete m_psdSqrt;
815  }
816 
817  m_psdSqrt = new realArrayT;
818 
819  (*m_psdSqrt) = npsd.sqrt();
820  m_owner = true;
821 
822  m_dFreq1 = dk1;
823  m_dFreq2 = dk2;
824 
825  setSize();
826 
827  return 0;
828 }
829 
830 template<typename realT, size_t rank>
831 template<size_t crank>
832 int psdFilter<realT,rank>::psd( const realArrayT & npsd,
833  const realT dk1,
834  const realT dk2,
835  const realT df,
836  typename std::enable_if<crank==3>::type*
837  )
838 {
839  if(m_psdSqrt && m_owner)
840  {
841  delete m_psdSqrt;
842  }
843 
844  m_psdSqrt = new realArrayT;
845 
846  //Cube
847  m_psdSqrt->resize(npsd.rows(), npsd.cols(), npsd.planes());
848  for(int pp=0;pp <npsd.planes();++pp)
849  {
850  for(int cc=0; cc<npsd.cols(); ++cc)
851  {
852  for(int rr=0; rr<npsd.rows(); ++rr)
853  {
854  m_psdSqrt->image(pp)(rr,cc) = sqrt(npsd.image(pp)(rr,cc));
855  }
856  }
857  }
858 
859  m_owner = true;
860 
861  m_dFreq1 = dk1;
862  m_dFreq2 = dk2;
863  m_dFreq3 = df;
864 
865  setSize();
866 
867  return 0;
868 }
869 
870 template<typename realT, size_t rank>
871 void psdFilter<realT,rank>::clear()
872 {
873  //m_ftWork.resize(0,0);
874  psdFilterTypes::arrayT<realT,rank>::clear(m_ftWork);
875 
876  m_rows = 0;
877  m_cols = 0;
878  m_planes = 0;
879 
880  if(m_psdSqrt && m_owner)
881  {
882  delete m_psdSqrt;
883  m_psdSqrt = 0;
884  }
885 }
886 
887 template<typename realT, size_t rank>
888 template<size_t crank>
889 int psdFilter<realT,rank>::filter( realArrayT & noise,
890  realArrayT * noiseIm,
891  typename std::enable_if<crank==1>::type*
892  ) const
893 {
894  for(int nn=0; nn< noise.size(); ++nn) m_ftWork[nn] = complexT(noise[nn],0);
895 
896  //Transform complex noise to Fourier domain.
897  m_fft_fwd(m_ftWork.data(), m_ftWork.data() );
898 
899  //Apply the filter.
900  for(int nn=0;nn<m_ftWork.size();++nn) m_ftWork[nn] *= (*m_psdSqrt)[nn];
901 
902  m_fft_back(m_ftWork.data(), m_ftWork.data());
903 
904  //Now take the real part, and normalize.
905  realT norm = sqrt(noise.size()/m_dFreq1);
906  for(int nn=0;nn<m_ftWork.size();++nn) noise[nn] = m_ftWork[nn].real()/norm;
907 
908  if(noiseIm != nullptr)
909  {
910  for(int nn=0;nn<m_ftWork.size();++nn) (*noiseIm)[nn] = m_ftWork[nn].imag()/norm;
911  }
912 
913  return 0;
914 }
915 
916 template<typename realT, size_t rank>
917 template<size_t crank>
918 int psdFilter<realT,rank>::filter( realArrayT & noise,
919  realArrayT * noiseIm,
920  typename std::enable_if<crank==2>::type*
921  ) const
922 {
923  //Make noise a complex number
924  for(int ii=0;ii<noise.rows();++ii)
925  {
926  for(int jj=0; jj<noise.cols(); ++jj)
927  {
928  m_ftWork(ii,jj) = complexT(noise(ii,jj),0);
929  }
930  }
931 
932  //Transform complex noise to Fourier domain.
933  m_fft_fwd(m_ftWork.data(), m_ftWork.data() );
934 
935  //Apply the filter.
936  m_ftWork *= *m_psdSqrt;
937 
938  m_fft_back(m_ftWork.data(), m_ftWork.data());
939 
940  realT norm = sqrt(noise.rows()*noise.cols()/(m_dFreq1*m_dFreq2));
941 
942  //Now take the real part, and normalize.
943  noise = m_ftWork.real()/norm;
944 
945  if(noiseIm != nullptr)
946  {
947  *noiseIm = m_ftWork.imag()/norm;
948  }
949 
950  return 0;
951 }
952 
953 template<typename realT, size_t rank>
954 template<size_t crank>
955 int psdFilter<realT,rank>::filter( realArrayMapT noise,
956  realArrayT * noiseIm,
957  typename std::enable_if<crank==2>::type*
958  ) const
959 {
960  //Make noise a complex number
961  for(int ii=0;ii<noise.rows();++ii)
962  {
963  for(int jj=0; jj<noise.cols(); ++jj)
964  {
965  m_ftWork(ii,jj) = complexT(noise(ii,jj),0);
966  }
967  }
968 
969  //Transform complex noise to Fourier domain.
970  m_fft_fwd(m_ftWork.data(), m_ftWork.data() );
971 
972  //Apply the filter.
973  m_ftWork *= *m_psdSqrt;
974 
975  m_fft_back(m_ftWork.data(), m_ftWork.data());
976 
977  realT norm = sqrt(noise.rows()*noise.cols()/(m_dFreq1*m_dFreq2));
978 
979  //Now take the real part, and normalize.
980  noise = m_ftWork.real()/norm;
981 
982  if(noiseIm != nullptr)
983  {
984  *noiseIm = m_ftWork.imag()/norm;
985  }
986 
987  return 0;
988 }
989 
990 template<typename realT, size_t rank>
991 template<size_t crank>
992 int psdFilter<realT,rank>::filter( realArrayT & noise,
993  realArrayT * noiseIm,
994  typename std::enable_if<crank==3>::type*
995  ) const
996 {
997  //Make noise a complex number
998  for(int pp=0;pp<noise.planes();++pp)
999  {
1000  for(int ii=0;ii<noise.rows();++ii)
1001  {
1002  for(int jj=0; jj<noise.cols(); ++jj)
1003  {
1004  m_ftWork.image(pp)(ii,jj) = complexT(noise.image(pp)(ii,jj),0);
1005  }
1006  }
1007  }
1008 
1009  //Transform complex noise to Fourier domain.
1010  m_fft_fwd(m_ftWork.data(), m_ftWork.data() );
1011 
1012  //Apply the filter.
1013  for(int pp=0;pp<noise.planes();++pp) m_ftWork.image(pp) *= m_psdSqrt->image(pp);
1014 
1015  m_fft_back(m_ftWork.data(), m_ftWork.data());
1016 
1017  //Now take the real part, and normalize.
1018 
1019  realT norm = sqrt(m_rows*m_cols*m_planes/(m_dFreq1*m_dFreq2*m_dFreq3));
1020  for(int pp=0; pp< noise.planes();++pp) noise.image(pp) = m_ftWork.image(pp).real()/norm;
1021 
1022  if(noiseIm != nullptr)
1023  {
1024  for(int pp=0; pp< noise.planes();++pp) noiseIm->image(pp) = m_ftWork.image(pp).imag()/norm;
1025  }
1026 
1027  return 0;
1028 }
1029 
1030 template<typename realT, size_t rank>
1031 int psdFilter<realT,rank>::operator()( realArrayT & noise ) const
1032 {
1033  return filter(noise);
1034 }
1035 
1036 template<typename realT, size_t rank>
1037 int psdFilter<realT,rank>::operator()( realArrayMapT noise ) const
1038 {
1039  return filter(noise);
1040 }
1041 
1042 template<typename realT, size_t rank>
1043 int psdFilter<realT,rank>::operator()( realArrayT & noise,
1044  realArrayT & noiseIm
1045  ) const
1046 {
1047  return filter(noise, &noiseIm);
1048 }
1049 
1050 } //namespace sigproc
1051 } //namespace mx
1052 
1053 #endif //psdFilter_hpp
int setSize(typename std::enable_if< crank==1 >::type *=0)
Set the size of the filter.
int operator()(realArrayT &noise, realArrayT &noiseIm) const
Apply the filter.
complexArrayT m_ftWork
Working memory for the FFT. Declared mutable so it can be accessed in the const filter method.
Definition: psdFilter.hpp:171
int rows()
Get the number of rows in the filter.
int psd(const realArrayT &npsd, const realT df, typename std::enable_if< crank==1 >::type *=0)
Set the sqaure-root of the PSD from the PSD.
math::fft::fftT< complexT, complexT, rank, 0 > m_fft_back
FFT object for the backward transfsorm.
Definition: psdFilter.hpp:174
int filter(realArrayMapT noise, realArrayT *noiseIm=nullptr, typename std::enable_if< crank==2 >::type *=0) const
Apply the filter.
psdFilterTypes::arrayT< realT, rank >::complexArrayT complexArrayT
std::vector for rank==1, Eigen::Array for rank==2, eigenCube for rank==3.
Definition: psdFilter.hpp:155
int psdSqrt(realArrayT *npsdSqrt, realT df, typename std::enable_if< crank==1 >::type *=0)
Set the sqaure-root of the PSD to be a pointer to an array containing the square root of the properly...
int filter(realArrayT &noise, realArrayT *noiseIm=nullptr, typename std::enable_if< crank==3 >::type *=0) const
Apply the filter.
psdFilterTypes::arrayT< realT, rank >::realArrayMapT realArrayMapT
std::vector for rank==1, Eigen::Map for rank==2, eigenCube for rank==3.
Definition: psdFilter.hpp:154
int filter(realArrayT &noise, realArrayT *noiseIm=nullptr, typename std::enable_if< crank==1 >::type *=0) const
Apply the filter.
int psdSqrt(realArrayT *npsdSqrt, realT dk1, realT dk2, typename std::enable_if< crank==2 >::type *=0)
Set the square-root of the PSD to be a pointer to an array containing the square root of the properly...
int setSize(typename std::enable_if< crank==2 >::type *=0)
Set the size of the filter.
int operator()(realArrayT &noise) const
Apply the filter.
int psd(const realArrayT &npsd, const realT dk1, const realT dk2, typename std::enable_if< crank==2 >::type *=0)
Set the sqaure-root of the PSD from the PSD.
int psdSqrt(realArrayT *npsdSqrt, realT dk1, realT dk2, realT df, typename std::enable_if< crank==3 >::type *=0)
Set the sqaure-root of the PSD to be a pointer to an array containing the square root of the properly...
int cols()
Get the number of columns in the filter.
std::complex< _realT > complexT
Complex floating point type.
Definition: psdFilter.hpp:149
psdFilterTypes::arrayT< realT, rank >::realArrayT realArrayT
std::vector for rank==1, Eigen::Array for rank==2, eigenCube for rank==3.
Definition: psdFilter.hpp:153
int psdSqrt(const realArrayT &npsdSqrt, realT dk1, realT dk2, realT df, typename std::enable_if< crank==3 >::type *=0)
Set the sqaure-root of the PSD.
int setSize(typename std::enable_if< crank==3 >::type *=0)
Set the size of the filter.
void clear()
De-allocate all working memory and reset to initial state.
int filter(realArrayT &noise, realArrayT *noiseIm=nullptr, typename std::enable_if< crank==2 >::type *=0) const
Apply the filter.
_realT realT
Real floating point type.
Definition: psdFilter.hpp:148
int operator()(realArrayMapT noise) const
Apply the filter.
int psdSqrt(const realArrayT &npsdSqrt, realT df, typename std::enable_if< crank==1 >::type *=0)
Set the sqaure-root of the PSD.
int psd(const realArrayT &npsd, const realT dk1, const realT dk2, const realT df, typename std::enable_if< crank==3 >::type *=0)
Set the sqaure-root of the PSD from the PSD.
int psdSqrt(const realArrayT &npsdSqrt)
Set the sqaure-root of the PSD.
int psdSqrt(const realArrayT &npsdSqrt, realT dk1, realT dk2, typename std::enable_if< crank==2 >::type *=0)
Set the sqaure-root of the PSD.
int planes()
Get the number of planes in the filter.
int psdSqrt(realArrayT *npsdSqrt)
Set the sqaure-root of the PSD to be a pointer to an array containing the square root of the properly...
math::fft::fftT< complexT, complexT, rank, 0 > m_fft_fwd
FFT object for the forward transform.
Definition: psdFilter.hpp:173
The mxlib c++ namespace.
Definition: mxError.hpp:107
Types for different ranks in psdFilter.
Definition: psdFilter.hpp:49