PhyloPic — Acquisition

acquire_phylopic and augment_phylopic resolve PBDB taxon names to PhyloPic silhouette image metadata using the PhyloPic /resolve/paleobiodb.org/txn API endpoint.

How it works

For each taxon name the following steps are performed automatically:

  1. PBDB lookuppbdb_taxon(name = X) retrieves the taxon's numeric ID (orig_no).
  2. Lineagepbdb_taxa(id = "txn:N", rel = "all_parents") fetches the full ancestor chain.
  3. PhyloPic resolve — the lineage IDs are sent to https://api.phylopic.org/resolve/paleobiodb.org/txn, which returns the UUID of the closest-matching node in PhyloPic's taxonomy.
  4. Image metadata — the node's primary image is fetched with all file links, licence, and attribution.

The current PhyloPic build number is cached in memory for one hour to avoid unnecessary round-trips.

When processing a DataFrame, each unique taxon name triggers exactly one set of API calls; duplicate names reuse the cached result. If a taxon cannot be found in PBDB or PhyloPic, all fields for that row are missing — no error is raised.

Output fields

Both functions produce the following fields. The fieldname_prefix argument (default "phylopic_") is prepended to every base name:

Base nameColumn (default prefix)Content
pbdb_taxon_idphylopic_pbdb_taxon_idPBDB orig_no of the query taxon
pbdb_lineagephylopic_pbdb_lineageComma-separated lineage orig_no values
node_uuidphylopic_node_uuidMatched PhyloPic node UUID
matched_namephylopic_matched_nameName of the matched PhyloPic node
uuidphylopic_uuidImage UUID
thumbnailphylopic_thumbnailURL to the largest thumbnail PNG
vectorphylopic_vectorURL to the vector SVG
rasterphylopic_rasterURL to the largest raster PNG
source_filephylopic_source_fileURL to the original uploaded file
og_imagephylopic_og_imageURL to the OG social-media preview image
licensephylopic_licenseLicence identifier (e.g. "CC BY 4.0")
license_urlphylopic_license_urlFull licence URL
contributorphylopic_contributorContributor resource href
attributionphylopic_attributionAttribution text

acquire_phylopic — single taxon

using PaleobiologyDB, PaleobiologyDB.TaxonomyMakie

# Default prefix → :phylopic_uuid, :phylopic_thumbnail, etc.
rec = acquire_phylopic("Tyrannosaurus")
rec.phylopic_thumbnail    # → "https://images.phylopic.org/…/thumbnail/…"
rec.phylopic_vector       # → SVG URL
rec.phylopic_license      # → "CC BY 4.0"
rec.phylopic_attribution  # → "Matt Martyniuk"
rec.phylopic_pbdb_taxon_id  # → 56230 (orig_no)

# Taxon not found in PBDB or PhyloPic → all fields missing
rec_missing = acquire_phylopic("UNKNOWN_TAXON_XYZ")
ismissing(rec_missing.phylopic_uuid)  # → true

acquire_phylopic — DataFrame (phylopic columns only)

using PaleobiologyDB, PaleobiologyDB.TaxonomyMakie, DataFrames

df   = pbdb_occurrences(base_name = "Ceratopsia", interval = "Cretaceous", show = "full")

# Returns a new DataFrame with ONLY the 14 phylopic columns (nrow(df) rows)
pics = acquire_phylopic(df)
pics.phylopic_thumbnail   # vector of URL strings / missings

# Custom taxon column (default is :accepted_name)
pics_genus = acquire_phylopic(df, :genus)

The returned DataFrame contains only the PhyloPic columns. Combine it with the original using hcat or use augment_phylopic for the one-call convenience:

enriched = hcat(df, pics)

augment_phylopic — enriched DataFrame

# Returns a copy of df with all original columns plus the 14 phylopic columns
enriched = augment_phylopic(df)

ncol(enriched) == ncol(df) + 14  # true
hasproperty(enriched, :accepted_name)   # original columns preserved
hasproperty(enriched, :phylopic_uuid)   # phylopic columns added

Multi-level enrichment with custom prefixes

Because the fieldname_prefix argument completely controls the output column names, you can acquire images at multiple taxonomic levels simultaneously without column-name conflicts:

using PaleobiologyDB, PaleobiologyDB.TaxonomyMakie, DataFrames

