diff --git a/Project.toml b/Project.toml index b958f53..a0e907e 100644 --- a/Project.toml +++ b/Project.toml @@ -16,6 +16,7 @@ SliceMap = "82cb661a-3f19-5665-9e27-df437c7e54c8" SpecialFunctions = "276daf66-3868-5448-9aa4-cd146d93841b" Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2" StatsBase = "2913bbd2-ae8a-5f71-8c99-4fb6c76f3a91" +Term = "22787eb5-b846-44ae-b979-8e399b8463ab" [weakdeps] SpeciesDistributionToolkit = "72b53823-5c0b-4575-ad0e-8e97227ad13b" @@ -26,11 +27,11 @@ SDMToolkitExt = ["SpeciesDistributionToolkit"] [compat] Distributions = "0.25" HaltonSequences = "0.2" +HiGHS = "1.5" +JuMP = "1.11" +ProgressMeter = "1.7.2" Requires = "1.3" SliceMap = "0.2.7" SpecialFunctions = "2.1" StatsBase = "0.34" -ProgressMeter = "1.7.2" -JuMP = "1.11" -HiGHS = "1.5" -julia = "1.9" +julia = "1.9" diff --git a/src/BiodiversityObservationNetworks.jl b/src/BiodiversityObservationNetworks.jl index fa08dd4..b4b7b47 100644 --- a/src/BiodiversityObservationNetworks.jl +++ b/src/BiodiversityObservationNetworks.jl @@ -10,10 +10,14 @@ using SliceMap using JuMP using HiGHS using LinearAlgebra +using Term include("types.jl") export BONSeeder, BONRefiner, BONSampler +include("exceptions.jl") +export BONException, SeederException, TooFewSites, TooManySites + include("simplerandom.jl") export SimpleRandom diff --git a/src/balancedacceptance.jl b/src/balancedacceptance.jl index 8c95df0..b81c34c 100644 --- a/src/balancedacceptance.jl +++ b/src/balancedacceptance.jl @@ -9,11 +9,7 @@ Base.@kwdef mutable struct BalancedAcceptance{I <: Integer, F <: AbstractFloat} α::F = 1.0 function BalancedAcceptance(numpoints, α) if numpoints < one(numpoints) - throw( - ArgumentError( - "You cannot have a BalancedAcceptance with fewer than one point", - ), - ) + throw(TooFewSites(numpoints)) end if α < zero(α) throw( @@ -39,27 +35,26 @@ function _generate!( np, α = sampler.numpoints, sampler.α x, y = size(uncertainty) - nonnan_indices = findall(!isnan, uncertainty) stduncert = similar(uncertainty) - + uncert_values = uncertainty[nonnan_indices] stduncert_values = similar(uncert_values) - zfit = nothing + zfit = nothing if var(uncert_values) > 0 zfit = StatsBase.fit(ZScoreTransform, uncert_values) stduncert_values = StatsBase.transform(zfit, uncert_values) end - + nonnan_counter = 1 for i in eachindex(uncertainty) - if isnan(uncertainty[i]) + if isnan(uncertainty[i]) stduncert[i] = NaN elseif !isnothing(zfit) stduncert[i] = stduncert_values[nonnan_counter] nonnan_counter += 1 - else - stduncert[i] = 1. + else + stduncert[i] = 1.0 end end diff --git a/src/exceptions.jl b/src/exceptions.jl new file mode 100644 index 0000000..08c140f --- /dev/null +++ b/src/exceptions.jl @@ -0,0 +1,27 @@ +abstract type BONException <: Base.Exception end +abstract type SeederException <: BONException end + +Base.showerror(io::IO, e::E) where {E <: BONException} = + tprint( + io, + "{bold red}$(supertype(E)){/bold red} | {bold yellow}$E{/bold yellow}\n" * + _error_message(e), + ) + +function _check_arguments(sampler::S) where {S <: BONSeeder} + sampler.numpoints > 1 || _throw(TooFewSites) + return sampler.numpoints <= n || _throw(TooManySites) +end + +struct TooFewSites{I} <: BONException where {I <: Integer} + provided_sites::I +end +_error_message(tfs::TooFewSites) = + "Number of sampling sites provided was $(tfs.provided_sites), but the number of sites must be {bold}greater than {cyan}1{/cyan}{/bold}.\n" + +struct TooManySites{I} <: BONException where {I <: Integer} + provided_sites::I + maximum_sites::I +end +_error_message(tms::TooManySites) = + "Number of sampling sites provided was $(tms.provided_sites), which {bold}exceeds the maximum possible{/bold} number of sites, $(tms.maximum_sites).\n" diff --git a/src/seed.jl b/src/seed.jl index 055aadc..b9cda73 100644 --- a/src/seed.jl +++ b/src/seed.jl @@ -11,13 +11,15 @@ function seed!( sampler::ST, uncertainty::Matrix{T}, ) where {ST <: BONSeeder, T <: AbstractFloat} - if length(coords) != sampler.numpoints + length(coords) != sampler.numpoints && throw( DimensionMismatch( - "The length of the coordinate vector must match the `numpoints` fields of the sampler", + "The length of the coordinate vector must match the `numpoints` fiel s of the sampler", ), ) - end + + max_sites = prod(size(uncertainty)) + max_sites < sampler.numpoints && throw(TooManySites(sampler.numpoints, max_sites)) return _generate!(coords, sampler, uncertainty) end @@ -42,7 +44,7 @@ end seed(sampler::ST, uncertainty::Matrix{T}) Produces a set of candidate sampling locations in a vector `coords` of length numpoints -from a raster `uncertainty` using `sampler`, where `sampler` is a [`BONSeeder`](@ref). +from a raster `uncertainty` using `sampler`, where `sampler` is a [`BONSeeder`](@ref). """ function seed( sampler::ST,