Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add GBIF/Phylopic integration #179

Merged
merged 11 commits into from
Apr 30, 2023
2 changes: 1 addition & 1 deletion .github/workflows/CompatHelper.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,4 @@ jobs:
- name: CompatHelper.main()
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: julia -e 'using CompatHelper; CompatHelper.main(; subdirs=["", "GBIF", "Fauxcurrences", "SimpleSDMDatasets", "SimpleSDMLayers"])'
run: julia -e 'using CompatHelper; CompatHelper.main(; subdirs=["", "GBIF", "Fauxcurrences", "SimpleSDMDatasets", "SimpleSDMLayers", "Phylopic"])'
4 changes: 2 additions & 2 deletions Phylopic/Project.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name = "Phylopic"
uuid = "c889285c-44aa-4473-b1e1-56f5d4e3ccf5"
authors = ["Timothée Poisot <timothee.poisot@umontreal.ca>"]
version = "0.0.1"
version = "0.0.2"

[deps]
HTTP = "cd3eb016-35fb-5094-929b-558a96fad6f3"
Expand All @@ -10,6 +10,6 @@ Markdown = "d6f4376e-aef5-505a-96c1-9c027394607a"
UUIDs = "cf7118a7-6976-5b1a-9a39-7adc72f591a4"

[compat]
HTTP = "1.7"
HTTP = "1"
JSON = "0.21"
julia = "1.8"
54 changes: 54 additions & 0 deletions Phylopic/src/images.jl
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,60 @@ twitterimage(dict::Dict{String,UUIDs.UUID}; kwargs...) = twitterimage.(collect(d
source(pair::Pair{String,UUIDs.UUID}; kwargs...) = source(pair.second; kwargs...)
source(dict::Dict{String,UUIDs.UUID}; kwargs...) = source.(collect(dict); kwargs...)

"""
Phylopic.available_resolutions(uuid::UUIDs.UUID)

Returns the available resolutions for a raster image given its UUID. The resolutions are given as a string, and can be passed as a second argument to the `Phylopic.raster` function. As the raster sizes can be different, there is no default argument to Phylopic.raster, and the first image will be used instead.
"""
function available_resolutions(uuid::UUIDs.UUID)
lnk = Phylopic.images_links(uuid)
resols = []
if haskey(lnk, "rasterFiles")
rasters = lnk["rasterFiles"]
for raster in rasters
push!(resols, raster["sizes"])
end
return resols
end
return nothing

end

"""
Phylopic.raster(uuid::UUIDs.UUID, resl)

Returns the URL to an image in raster format, at the given resolution. Available resolutions for any image can be obtained with `Phylopic.available_resolutions`.
"""
function raster(uuid::UUIDs.UUID, resl)
lnk = Phylopic.images_links(uuid)
@assert resl in Phylopic.available_resolutions(uuid)
if ~isnothing(lnk)
res = filter(spec -> isequal(resl)(spec["sizes"]), lnk["rasterFiles"])
return first(res)["href"]
end
return nothing
end

"""
Phylopic.raster(uuid::UUIDs.UUID)

Returns the URL to an image in raster format when no resolution is specified. In this case, the first (usually the largest) image will be returned.
"""
function raster(uuid::UUIDs.UUID)
lnk = Phylopic.images_links(uuid)
if ~isnothing(lnk)
return first(lnk)["href"]
end
return nothing
end

available_resolutions(pair::Pair{String,UUIDs.UUID}) = available_resolutions(pair.second)
available_resolutions(dict::Dict{String,UUIDs.UUID}) = available_resolutions.(collect(dict))
raster(pair::Pair{String,UUIDs.UUID}) = raster(pair.second)
raster(dict::Dict{String,UUIDs.UUID}) = raster.(collect(dict))
raster(pair::Pair{String,UUIDs.UUID}, resl) = raster(pair.second, resl)
raster(dict::Dict{String,UUIDs.UUID}, resl) = raster.(collect(dict), resl)

function images_data(uuid::UUIDs.UUID)
query = [
"build" => Phylopic.buildnumber,
Expand Down
6 changes: 4 additions & 2 deletions Project.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name = "SpeciesDistributionToolkit"
uuid = "72b53823-5c0b-4575-ad0e-8e97227ad13b"
authors = ["Timothée Poisot <timothee.poisot@umontreal.ca>"]
version = "0.0.5"
version = "0.0.6"

[deps]
ArchGDAL = "c9ce4bd3-c3d5-55b8-8973-c0e20141b8c3"
Expand All @@ -10,6 +10,7 @@ Fauxcurrences = "a2d61402-033a-4ca9-aef4-652d70cf7c9c"
GBIF = "ee291a33-5a6c-5552-a3c8-0f29a1181037"
GDAL = "add2ef01-049f-52c4-9ee2-e494f65e021a"
MakieCore = "20f20a25-4f0e-4fdf-b5d1-57303727442b"
Phylopic = "c889285c-44aa-4473-b1e1-56f5d4e3ccf5"
Reexport = "189a3867-3050-52da-a836-e630ba90ab69"
SimpleSDMDatasets = "2c7d61d0-5c73-410d-85b2-d2e7fbbdcefa"
SimpleSDMLayers = "2c645270-77db-11e9-22c3-0f302a89c64c"
Expand All @@ -22,8 +23,9 @@ Fauxcurrences = "0.1"
GBIF = "0.4"
GDAL = "1.5"
MakieCore = "0.6"
Phylopic = "0"
Reexport = "1.2"
SimpleSDMLayers = "0.9"
SimpleSDMDatasets = "0.1"
SimpleSDMLayers = "0.9"
StatsBase = "0.33"
julia = "1.8"
2 changes: 2 additions & 0 deletions docs/src/manual/Phylopic/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,14 @@ Phylopic.thumbnail
Phylopic.vector
Phylopic.twitterimage
Phylopic.source
Phylopic.raster
```

## Additional functions

```@docs
Phylopic.attribution
Phylopic.available_resolutions
```

## API interaction functions
Expand Down
5 changes: 3 additions & 2 deletions docs/src/vignettes/occurrences/02_occurrences_and_layers.jl
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,10 @@ current_figure()

# We can now add a silhouette of a bat using Phylopic. We only want a single item here, and
# the search will by default be restricted to images that can be used with the least
# constraints.
# constraints. Note that we are searching using the `GBIFTaxon` object representing our
# species.

bat_uuid = Phylopic.imagesof("chiroptera"; items = 1)
bat_uuid = Phylopic.imagesof(bat; items = 1)

# The next step is to get the url of the image -- we are going to get the largest thumbnail
# (which is the default):
Expand Down
3 changes: 3 additions & 0 deletions src/SpeciesDistributionToolkit.jl
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ include("integrations/datasets_layers.jl")
# GBIF to get species occurrence data
include("integrations/gbif_layers.jl")

# GBIF and Phylopic integration
include("integrations/gbif_phylopic.jl")

# Plotting
include("integrations/makie.jl")

Expand Down
17 changes: 17 additions & 0 deletions src/integrations/gbif_phylopic.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
"""
Phylopic.imagesof(taxon::GBIF.GBIFTaxon; kwargs...)

Performs a search in phylopic for a given GBIF taxon object, walking from the lowermost taxonomic level up to the top. This is not guaranteed to give the best results.
"""
function Phylopic.imagesof(tax::GBIF.GBIFTaxon; kwargs...)
for rank in [:species, :genus, :family, :order, :class, :phylum, :kingdom]
if ~ismissing(getfield(tax, rank))
rankinfo = getfield(tax, rank)
phylopic_matches = Phylopic.imagesof(rankinfo.first; kwargs...)
if ~isnothing(phylopic_matches)
return phylopic_matches
end
end
end
return nothing
end