From 10505291a1579b874fa1869bc8249d53a92d7db1 Mon Sep 17 00:00:00 2001 From: RainerHeintzmann Date: Tue, 28 Feb 2023 18:56:58 +0100 Subject: [PATCH 1/4] fixed a bug in select_region, select_region! and added the dst_center argument to select_region_view --- src/selection_tools.jl | 33 +++++++++++++++++++++------------ test/selection_tools.jl | 2 ++ 2 files changed, 23 insertions(+), 12 deletions(-) diff --git a/src/selection_tools.jl b/src/selection_tools.jl index c2fcc1b..3f145c9 100644 --- a/src/selection_tools.jl +++ b/src/selection_tools.jl @@ -125,7 +125,7 @@ end """ - select_region_view(src; new_size=size(src), center=ft_center_diff(size(src)).+1, pad_value=zero(eltype(src))) + select_region_view(src; new_size=size(src), center=ft_center_diff(size(src)).+1, dst_center=ft_center_diff(new_size), pad_value=zero(eltype(src))) selects (extracts) a region of interest (ROI), defined by `new_size` and centered at `center` in the source image. Note that the number of dimensions can be smaller in `new_size` and `center`, in which case the default values will be insterted @@ -135,6 +135,7 @@ Arguments: + `src`. The source array to select from. + `new_size`. The size of the array view after the operation finished. By default the original size is assumed + `center`. Specifies the center of the new view in coordinates of the old view. By default an alignment of the Fourier-centers is assumed. ++ `dst_center`. Specifies the destination center of the new view to be mapped to the source center as given by `center`. + `pad_value`. Specifies the value which is inserted in case the ROI extends to outside the source area. The returned results is a mutable view, which allows this method to also be used for writing into a ROI @@ -156,11 +157,10 @@ julia> select_region_view(ones(3,3),new_size=(7,7),center=(1,3)) 0.0 0.0 0.0 0.0 0.0 0.0 0.0 ``` """ -function select_region_view(src::Array{T,N}; new_size=size(src), center=ft_center_diff(size(src)).+1, pad_value=zero(eltype(src))) where {T,N} +function select_region_view(src::Array{T,N}; new_size=size(src), center=ft_center_diff(size(src)).+1, dst_center=ft_center_diff(new_size).+1, pad_value=zero(eltype(src))) where {T,N} new_size = Tuple(expand_size(new_size, size(src))) center = Tuple(expand_size(center, ft_center_diff(size(src)).+1)) - oldcenter = ft_center_diff(new_size).+1 - MutablePaddedView(PaddedView(pad_value, src,new_size, oldcenter .- center.+1)) :: MutablePaddedView{T, N, NTuple{N,Base.OneTo{Int64}}, OffsetArrays.OffsetArray{T, N, Array{T, N}}} + MutablePaddedView(PaddedView(pad_value, src,new_size, dst_center .- center.+1)) :: MutablePaddedView{T, N, NTuple{N,Base.OneTo{Int64}}, OffsetArrays.OffsetArray{T, N, Array{T, N}}} end """ @@ -171,8 +171,10 @@ integer center position of the destination aligning with the position in the sou """ function get_src_dst_range(src_size, dst_size, new_size, src_center, dst_ctr=dst_size .÷2 .+1) ROI_center = (new_size.÷2 .+1) - src_start = src_center .- ROI_center .+1 # start of the first pixel to copy (without clipping) - src_end = src_start .+ new_size .- 1 # the last pixel to copy + # start of the first pixel to copy (without clipping): + src_start = src_center .- ROI_center .+1 + # the last pixel to copy: + src_end = src_start .+ new_size .- 1 src_start_clip = max.(1, src_start) src_end_clip = min.(src_end, src_size) if any(src_start_clip .> src_size) || any(src_end_clip .< 1) @@ -187,7 +189,8 @@ function get_src_dst_range(src_size, dst_size, new_size, src_center, dst_ctr=dst dst_end_clip = min.(dst_end, dst_size) dst_start_clip = max.(1, dst_start) if any(dst_start_clip .> dst_size) || any(dst_end_clip .< 1) - return (1:0), (1:0) # returns an empty range for all coordinates + # returns an empty range for all coordinates + return (1:0), (1:0) end extra_dst_start = max.(0, dst_start_clip .- dst_start) @@ -252,7 +255,10 @@ end """ - select_region!(src, dst=nothing; new_size=size(src), center=size(src).÷2 .+1, dst_center=nothing, pad_value=zero(eltype(mat), operator!=assign_to!)) + select_region!(src, dst=nothing; + new_size=ntuple((d)->typemax(Int)÷2,Val(length(size(src)))), + center=size(src).÷2 .+1, dst_center=nothing, + pad_value=zero(eltype(mat), operator!=assign_to!)) selects (extracts, pads, shifts) a region of interest (ROI), defined by `new_size` and centered with the destination center aligned at the position `center` in the source image. Note that the number of dimensions in `new_size`, `center` and `dst_center` can be smaller , @@ -266,7 +272,8 @@ If `nothing` is provided for `dst`, a new array of size `new_size` is created. Arguments: + `src`. The source array to select from. + `dst`. The destination array to write into, if provided. By default `dst=nothing` a new array is created. The `dst`array (or new array) is returned. -+ `new_size`. The size of the array view after the operation finished. By default the original size is assumed ++ `new_size`. The size of the array view after the operation finished. By default a maximally large destination size is chosen, which means that any overlap is copied. + If you specify `new_size`, be aware that the `center` and `dst_center` specifications below really have to refer to centers to be copied! + `center`. Specifies the center of the new view in coordinates of the old view. By default an alignment of the Fourier-center (right center) is assumed. + `dst_center`. defines the center coordinate in the destination array which should align with the above source center. If nothing is provided, the right center pixel of the `dst` array or new array is used. + `pad_value`. specifies the value which is inserted in case the ROI extends to outside the source area. This is only used, if no `dst` array is provided. @@ -311,9 +318,9 @@ julia> dst=select_region(a,new_size=(10,10), dst_center=(1,1)) # pad a with zero 0.0 0.0 0.0 0.0 0.0 0.0 2.0 2.0 2.0 2.0 ``` """ -function select_region!(src, dst; new_size=size(dst), +function select_region!(src, dst; new_size=ntuple((d)->typemax(Int)÷2,Val(length(size(src)))), center=size(src).÷2 .+1, dst_center=size(dst).÷ 2 .+1, operator! =assign_to!) - new_size = Tuple(expand_size(new_size, size(dst))) + new_size = Tuple(expand_size(new_size, size(dst))) center = Tuple(expand_size(center, size(src).÷2 .+1)) dst_center = Tuple(expand_size(dst_center, size(dst).÷ 2 .+1)) @@ -412,7 +419,9 @@ function select_region(src::AbstractArray{T,N}; M=nothing, fill!(arr_n, pad_value) end end - select_region!(src,dst;new_size=new_size, center=center, dst_center=dst_center) + # new_size is intentionally not specified which forces the method to adapt for maximal overlay + # of source and destination. + select_region!(src, dst; center=center, dst_center=dst_center) return dst end diff --git a/test/selection_tools.jl b/test/selection_tools.jl index fb9ef6f..eb2d430 100644 --- a/test/selection_tools.jl +++ b/test/selection_tools.jl @@ -83,6 +83,8 @@ @test all(select_region(a, new_size=nz, center=(-100,100), pad_value=10) .== 10) # only pad values function f(a,b) a.+=1 end # user-defined function @test all(select_region!(2 .*a, a, operator! = f) .== 2) # let the operator add one to destination + @test select_region(collect(1:10), new_size=(5,), center=(1,), dst_center=(1,)) == collect(1:5) + @test select_region_view(collect(1:10), new_size=(5,), center=(1,), dst_center=(1,)) == collect(1:5) end @testset "Test Magnificiation" begin From a690772190b2ddf7da57b654f6439375392aa180 Mon Sep 17 00:00:00 2001 From: RainerHeintzmann Date: Wed, 20 Dec 2023 13:28:42 +0100 Subject: [PATCH 2/4] fixd the use of length --- src/selection_tools.jl | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/selection_tools.jl b/src/selection_tools.jl index 3f145c9..ab82d2f 100644 --- a/src/selection_tools.jl +++ b/src/selection_tools.jl @@ -255,10 +255,10 @@ end """ - select_region!(src, dst=nothing; - new_size=ntuple((d)->typemax(Int)÷2,Val(length(size(src)))), + select_region!(srcsrc::AbstractArray{T, N}, dst=nothing; + new_size=ntuple((d)->typemax(Int)÷2,Val(N)), center=size(src).÷2 .+1, dst_center=nothing, - pad_value=zero(eltype(mat), operator!=assign_to!)) + pad_value=zero(eltype(mat), operator!=assign_to!)) where {T,N} selects (extracts, pads, shifts) a region of interest (ROI), defined by `new_size` and centered with the destination center aligned at the position `center` in the source image. Note that the number of dimensions in `new_size`, `center` and `dst_center` can be smaller , @@ -318,8 +318,8 @@ julia> dst=select_region(a,new_size=(10,10), dst_center=(1,1)) # pad a with zero 0.0 0.0 0.0 0.0 0.0 0.0 2.0 2.0 2.0 2.0 ``` """ -function select_region!(src, dst; new_size=ntuple((d)->typemax(Int)÷2,Val(length(size(src)))), - center=size(src).÷2 .+1, dst_center=size(dst).÷ 2 .+1, operator! =assign_to!) +function select_region!(src::AbstractArray{T, N}, dst; new_size=ntuple((d)->typemax(Int)÷2,Val(N)), + center=size(src).÷2 .+1, dst_center=size(dst).÷ 2 .+1, operator! =assign_to!) where {T,N} new_size = Tuple(expand_size(new_size, size(dst))) center = Tuple(expand_size(center, size(src).÷2 .+1)) dst_center = Tuple(expand_size(dst_center, size(dst).÷ 2 .+1)) From 1acfb487b4f611ce2bd7fb522900f65d47a541d3 Mon Sep 17 00:00:00 2001 From: RainerHeintzmann Date: Wed, 20 Dec 2023 18:40:14 +0100 Subject: [PATCH 3/4] new equation for default size --- src/selection_tools.jl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/selection_tools.jl b/src/selection_tools.jl index ab82d2f..a54a96e 100644 --- a/src/selection_tools.jl +++ b/src/selection_tools.jl @@ -256,8 +256,8 @@ end """ select_region!(srcsrc::AbstractArray{T, N}, dst=nothing; - new_size=ntuple((d)->typemax(Int)÷2,Val(N)), center=size(src).÷2 .+1, dst_center=nothing, + new_size==2 .*abs.(dst_center.-(size(dst).÷ 2 .+1)) .+ size(dst), pad_value=zero(eltype(mat), operator!=assign_to!)) where {T,N} selects (extracts, pads, shifts) a region of interest (ROI), defined by `new_size` and centered with the destination center aligned at @@ -318,8 +318,8 @@ julia> dst=select_region(a,new_size=(10,10), dst_center=(1,1)) # pad a with zero 0.0 0.0 0.0 0.0 0.0 0.0 2.0 2.0 2.0 2.0 ``` """ -function select_region!(src::AbstractArray{T, N}, dst; new_size=ntuple((d)->typemax(Int)÷2,Val(N)), - center=size(src).÷2 .+1, dst_center=size(dst).÷ 2 .+1, operator! =assign_to!) where {T,N} +function select_region!(src::AbstractArray{T, N}, dst; + center=size(src).÷2 .+1, dst_center=size(dst).÷ 2 .+1, new_size=2 .*abs.(dst_center.-(size(dst).÷ 2 .+1)) .+ size(dst), operator! =assign_to!) where {T,N} new_size = Tuple(expand_size(new_size, size(dst))) center = Tuple(expand_size(center, size(src).÷2 .+1)) dst_center = Tuple(expand_size(dst_center, size(dst).÷ 2 .+1)) From 4fbe45e9187aec0c72d52804650e28cdac5fc5c5 Mon Sep 17 00:00:00 2001 From: RainerHeintzmann Date: Thu, 21 Dec 2023 14:50:57 +0100 Subject: [PATCH 4/4] bug fix and fix in documentation --- src/selection_tools.jl | 9 ++++++--- test/selection_tools.jl | 8 ++++++++ 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/src/selection_tools.jl b/src/selection_tools.jl index a54a96e..0909ca8 100644 --- a/src/selection_tools.jl +++ b/src/selection_tools.jl @@ -255,9 +255,9 @@ end """ - select_region!(srcsrc::AbstractArray{T, N}, dst=nothing; + select_region!(src::AbstractArray{T, N}, dst=nothing; center=size(src).÷2 .+1, dst_center=nothing, - new_size==2 .*abs.(dst_center.-(size(dst).÷ 2 .+1)) .+ size(dst), + new_size=2 .*(1 .+ abs.(dst_center.-(size(src).÷ 2 .+ 1))) .+ size(src), pad_value=zero(eltype(mat), operator!=assign_to!)) where {T,N} selects (extracts, pads, shifts) a region of interest (ROI), defined by `new_size` and centered with the destination center aligned at @@ -274,6 +274,7 @@ Arguments: + `dst`. The destination array to write into, if provided. By default `dst=nothing` a new array is created. The `dst`array (or new array) is returned. + `new_size`. The size of the array view after the operation finished. By default a maximally large destination size is chosen, which means that any overlap is copied. If you specify `new_size`, be aware that the `center` and `dst_center` specifications below really have to refer to centers to be copied! + If `new_size` is not specified, a size to fully encompass the (potentially displaced) source array is automatically chosen. + `center`. Specifies the center of the new view in coordinates of the old view. By default an alignment of the Fourier-center (right center) is assumed. + `dst_center`. defines the center coordinate in the destination array which should align with the above source center. If nothing is provided, the right center pixel of the `dst` array or new array is used. + `pad_value`. specifies the value which is inserted in case the ROI extends to outside the source area. This is only used, if no `dst` array is provided. @@ -319,7 +320,9 @@ julia> dst=select_region(a,new_size=(10,10), dst_center=(1,1)) # pad a with zero ``` """ function select_region!(src::AbstractArray{T, N}, dst; - center=size(src).÷2 .+1, dst_center=size(dst).÷ 2 .+1, new_size=2 .*abs.(dst_center.-(size(dst).÷ 2 .+1)) .+ size(dst), operator! =assign_to!) where {T,N} + center=size(src).÷2 .+1, dst_center=size(dst).÷ 2 .+1, + new_size=2 .*(1 .+ abs.(dst_center.-(size(src).÷ 2 .+ 1))) .+ size(src), + operator! =assign_to!) where {T,N} new_size = Tuple(expand_size(new_size, size(dst))) center = Tuple(expand_size(center, size(src).÷2 .+1)) dst_center = Tuple(expand_size(dst_center, size(dst).÷ 2 .+1)) diff --git a/test/selection_tools.jl b/test/selection_tools.jl index eb2d430..098046b 100644 --- a/test/selection_tools.jl +++ b/test/selection_tools.jl @@ -85,6 +85,14 @@ @test all(select_region!(2 .*a, a, operator! = f) .== 2) # let the operator add one to destination @test select_region(collect(1:10), new_size=(5,), center=(1,), dst_center=(1,)) == collect(1:5) @test select_region_view(collect(1:10), new_size=(5,), center=(1,), dst_center=(1,)) == collect(1:5) + a = ones(10,10) + select_region!(2 .*a, a, dst_center=(10,10)); + @test all(a[5:end,5:end] .== 2) # check the overwritten part + @test all(a[1:4,1:4] .== 1) # check part of the non-overwritten part + a = ones(10,10) + b = 4*ones(70,70) + select_region!(b, a, dst_center=(-20,20)); + @test all(a .== 4) # check the automatic selection of a large enough new_size end @testset "Test Magnificiation" begin