Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions Project.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name = "RegisterMismatch"
uuid = "3c0dd727-6833-5f5d-a1e8-c0d421935c74"
version = "1.0.0"
version = "1.0.1"
authors = ["Tim Holy <tim.holy@gmail.com>"]

[deps]
Expand Down Expand Up @@ -29,7 +29,7 @@ Printf = "1"
RFFT = "0.1, 1"
Reexport = "0.2, 1"
RegisterCore = "1"
RegisterMismatchCommon = "1"
RegisterMismatchCommon = "1.0.3"
Test = "1"
julia = "1.10"

Expand Down
51 changes: 34 additions & 17 deletions src/RegisterMismatch.jl
Original file line number Diff line number Diff line change
Expand Up @@ -9,38 +9,49 @@ using PaddedViews: PaddedViews, PaddedView
using Printf: Printf, @printf
using RFFT: RFFT, RCpair, plan_irfft!, plan_rfft!
using Reexport: Reexport, @reexport
using RegisterCore: RegisterCore, MismatchArray, highpass, maxshift
using RegisterCore: RegisterCore, MismatchArray, highpass, highpass!, maxshift
import RegisterMismatchCommon: mismatch0, mismatch, mismatch_apertures
@reexport using RegisterMismatchCommon: DimsLike, RegisterMismatchCommon, WidthLike,
FFTPROD, set_FFTPROD,
allocate_mmarrays, aperture_grid, aperture_range,
assertsamesize, checksize_maxshift, correctbias!,
default_aperture_width, each_point, nanpad,
padranges, padsize, register_translate, set_FFTPROD,
shiftrange, tovec, truncatenoise!
assertsamesize, checksamesize,
checksize_maxshift, checksizemaxshift,
correctbias!, correctbias,
default_aperture_width,
each_aperture_center, each_point,
mismatch_zeroshift,
nanpad, padranges, padsize,
register_translate, shiftrange, tovec,
truncatenoise!, truncatenoise

export
CMStorage,
fillfixed!,
highpass,
highpass!,
inner_threading,
mismatch0,
mismatch,
mismatch!,
mismatch_apertures,
mismatch_apertures!
mismatch_apertures!,
set_inner_threading!

const INNER_THREADING = Ref{Bool}(true)

"""
allow_inner_threading!(state::Bool)
set_inner_threading!(state::Bool)

Control whether threading is enabled in inner functions here. Enabled by default.
Enable (`true`) or disable (`false`) threading in inner mismatch loops. Enabled by default.
"""
allow_inner_threading!(state::Bool) = (INNER_THREADING[] = state)
set_inner_threading!(state::Bool) = (INNER_THREADING[] = state)

Base.@deprecate allow_inner_threading!(state) set_inner_threading!(state)

"""
inner_threading()::Bool
inner_threading() -> Bool

Return whether threading is enabled in inner functions here. Enabled by default.
Return whether threading is currently enabled in inner mismatch loops.
"""
inner_threading() = INNER_THREADING[]

Expand All @@ -59,7 +70,7 @@ The major types and functions exported are:

- `mismatch` and `mismatch!`: compute the mismatch between two images
- `mismatch_apertures` and `mismatch_apertures!`: compute apertured mismatch between two images
- `mismatch0`: simple direct mismatch calculation with no shift
- `mismatch_zeroshift` (alias: `mismatch0`): simple direct mismatch calculation with no shift
- `nanpad`: pad the smaller image with NaNs
- `highpass`: highpass filter an image
- `correctbias!`: replace corrupted mismatch data (due to camera bias inhomogeneity) with imputed data
Expand All @@ -71,7 +82,7 @@ The major types and functions exported are:
RegisterMismatch

FFTW.set_num_threads(min(Sys.CPU_THREADS, 8))
set_FFTPROD([2, 3])
set_FFTPROD([2, 3]) # default: FFT sizes are products of 2^a * 3^b

