From 642d925282581e82956052ab76697cd857d9cefe Mon Sep 17 00:00:00 2001 From: Rafael Schouten Date: Fri, 12 Aug 2022 02:09:53 +0200 Subject: [PATCH] Show lookup labels with AbstractDimArray (#389) * show labels with array * fix show for OffsetArray * fix docs and show labels as MIME text/plain --- src/Dimensions/dimension.jl | 34 ++++++------- src/LookupArrays/lookup_arrays.jl | 11 +++-- src/LookupArrays/selector.jl | 11 +++-- src/array/show.jl | 80 +++++++++++++++++++++++++++---- src/set.jl | 34 +++++++------ test/ecosystem.jl | 4 ++ 6 files changed, 126 insertions(+), 48 deletions(-) diff --git a/src/Dimensions/dimension.jl b/src/Dimensions/dimension.jl index 023309f53..6fa44c0dc 100644 --- a/src/Dimensions/dimension.jl +++ b/src/Dimensions/dimension.jl @@ -38,9 +38,10 @@ A = DimArray(zeros(3, 5, 12), (y, x, ti)) X Sampled 2:2:10 ForwardOrdered Regular Points, Ti Sampled DateTime("2021-01-01T00:00:00"):Month(1):DateTime("2021-12-01T00:00:00") ForwardOrdered Regular Points [:, :, 1] - 0.0 0.0 0.0 0.0 0.0 - 0.0 0.0 0.0 0.0 0.0 - 0.0 0.0 0.0 0.0 0.0 + 2 4 6 8 10 + 'a' 0.0 0.0 0.0 0.0 0.0 + 'b' 0.0 0.0 0.0 0.0 0.0 + 'c' 0.0 0.0 0.0 0.0 0.0 [and 11 more slices...] ``` @@ -57,18 +58,18 @@ x = A[X(2), Y(3)] and reference dimensions: Y Categorical Char[c] ForwardOrdered, X Sampled 4:2:4 ForwardOrdered Regular Points - 0.0 - 0.0 - 0.0 - 0.0 - 0.0 - 0.0 - 0.0 - 0.0 - 0.0 - 0.0 - 0.0 - 0.0 + 2021-01-01T00:00:00 0.0 + 2021-02-01T00:00:00 0.0 + 2021-03-01T00:00:00 0.0 + 2021-04-01T00:00:00 0.0 + 2021-05-01T00:00:00 0.0 + 2021-06-01T00:00:00 0.0 + 2021-07-01T00:00:00 0.0 + 2021-08-01T00:00:00 0.0 + 2021-09-01T00:00:00 0.0 + 2021-10-01T00:00:00 0.0 + 2021-11-01T00:00:00 0.0 + 2021-12-01T00:00:00 0.0 ``` A `Dimension` can also wrap [`Selector`](@ref). @@ -83,7 +84,8 @@ x = A[X(Between(3, 4)), Y(At('b'))] Ti Sampled DateTime("2021-01-01T00:00:00"):Month(1):DateTime("2021-12-01T00:00:00") ForwardOrdered Regular Points and reference dimensions: Y Categorical Char[b] ForwardOrdered - 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 + 2021-01-01T00:00:00 … 2021-12-01T00:00:00 + 4 0.0 0.0 ``` `Dimension` objects may have [`lookup`](@ref) and [`metadata`](@ref) fields diff --git a/src/LookupArrays/lookup_arrays.jl b/src/LookupArrays/lookup_arrays.jl index 3c0251e20..d35128421 100644 --- a/src/LookupArrays/lookup_arrays.jl +++ b/src/LookupArrays/lookup_arrays.jl @@ -255,11 +255,12 @@ A = ones(x, y) 5×4 DimArray{Float64,2} with dimensions: X Sampled 100:-20:20 ReverseOrdered Regular Intervals, Y Sampled Int64[1, 4, 7, 10] ForwardOrdered Regular Intervals - 1.0 1.0 1.0 1.0 - 1.0 1.0 1.0 1.0 - 1.0 1.0 1.0 1.0 - 1.0 1.0 1.0 1.0 - 1.0 1.0 1.0 1.0 + 1 4 7 10 + 100 1.0 1.0 1.0 1.0 + 80 1.0 1.0 1.0 1.0 + 60 1.0 1.0 1.0 1.0 + 40 1.0 1.0 1.0 1.0 + 20 1.0 1.0 1.0 1.0 ``` """ struct Sampled{T,A<:AbstractVector{T},O,Sp,Sa,M} <: AbstractSampled{T,O,Sp,Sa} diff --git a/src/LookupArrays/selector.jl b/src/LookupArrays/selector.jl index c984eac71..72f2c7d2b 100644 --- a/src/LookupArrays/selector.jl +++ b/src/LookupArrays/selector.jl @@ -403,7 +403,8 @@ A[X(Between(15, 25)), Y(Between(4, 6.5))] 1×2 DimArray{Int64,2} with dimensions: X Sampled 20:10:20 ForwardOrdered Regular Points, Y Sampled 5:6 ForwardOrdered Regular Points - 4 5 + 5 6 + 20 4 5 ``` """ struct Between{T<:Union{<:AbstractVector{<:Tuple{Any,Any}},Tuple{Any,Any},Nothing}} <: ArraySelector{T} @@ -643,7 +644,8 @@ A[X(Where(x -> x > 15)), Y(Where(x -> x in (19, 21)))] 1×2 DimArray{Int64,2} with dimensions: X Sampled Int64[20] ForwardOrdered Regular Points, Y Sampled Int64[19, 21] ForwardOrdered Regular Points - 4 6 + 19 21 + 20 4 6 ``` """ struct Where{T} <: ArraySelector{T} @@ -679,8 +681,9 @@ A[X=All(At(10.0), At(50.0)), Ti=All(1u"s"..10u"s", 90u"s"..100u"s")] 2×4 DimArray{Int64,2} with dimensions: X Sampled Float64[10.0, 50.0] ForwardOrdered Regular Points, Ti Sampled Quantity{Int64, 𝐓, Unitful.FreeUnits{(s,), 𝐓, nothing}}[1 s, 6 s, 91 s, 96 s] ForwardOrdered Regular Points - 1 2 19 20 - 3 6 57 60 + 1 s 6 s 91 s 96 s + 10.0 1 2 19 20 + 50.0 3 6 57 60 ``` """ struct All{S<:Tuple{Vararg{<:SelectorOrInterval}}} <: Selector{S} diff --git a/src/array/show.jl b/src/array/show.jl index c4548a727..da44df164 100644 --- a/src/array/show.jl +++ b/src/array/show.jl @@ -30,27 +30,27 @@ end # Semi-interface methods for adding addional `show` text # for AbstractDimArray/AbstractDimStack subtypes # TODO actually document in the interface -show_after(io::IO, mime, A::AbstractDimArray) = print_array(io, mime, parent(A)) +show_after(io::IO, mime, A::AbstractDimArray) = print_array(io, mime, A) # Showing the array is optional for AbstractDimArray # `print_array` must be called from `show_after`. -function print_array(io::IO, mime, A::AbstractArray{T,0}) where T +function print_array(io::IO, mime, A::AbstractDimArray{T,0}) where T print(_print_array_ctx(io, T), "\n", A[]) end -function print_array(io::IO, mime, A::AbstractArray{T,1}) where T +function print_array(io::IO, mime, A::AbstractDimArray{T,1}) where T Base.print_matrix(_print_array_ctx(io, T), A) end -function print_array(io::IO, mime, A::AbstractArray{T,2}) where T +function print_array(io::IO, mime, A::AbstractDimArray{T,2}) where T Base.print_matrix(_print_array_ctx(io, T), A) end -function print_array(io::IO, mime, A::AbstractArray{T,N}) where {T,N} - o = ones(Int, N-2) - frame = A[:, :, o...] +function print_array(io::IO, mime, A::AbstractDimArray{T,N}) where {T,N} + o = ntuple(x -> 1, N-2) + frame = view(A, :, :, o...) onestring = join(o, ", ") println(io, "[:, :, $(onestring)]") Base.print_matrix(_print_array_ctx(io, T), frame) nremaining = prod(size(A, d) for d=3:N) - 1 - nremaining > 0 && print(io, "\n[and ", nremaining," more slices...]") + nremaining > 0 && printstyled(io, "\n[and ", nremaining," more slices...]"; color=:light_black) end function _print_array_ctx(io, T) @@ -63,3 +63,67 @@ function print_name(io::IO, name) end end +# Labelled matrix printing is modified from AxisKeys.jl, thanks @mcabbot +function Base.print_matrix(io::IO, A::AbstractDimArray) + h, w = displaysize(io) + wn = w ÷ 3 # integers take 3 columns each when printed, floats more + + A_dims = if ndims(A) == 1 + f1, l1, s1 = firstindex(A, 1), lastindex(A, 1), size(A, 1) + itop = s1 < h ? (f1:l1) : (1:(h ÷ 2)) + ibottom = s1 < h ? (1:0) : s1-(h ÷ 2):s1 + labels = vcat(ShowWith.(lookup(A, 1)[itop]), ShowWith.(lookup(A, 1))[ibottom]) + vals = vcat(parent(A)[itop], parent(A)[ibottom]) + hcat(labels, vals) + else + f1, f2 = firstindex(A, 1), firstindex(A, 2) + l1, l2 = lastindex(A, 1), lastindex(A, 2) + s1, s2 = size(A) + itop = s1 < h ? (f1:l1) : (f1:h ÷ 2 + f1 - 1) + ibottom = s1 < h ? (f1:f1 - 1) : (s1 - h ÷ 2 + f1 - 1:s1 + f1 - 1) + ileft = s2 < wn ? (f2:l2) : (f2:wn ÷ 2 + f2 - 1) + iright = s2 < wn ? (f2:f2 - 1) : (s2 - wn ÷ 2 + f2:s2 + f2 - 1) + + topleft = collect(A[itop, ileft]) + bottomleft = collect(A[ibottom, ileft]) + if !(lookup(A, 1) isa NoLookup) + topleft = hcat(ShowWith.(lookup(A,1)[itop]), topleft) + bottomleft = hcat(ShowWith.(lookup(A, 1)[ibottom]), bottomleft) + end + + leftblock = vcat(topleft, bottomleft) + rightblock = vcat(collect(A[itop, iright]), collect(A[ibottom, iright])) + bottomblock = hcat(leftblock, rightblock) + + if lookup(A, 2) isa NoLookup + bottomblock + else + toplabels = ShowWith.(lookup(A, 2))[ileft], ShowWith.(lookup(A, 2))[iright] + toprow = if lookup(A, 1) isa NoLookup + vcat(toplabels...) + else + vcat(ShowWith(0, hide=true), toplabels...) + end |> permutedims + vcat(toprow, bottomblock) + end + end + Base.print_matrix(io, A_dims) +end + +struct ShowWith{T,NT} <: AbstractString + val::T + hide::Bool + nt::NT + function ShowWith(val; hide::Bool=false, kw...) + new{typeof(val),typeof(values(kw))}(val, hide, values(kw)) + end +end +function Base.show(io::IO, x::ShowWith; kw...) + s = sprint(show, MIME"text/plain"(), x.val; context=io, kw...) + s1 = x.hide ? " "^length(s) : s + printstyled(io, s1; color=:light_black, x.nt...) +end +Base.alignment(io::IO, x::ShowWith) = Base.alignment(io, x.val) +Base.length(x::ShowWith) = length(string(x.val)) +Base.ncodeunits(x::ShowWith) = ncodeunits(string(x.val)) +Base.print(io::IO, x::ShowWith) = printstyled(io, string(x.val); x.nt...) diff --git a/src/set.jl b/src/set.jl index 28258dd25..f081a8e54 100644 --- a/src/set.jl +++ b/src/set.jl @@ -42,9 +42,10 @@ julia> set(da, ones(3, 4)) 3×4 DimArray{Float64,2} with dimensions: Dim{:custom} Sampled 10.0:10.0:30.0 ForwardOrdered Regular Points, Z Sampled -20.0:10.0:10.0 ForwardOrdered Regular Points - 1.0 1.0 1.0 1.0 - 1.0 1.0 1.0 1.0 - 1.0 1.0 1.0 1.0 + -20.0 -10.0 0.0 10.0 + 10.0 1.0 1.0 1.0 1.0 + 20.0 1.0 1.0 1.0 1.0 + 30.0 1.0 1.0 1.0 1.0 ``` Change the `Dimension` wrapper type: @@ -54,9 +55,10 @@ julia> set(da, :Z => Ti, :custom => Z) 3×4 DimArray{Float64,2} with dimensions: Z Sampled 10.0:10.0:30.0 ForwardOrdered Regular Points, Ti Sampled -20.0:10.0:10.0 ForwardOrdered Regular Points - 0.0 0.0 0.0 0.0 - 0.0 0.0 0.0 0.0 - 0.0 0.0 0.0 0.0 + -20.0 -10.0 0.0 10.0 + 10.0 0.0 0.0 0.0 0.0 + 20.0 0.0 0.0 0.0 0.0 + 30.0 0.0 0.0 0.0 0.0 ``` Change the lookup `Vector`: @@ -66,9 +68,10 @@ julia> set(da, Z => [:a, :b, :c, :d], :custom => [4, 5, 6]) 3×4 DimArray{Float64,2} with dimensions: Dim{:custom} Sampled Int64[4, 5, 6] ForwardOrdered Regular Points, Z Sampled Symbol[a, b, c, d] ForwardOrdered Regular Points - 0.0 0.0 0.0 0.0 - 0.0 0.0 0.0 0.0 - 0.0 0.0 0.0 0.0 + :a :b :c :d + 4 0.0 0.0 0.0 0.0 + 5 0.0 0.0 0.0 0.0 + 6 0.0 0.0 0.0 0.0 ``` Change the `LookupArray` type: @@ -78,9 +81,9 @@ julia> set(da, Z=DD.NoLookup(), custom=DD.Sampled()) 3×4 DimArray{Float64,2} with dimensions: Dim{:custom} Sampled 10.0:10.0:30.0 ForwardOrdered Regular Points, Z - 0.0 0.0 0.0 0.0 - 0.0 0.0 0.0 0.0 - 0.0 0.0 0.0 0.0 + 10.0 0.0 0.0 0.0 0.0 + 20.0 0.0 0.0 0.0 0.0 + 30.0 0.0 0.0 0.0 0.0 ``` Change the `Sampling` trait: @@ -90,9 +93,10 @@ julia> set(da, :custom => DD.Irregular(10, 12), Z => DD.Regular(9.9)) 3×4 DimArray{Float64,2} with dimensions: Dim{:custom} Sampled 10.0:10.0:30.0 ForwardOrdered Irregular Points, Z Sampled -20.0:10.0:10.0 ForwardOrdered Regular Points - 0.0 0.0 0.0 0.0 - 0.0 0.0 0.0 0.0 - 0.0 0.0 0.0 0.0 + -20.0 -10.0 0.0 10.0 + 10.0 0.0 0.0 0.0 0.0 + 20.0 0.0 0.0 0.0 0.0 + 30.0 0.0 0.0 0.0 0.0 ``` """ function set end diff --git a/test/ecosystem.jl b/test/ecosystem.jl index 9b1de3094..efbe0ff31 100644 --- a/test/ecosystem.jl +++ b/test/ecosystem.jl @@ -28,6 +28,10 @@ end @test axes(oda[0:1, 7:8]) == (1:2, 1:2) @test axes.(dims(oda[0:1, 7:8])) == ((1:2,), (1:2,)) end + @testset "show" begin + s = sprint(show, MIME("text/plain"), oda) + @test occursin(":a", s) + end end @testset "ImageFiltering and ImageTransformations" begin