df = pbdb_occurrences(base_name = "Dinosauria", interval = "Cretaceous",
                      show = "full", limit = 100)

# Silhouettes matched at genus level
genus_pics = acquire_phylopic(df, :genus, "genus_phylopic_")
# → columns :genus_phylopic_uuid, :genus_phylopic_thumbnail, …

# Silhouettes matched at species level
sp_pics = acquire_phylopic(df, :accepted_name, "sp_phylopic_")
# → columns :sp_phylopic_uuid, :sp_phylopic_thumbnail, …

# Combine everything
full = hcat(df, genus_pics, sp_pics)

# Compare: genus-level match vs. species-level match
full[!, [:accepted_name, :genus_phylopic_matched_name, :sp_phylopic_matched_name]]

This is especially useful when the species-level image is absent (returns missing) but a genus- or family-level silhouette is available.

Downloading and saving images

The functions return URLs as plain strings. Downloads (a Julia standard library, no installation required) is all you need to save files to disk:

using Downloads
using PaleobiologyDB, PaleobiologyDB.TaxonomyMakie

rec = acquire_phylopic("Tyrannosaurus")

# Save to disk — no extra dependencies needed
Downloads.download(rec.phylopic_raster,    "tyrannosaurus.png")   # raster PNG
Downloads.download(rec.phylopic_vector,    "tyrannosaurus.svg")   # vector SVG
Downloads.download(rec.phylopic_thumbnail, "tyrannosaurus_thumb.png")

Enhancing Makie plots with PhyloPic silhouettes

The PaleobiologyDB.TaxonomyMakie extension provides a high-level API for overlaying PhyloPic silhouettes on existing Makie axes. It activates when both a Makie backend (e.g. CairoMakie) and PhyloPicMakie are loaded.

pkg> add CairoMakie PhyloPicMakie
using PaleobiologyDB
import PhyloPicMakie
using CairoMakie
using PaleobiologyDB.TaxonomyMakie

taxa      = ["Tyrannosaurus", "Triceratops", "Ankylosaurus",
             "Pachycephalosaurus", "Edmontosaurus"]
first_app = [68.0, 68.0, 70.0, 74.0, 76.0]
last_app  = [66.0, 66.0, 66.0, 66.0, 66.0]

fig = Figure(size = (800, 420))
ax  = Axis(fig[1, 1];
    xlabel = "Age (Ma)", xreversed = true,
    yticks = (1:length(taxa), taxa), yticklabelsize = 13,
)

for (i, (fa, la)) in enumerate(zip(first_app, last_app))
    lines!(ax, [fa, la], [i, i]; linewidth = 6, color = :gray30)
end

augment_phylopic_ranges!(
    ax, first_app, last_app, collect(1.0:length(taxa));
    taxon      = taxa,
    at         = :start,
    glyph_size = 0.38,
    placement  = :center,
)

xlims!(ax, 78, 64)
display(fig)

See the PhyloPic rendering guide and PhyloPic: Rendering API reference for the full API, table- oriented variants, and keyword-argument reference.

TaxonomyMakie.PhyloPicPBDB.acquire_phylopicFunction
acquire_phylopic(taxon_name, fieldname_prefix = "phylopic_"; image_selector = :primary) -> NamedTuple

Look up PhyloPic silhouette image metadata for a single PBDB taxon name.

Arguments

  • taxon_name: A taxon name as it appears in the Paleobiology Database.
  • fieldname_prefix: String prepended to every key in the returned NamedTuple. Default "phylopic_". Use a custom prefix (e.g. "genus_phylopic_") when combining lookups at different taxonomic levels.
  • image_selector: Controls which image is selected for the resolved node:
    • :primary (default) — the node's designated primary image; one round-trip.
    • Int n — the n-th image in the clade-ordered list. Out-of-bounds returns all-missing fields (no fallback to primary).
    • Callable f — called with Vector{PhyloPicImage} and must return a PhyloPicImage or nothing.

Returns

A NamedTuple with 14 base keys (each prefixed by fieldname_prefix):