mutable struct NanCorrFFTs{T <: AbstractFloat, N, RCType <: RCpair{T, N}}
const I0::RCType
Expand Down Expand Up @@ -151,8 +162,14 @@ function CMStorage{T, N}(::UndefInitializer, aperture_width::NTuple{N, <:Real},
return CMStorage{T, N, typeof(buf1), typeof(fftfunc), typeof(ifftfunc)}(Float64[aperture_width...], maxshiftv, getindices, padded, fixed, moving, buf1, buf2, fftfunc, ifftfunc, shiftindices)
end

CMStorage{T}(::UndefInitializer, aperture_width::NTuple{N, <:Real}, maxshift::Dims{N}; kwargs...) where {T <: Real, N} =
CMStorage{T, N}(undef, aperture_width, maxshift; kwargs...)
function CMStorage{T}(::UndefInitializer, aperture_width::WidthLike, maxshift::DimsLike; kwargs...) where {T <: Real}
N = length(aperture_width)
length(maxshift) == N || error("aperture_width and maxshift must have the same length, got $N and $(length(maxshift))")
return CMStorage{T, N}(undef,
ntuple(i -> Float64(aperture_width[i]), N),
ntuple(i -> Int(maxshift[i]), N);
kwargs...)
end

eltype(cms::CMStorage{T, N}) where {T, N} = T
ndims(cms::CMStorage{T, N}) where {T, N} = N
Expand Down Expand Up @@ -212,7 +229,7 @@ function mismatch!(mm::MismatchArray, cms::CMStorage, moving::AbstractArray; nor
# regions that might be in the parent Array but are not present
# within the boundaries of the SubArray. Use NaN only for pixels
# truly lacking data.
checksize_maxshift(mm, cms.maxshift)
checksizemaxshift(mm, cms.maxshift)
copyto!(cms.padded, CartesianIndices(cms.padded), moving, CartesianIndices(moving))
fftnan!(cms.moving, cms.padded, cms.fftfunc!)
# Compute the mismatch
Expand Down Expand Up @@ -313,7 +330,7 @@ function mismatch_apertures!(mms, fixed, moving, aperture_centers, cms::CMStorag
fillvalue = convert(T, NaN)
getinds = (cms.getindices...,)::NTuple{ndims(fixed), UnitRange{Int}}
fixedT, movingT = of_eltype(T, fixed), of_eltype(T, moving)
for (mm, center) in zip(mms, each_point(aperture_centers))
for (mm, center) in zip(mms, each_aperture_center(aperture_centers))
rng = aperture_range(center, cms.aperture_width)
fsnip = PaddedView(fillvalue, fixedT, rng)
erng = shiftrange.(getinds, first.(rng) .- 1) # expanded rng
Expand Down
20 changes: 10 additions & 10 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -46,11 +46,11 @@ accuracy = 1.0e-5 # new isapprox accuracy = 1e-6
(10, 1) (10, 3) (10, 5) (10, 7)
]
@test RegisterMismatch.aperture_grid((10, 7), (4, 4)) == agrid
for (i, pt) in enumerate(RegisterMismatch.each_point(agrid))
for (i, pt) in enumerate(RegisterMismatch.each_aperture_center(agrid))
@test pt == agrid[i]
end
agrida = reshape(reinterpret(Int, vec(agrid)), (2, 4, 4))
for (i, pt) in enumerate(RegisterMismatch.each_point(agrida))
for (i, pt) in enumerate(RegisterMismatch.each_aperture_center(agrida))
@test pt == [agrid[i]...]
end

Expand Down Expand Up @@ -92,7 +92,7 @@ end
mdutils = nothing
devlist = nothing
@testset for threading in (true, false)
RegisterMismatch.allow_inner_threading!(threading)
RegisterMismatch.set_inner_threading!(threading)
@testset for imsz in ((7, 10), (6, 5))
@testset for maxshift in ((4, 3), (3, 2))
Apad = parent(ImageFiltering.padarray(reshape(1:prod(imsz), imsz[1], imsz[2]), Fill(0, maxshift, maxshift)))
Expand Down Expand Up @@ -121,13 +121,13 @@ end
end
end

# Test for denom overflow with mismatch0
# Test for denom overflow with mismatch_zeroshift
@testset "Denom overflow" begin
C16 = N0f16[0.6 0.1; 0.7 0.1]
D16 = N0f16[0.7 0.1; 0.6 0.1]
C = Float64.(C16)
D = Float64.(D16)
nd = RegisterMismatch.mismatch0(C16, D16; normalization = :intensity)
nd = RegisterMismatch.mismatch_zeroshift(C16, D16; normalization = :intensity)
@test nd.denom ≈ sum((C .^ 2) .+ (D .^ 2))
@test nd.num ≈ sum((C .- D) .^ 2)
end
Expand All @@ -137,17 +137,17 @@ end
C = rand(7, 9)
D = rand(7, 9)
mm = RegisterMismatch.mismatch(C, D, (3, 3))
nd = RegisterMismatch.mismatch0(C, D)
nd = RegisterMismatch.mismatch_zeroshift(C, D)
@test mm[0, 0].num ≈ nd.num
@test mm[0, 0].denom ≈ nd.denom
mm = RegisterMismatch.mismatch(C, D, (3, 3), normalization = :pixels)
nd = RegisterMismatch.mismatch0(C, D, normalization = :pixels)
nd = RegisterMismatch.mismatch_zeroshift(C, D, normalization = :pixels)
@test mm[0, 0].num ≈ nd.num
@test mm[0, 0].denom ≈ nd.denom

mms = RegisterMismatch.mismatch_apertures(C, D, (2, 2), (3, 2), normalization = :intensity)
nd0 = RegisterMismatch.mismatch0(C, D)
nd1 = RegisterMismatch.mismatch0(mms)
nd0 = RegisterMismatch.mismatch_zeroshift(C, D)
nd1 = RegisterMismatch.mismatch_zeroshift(mms)
@test nd0.num ≈ nd1.num
@test nd0.denom ≈ nd1.denom
end
Expand Down Expand Up @@ -265,7 +265,7 @@ end
@testset "Mismatched types" begin
A = rand(Float32, 5, 5)
B = rand(5, 5)
mm = RegisterMismatch.mismatch0(A, B)
mm = RegisterMismatch.mismatch_zeroshift(A, B)
@test eltype(mm) == Float64
end

Expand Down
Loading