Skip to content
This repository has been archived by the owner on Dec 11, 2022. It is now read-only.

Fix cropping when omitting a limit #18

Merged
merged 8 commits into from
Apr 10, 2020
26 changes: 21 additions & 5 deletions src/lib/overloads.jl
Original file line number Diff line number Diff line change
Expand Up @@ -162,15 +162,31 @@ Returns a subset of the argument layer, where the new limits are given by
`left`, `right`, `top`, and `bottom`. Up to three of these can be omitted, and
if so these limits will not be affected.
"""
function Base.getindex(p::T; left::K=nothing, right::K=nothing, top::K=nothing, bottom::K=nothing) where {T <: SimpleSDMLayer, K <: Union{Nothing,AbstractFloat}}
imax = isnothing(right) ? p.right : match_longitude(p, right)
imin = isnothing(left) ? p.left : match_longitude(p, left)
jmax = isnothing(top) ? p.top : match_latitude(p, top)
jmin = isnothing(bottom) ? p.bottom : match_latitude(p, bottom)
function Base.getindex(p::T; left::Union{N,A}=nothing, right::Union{N,A}=nothing, top::Union{N,A}=nothing, bottom::Union{N,A}=nothing) where {T <: SimpleSDMLayer, N <: Nothing, A <: AbstractFloat}
Copy link
Member Author

@gabrieldansereau gabrieldansereau Apr 9, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a better way to make the types work? They have to be "independent", so that one can be Nothing while the others are AbstractFloat. The previous code only worked if they were all Nothing or all AbstractFloat.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, we can always not be specific about the types here, since there is an isnothing on one side, and the getindex measures do not have methods for anything other than a float in this case... would it fix the tests?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, it already works like this. I was just wondering if there was a cleaner way to call the types.
It works the same if we're not specific about them, as match_longitude is specific for floats.

imax = match_longitude(p, isnothing(right) ? p.right : right)
imin = match_longitude(p, isnothing(left) ? p.left : left)
jmax = match_latitude(p, isnothing(top) ? p.top : top)
jmin = match_latitude(p, isnothing(bottom) ? p.bottom : bottom)
any(isnan.([imin, imax, jmin, jmax])) && throw(ArgumentError("Unable to extract, coordinates outside of range"))
return p[jmin:jmax, imin:imax]
end

"""
Base.getindex(p::T, n::NT) where {T <: SimpleSDMLayer, NT <: NamedTuple}

Returns a subset of the argument layer, where the new limits are given in
a NamedTuple by `left`, `right`, `top`, and `bottom`, in any order. Up to
three of these can be omitted, and if so these limits will not be affected.
"""

function Base.getindex(p::T, n::NT) where {T <: SimpleSDMLayer, NT <: NamedTuple}
l = isdefined(n, :left) ? n.left : nothing
r = isdefined(n, :right) ? n.right : nothing
t = isdefined(n, :top) ? n.top : nothing
b = isdefined(n, :bottom) ? n.bottom : nothing
Base.getindex(p; left = l, right = r, top = t, bottom = b)
end

"""
Base.getindex(p1::T1, p2::T2) where {T1 <: SimpleSDMLayer, T2 <: SimpleSDMLayer}

Expand Down
9 changes: 9 additions & 0 deletions test/overloads.jl
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,15 @@ end
@test S[left=0.2, right=0.6, bottom=0.5, top=1.0].right ≈ 0.6
@test S[left=0.2, right=0.6, bottom=0.5, top=1.0].left ≈ 0.2

@test typeof(S[left=0.2, bottom=0.5]) == typeof(S)
@test S[left=0.2, bottom=0.5].top ≈ 1.0
@test S[left=0.2, bottom=0.5].bottom ≈ 0.4
@test S[left=0.2, bottom=0.5].right ≈ 1.0
@test S[left=0.2, bottom=0.5].left ≈ 0.2

C = (left=0.2, bottom=0.5)
@test typeof(S[C]) == typeof(S)

Y = SimpleSDMResponse(zeros(Float64, (5,5)), 0.0, 1.0, 0.0, 1.0)
Y[0.1,0.1] = 0.2
@test Y[0.1,0.1] == 0.2
Expand Down