Base keyContent
pbdb_taxon_idPBDB orig_no of the query taxon
pbdb_lineageComma-separated lineage orig_no values
node_uuidMatched PhyloPic node UUID
matched_nameName of the matched PhyloPic node
uuidImage UUID
thumbnailURL of the largest thumbnail PNG
vectorURL of the vector SVG
rasterURL of the largest raster PNG
source_fileURL of the original source file
og_imageURL of the OG preview image
licenseLicense identifier (e.g. "CC BY 4.0")
license_urlFull license URL
contributorContributor resource href
attributionAttribution text

All fields are missing when the taxon cannot be found.

Examples

rec = acquire_phylopic("Tyrannosaurus")
rec.phylopic_thumbnail

# Second clade image, or all-missing if fewer than 2:
rec2 = acquire_phylopic("Tyrannosaurus"; image_selector = 2)

# Custom prefix:
genus_rec = acquire_phylopic("Tyrannosaurus", "genus_phylopic_")
genus_rec.genus_phylopic_uuid

See also acquire_phylopic (DataFrame variant), augment_phylopic.

source
acquire_phylopic(df, taxon_field = :accepted_name, fieldname_prefix = "phylopic_";
                 image_selector = :primary) -> DataFrame

Return a DataFrame of PhyloPic columns for every row in df, aligned by row.

Each unique value in df[!, taxon_field] triggers exactly one set of API calls; duplicate names reuse the cached result.

Arguments

  • df: Any AbstractDataFrame.
  • taxon_field: Column of PBDB taxon names. Default :accepted_name.
  • fieldname_prefix: Prepended to every output column name. Default "phylopic_".
  • image_selector: As for the single-taxon variant. Default :primary.

Returns

A DataFrame with nrow(df) rows and 14 PhyloPic columns. Use augment_phylopic or hcat to combine with the original DataFrame.

Examples

pics     = acquire_phylopic(df)
enriched = hcat(df, pics)

# Multi-level:
g_pics = acquire_phylopic(df, :genus,         "genus_phylopic_")
s_pics = acquire_phylopic(df, :accepted_name, "sp_phylopic_")
hcat(df, g_pics, s_pics)
source

phylopicimagesdataframe — all images for a taxon

acquire_phylopic returns one representative image per taxon — the primary image of the best-matching PhyloPic node. phylopic_images_dataframe does the opposite: it pages through the PhyloPic /images endpoint and returns every image available for the taxon's clade (or just the node, with filter = :node), one row per image.

using PaleobiologyDB, PaleobiologyDB.TaxonomyMakie

# All images within the Carnivora clade (one row per image, hundreds of rows)
imgs = phylopic_images_dataframe("Carnivora")

nrow(imgs)                   # total number of PhyloPic images for Carnivora
ncol(imgs)                   # 12 — see column reference below
imgs.phylopic_uuid[1:5]      # image UUIDs
imgs.phylopic_raster[1:5]    # raster PNG URLs (largest available size)
imgs.phylopic_thumbnail[1:5] # thumbnail PNG URLs

# context columns — same for every row in a single call
imgs.phylopic_query_taxon_name[1]  # → "Carnivora"
imgs.phylopic_query_node_uuid[1]   # → PhyloPic node UUID for Carnivora

# Images tagged to exactly the Carnivora node only (no descendants)
imgs_node = phylopic_images_dataframe("Carnivora"; filter = :node)

# Fetch only the first page (~30 images) for a quick preview
imgs_quick = phylopic_images_dataframe("Carnivora"; max_pages = 1)

# Custom column prefix
imgs_dog = phylopic_images_dataframe("Canis", "dog_")
imgs_dog.dog_uuid
imgs_dog.dog_raster

# Unknown or unresolvable taxon → empty DataFrame with correct columns
result = phylopic_images_dataframe("NOT_A_REAL_TAXON_XYZ")
nrow(result)   # → 0
ncol(result)   # → 12

Output columns

With the default prefix "phylopic_":

Base nameColumn (default prefix)Content
query_taxon_namephylopic_query_taxon_nameInput taxon name
query_node_uuidphylopic_query_node_uuidPhyloPic node UUID resolved for the query taxon
uuidphylopic_uuidImage UUID
thumbnailphylopic_thumbnailURL of the largest thumbnail PNG
vectorphylopic_vectorURL of the vector SVG
rasterphylopic_rasterURL of the largest raster PNG
source_filephylopic_source_fileURL of the original source file
og_imagephylopic_og_imageURL of the OG social-media preview image
licensephylopic_licenseLicence identifier (e.g. "CC BY 4.0")
license_urlphylopic_license_urlFull licence URL
contributorphylopic_contributorContributor resource href
attributionphylopic_attributionAttribution text

