bionanoimaging / FourierTools.jl

Tools for working with Fourier space.
https://bionanoimaging.github.io/FourierTools.jl/stable/
MIT License
55 stars 6 forks source link

Subpixel shifting a `delta` peak #47

Open roflmaostc opened 3 weeks ago

roflmaostc commented 3 weeks ago

Hi,

a single pixel in the digital domain should correspond to a sampled sinc function in the center, right?

But why is the following not the same. sinc(x .- 0.5) is not equal to shift(x, 0.5)

julia> sinc.([-2, -1, 0, 1, 2])
5-element Vector{Int64}:
 0
 0
 1
 0
 0

julia> FourierTools.shift([0.0,0,1,0,0],0.0)
5-element Vector{Float64}:
 0.0
 0.0
 1.0
 0.0
 0.0

julia> sinc.([-2, -1, 0, 1, 2] .- 0.5)
5-element Vector{Float64}:
  0.12732395447351627
 -0.2122065907891938
  0.6366197723675814
  0.6366197723675814
 -0.2122065907891938

julia> FourierTools.shift([0.0,0,1,0,0], 0.5)
5-element Vector{Float64}:
  0.20000000000000007
 -0.24721359549995797
  0.6472135954999579
  0.647213595499958
 -0.24721359549995797

julia> FourierTools.shift([0.0,0,1,0,0], 1)
5-element Vector{Float64}:
 -8.881784197001253e-17
  0.0
  0.0
  1.0
  8.881784197001253e-17

julia> sinc.([-2, -1, 0, 1, 2] .- 1)
5-element Vector{Int64}:
 0
 0
 0
 1
 0
RainerHeintzmann commented 3 weeks ago

Interesting observation. For larger array sizes this is much less of a problem:

julia> z = zeros(1001); z[501]=1; w = FourierTools.shift(z, 0.5)[499:503]
5-element Vector{Float64}:
  0.12732526086576593
 -0.21220737462094055
  0.6366200336442296
  0.6366200336442298
 -0.21220737462094055

julia> q = sinc.([(-2:2)...] .- 0.5)
5-element Vector{Float64}:
  0.12732395447351627
 -0.2122065907891938
  0.6366197723675814
  0.6366197723675814
 -0.2122065907891938

It is some border-problem. But I cannot quite pin it down yet. First I thought is has to do with the normalization but this does not seem to explain it.

RainerHeintzmann commented 3 weeks ago

The Fourier-transformation of the sinc-function is actually non-uniform in spectral power:

julia> abs2.(ft(sinc.([(-2:2)...] .- 0.5)))
5-element Vector{Float64}:
 0.7467277224593416
 1.0689478884113515
 0.952869442609719
 1.0689478884113515
 0.7467277224593416

This deviation appears particularly precisely very close to the limit frequency, this time independent of the array size. I guess it stems from the non-circular match (i.e. first order discontinuity of the shifted sinc.

roflmaostc commented 3 weeks ago

Yeah normalization is not the issue, if you normalize both to 1.

But you are right, bigger arrays are less affected.

Is it because of some periodic boundaries in the FFT? Is the sinc in a 5x5 rectangle in Fourier space simply not a correct sinc?

RainerHeintzmann commented 3 weeks ago

The solution is that the sinc needs to be wrapped (an infinte amount of times) and added to itself:

julia> q = sum(reshape(sinc.([(-2-1000:2+1000)...] .- 0.5), 5,401), dims=2)
5×1 Matrix{Float64}:
  0.1999992081991348
 -0.24721312042132984
  0.6472134371407297
  0.6472134371407297
 -0.2472131204213295

julia> w = FourierTools.shift([0.0,0,1,0,0], +0.5)
5-element Vector{Float64}:
  0.20000000000000007
 -0.24721359549995797
  0.6472135954999579
  0.647213595499958
 -0.24721359549995797
roflmaostc commented 3 weeks ago
julia> abs2.(ft(sinc.([(-10_000:10_000)...] .- 0.5)))
20001-element Vector{Float64}:
 0.7615255254412523
 1.0484160512275191
 0.9810363049226482
 1.0101003912859294
 0.9938140836143488
 1.0041884170316577
 0.9969908766855481
 1.0022707773397115
 0.9982298561760339
 1.0014205141014783
 0.9988365517034244
 1.000971291097762
 0.9991777005374828
 1.0007056426037222
 0.9993882654218811
 1.0005356915444823
 0.9995272534217904
 1.0004204590383112
 0.9996237645641359
 1.0003387568336708
 0.9996934896270387
 1.0002787380863067
 0.9997454929884312
 ⋮
 0.9997454929884303
 1.0002787380863085
 0.9996934896270396
 1.0003387568336695
 0.9996237645641368
 1.0004204590383086
 0.9995272534217908
 1.0005356915444787
 0.9993882654218798
 1.0007056426037209
 0.9991777005374801
 1.0009712910977615
 0.998836551703424
 1.0014205141014774
 0.9982298561760337
 1.0022707773397097
 0.9969908766855485
 1.0041884170316568
 0.9938140836143479
 1.0101003912859285
 0.9810363049226444
 1.0484160512275182
 0.7615255254412541