LCOV - code coverage report
Current view: top level - include/sigproc - psdFilter.hpp (source / functions) Coverage Total Hit
Test: mxlib Lines: 89.9 % 188 169
Test Date: 2026-08-30 22:23:37 Functions: 100.0 % 27 27

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

Generated by: LCOV version 2.0-1