3 #include "../../catch2/catch.hpp"
8 #define MX_NO_ERROR_REPORTS
10 #include "../../../include/sigproc/psdFilter.hpp"
11 #include "../../../include/sigproc/psdUtils.hpp"
12 #include "../../../include/improc/eigenCube.hpp"
13 #include "../../../include/math/randomT.hpp"
14 #include "../../../include/math/vectorUtils.hpp"
22 SCENARIO(
"compiling psdFilter",
"[sigproc::psdFilter]" )
24 GIVEN(
"a psdFilter, sqrt pointer")
28 mx::sigproc::psdFilter<double, 1> psdF;
30 std::vector<double> psdSqrt(1024,1);
32 int rv = psdF.psdSqrt(&psdSqrt, 1);
35 REQUIRE(psdF.rows() == 1024);
36 REQUIRE(psdF.cols() == 1);
37 REQUIRE(psdF.planes() == 1);
40 REQUIRE(psdF.rows() == 0);
41 REQUIRE(psdF.cols() == 0);
42 REQUIRE(psdF.planes() == 0);
47 mx::sigproc::psdFilter<double, 2> psdF;
49 Eigen::Array<double,-1,-1> psdSqrt;
50 psdSqrt.resize(256,256);
51 psdSqrt.setConstant(1);
53 int rv = psdF.psdSqrt(&psdSqrt, 1, 1);
56 REQUIRE(psdF.rows() == 256);
57 REQUIRE(psdF.cols() == 256);
58 REQUIRE(psdF.planes() == 1);
61 REQUIRE(psdF.rows() == 0);
62 REQUIRE(psdF.cols() == 0);
63 REQUIRE(psdF.planes() == 0);
67 mx::sigproc::psdFilter<double, 3> psdF;
70 psdSqrt.resize(128,128,256);
73 int rv = psdF.psdSqrt(&psdSqrt, 1, 1, 1);
76 REQUIRE(psdF.rows() == 128);
77 REQUIRE(psdF.cols() == 128);
78 REQUIRE(psdF.planes() == 256);
81 REQUIRE(psdF.rows() == 0);
82 REQUIRE(psdF.cols() == 0);
83 REQUIRE(psdF.planes() == 0);
87 GIVEN(
"a psdFilter, sqrt reference")
91 mx::sigproc::psdFilter<double, 1> psdF;
93 std::vector<double> psdSqrt(1024,1);
95 int rv = psdF.psdSqrt(psdSqrt, 1);
98 REQUIRE(psdF.rows() == 1024);
99 REQUIRE(psdF.cols() == 1);
100 REQUIRE(psdF.planes() == 1);
103 REQUIRE(psdF.rows() == 0);
104 REQUIRE(psdF.cols() == 0);
105 REQUIRE(psdF.planes() == 0);
109 mx::sigproc::psdFilter<double, 2> psdF;
111 Eigen::Array<double,-1,-1> psdSqrt;
112 psdSqrt.resize(256,256);
113 psdSqrt.setConstant(1);
115 int rv = psdF.psdSqrt(psdSqrt, 1, 1);
118 REQUIRE(psdF.rows() == 256);
119 REQUIRE(psdF.cols() == 256);
120 REQUIRE(psdF.planes() == 1);
123 REQUIRE(psdF.rows() == 0);
124 REQUIRE(psdF.cols() == 0);
125 REQUIRE(psdF.planes() == 0);
129 mx::sigproc::psdFilter<double, 3> psdF;
132 psdSqrt.resize(128,128,256);
135 int rv = psdF.psdSqrt(psdSqrt, 1, 1, 1);
138 REQUIRE(psdF.rows() == 128);
139 REQUIRE(psdF.cols() == 128);
140 REQUIRE(psdF.planes() == 256);
143 REQUIRE(psdF.rows() == 0);
144 REQUIRE(psdF.cols() == 0);
145 REQUIRE(psdF.planes() == 0);
149 GIVEN(
"a psdFilter, psd reference")
153 mx::sigproc::psdFilter<double, 1> psdF;
155 std::vector<double> psd(1024,1);
157 int rv = psdF.psd(psd, 1.0);
160 REQUIRE(psdF.rows() == 1024);
161 REQUIRE(psdF.cols() == 1);
162 REQUIRE(psdF.planes() == 1);
165 REQUIRE(psdF.rows() == 0);
166 REQUIRE(psdF.cols() == 0);
167 REQUIRE(psdF.planes() == 0);
171 mx::sigproc::psdFilter<double, 2> psdF;
173 Eigen::Array<double,-1,-1> psd;
177 int rv = psdF.psd(psd, 1.0, 1.0);
180 REQUIRE(psdF.rows() == 256);
181 REQUIRE(psdF.cols() == 256);
182 REQUIRE(psdF.planes() == 1);
185 REQUIRE(psdF.rows() == 0);
186 REQUIRE(psdF.cols() == 0);
187 REQUIRE(psdF.planes() == 0);
191 mx::sigproc::psdFilter<double, 3> psdF;
194 psd.resize(128,128,256);
197 int rv = psdF.psd(psd, 1, 1, 1);
200 REQUIRE(psdF.rows() == 128);
201 REQUIRE(psdF.cols() == 128);
202 REQUIRE(psdF.planes() == 256);
205 REQUIRE(psdF.rows() == 0);
206 REQUIRE(psdF.cols() == 0);
207 REQUIRE(psdF.planes() == 0);
218 SCENARIO(
"filtering with psdFilter",
"[sigproc::psdFilter]" )
220 GIVEN(
"a rank 1 psd")
222 WHEN(
"alpha=-2.5, df Nyquist matched to array size, var=1")
224 mx::sigproc::psdFilter<double, 1> psdF;
226 std::vector<double> f(2049), psd(2049);
228 for(
size_t n=0;n<psd.size();++n) f[n] = n*1.0/4096.;
230 for(
size_t n=1;n<psd.size();++n) psd[n] = pow(f[n], -2.5);
235 std::vector<double> f2s, psd2s;
239 double df = f2s[1]-f2s[0];
241 int rv = psdF.psd(psd2s, df);
244 REQUIRE(psdF.rows() == 2.*psd.size()-2);
245 REQUIRE(psdF.cols() == 1);
246 REQUIRE(psdF.planes() == 1);
248 std::vector<double> noise(psdF.rows());
254 for(
int k=0;
k<10000;++
k)
256 for(
size_t n=0;n<noise.size();++n) noise[n] = normVar;
261 avgRms = sqrt(avgRms/10000);
263 REQUIRE(fabs(avgRms - 1.0) < 0.02);
266 WHEN(
"alpha=-1.5, df arbitrary, var = 2.2")
268 mx::sigproc::psdFilter<double, 1> psdF;
270 std::vector<double> f(1025), psd(1025);
272 for(
size_t n=0;n<psd.size();++n) f[n] = n*1.0/7000.;
274 for(
size_t n=1;n<psd.size();++n) psd[n] = pow(f[n], -1.5);
277 std::vector<double> f2s, psd2s;
281 double df = f2s[1]-f2s[0];
285 int rv = psdF.psd(psd2s, df);
288 REQUIRE(psdF.rows() == 2.*psd.size()-2);
289 REQUIRE(psdF.cols() == 1);
290 REQUIRE(psdF.planes() == 1);
292 std::vector<double> noise(psdF.rows());
298 for(
int k=0;
k<10000;++
k)
300 for(
size_t n=0;n<noise.size();++n) noise[n] = normVar;
305 avgRms = sqrt(avgRms/10000);
307 REQUIRE(fabs(avgRms - sqrt(2.2)) < 0.02*sqrt(2.2));
311 GIVEN(
"a rank 2 psd")
313 WHEN(
"alpha=-2.5, dk Nyquist matched to array size, var=1")
315 mx::sigproc::psdFilter<double, 2> psdF;
317 Eigen::Array<double, -1, -1>
k, psd;
323 for(
int cc=0; cc< psd.cols(); ++cc)
325 for(
int rr=0; rr<psd.rows(); ++rr)
327 if(
k(rr,cc) == 0) psd(rr,cc) = 0;
328 else psd(rr,cc) = pow(
k(rr,cc), -2.5);
332 double dk =
k(0,1) -
k(0,0);
336 int rv = psdF.psd(psd, dk, dk);
339 REQUIRE(psdF.rows() == psd.rows());
340 REQUIRE(psdF.cols() == psd.cols());
341 REQUIRE(psdF.planes() == 1);
343 Eigen::Array<double, -1, -1> noise(psdF.rows(), psdF.cols());
349 for(
int k=0;
k<10000;++
k)
351 for(
int cc=0; cc< psd.cols(); ++cc)
353 for(
int rr=0; rr<psd.rows(); ++rr)
355 noise(rr,cc) = normVar;
360 avgRms += noise.square().sum();
363 avgRms = sqrt(avgRms/(psd.rows()*psd.cols())/10000);
366 REQUIRE(fabs(avgRms - 1.0) < 0.02);
369 WHEN(
"alpha=-1.5, dk arb, var=2.2")
371 mx::sigproc::psdFilter<double, 2> psdF;
373 Eigen::Array<double, -1, -1>
k, psd;
379 for(
int cc=0; cc< psd.cols(); ++cc)
381 for(
int rr=0; rr<psd.rows(); ++rr)
383 if(
k(rr,cc) == 0) psd(rr,cc) = 0;
384 else psd(rr,cc) = pow(
k(rr,cc), -1.5);
388 double dk =
k(0,1) -
k(0,0);
392 int rv = psdF.psd(psd, dk, dk);
395 REQUIRE(psdF.rows() == psd.rows());
396 REQUIRE(psdF.cols() == psd.cols());
397 REQUIRE(psdF.planes() == 1);
399 Eigen::Array<double, -1, -1> noise(psdF.rows(), psdF.cols());
405 for(
int k=0;
k<10000;++
k)
407 for(
int cc=0; cc< psd.cols(); ++cc)
409 for(
int rr=0; rr<psd.rows(); ++rr)
411 noise(rr,cc) = normVar;
416 avgRms += noise.square().sum();
419 avgRms = sqrt(avgRms/(psd.rows()*psd.cols())/10000);
422 REQUIRE(fabs(avgRms - sqrt(2.2)) < 0.02*sqrt(2.2));
426 GIVEN(
"a rank 3 psd")
428 WHEN(
"k-alpha=-2.5, f-alph=-2.5, dk Nyquist matched to array size, df Nyquist matched to array size, var=1")
430 mx::sigproc::psdFilter<double, 3> psdF;
432 Eigen::Array<double, -1, -1>
k, psdk;
433 std::vector<double> f, f2s, psd2s;
443 psdk.resize(
k.rows(),
k.cols());
444 for(
int cc=0; cc< psdk.cols(); ++cc)
446 for(
int rr=0; rr<psdk.rows(); ++rr)
448 if(
k(rr,cc) == 0) psdk(rr,cc) = 0;
449 else psdk(rr,cc) = pow(
k(rr,cc), -2.5);
454 for(
size_t n=0;n<f.size();++n) f[n] = n*1.0/64.;
456 psd2s.resize(f2s.size());
457 for(
size_t n=0;n<psd2s.size();++n) psd2s[n] = pow(fabs(f2s[n]), -2.5);
461 psd.resize(
k.rows(),
k.cols(), f2s.size());
464 for(
int cc=0; cc< psd.cols(); ++cc)
466 for(
int rr=0; rr<psd.rows(); ++rr)
468 if(
k(rr,cc) == 0) psd.
pixel(rr,cc).setZero();
471 double p = psdk(rr,cc);
474 for(
int pp=0;pp<psd.planes();++pp) psd.
image(pp)(rr,cc)=psd2s[pp];
479 double dk =
k(0,1) -
k(0,0);
480 double df = f[1]- f[0];
482 int rv = psdF.psd(psd, dk, dk, df);
485 REQUIRE(psdF.rows() == psd.rows());
486 REQUIRE(psdF.cols() == psd.cols());
487 REQUIRE(psdF.planes() == psd.planes());
495 for(
int k=0;
k<10000;++
k)
497 for(
int pp=0;pp<psd.planes(); ++pp)
499 for(
int cc=0; cc< psd.cols(); ++cc)
501 for(
int rr=0; rr<psd.rows(); ++rr)
503 noise.
image(pp)(rr,cc) = normVar;
509 for(
int pp=0;pp<noise.planes();++pp) avgRms += noise.
image(pp).square().sum();
512 avgRms = sqrt(avgRms/(psd.rows()*psd.cols()*psd.planes())/10000);
515 REQUIRE(fabs(avgRms - 1.0) < 0.02);
518 WHEN(
"k-alpha=-3.5, f-alph=-1.5, dk arb, df arb, var=2")
520 mx::sigproc::psdFilter<double, 3> psdF;
522 Eigen::Array<double, -1, -1>
k, psdk;
523 std::vector<double> f, f2s, psd2s;
533 psdk.resize(
k.rows(),
k.cols());
534 for(
int cc=0; cc< psdk.cols(); ++cc)
536 for(
int rr=0; rr<psdk.rows(); ++rr)
538 if(
k(rr,cc) == 0) psdk(rr,cc) = 0;
539 else psdk(rr,cc) = pow(
k(rr,cc), -3.5);
544 for(
size_t n=0;n<f.size();++n) f[n] = n*1.0/78.;
546 psd2s.resize(f2s.size());
547 for(
size_t n=0;n<psd2s.size();++n) psd2s[n] = pow(fabs(f2s[n]), -1.5);
551 psd.resize(
k.rows(),
k.cols(), f2s.size());
554 for(
int cc=0; cc< psd.cols(); ++cc)
556 for(
int rr=0; rr<psd.rows(); ++rr)
558 if(
k(rr,cc) == 0) psd.
pixel(rr,cc).setZero();
561 double p = psdk(rr,cc);
564 for(
int pp=0;pp<psd.planes();++pp) psd.
image(pp)(rr,cc)=psd2s[pp];
569 double dk =
k(0,1) -
k(0,0);
570 double df = f[1]- f[0];
572 int rv = psdF.psd(psd, dk, dk, df);
575 REQUIRE(psdF.rows() == psd.rows());
576 REQUIRE(psdF.cols() == psd.cols());
577 REQUIRE(psdF.planes() == psd.planes());
585 for(
int k=0;
k<10000;++
k)
587 for(
int pp=0;pp<psd.planes(); ++pp)
589 for(
int cc=0; cc< psd.cols(); ++cc)
591 for(
int rr=0; rr<psd.rows(); ++rr)
593 noise.
image(pp)(rr,cc) = normVar;
599 for(
int pp=0;pp<noise.planes();++pp) avgRms += noise.
image(pp).square().sum();
602 avgRms = sqrt(avgRms/(psd.rows()*psd.cols()*psd.planes())/10000);
605 REQUIRE(fabs(avgRms - sqrt(2.0)) < 0.02*sqrt(2));
An image cube with an Eigen-like API.
Eigen::Map< Eigen::Array< dataT, Eigen::Dynamic, Eigen::Dynamic >, Eigen::Unaligned, Eigen::Stride< Eigen::Dynamic, Eigen::Dynamic > > pixel(Index i, Index j)
Returns an Eigen::Eigen::Map-ed vector of the pixels at the given coordinate.
Eigen::Map< Eigen::Array< dataT, Eigen::Dynamic, Eigen::Dynamic > > image(Index n)
Returns a 2D Eigen::Eigen::Map pointed at the specified image.
constexpr units::realT k()
Boltzmann Constant.
void augment1SidedPSD(vectorTout &psdTwoSided, vectorTin &psdOneSided, bool addZeroFreq=false, typename vectorTin::value_type scale=0.5)
Augment a 1-sided PSD to standard 2-sided FFT form.
void augment1SidedPSDFreq(std::vector< T > &freqTwoSided, std::vector< T > &freqOneSided)
Augment a 1-sided frequency scale to standard FFT form.
int normPSD(std::vector< floatT > &psd, std::vector< floatT > &f, floatParamT normT, floatT fmin=std::numeric_limits< floatT >::min(), floatT fmax=std::numeric_limits< floatT >::max())
Normalize a 1-D PSD to have a given variance.
int frequencyGrid(std::vector< realT > &vec, realParamT dt, bool fftOrder=true)
Create a 1-D frequency grid.
valueT vectorVariance(const valueT *vec, size_t sz, valueT mean)
Calculate the variance of a vector relative to a supplied mean value.
SCENARIO("compiling psdFilter", "[sigproc::psdFilter]")