Skip to content

Commit 61c5ed6

Browse files
committed
Added helper functions (fftfreq and fftshift) + tests
1 parent 3eb6731 commit 61c5ed6

4 files changed

Lines changed: 137 additions & 0 deletions

File tree

CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@ endif(FIX_RPATH)
109109

110110
set(XTENSOR_FFTW_HEADERS
111111
${XTENSOR_FFTW_INCLUDE_DIR}/xtensor-fftw/basic.hpp
112+
${XTENSOR_FFTW_INCLUDE_DIR}/xtensor-fftw/helper.hpp
112113
${XTENSOR_FFTW_INCLUDE_DIR}/xtensor-fftw/xtensor-fftw_config.hpp
113114
)
114115

include/xtensor-fftw/helper.hpp

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
/*
2+
* xtensor-fftw
3+
* Copyright (c) 2017, Patrick Bos
4+
* Distributed under the terms of the BSD 3-Clause License.
5+
*
6+
* The full license is in the file LICENSE, distributed with this software.
7+
*/
8+
9+
#ifndef XTENSOR_FFTW_HELPER_HPP
10+
#define XTENSOR_FFTW_HELPER_HPP
11+
12+
#include <xtensor/xarray.hpp>
13+
14+
namespace xt {
15+
namespace fftw {
16+
17+
template <typename T>
18+
xt::xarray<T> fftshift(xt::xarray<T> in) {
19+
// partly mimic np.fftshift (only 1D arrays)
20+
xt::xarray<T> shifted(in);
21+
auto it_in = in.begin();
22+
for (std::size_t ix_shifted = in.size()/2; it_in != in.end(); ++it_in, ++ix_shifted) {
23+
shifted[ix_shifted % in.size()] = *it_in;
24+
}
25+
return shifted;
26+
}
27+
28+
template <typename T>
29+
xt::xarray<T> ifftshift(xt::xarray<T> shifted) {
30+
// partly mimic np.ifftshift (only 1D arrays)
31+
xt::xarray<T> out(shifted);
32+
auto it_out = out.begin();
33+
for (std::size_t ix_shifted = out.size()/2; it_out != out.end(); ++ix_shifted, ++it_out) {
34+
*it_out = shifted[ix_shifted % out.size()];
35+
}
36+
return out;
37+
}
38+
39+
40+
template <typename T>
41+
xt::xarray<T> fftfreq(unsigned long n, T d=1.0) {
42+
// mimic np.fftfreq
43+
T df = 1 / (d * static_cast<T>(n));
44+
xt::xarray<T> frequencies;
45+
if (n % 2 == 0) {
46+
frequencies = xt::arange<T>(-static_cast<long>(n/2), n/2) * df;
47+
} else {
48+
frequencies = xt::arange<T>(-static_cast<long>(n/2), n/2 + 1) * df;
49+
}
50+
frequencies = ifftshift(frequencies);
51+
return frequencies;
52+
}
53+
54+
template <typename T>
55+
xt::xarray<T> fftscale(unsigned long n, T d=1.0) {
56+
// mimic np.fftfreq, but in scale space instead of frequency space (dk = 2\pi df)
57+
return 2 * M_PI * fftfreq(n, d);
58+
}
59+
60+
61+
template <typename T>
62+
xt::xarray<T> rfftfreq(unsigned long n, T d=1.0) {
63+
// mimic np.rfftfreq
64+
T df = 1 / (d * static_cast<T>(n));
65+
xt::xarray<T> frequencies = xt::arange<T>(0., n/2 + 1) * df;
66+
return frequencies;
67+
}
68+
69+
template <typename T>
70+
xt::xarray<T> rfftscale(unsigned long n, T d=1.0) {
71+
// mimic np.rfftfreq, but in scale space instead of frequency space (dk = 2\pi df)
72+
return 2 * M_PI * rfftfreq(n, d);
73+
}
74+
75+
}
76+
}
77+
78+
#endif //XTENSOR_FFTW_HELPER_HPP

