diff --git a/docs/src/intro.md b/docs/src/intro.md index 538768f..d4b11ed 100644 --- a/docs/src/intro.md +++ b/docs/src/intro.md @@ -77,16 +77,12 @@ through Julia's type system. However, functions that receive an in your own code it's fine to use properties to your advantage for custom tasks. -### getindexim/viewim +### Vector indexing (region-of-interest selection) -As with the rest of julia, `img[i,j,...]` will return just the values -in an `ImageMeta`; the properties dictionary is "left behind." You can -ensure that the return is also an `ImageMeta` using `getindexim` -instead of `getindex` (`img[i,j]` gets converted into `getindex(img, -i, j)`, hence the name): +When indexing over an extended area, `img[i,j,...]` returns an `ImageMeta`: ```julia -julia> c = getindexim(img, 1:2, 1:2) +julia> c = img[1:2, 1:2] RGB ImageMeta with: data: 2×2 Array{ColorTypes.RGB{FixedPointNumbers.Normed{UInt8,8}},2} properties: @@ -97,7 +93,7 @@ RGB ImageMeta with: This copies both the data (just the relevant portions) and the properties dictionary. In contrast, ```julia -julia> v = viewim(img, 1:2, 1:2) +julia> v = view(img, 1:2, 1:2) RGB ImageMeta with: data: 2×2 SubArray{ColorTypes.RGB{FixedPointNumbers.Normed{UInt8,8}},2,Array{ColorTypes.RGB{FixedPointNumbers.Normed{UInt8,8}},2},Tuple{UnitRange{Int64},UnitRange{Int64}},false} properties: diff --git a/src/ImageMetadata.jl b/src/ImageMetadata.jl index 48cc57e..6059cf3 100644 --- a/src/ImageMetadata.jl +++ b/src/ImageMetadata.jl @@ -19,11 +19,9 @@ export # functions copyproperties, data, - getindexim, properties, shareproperties, - spatialproperties, - viewim + spatialproperties #### types and constructors #### @@ -91,10 +89,10 @@ for AType in (ImageMeta, ImageMetaAxis) end @inline function Base.getindex(img::ImageMetaAxis, ax::Axis, I...) - img.data[ax, I...] + copyproperties(img, img.data[ax, I...]) end @inline function Base.getindex(img::ImageMetaAxis, i::Union{Integer,AbstractVector,Colon}, I...) - img.data[i, I...] + copyproperties(img, img.data[i, I...]) end @inline function Base.setindex!(img::ImageMetaAxis, val, ax::Axis, I...) @@ -104,10 +102,10 @@ end setindex!(img.data, val, i, I...) end -Base.view(img::ImageMetaAxis, ax::Axis, I...) = view(img.data, ax, I...) -Base.view{T,N}(img::ImageMetaAxis{T,N}, I::Vararg{ViewIndex,N}) = view(img.data, I...) -Base.view(img::ImageMetaAxis, i::ViewIndex) = view(img.data, i) -Base.view{N}(img::ImageMetaAxis, I::Vararg{ViewIndex,N}) = view(img.data, I...) +Base.view(img::ImageMeta, ax::Axis, I...) = shareproperties(img, view(img.data, ax, I...)) +Base.view{T,N}(img::ImageMeta{T,N}, I::Vararg{ViewIndex,N}) = shareproperties(img, view(img.data, I...)) +Base.view(img::ImageMeta, i::ViewIndex) = shareproperties(img, view(img.data, i)) +Base.view{N}(img::ImageMeta, I::Vararg{ViewIndex,N}) = shareproperties(img, view(img.data, I...)) Base.getindex(img::ImageMeta, propname::AbstractString) = img.properties[propname] @@ -160,29 +158,6 @@ shareproperties(img::ImageMeta, data::AbstractArray) = ImageMeta(data, img.prope # Delete a property! Base.delete!(img::ImageMeta, propname::AbstractString) = delete!(img.properties, propname) -""" - getindexim(img::ImageMeta, I...) -> newimg - -Like `img[I...]`, except that the returned `newimg` is another -ImageMeta. Like the data component, the properties dictionary of `img` -is copied, so `newimg` is not linked in any way to `img`. - -See also: [`viewim`](@ref). -""" -getindexim(img::ImageMeta, I...) = copyproperties(img, img.data[I...]) - -""" - viewim(img::ImageMeta, I...) -> newimg - -Like `view(img, I...)`, except that the returned `newimg` is another -ImageMeta. Like the data component, the properties dictionary of `img` -is shared with `img`, so that changes to either the data or the -properties apply to both. - -See also: [`getindexim`](@ref). -""" -viewim(img::ImageMeta, I...) = shareproperties(img, view(img.data, I...)) - # Iteration # Defer to the array object in case it has special iteration defined Base.start(img::ImageMeta) = start(data(img)) diff --git a/src/deprecated.jl b/src/deprecated.jl index eef5eb6..9ee7a7e 100644 --- a/src/deprecated.jl +++ b/src/deprecated.jl @@ -14,13 +14,13 @@ Base.@deprecate_binding AbstractImageIndexed ImageMetaIndirect @deprecate ImageCmap(data, cmap; kwargs...) ImageMeta(IndirectArray(data, cmap); kwargs...) @deprecate ImageCmap(data, cmap, properties) ImageMeta(IndirectArray(data, cmap), properties) -Base.@deprecate_binding sliceim viewim +Base.@deprecate_binding sliceim view function subim(img::Union{AxisArray,ImageMeta}, args...) newargs = _subim_indexes(args) newargstr = join(map(string, newargs), ", ") - Base.depwarn("subim is deprecated, call viewim(img, $newargstr) instead", :subim) - viewim(img, newargs...) + Base.depwarn("subim is deprecated, call view(img, $newargstr) instead", :subim) + view(img, newargs...) end export subim @@ -46,12 +46,6 @@ end using ImageAxes: getaxes function Base.view(img::ImageMetaAxis, dimname::AbstractString, ind::Base.ViewIndex, args...) - axs = getaxes(dimname, ind, args...) - Base.depwarn("indexing with strings is deprecated, use view(img, $(axs...)) instead", :view!) - view(img.data, axs...) -end - -function viewim(img::ImageMetaAxis, dimname::AbstractString, ind::Base.ViewIndex, args...) axs = getaxes(dimname, ind, args...) Base.depwarn("indexing with strings is deprecated, use view(img, $(axs...)) instead", :view!) shareproperties(img, view(img.data, axs...)) @@ -60,8 +54,6 @@ end @deprecate copyproperties(img::AbstractArray, data::AbstractArray) data @deprecate shareproperties(img::AbstractArray, data::AbstractArray) data -@deprecate getindexim(img::AbstractArray, I...) img[I...] -@deprecate viewim(img::AbstractArray, I...) view(img, I...) #### Properties #### @@ -152,3 +144,6 @@ import ImageAxes.storageorder @deprecate real(img::ImageMeta) shareproperties(img,real.(data(img))) @deprecate imag(img::ImageMeta) shareproperties(img,imag.(data(img))) @deprecate abs(img::ImageMeta) shareproperties(img,abs.(data(img))) + +@deprecate getindexim getindex +@deprecate viewim view diff --git a/test/core.jl b/test/core.jl index 547cc20..ca88e6c 100644 --- a/test/core.jl +++ b/test/core.jl @@ -15,10 +15,10 @@ using Base.Test @test size(img) == (3,) @test data(img) === A for i = 1:3 - @test img[i] === A[i] + @test @inferred(img[i]) === A[i] end for I in eachindex(img) - @test img[I] === A[I] + @test @inferred(img[I]) === A[I] end k = 0 for a in img @@ -49,13 +49,13 @@ using Base.Test @test size(img) == (3,5) @test data(img) === A for j = 1:5, i = 1:3 - @test img[i,j] === A[i,j] + @test @inferred(img[i,j]) === A[i,j] end for k = 1:15 - @test img[k] === A[k] + @test @inferred(img[k]) === A[k] end for I in eachindex(img) - @test img[I] === A[I] + @test @inferred(img[I]) === A[I] end k = 0 for a in img @@ -74,6 +74,17 @@ using Base.Test @test img["prop2"] == [1,2,3] img["prop1"] = -1 @test img["prop1"] == -1 + # vector-indexing + @test isa(@inferred(img[:,:]), ImageMeta) && img[:,:] == img + @test isa(@inferred(img[:]), ImageMeta) && img[:] == A[:] + @test isa(@inferred(img[1:2,1:2]), ImageMeta) && img[1:2,1:2] == A[1:2,1:2] + @test isa(@inferred(img[1:2,:]), ImageMeta) && img[1:2,:] == A[1:2,:] + @test isa(@inferred(img[:,1:2]), ImageMeta) && img[:,1:2] == A[:,1:2] + @test isa(@inferred(view(img,:,:)), ImageMeta) && view(img,:,:) == img + @test isa(@inferred(view(img,:)), ImageMeta) && view(img,:) == A[:] + @test isa(@inferred(view(img,1:2,1:2)), ImageMeta) && view(img,1:2,1:2) == A[1:2,1:2] + @test isa(@inferred(view(img,1:2,:)), ImageMeta) && view(img,1:2,:) == A[1:2,:] + @test isa(@inferred(view(img,:,1:2)), ImageMeta) && view(img,:,1:2) == A[:,1:2] end # Test bounds-checking removal by @inbounds if Base.JLOptions().check_bounds != 1 && Base.JLOptions().can_inline == 1 @@ -90,12 +101,12 @@ using Base.Test A = AxisArray(rand(3,5), :y, :x) B = ImageMeta(A, info="blah") Broi = B[2:3, 2:3] - @test isa(Broi, AxisArray) + @test isa(Broi, ImageMeta) @test axisnames(Broi) == (:y, :x) A1, B1 = A[2:7], B[2:7] - @test typeof(A1) == typeof(B1) && A1 == B1 + @test isa(B1, ImageMeta) && A1 == B1 Broi = view(B, 2:3, 2:3) - @test isa(Broi, AxisArray) + @test isa(Broi, ImageMeta) @test axisnames(Broi) == (:y, :x) end @@ -164,8 +175,8 @@ end @testset "copy/shareproperties/viewim" begin img = ImageMeta(rand(3,5); prop1 = 1, prop2 = [1,2,3]) @test !isempty(properties(img)) - v = viewim(img, 1:2, 1:2) - c = getindexim(img, 1:2, 1:2) + v = view(img, 1:2, 1:2) + c = img[1:2, 1:2] @test v["prop1"] == 1 @test c["prop1"] == 1 img2 = copyproperties(img, reshape(1:15, 5, 3)) @@ -194,8 +205,8 @@ end Axis{:y}(1:5), Axis{:time}(0.1:0.1:0.8)); prop1 = 1, prop2 = [1,2,3]) - v = viewim(img, Axis{:time}(0.25..0.5)) - c = getindexim(img, Axis{:time}(0.25..0.5)) + v = view(img, Axis{:time}(0.25..0.5)) + c = img[Axis{:time}(0.25..0.5)] @test v["prop1"] == 1 @test c["prop1"] == 1 end diff --git a/test/deprecated.jl b/test/deprecated.jl index 08adbaf..08bf560 100644 --- a/test/deprecated.jl +++ b/test/deprecated.jl @@ -70,6 +70,13 @@ msg_contains(pass, msg) = contains(pass.value.msg, msg) || error(pass.value.msg, msg_contains(result, "data, :boo, :rah") end end + + @testset "getindexim/viewim" begin + img = ImageMeta(rand(3,5); prop1 = 1, prop2 = [1,2,3]) + @test !isempty(properties(img)) + @test isa(viewim(img, 1:2, 1:2), ImageMeta) + @test isa(getindexim(img, 1:2, 1:2), ImageMeta) + end end nothing