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

Commit

Permalink
Merge pull request #18 from EcoJulia/fix/cropping-limit
Browse files Browse the repository at this point in the history
Fix cropping when omitting a limit
  • Loading branch information
tpoisot authored Apr 10, 2020
2 parents 4fe8fb9 + b5537f2 commit 17db192
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 13 deletions.
2 changes: 1 addition & 1 deletion Project.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name = "SimpleSDMLayers"
uuid = "2c645270-77db-11e9-22c3-0f302a89c64c"
authors = ["Timothée Poisot <[email protected]>"]
version = "0.2.0"
version = "0.2.1"

[deps]
GDAL = "add2ef01-049f-52c4-9ee2-e494f65e021a"
Expand Down
44 changes: 32 additions & 12 deletions src/lib/overloads.jl
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ end
Given a layer and a latitude, returns NaN if the latitude is outside the
range, or the grid index containing this latitude if it is within range
"""
function match_latitude(p::T, l::K) where {T <: SimpleSDMLayer, K <: AbstractFloat}
function _match_latitude(p::T, l::K) where {T <: SimpleSDMLayer, K <: AbstractFloat}
l > p.top && return NaN
l < p.bottom && return NaN
return findmin(abs.(l .- latitudes(p)))[2]
Expand All @@ -135,7 +135,7 @@ end
Given a layer and a longitude, returns NaN if the longitude is outside the
range, or the grid index containing this longitude if it is within range
"""
function match_longitude(p::T, l::K) where {T <: SimpleSDMLayer, K <: AbstractFloat}
function _match_longitude(p::T, l::K) where {T <: SimpleSDMLayer, K <: AbstractFloat}
l > p.right && return NaN
l < p.left && return NaN
return findmin(abs.(l .- longitudes(p)))[2]
Expand All @@ -148,29 +148,49 @@ Extracts the value of a layer at a given latitude and longitude. If values
outside the range are requested, will return `NaN`.
"""
function Base.getindex(p::T, longitude::K, latitude::K) where {T <: SimpleSDMLayer, K <: AbstractFloat}
i = match_longitude(p, longitude)
j = match_latitude(p, latitude)
i = _match_longitude(p, longitude)
j = _match_latitude(p, latitude)
isnan(i) && return NaN
isnan(j) && return NaN
return p.grid[j, i]
end

"""
Base.getindex(p::T; left::K=nothing, right::K=nothing, top::K=nothing, bottom::K=nothing) where {T <: SimpleSDMLayer, K <: Union{Nothing,AbstractFloat}}
Base.getindex(p::T; left=nothing, right=nothing, top=nothing, bottom=nothing) where {T <: SimpleSDMLayer, K <: Union{Nothing,AbstractFloat}}
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=nothing, right=nothing, top=nothing, bottom=nothing) where {T <: SimpleSDMLayer}
for limit in [left, right, top, bottom]
if !isnothing(limit)
@assert typeof(limit) <: AbstractFloat
end
end
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 Expand Up @@ -201,8 +221,8 @@ Changes the values of the cell including the point at the requested latitude and
longitude.
"""
function Base.setindex!(p::SimpleSDMResponse{T}, v::T, lon::Float64, lat::Float64) where {T}
i = match_longitude(p, lon)
j = match_latitude(p, lat)
i = _match_longitude(p, lon)
j = _match_latitude(p, lat)
p[j,i] = v
end

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

2 comments on commit 17db192

@tpoisot
Copy link
Member Author

Choose a reason for hiding this comment

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

@JuliaRegistrator
Copy link

Choose a reason for hiding this comment

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

Registration pull request created: JuliaRegistries/General/12683

After the above pull request is merged, it is recommended that a tag is created on this repository for the registered package version.

This will be done automatically if the Julia TagBot GitHub Action is installed, or can be done manually through the github interface, or via:

git tag -a v0.2.1 -m "<description of version>" 17db192af94c2efbf3bd6078e27e6d2ebc3516e9
git push origin v0.2.1

Please sign in to comment.