Skip to content

Commit e3be54a

Browse files
committed
More progress in FRFFT
1 parent 970f77c commit e3be54a

File tree

6 files changed

+67
-10
lines changed

6 files changed

+67
-10
lines changed

Project.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,8 @@ FractionalTransforms = "e50ca838-b4f0-4a10-ad18-4b920bf1ae5c"
3030
ImageTransformations = "02fcd773-0e25-5acc-982a-7f6622650795"
3131
Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
3232
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
33+
TestImages = "5e47fb64-e119-507b-a336-dd2b206d9990"
3334
Zygote = "e88e6eb3-aa80-5325-afca-941959d7151f"
3435

3536
[targets]
36-
test = ["Test", "FractionalTransforms", "Random", "ImageTransformations", "Zygote"]
37+
test = ["Test", "TestImages", "FractionalTransforms", "Random", "ImageTransformations", "Zygote"]

README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,14 @@ The main features are:
2828
* array/image shifting (including noteworthy subpixel shifts)
2929
* array/image shearing
3030
* several tools like `ffts`, `ft`, `fftshift_view` etc. allowing simpler use with Fourier transforms
31+
* Chirp Z-Transform
32+
* Fractional Fourier Transform
3133

3234
Have a look in the [examples folder](examples/) for interactive examples. The [documentation](https://bionanoimaging.github.io/FourierTools.jl/dev/) offers a quick overview.
3335

36+
## FFTW Threading
37+
By default we set 4 Threads. Use `FFTW.set_num_threads(N)` to set `N` threads.
38+
3439

3540
## Cite
3641
If you use this package in an academic work, please cite us!

examples/fractional_fourier_transform.jl

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -70,18 +70,24 @@ img = Float32.(testimage("resolution_test_512"));
7070
md"
7171
Fractional order
7272
73-
$(@bind s Slider(-1.5:0.01:2, show_value=true))
73+
$(@bind s Slider(-3:0.05:3, show_value=true))
7474
"
7575

7676
# ╔═╡ 7c445baa-d970-4954-a3dc-df828971bfd7
77-
[gray_show(log1p.(abs.(ft(img)))) gray_show(log1p.(abs.(sqrt(length(img)) .* frfft(img, s))))]
77+
[gray_show(log1p.(abs.(ft(img)))) gray_show(log1p.(abs.(sqrt(length(img)) .* frfft(img, s, shift=true))))]
7878

7979
# ╔═╡ 1915c023-69cf-4d18-90cb-b47465dbef69
8080
begin
8181
plot(log1p.(abs.(ft(img)[(end+begin)÷2+1,:] ./ sqrt(length(img)))))
8282
plot!(log1p.(abs.(frfft(img, s)[(end+begin)÷2+1,:])))
8383
end
8484

85+
# ╔═╡ 227ae9a3-9387-4ac3-b391-e2a78ce40d49
86+
begin
87+
plot((real.(ft(img)[(end+begin)÷2+1,200:300] ./ sqrt(length(img)))))
88+
plot!((real.(frfft(img, s)[(end+begin)÷2+1,200:300])))
89+
end
90+
8591
# ╔═╡ abff911a-e10d-4311-955a-7afc4e0d344c
8692
md"## Fractional Fourier Transform on Vector
8793
Comparison with [FractionalTransforms.jl](https://github.com/SciFracX/FractionalTransforms.jl) roughly matches.
@@ -110,9 +116,10 @@ end
110116
# ╠═459649ed-ca70-426e-8273-97b146b5bcd5
111117
# ╟─4371cfbf-a3b3-45dc-847b-019994fbb234
112118
# ╠═d90b7f67-4166-44fa-aab7-de2c4f38fc00
113-
# ╟─24901666-4cc4-497f-a6ff-68c3e7ead629
119+
# ╠═24901666-4cc4-497f-a6ff-68c3e7ead629
114120
# ╠═7c445baa-d970-4954-a3dc-df828971bfd7
115121
# ╠═1915c023-69cf-4d18-90cb-b47465dbef69
122+
# ╠═227ae9a3-9387-4ac3-b391-e2a78ce40d49
116123
# ╟─abff911a-e10d-4311-955a-7afc4e0d344c
117124
# ╠═bae3c5b7-8964-493b-9e7b-d343e092219c
118125
# ╠═07d2b3b6-3584-4c64-9c4a-138beb3d6b88

src/fractional_fourier_transform.jl

Lines changed: 36 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,17 @@ export frfft
33
"""
44
frfft(arr, p; shift=false, method=:garcia)
55
6-
Calculates the fractional Fourier transform (FRFFT) of the order `p` of `arr`.
6+
Calculates the fractional Fast Fourier transform (FRFFT) of the order `p` of `arr`.
7+
No `dims` argument is supported yet.
78
8-
If `shift=false` the fraction FFT is calculated around the first entry.
9-
If `shift=true` the FRFT
9+
If `shift=false` the FRFFT is calculated around the first entry.
10+
If `shift=true` the FRFFT is calculated aroound the center.
1011
1112
1213
## Methods
1314
Several implementation exists. The following are implemented:
1415
15-
* `method=:garcia`: García, J., Mas, D., & Dorsch, R. G. (1996). Fractional-Fourier-transform calculation through the fast-Fourier-transform algorithm. Applied Optics, 35(35), 7013. doi:10.1364/ao.35.007013
16+
* `method=:garcia`: A convolutional approach based on 2 FFTs. See García, J., Mas, D., & Dorsch, R. G. (1996). Fractional-Fourier-transform calculation through the fast-Fourier-transform algorithm. Applied Optics, 35(35), 7013. doi:10.1364/ao.35.007013
1617
1718
"""
1819
function frfft(_arr, p; shift=true, method=:garcia)
@@ -44,7 +45,7 @@ function frfft(_arr, p; shift=true, method=:garcia)
4445

4546
# trivial case
4647
if iszero(p)
47-
return copy(_arr)
48+
return complex.(_arr)
4849
end
4950

5051
# handle shifting
@@ -105,7 +106,36 @@ function _frfft_garcia(arr::AbstractMatrix{T}, _p) where T
105106
t2 = -1im .* T(π) ./ size(arr) .* sin(p * T(π) / 2)
106107
φ2 = exp.(t2[1] .* m[1].^2 .+ t2[2] .* m[2]'.^2)
107108

108-
Mp = exp(-1im * T(π) * sign(sin(p * T(π) / 2)) / 4 + 1im * p * T(π) / 4 + 1im * T(π) /4)
109+
Mp = exp(-1im * T(π) * sign(sin(p * T(π) / 2)) / 4 + 1im * p * T(π) / 4 + 1im * T(π) / 4)
110+
# can do an in-place fft
111+
res = Mp .* φ1 .* ifft!(φ2 .* fft!(arr .* φ1))
112+
return res
113+
end
114+
115+
116+
function _frfft_garcia(arr::AbstractArray{T, N}, _p) where {N, T}
117+
p = T(_p)
118+
119+
120+
m = fftfreq.(size(arr), T.(size(arr)))
121+
122+
p1 = -1im .* T(π) ./ size(arr) .* tan(p * T(π) / 4)
123+
t1 = similar(arr, complex(T))
124+
fill!(t1, zero(T))
125+
126+
127+
p2 = -1im .* T(π) ./ size(arr) .* sin(p * T(π) / 2)
128+
t2 = similar(arr, complex(T))
129+
fill!(t2, zero(T))
130+
for d in 1:ndims(arr)
131+
ns = ntuple(i -> i == d ? size(arr, i) : 1, Val(ndims(arr)))
132+
t1 .+= reshape(p1[d] .* m[d].^2, ns...)
133+
t2 .+= reshape(p2[d] .* m[d].^2, ns...)
134+
end
135+
136+
φ1 = exp.(t1)
137+
φ2 = exp.(t2)
138+
Mp = exp(-1im * T(π) * sign(sin(p * T(π) / 2)) / 4 + 1im * p * T(π) / 4 + 1im * T(π) / 4)
109139
# can do an in-place fft
110140
res = Mp .* φ1 .* ifft!(φ2 .* fft!(arr .* φ1))
111141
return res

test/fractional_fourier_transform.jl

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,4 +29,17 @@
2929

3030
@test all(.≈(real(frfft(frfft(box1d, 0.5, shift=true), -0.5, shift=true))[30:70] , real(box1d)[30:70], rtol=1e-1))
3131
@test all(.≈(real(frfft(frfft(box1d_, 0.5, shift=true), -0.5, shift=true))[30:70] , real(box1d_)[30:70], rtol=1e-1))
32+
33+
34+
35+
img = Float32.(testimage("resolution_test"))
36+
37+
@test abs.(ft(img)) ./ sqrt(length(img)) .+ 10 10 .+ abs.(frfft(img, 0.999999)) rtol=1e-4
38+
@test (real.(ft(img)) ./ sqrt(length(img)))[200:300] (real.(frfft(img, 0.999999)))[200:300] rtol=0.8
39+
40+
41+
x = randn((12,))
42+
x2 = randn((13,))
43+
@test frft(x, 0.5) frft(reshape(x, 12,1,1,1,1), 0.5)
44+
@test frft(x, 0.5) reshape(frft(reshape(x, 1,12,1,1), 0.5), 12)
3245
end

test/runtests.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ using Zygote
66
using NDTools
77
using LinearAlgebra # for the assigned nfft function LinearAlgebra.mul!
88
using FractionalTransforms
9+
using TestImages
910

1011
Random.seed!(42)
1112

0 commit comments

Comments
 (0)