test/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ include_directories(${GTEST_INCLUDE_DIRS})
9696

9797
set(XTENSOR_FFTW_TESTS
9898
basic_interface.cpp
99+
helper.cpp
99100
)
100101

101102
set(XTENSOR_FFTW_TARGET test_xtensor-fftw)

test/helper.cpp

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
/*
2+
* xtensor-fftw
3+
* Copyright (c) 2017, Patrick Bos
4+
* Distributed under the terms of the BSD 3-Clause License.
5+
*
6+
* The full license is in the file LICENSE, distributed with this software.
7+
*/
8+
9+
#include <xtensor/xarray.hpp>
10+
#include <xtensor-fftw/helper.hpp>
11+
12+
#include "gtest/gtest.h"
13+
14+
15+
TEST(helper, fftshift) {
16+
xt::xarray<double> odd = {3, 4, 0, 1, 2};
17+
xt::xarray<double> even = {3, 4, 5, 0, 1, 2};
18+
xt::xarray<double> odd_range = xt::arange<double>(5);
19+
xt::xarray<double> even_range = xt::arange<double>(6);
20+
EXPECT_EQ(xt::fftw::fftshift(odd_range), odd);
21+
EXPECT_EQ(xt::fftw::fftshift(even_range), even);
22+
}
23+
24+
TEST(helper, ifftshift) {
25+
xt::xarray<double> odd = {3, 4, 0, 1, 2};
26+
xt::xarray<double> even = {3, 4, 5, 0, 1, 2};
27+
EXPECT_EQ(xt::fftw::ifftshift(odd), xt::arange<double>(5));
28+
EXPECT_EQ(xt::fftw::ifftshift(even), xt::arange<double>(6));
29+
}
30+
31+
TEST(helper, fftfreq) {
32+
xt::xarray<double> reference9 = {0., 1., 2., 3., 4., -4., -3., -2., -1.};
33+
xt::xarray<double> reference10 = {0. , 0.04, 0.08, 0.12, 0.16, -0.2 , -0.16, -0.12, -0.08, -0.04};
34+
EXPECT_EQ(xt::fftw::fftfreq(9, 1./9), reference9);
35+
EXPECT_EQ(xt::fftw::fftfreq(10, 2.5), reference10);
36+
}
37+
38+
TEST(helper, fftscale) {
39+
xt::xarray<double> reference9 = {0., 1., 2., 3., 4., -4., -3., -2., -1.};
40+
xt::xarray<double> reference10 = {0. , 0.04, 0.08, 0.12, 0.16, -0.2 , -0.16, -0.12, -0.08, -0.04};
41+
EXPECT_EQ(xt::fftw::fftscale(9, 1./9), 2 * M_PI * reference9);
42+
EXPECT_EQ(xt::fftw::fftscale(10, 2.5), 2 * M_PI * reference10);
43+
}
44+
45+
TEST(helper, rfftfreq) {
46+
xt::xarray<double> reference9 = {0., 1., 2., 3., 4.};
47+
xt::xarray<double> reference10 = {0. , 0.04, 0.08, 0.12, 0.16, 0.2};
48+
EXPECT_EQ(xt::fftw::rfftfreq(9, 1./9), reference9);
49+
EXPECT_EQ(xt::fftw::rfftfreq(10, 2.5), reference10);
50+
}
51+
52+
TEST(helper, rfftscale) {
53+
xt::xarray<double> reference9 = {0., 1., 2., 3., 4.};
54+
xt::xarray<double> reference10 = {0. , 0.04, 0.08, 0.12, 0.16, 0.2};
55+
EXPECT_EQ(xt::fftw::rfftscale(9, 1./9), 2 * M_PI * reference9);
56+
EXPECT_EQ(xt::fftw::rfftscale(10, 2.5), 2 * M_PI * reference10);
57+
}

0 commit comments

Comments
 (0)