Choosing between acquirephylopic and phylopicimages_dataframe

NeedFunction
One silhouette per taxon for a plot or DataFrame columnacquire_phylopic / augment_phylopic
Browse or enumerate all images for a taxon (image gallery, selection UI)phylopic_images_dataframe
Download all raster files for a clade for offline usephylopic_images_dataframe + Downloads.download
TaxonomyMakie.PhyloPicPBDB.phylopic_images_dataframeFunction
phylopic_images_dataframe(taxon_name, fieldname_prefix = "phylopic_";
                     filter = :clade, max_pages = nothing) -> DataFrame

Return a DataFrame of all PhyloPic images for a taxon, one row per image.

Unlike acquire_phylopic which returns one representative image, this function pages through the /images list and collects every image whose subject falls within the taxon's clade (or exactly that node when filter = :node).

Arguments

  • taxon_name: A taxon name as it appears in the Paleobiology Database.
  • fieldname_prefix: Prepended to every column name. Default "phylopic_".
  • filter: :clade (default) or :node.
  • max_pages: Maximum pages to fetch (~30 images each). nothing fetches all.

Returns

A DataFrame with one row per image and 12 base columns (each prefixed). Returns an empty DataFrame (with all columns present) when the taxon cannot be resolved or has no images.

Examples

imgs = phylopic_images_dataframe("Carnivora")
imgs.phylopic_thumbnail[1:5]

imgs_node = phylopic_images_dataframe("Carnivora"; filter = :node)
imgs_quick = phylopic_images_dataframe("Carnivora"; max_pages = 2)

# Custom prefix
imgs = phylopic_images_dataframe("Canis", "dog_")
imgs.dog_uuid

See also acquire_phylopic, phylopic_images.

source

phylopicnode and phylopicimages

TaxonomyMakie.PhyloPicPBDB.phylopic_nodeFunction
phylopic_node(taxon_name; build = nothing) -> Union{PhyloPicNode, Nothing}

Resolve a PBDB taxon name to its matching PhyloPic phylogenetic node.

This is the first stage of the two-stage pipeline for acquiring silhouette images: resolve the node here, then retrieve images via PhyloPicDB functions.

Arguments

  • taxon_name: A taxon name as it appears in the Paleobiology Database.
  • build: PhyloPic build index. nothing (default) fetches the current build.

Returns

A PhyloPicDB.PhyloPicNode, or nothing if the taxon cannot be found in PBDB or PhyloPic. The result is cached per (taxon_name, build).

Examples

node = phylopic_node("Tyrannosaurus")
isnothing(node) || println(node.preferred_name)

# Two-stage pipeline — resolve once, then choose images:
node = phylopic_node("Carnivora")
imgs = PhyloPicDB.clade_images(node.uuid; max_pages = 2)

See also phylopic_images, acquire_phylopic.

source
TaxonomyMakie.PhyloPicPBDB.phylopic_imagesFunction
phylopic_images(taxon_name; build = nothing, filter = :clade, max_pages = nothing)
    -> Vector{PhyloPicDB.PhyloPicImage}

Return all PhyloPic images for a PBDB taxon as a typed vector.

Typed companion to phylopic_images_dataframe: returns the same images as a Vector{PhyloPicDB.PhyloPicImage} rather than a DataFrame, making it easy to pass the result directly to PhyloPicDB.select_image.

Arguments

  • taxon_name: A taxon name as it appears in the Paleobiology Database.
  • build: PhyloPic build index. nothing fetches the current build.
  • filter: :clade (default) returns images for the node and all descendants; :node restricts to images tagged directly to the resolved node.
  • max_pages: Maximum pages to fetch. nothing fetches all pages.

Returns

A Vector{PhyloPicDB.PhyloPicImage}. Empty if the taxon cannot be resolved or has no images.

Examples

imgs = phylopic_images("Carnivora"; max_pages = 2)
chosen = PhyloPicDB.select_image(imgs, 3)

See also phylopic_images_dataframe, phylopic_node.

source