Using the APD: exploring and extracting trait definitions and metadata

Author

Elizabeth Wenk

The AusTraits Plant Dictionary (APD) is a published vocabulary, documenting explicit definitions for more than 500 plant trait concepts. Every trait concept, trait grouping, allowed categorical value and glossary term has a persistent identifier under https://w3id.org/APD/, and the same content is published simultaneously as a human-readable document, as RDF, and as a pair of flat tables.

Ways to use the APD

There are four routes into the dictionary. They are views of the same content, so the choice is about what you are doing rather than what you can reach.

If you want to Use Start at
look up, link to or cite a single trait concept the dictionary document — one page, one entry per term https://w3id.org/APD/traits/trait_0000012
browse the trait hierarchy, search definitions, or offer APD terms in your own data-entry form ARDC Research Vocabularies Australia (RVA) https://vocabs.ardc.edu.au/viewById/649
query the vocabulary as a graph, or load it into a triplestore the RDF serialisations: APD.ttl, APD.nt, APD.nq, APD.json content negotiation on https://w3id.org/APD/
filter, subset and join trait metadata inside an analysis the two tables: APD_traits.csv, APD_categorical_values.csv the worked examples below

The last of these is the bulk of this document: the worked examples show how definitions and metadata for specific traits or trait clusters can be extracted, allowing searches by trait name, trait cluster, characteristic measured, reference, previously used trait labels, or matches to identical or similar trait concepts in other vocabularies and databases.

Referring to trait concepts: w3id identifiers

https://w3id.org/APD/ is the APD’s persistent identifier, and the one to use in citations, dataset metadata and code. It redirects to wherever the dictionary is currently served, so a link written against it keeps working if the hosting changes.

Each class of entity has its own identifier pattern:

Entity Identifier
trait concept https://w3id.org/APD/traits/trait_0000012
trait grouping https://w3id.org/APD/traits/trait_group_0000008
allowed categorical value https://w3id.org/APD/traits/plant_growth_form_tree
glossary term https://w3id.org/APD/glossary/glossary_40004

Each of these resolves to that term’s own entry in the dictionary — follow any of them to see. The collection identifiers https://w3id.org/APD/traits/ and https://w3id.org/APD/glossary/ land on the corresponding section.

The identifier above without a release path always resolves to the current release: https://w3id.org/APD/. To pin a version instead, insert a release path — https://w3id.org/APD/release/2.1.1/. Content negotiation (below) works on either, so a pinned identifier can be resolved as RDF as well as HTML.

For citation, use the paper (Wenk et al. 2024, doi:10.1038/s41597-024-03368-z) together with the version you used; the archived deposits carry DOI 10.5281/zenodo.8040789.

Browsing and searching: Research Vocabularies Australia

A copy of the APD is deposited in Research Vocabularies Australia (RVA), the ARDC’s national vocabulary service. RVA is the route that requires no downloads and no code, and it is the easiest place to:

  • browse the SKOS concept tree — trait groupings, the traits within them, and the allowed values beneath each categorical trait — and search across labels and definitions;
  • download the vocabulary in serialisations beyond the four published here, which RVA generates on request (RDF/XML, TriG, RDF/JSON and others);
  • run SPARQL queries from the browser against RVA’s hosted endpoint, without loading the graph locally;
  • embed RVA’s vocabulary widget in your own data-entry form, so contributors choose a defined APD term instead of typing free text.

The RVA copy is refreshed as part of each APD release, so check the version shown on the record: at the time of writing it trails the current release. Where it matters that you have the definitions exactly as published in the latest version, work from https://w3id.org/APD/.

Machine-readable serialisations: APD.ttl, APD.nt, APD.nq, APD.json

The dictionary is published as RDF in four serialisations. All four carry the same 27,500 or so triples describing 1,473 concepts — 559 trait concepts, 819 allowed categorical values, plus trait groupings and glossary terms — so the choice is about tooling, not content.

File Format Suits
APD.ttl Turtle reading by eye, and loading into a triplestore or an RDF library — the most compact of the four (~1.6 MB)
APD.nt N-Triples one triple per line: streamable, greppable, diffable, and parseable without an RDF library (~4 MB)
APD.nq N-Quads as APD.nt, plus a graph column, for loading into a named graph in a quad store (~4 MB)
APD.json JSON-LD JavaScript and Python web tooling, or anything that would rather consume JSON than RDF (~3.5 MB)

Fetching a serialisation

Ask https://w3id.org/APD/ for the format you want with an Accept header. The -L is needed because the request is answered with a 303 redirect to the file:

# The latest release, as Turtle
curl -L -H "Accept: text/turtle" https://w3id.org/APD/ -o APD.ttl

# A pinned release, as JSON-LD -- negotiation works on any release path
curl -L -H "Accept: application/ld+json" https://w3id.org/APD/release/2.1.1/ -o APD_2.1.1.json
Accept header You get
text/turtle APD.ttl
application/n-triples APD.nt
application/n-quads APD.nq
application/ld+json APD.json
text/html, or no header the dictionary document
Warningw3id resolves identifiers, not file paths

w3id.org recognises entity identifiers, release paths and Accept headers — nothing else. You cannot name a file in a w3id URL. Both https://w3id.org/APD/APD.ttl and https://w3id.org/APD/release/2.1.1/APD_traits.csv return HTTP 200 with the dictionary document, not the file you asked for, because anything unrecognised falls through to it. That is a silent failure if you pipe the result into a parser.

For the RDF, name the format with an Accept header rather than in the path, as above.

There is no Accept header that returns a CSV. The two flat tables are not part of content negotiation at all, so APD_traits.csv and APD_categorical_values.csv can only be fetched from the site:

# Right
curl -L -O https://traitecoevo.github.io/APD/release/2.1.1/APD_traits.csv

# Wrong -- returns the dictionary page, with a 200
curl -L -O https://w3id.org/APD/release/2.1.1/APD_traits.csv

Querying the RDF with SPARQL

The graph answers questions the flat tables cannot. In the CSVs, a trait’s keywords, units, structures and cross-vocabulary matches arrive as ;-delimited text that you have to split and string-match; in the RDF each one is an identifier pointing into the vocabulary it came from. So the graph lets you ask questions through those identifiers rather than about the words that happen to spell them:

  • every trait measured on a leaf, by the Plant Ontology’s identifier for a leaf — which finds traits whose labels never say “leaf”, and excludes ones that mention leaves incidentally
  • every trait sharing a unit, a characteristic or a keyword with a given trait
  • which external vocabularies the APD asserts skos:exactMatch against, and how often
  • the trait hierarchy as a hierarchy, following skos:broader upwards, rather than as a delimited string

SPARQL is the query language for that, and it needs no server: the whole graph is 1.6 MB, so it loads into memory locally. In R, rdflib parses any of the four serialisations and queries the result, returning a plain data frame. The example needs rdflib and httr in addition to the packages above — install.packages(c("rdflib", "httr")):

library(httr)
library(rdflib)
library(dplyr)
library(stringr)

# Fetch the latest release as Turtle, via the persistent identifier
ttl <- tempfile(fileext = ".ttl")
GET("https://w3id.org/APD/", accept("text/turtle"), write_disk(ttl, overwrite = TRUE))

APD_rdf <- rdf_parse(ttl, format = "turtle")

Every trait measured on a leaf, found through the Plant Ontology identifier for a leaf (PO_0025034) rather than by matching the word “leaf”, together with its expected unit:

leaf_traits <-
  rdflib::rdf_query(APD_rdf, '
    PREFIX skos: <http://www.w3.org/2004/02/skos/core#>
    PREFIX ont:  <https://w3id.org/iadopt/ont/>
    PREFIX obo:  <http://purl.obolibrary.org/obo/>
    PREFIX ets:  <http://terminologies.gfbio.org/terms/ETS/>

    SELECT ?trait ?label ?unit
    WHERE {
      ?trait ont:hasContextObject obo:PO_0025034 ;
             skos:prefLabel ?label ;
             ets:expectedUnit ?unit .
      FILTER(isURI(?unit))
    }')
trait label unit
https://w3id.org/APD/traits/trait_0030716 Fire time to ignition https://w3id.org/uom/s
https://w3id.org/APD/traits/trait_0030715 Leaf flame and smoulder duration https://w3id.org/uom/s
https://w3id.org/APD/traits/trait_0030714 Leaf flame duration https://w3id.org/uom/s
https://w3id.org/APD/traits/trait_0030713 Leaf smoulder duration https://w3id.org/uom/s
https://w3id.org/APD/traits/trait_0030711 Fuel consumption by fire https://w3id.org/uom/g.g-1
https://w3id.org/APD/traits/trait_0030710 Fuel bed bulk density https://w3id.org/uom/g.cm-3
https://w3id.org/APD/traits/trait_0030025 Leaf lifespan https://w3id.org/uom/mo
https://w3id.org/APD/traits/trait_0022013 Leaf phosphorus resorption efficiency https://w3id.org/uom/mg.mg-1
https://w3id.org/APD/traits/trait_0022012 Leaf nitrogen resorption efficiency https://w3id.org/uom/mg.mg-1
https://w3id.org/APD/traits/trait_0021066 Leaf xylem pressure, 88% lost conductance (P88) https://w3id.org/uom/MPa

A query result is a data frame, so anything awkward to express in SPARQL can be left to dplyr. Counting the formally asserted skos:exactMatch links by the vocabulary they point into:

exact_matches <-
  rdflib::rdf_query(APD_rdf, '
    PREFIX skos: <http://www.w3.org/2004/02/skos/core#>
    SELECT ?trait ?match WHERE { ?trait skos:exactMatch ?match }') %>%
  dplyr::count(vocabulary = stringr::str_extract(match, "^https?://[^/]+/[^/]+")) %>%
  dplyr::arrange(dplyr::desc(n))
vocabulary n
http://purl.obolibrary.org/obo 127
https://cropontology.org/rdf 45
http://vocabs.lter-europe.net/EnvThes 20
http://www.ebi.ac.uk/efo 1

The same queries run unchanged in Python (rdflib), or in any triplestore you load APD.nq into. scripts/sparql_examples.R in the APD repository holds further examples.

Exploring the tables

For everyday filtering and joining, the two flat tables are easier than the graph: APD_traits.csv carries one row per trait concept with all its metadata, and APD_categorical_values.csv one row per allowed value of a categorical trait. Both can be downloaded from traitecoevo.github.io/APD or from Zenodo, DOI 10.5281/zenodo.8040789.

They are ordinary CSVs, so nothing here is R-specific — the examples below use dplyr, and each has a direct equivalent in pandas or any other table library. Multi-valued fields such as keywords, references and trait_groupings hold ;-delimited text, so the recurring pattern is split-then-unnest, whatever you split with.

library(dplyr)
library(tidyr)
library(readr)
library(stringr)
library(kableExtra)

# The published tables. Pin the version so your analysis stays reproducible; drop
# `release/2.1.1/` for whatever the current release is.
#
# These are github.io URLs. Cite the APD by its persistent identifier,
# https://w3id.org/APD, and use that with an `Accept` header to fetch the RDF (see
# above) -- but fetch the data files from here: w3id.org resolves anything it does
# not recognise as an entity to the dictionary page.
apd <- "https://traitecoevo.github.io/APD/release/2.1.1"

APD_traits <- read_csv(file.path(apd, "APD_traits.csv"), show_col_types = FALSE)
APD_categorical_values <- read_csv(file.path(apd, "APD_categorical_values.csv"), show_col_types = FALSE)

Metadata fields (annotation properties) documented for each trait include:

names(APD_traits)
field
Entity
trait
label
description
comments
trait_type
allowed_values_min
allowed_values_max
units
constraints
trait_groupings
structure_measured
characteristic_measured
keywords
references
reviewers
created
modified
exact_match
close_match
related_match
examples
description_encoded
deprecated_trait_name
identifier
inScheme

Extracting terms based on specific fields

The following examples show how to extract terms based on specific fields in the APD.

Structure measured

To determine the possible values for structure_measured:

structure_measured <- 
  APD_traits %>%
  dplyr::select(structure_measured) %>%
  dplyr::mutate(structure_measured = (stringr::str_split(structure_measured, "; "))) %>%
  tidyr::unnest_longer("structure_measured") %>%
  dplyr::distinct()
structure_measured
leaf [PO_0025034]
stem [PO_0009047]
wood, secondary xylem [PO_0005848]
bark [PO_0004518]
root [PO_0009005]
reproductive shoot system [PO_0025082]
flower [PO_0009046]
fruit [PO_0009001]
seed [PO_0009010]
whole plant [PO_0000003]
leaflet [PO_0020049]
bud [PO_0000055]
inflorescence [PO_0009049]

You can then select the subset of traits that relate to a specific structure.

For instance, to extract traits relating to seeds:

seed_traits <- 
  APD_traits %>%
  dplyr::filter(stringr::str_detect(structure_measured, "seed"))

The first 10 traits on this list are:

trait label structure_measured
seed_Ca_per_seed_dry_mass Seed calcium (Ca) content per unit seed dry mass reproductive shoot system [PO_0025082]; seed [PO_0009010]
seed_K_per_seed_dry_mass Seed potassium (K) content per unit seed dry mass reproductive shoot system [PO_0025082]; seed [PO_0009010]
seed_Mg_per_seed_dry_mass Seed magnesium (Mg) content per unit seed dry mass reproductive shoot system [PO_0025082]; seed [PO_0009010]
seed_N_per_seed_dry_mass Seed nitrogen (N) content per unit seed dry mass reproductive shoot system [PO_0025082]; seed [PO_0009010]
seed_P_per_seed_dry_mass Seed phosphorus (P) content per unit seed dry mass reproductive shoot system [PO_0025082]; seed [PO_0009010]
seed_S_per_seed_dry_mass Seed sulphur (S) content per unit seed dry mass reproductive shoot system [PO_0025082]; seed [PO_0009010]
seed_protein_per_seed_dry_mass Seed protein content per unit seed dry mass reproductive shoot system [PO_0025082]; seed [PO_0009010]
seed_oil_per_seed_dry_mass Seed oil content per unit seed dry mass reproductive shoot system [PO_0025082]; seed [PO_0009010]
accessory_cost_fraction Seed accessory cost fraction reproductive shoot system [PO_0025082]; flower [PO_0009046]; fruit [PO_0009001]; seed [PO_0009010]
accessory_cost_mass Seed accessory cost mass reproductive shoot system [PO_0025082]; flower [PO_0009046]; fruit [PO_0009001]; seed [PO_0009010]

Trait groupings

To extract all traits within one of the defined trait groupings.

First, generate a list of trait_grouping terms:

trait_groupings <- 
  APD_traits %>%
  dplyr::select(trait_groupings) %>%
  dplyr::mutate(trait_groupings = (stringr::str_split(trait_groupings, "; "))) %>%
  tidyr::unnest_longer("trait_groupings") %>%
  dplyr::distinct()

Items 20:29 on this list are:

trait_groupings
plant structure morphology trait [trait_group_0011001]
plant embryo morphology trait [trait_group_0010104]
leaf morphology trait [trait_group_0011202]
leaf size trait [trait_group_0011204]
leaf mass trait [trait_group_0011206]
leaf position trait [trait_group_0011402]
portion of plant tissue morphology trait [trait_group_0011502]
plant cell morphology trait [trait_group_0011503]
leaf stomatal complex morphology trait [trait_group_0011602]
leaf optical properties trait [trait_group_0011702]

Filter the APD for leaf stomatal complex morphology traits:

stomatal_traits <- 
  APD_traits %>%
  dplyr::filter(stringr::str_detect(trait_groupings, "leaf stomatal complex morphology trait"))
trait label trait_groupings
leaf_stomatal_density_abaxial Stomatal density on the lower leaf surface leaf stomatal complex morphology trait [trait_group_0011602]
leaf_stomatal_density_adaxial Stomatal density on the upper leaf surface leaf stomatal complex morphology trait [trait_group_0011602]
leaf_stomatal_density_average Stomatal density averaged across both leaf surfaces leaf stomatal complex morphology trait [trait_group_0011602]
leaf_stomatal_distribution Stomatal distribution leaf stomatal complex morphology trait [trait_group_0011602]
leaf_stomatal_hairs Stomatal hairiness leaf stomatal complex morphology trait [trait_group_0011602]
leaf_guard_cell_length Guard cell length leaf stomatal complex morphology trait [trait_group_0011602]

Characteristic measured

The term characteristic_measured documents “what” is being measured - a mass, length, etc.

Multiple terms may be used, for instance to indicate a trait captures volume and is a ratio:

volume_ratio_traits <- 
  APD_traits %>%
  select(trait, label, characteristic_measured) %>%
  filter(
    str_detect(characteristic_measured, "volume") &
    str_detect(characteristic_measured, "ratio") 
    )
trait label characteristic_measured
wood_density Wood density mass [PATO_0000125]; volume density [PATO_0001353]; ratio; proportion [PATO_0001470]; mass density, density [PATO_0001019]
stem_density Herbaceous stem density mass [PATO_0000125]; volume density [PATO_0001353]; ratio; proportion [PATO_0001470]; mass density, density [PATO_0001019]
bark_density Bark density mass [PATO_0000125]; volume density [PATO_0001353]; ratio; proportion [PATO_0001470]; mass density, density [PATO_0001019]
root_fine_root_coarse_root_ratio Fine root volume to coarse root volume ratio volume [PATO_0000918]; ratio; proportion [PATO_0001470]
root_wood_density Root wood density mass [PATO_0000125]; volume density [PATO_0001353]; ratio; proportion [PATO_0001470]; mass density, density [PATO_0001019]
bulk_modulus_of_elasticity Bulk modulus of elasticity (e) pressure [PATO_0001025]; force [PATO_0001035]; volume [PATO_0000918]; ratio; proportion [PATO_0001470]; model parameter [STATO_0000034]
fire_fuel_bed_bulk_density Fuel bed bulk density mass [PATO_0000125]; mass fraction [ECSO_00000619]; ratio; proportion [PATO_0001470]; volume density [PATO_0001353]; mass density, density [PATO_0001019]

Or all terms that measure a force:

force_traits <-
  APD_traits %>%
  select(trait, label, characteristic_measured) %>%
  filter(
    str_detect(characteristic_measured, "force") 
    )
trait label characteristic_measured
leaf_work_to_punch Leaf work to punch work [PATO_0001026]; force [PATO_0001035]
leaf_work_to_punch_adjusted Leaf specific work to punch work [PATO_0001026]; force [PATO_0001035]; ratio; proportion [PATO_0001470]; thickness [PATO_0000915]
leaf_work_to_shear Leaf work to shear work [PATO_0001026]; force [PATO_0001035]
leaf_work_to_shear_adjusted Leaf specific work to shear (fracture toughness) work [PATO_0001026]; force [PATO_0001035]; ratio; proportion [PATO_0001470]; thickness [PATO_0000915]
leaf_work_to_tear Leaf work to tear work [PATO_0001026]; force [PATO_0001035]
leaf_work_to_tear_adjusted Leaf specific work to tear work [PATO_0001026]; force [PATO_0001035]; ratio; proportion [PATO_0001470]; thickness [PATO_0000915]
bark_modulus_of_elasticity Bark modulus of elasticity work [PATO_0001026]; force [PATO_0001035]
stem_modulus_of_elasticity Stem modulus of elasticity work [PATO_0001026]; force [PATO_0001035]
xylem_modulus_of_elasticity Xylem modulus of elasticity work [PATO_0001026]; force [PATO_0001035]
modulus_of_rupture Modulus of rupture pressure [PATO_0001025]; force [PATO_0001035]; strength [PATO_0001230]
sapwood_specific_hydraulic_conductivity Sapwood specific hydraulic conductivity (Ks) conductivity [PATO_0001585]; per unit length [EnvThes:22004]; ratio; proportion [PATO_0001470]; rate [PATO_0000161]; force [PATO_0001035]; efficiency [PATO_0001029]
sapwood_specific_hydraulic_conductivity_theoretical Theoretical sapwood specific hydraulic conductivity (Ks) conductivity [PATO_0001585]; per unit area [EnvThes:22003]; ratio; proportion [PATO_0001470]; rate [PATO_0000161]; force [PATO_0001035]; efficiency [PATO_0001029]
stem_specific_hydraulic_conductivity Stem specific hydraulic conductivity (Ks) conductivity [PATO_0001585]; per unit length [EnvThes:22004]; ratio; proportion [PATO_0001470]; rate [PATO_0000161]; force [PATO_0001035]; efficiency [PATO_0001029]
leaf_specific_hydraulic_conductance Leaf specific hydraulic conductance (kleaf) conductivity [PATO_0001585]; per unit area [EnvThes:22003]; ratio; proportion [PATO_0001470]; rate [PATO_0000161]; force [PATO_0001035]; efficiency [PATO_0001029]
leaf_specific_hydraulic_conductivity Leaf specific hydraulic conductivity (Kl) conductivity [PATO_0001585]; per unit area [EnvThes:22003]; ratio; proportion [PATO_0001470]; rate [PATO_0000161]; force [PATO_0001035]; efficiency [PATO_0001029]
root_specific_hydraulic_conductivity Root specific hydraulic conductivity conductivity [PATO_0001585]; per unit length [EnvThes:22004]; ratio; proportion [PATO_0001470]; rate [PATO_0000161]; force [PATO_0001035]; efficiency [PATO_0001029]
water_potential_predawn Pre-dawn water potential tension [PATO_0002284]; force [PATO_0001035]
water_potential_midday Midday water potential tension [PATO_0002284]; force [PATO_0001035]
leaf_water_potential_50percent_lost_conductivity Leaf xylem pressure, 50% lost conductance (P50) (leaf hydraulic vulnerability) tension [PATO_0002284]; force [PATO_0001035]
stem_water_potential_12percent_lost_conductivity Stem xylem pressure, 12% lost conductivity (P12) tension [PATO_0002284]; force [PATO_0001035]
stem_water_potential_50percent_lost_conductivity Stem xylem pressure, 50% lost conductivity (P50) tension [PATO_0002284]; force [PATO_0001035]
stem_water_potential_88percent_lost_conductivity Stem xylem pressure, 88% lost conductivity (P88) tension [PATO_0002284]; force [PATO_0001035]
hydraulic_safety_margin_50 Hydraulic safety margin, 50% tension [PATO_0002284]; force [PATO_0001035]
hydraulic_safety_margin_88 Hydraulic safety margin, 88% tension [PATO_0002284]; force [PATO_0001035]
leaf_turgor_loss_point Leaf turgor loss point tension [PATO_0002284]; force [PATO_0001035]; model parameter [STATO_0000034]
osmotic_potential Osmotic potential pressure [PATO_0001025]; force [PATO_0001035]
osmotic_potential_at_full_turgor Osmotic potential at full tugor pressure [PATO_0001025]; force [PATO_0001035]; model parameter [STATO_0000034]
bulk_modulus_of_elasticity Bulk modulus of elasticity (e) pressure [PATO_0001025]; force [PATO_0001035]; volume [PATO_0000918]; ratio; proportion [PATO_0001470]; model parameter [STATO_0000034]
root_water_potential_50percent_lost_conductivity Root xylem pressure, 50% lost conductivity (P50) tension [PATO_0002284]; force [PATO_0001035]
root_water_potential_12percent_lost_conductivity Root xylem pressure, 12% lost conductivity (P12) tension [PATO_0002284]; force [PATO_0001035]
root_water_potential_88percent_lost_conductivity Root xylem pressure, 88% lost conductivity (P88) tension [PATO_0002284]; force [PATO_0001035]
leaf_water_potential_12percent_lost_conductivity Leaf xylem pressure, 12% lost conductance (P12) tension [PATO_0002284]; force [PATO_0001035]
leaf_water_potential_88percent_lost_conductivity Leaf xylem pressure, 88% lost conductance (P88) tension [PATO_0002284]; force [PATO_0001035]

Categorical values

The allowed values for categorical traits are output in the second table, APD_categorical_values.

You can first extract all metadata fields for the trait from APD_traits, then merge in the allowed categorical trait values. Researchers might use this information either when merging together disparate datasets or databases, or to acquire a list of trait values to use when scoring study plants.

For life_history:

life_history_values <-
  APD_categorical_values %>%
    filter(trait == "life_history") %>%
    select(-trait, -categorical_trait_identifier, -categorical_trait_synonyms) %>%
    mutate(
      term = "allowed_values_levels",
      value = paste0(allowed_values_levels, ": ", categorical_trait_description)
      ) %>%
    select(term, value)

life_history <- 
  APD_traits %>% 
    filter(trait == "life_history") %>%
    mutate(across(c(1:ncol(APD_traits)), ~ as.character(.x))) %>%
    pivot_longer(cols = 1:ncol(APD_traits)) %>%
    rename(term = name) %>%
    bind_rows(life_history_values) %>%
    filter(!is.na(value))
term value
Entity https://w3id.org/APD/traits/trait_0030012
trait life_history
label Life history
description Categorical description of the duration of a plant’s lifespan, from germination to death.
comments Studies will differ in the subset of terms they use to describe a plant’s life history, such that some researchers will distinguish between ephemeral and annual species, and other researchers will group these life history categories together under annual. In addition, only a subset of studies will use the term short-lived perennial; the majority will score all perennial plants as perennial. Rangeland studies and post-fire studies are those most likely to score species as ephemeral or short-lived perennial, as these are environments where perennial species’ lifespans are often divided into those that are short-lived due to environmental conditions and those that are able to persist through the environmentally unfavourable period.
trait_type categorical variable [STATO_0000252]
constraints none
trait_groupings whole plant phenotype trait [trait_group_0030006]
structure_measured whole plant [PO_0000003]
characteristic_measured organismal quality [PATO_0001995]; duration [PATO_0001309]; time [PATO_0000165]
keywords death [GO_0016265]; longevity [NCIT_C153298]
references Pérez-Harguindeguy 2013 [https://doi.org/10.1071/BT12225]; LEDA Data Standards 2005 [https://uol.de/en/landeco/research/leda/standards]
reviewers Elizabeth Wenk [https://orcid.org/0000-0001-5640-5910]; Hervé Sauquet [https://orcid.org/0000-0001-8305-3236]; Russell Barrett [https://orcid.org/0000-0003-0360-8321]; Ian J. Wright [https://orcid.org/0000-0001-8338-9143]; Peter Vesk [https://orcid.org/0000-0003-2008-7062]; Gregory J. Jordan [https://orcid.org/0000-0002-6033-2766]; Andy Leigh [https://orcid.org/0000-0003-3568-2606]; Patricia Lu-Irving [https://orcid.org/0000-0003-1116-9402]; Lily Dun [https://orcid.org/0000-0002-0712-5143]; David Coleman [https://orcid.org/0000-0002-1773-6597]
created 2021-07-14
modified 2024-02-05
exact_match life cycle habit [http://purl.obolibrary.org/obo/TO_0002725]
examples exact match: Plant lifespan (longevity) [TRY:59] (https://www.try-db.org/de/de.php); exact match: Lifecycle [GIFT:2.1.1] (https://gift.uni-goettingen.de); related match: Growth form [BROT:1] (http://doi.org/10.1038/sdata.2018.135) (http://doi.org/10.1038/sdata.2018.135); close match: plant lifespan and age of first flowering [LEDA:1.3] (https://uol.de/en/landeco/research/leda/standards)
description_encoded Categorical description of the duration [PATO:0001309] of a plant’s lifespan (longevity [NCIT:C153298]), from seed germination [GO:0009845] to death [GO:0016265].
identifier trait_0030012
inScheme https://w3id.org/APD
allowed_values_levels ephemeral: A very short-lived plant, generally with a lifespan of only a few months and the exact length of lifespan quite variable and determined by environmental conditions.
allowed_values_levels annual: A plant that lives for up to one year after germinating, completing its life cycle in a single growing season.
allowed_values_levels biennial: A plant that lives for up to two years after germinating, requiring two growing seasons to complete its life cycle and dying following the second growing season.
allowed_values_levels perennial: A plant that lives for three or more growing seasons, with an exact lifespan that is indeterminate.
allowed_values_levels short_lived_perennial: A perennial whose lifespan is less than approximately five years, with the exact lifespan generally dependent on environmental conditions.

Matches to other databases and vocabularies

Informal matches to traits included in databases and unpublished dictionaries are mapped in as examples, while matches to published vocabularies and ontologies and mapped using the formal terms, exact_match, close_match, and related_match`

To identify all traits that are also in the TRY trait database:

matches_to_TRY <- 
  APD_traits %>%
  select(trait, examples) %>%
  filter(!is.na(examples)) %>%
  mutate(examples = stringr::str_split(examples, "; ")) %>%
  unnest_longer(examples) %>%
  filter(stringr::str_detect(examples, "\\[TRY"))

The first 20 of many trait matches:

trait examples
leaf_Al_per_dry_mass exact match: Leaf aluminium (Al) content per leaf dry mass [TRY:249] (https://www.try-db.org/de/de.php)
leaf_B_per_dry_mass exact match: Leaf boron (B) content per leaf dry mass [TRY:250] (https://www.try-db.org/de/de.php)
leaf_C_per_dry_mass exact match: Leaf carbon (C) content per leaf dry mass [TRY:13] (https://www.try-db.org/de/de.php)
leaf_Ca_per_dry_mass exact match: Leaf calcium (Ca) content per leaf dry mass [TRY:252] (https://www.try-db.org/de/de.php)
leaf_Cl_per_dry_mass exact match: Leaf chlorine (Cl) content per leaf dry mass [TRY:539] (https://www.try-db.org/de/de.php)
leaf_Cr_per_dry_mass exact match: Leaf chromium (Cr) content per leaf dry mass [TRY:254] (https://www.try-db.org/de/de.php)
leaf_Co_per_dry_mass exact match: Leaf cobalt (Co) content per leaf dry mass [TRY:253] (https://www.try-db.org/de/de.php)
leaf_Cu_per_dry_mass exact match: Leaf copper (Cu) content per leaf dry mass [TRY:255] (https://www.try-db.org/de/de.php)
leaf_Fe_per_dry_mass exact match: Leaf iron (Fe) content per leaf dry mass [TRY:256] (https://www.try-db.org/de/de.php)
leaf_K_per_area exact match: Leaf potassium (K) content per leaf area [TRY:52] (https://www.try-db.org/de/de.php)
leaf_K_per_dry_mass exact match: Leaf potassium (K) content per leaf dry mass [TRY:44] (https://www.try-db.org/de/de.php)
leaf_Mg_per_dry_mass exact match: Leaf magnesium (Mg) content per leaf dry mass [TRY:257] (https://www.try-db.org/de/de.php)
leaf_Mn_per_dry_mass exact match: Leaf manganese (Mn) content per leaf dry mass [TRY:258] (https://www.try-db.org/de/de.php)
leaf_Mo_per_dry_mass exact match: Leaf molybdenum (Mo) content per leaf dry mass [TRY:259] (https://www.try-db.org/de/de.php)
leaf_N_per_area exact match: Leaf nitrogen (N) content per leaf area [TRY:50] (https://www.try-db.org/de/de.php)
leaf_N_per_dry_mass exact match: Leaf nitrogen (N) content per leaf dry mass [TRY:14] (https://www.try-db.org/de/de.php)
leaf_Na_per_dry_mass exact match: Leaf sodium (Na) content per leaf dry mass [TRY:260] (https://www.try-db.org/de/de.php)
leaf_Ni_per_dry_mass exact match: Leaf nickel (Ni) content per leaf dry mass [TRY:261] (https://www.try-db.org/de/de.php)
leaf_P_per_area exact match: Leaf phosphorus (P) content per leaf area [TRY:51] (https://www.try-db.org/de/de.php)
leaf_P_per_dry_mass exact match: Leaf phosphorus (P) content per leaf dry mass [TRY:15] (https://www.try-db.org/de/de.php)

To obtain matches to other informally published trait matches in dictionary and ontologies, use the following patterns with str_detect:

Vocabulary / Database string to match to
TRY Plant Trait Database \\[TRY
TOP Thesaurus \\[TOP
BIEN \\[BIEN
GIFT \\[GIFT
LEDA \\[LEDA
BROT Database \\[BROT
Palm Traits Database \\[Palm

Slightly different code is required to extract lists of formally published trait definitions for which there are matches:

matches_to_WoodyPlants <- 
  APD_traits %>%
  select(trait, exact_match, close_match, related_match) %>%
  pivot_longer(cols = 2:4) %>%
  filter(!is.na(value)) %>%
  mutate(value = stringr::str_split(value, "; ")) %>%
  unnest_longer(value) %>%
  filter(stringr::str_detect(value, "CO_357"))

The first 20 matches to the Woody Plants Ontology are:

trait name value
leaf_C_per_dry_mass exact_match Leaf carbon content [https://cropontology.org/rdf/CO_357:0000086]
leaf_N_per_area exact_match Leaf nitrogen content [https://cropontology.org/rdf/CO_357:0000159]
leaf_N_per_dry_mass exact_match Leaf nitrogen content [https://cropontology.org/rdf/CO_357:0000159]
leaf_CN_ratio exact_match Ratio leaf nitrogen to leaf carbon [https://cropontology.org/rdf/CO_357:0000287]
leaf_CN_ratio exact_match C/N [https://cropontology.org/rdf/CO_357:0000512]
leaf_soluble_protein_per_area exact_match Leaf soluble protein content [https://cropontology.org/rdf/CO_357:0000281]
leaf_chlorophyll_per_area exact_match Leaf chlorophyll content [https://cropontology.org/rdf/CO_357:0000249]
leaf_chlorophyll_per_dry_mass exact_match Leaf chlorophyll content [https://cropontology.org/rdf/CO_357:0000250]
leaf_chlorophyll_A_per_area close_match Chlorophyll a [https://cropontology.org/rdf/CO_357:0000514]
leaf_chlorophyll_A_per_dry_mass exact_match Chlorophyll a [https://cropontology.org/rdf/CO_357:0000514]
leaf_chlorophyll_B_per_area close_match Chlorophyll b [https://cropontology.org/rdf/CO_357:0000515]
leaf_chlorophyll_B_per_dry_mass exact_match Chlorophyll b [https://cropontology.org/rdf/CO_357:0000515]
leaf_chlorophyll_A_B_ratio exact_match Chlorophyll a to b ratio [https://cropontology.org/rdf/CO_357:0000516]
leaf_rubisco_per_leaf_dry_mass exact_match Leaf rubisco content [https://cropontology.org/rdf/CO_357:0000273]
leaf_delta13C exact_match Delta C13 [https://cropontology.org/rdf/CO_357:0000085]
wood_delta13C exact_match Wood Carbon content [https://cropontology.org/rdf/CO_357:0000113]
leaf_delta15N exact_match Delta 15N [https://cropontology.org/rdf/CO_357:0000513]
plant_width close_match Crown size [https://cropontology.org/rdf/CO_357:0000101]
plant_height exact_match Tree height [https://cropontology.org/rdf/CO_357:0000111]
plant_height exact_match Tree height [https://cropontology.org/rdf/CO_357:0000048]

To obtain matches to other formally published trait in ontologies, use the following patterns with str_detect:

Vocabulary / Database string to match to
Woody Plants Ontology CO_357
Plant Trait Ontology (TO) obo\\/TO_
Flora Phenotype Ontology (FLOPO) obo\\/FLOPO_
EnvThes EnvThes

References

As appropriate, references are listed for each trait concept, under references.

fluorescence <- 
  APD_traits %>%
  select(trait, label, references) %>%
  filter(str_detect(trait, "fluorescence"))
trait label references
leaf_fluorescence_fv_over_fm Leaf maximum quantum yield (Fv/Fm) Maxwell & Johnson 2000 [https://doi.org/10.1093/jexbot/51.345.659]; Long 1993 [https://doi.org/10.1007/BF00195081]
leaf_fluorescence_quantum_yield Leaf ambient quantum yield Maxwell & Johnson 2000 [https://doi.org/10.1093/jexbot/51.345.659]; Long 1993 [https://doi.org/10.1007/BF00195081]

Alternatively, if you know the doi for a reference andyou can search for traits that reference it.

BT12225 <- 
  APD_traits %>%
  select(trait, label, references) %>%
  filter(str_detect(references, "doi.org/10.1071/BT12225"))

The first 15 traits referencing Pérez-Harguindeguy 2013:

trait label references
plant_height Plant vegetative height Pérez-Harguindeguy 2013 [https://doi.org/10.1071/BT12225]; Falster 2003a [https://doi.org/10.1016/S0169-5347(03)00061-2]
plant_spinescence Plant spinescence Pérez-Harguindeguy 2013 [https://doi.org/10.1071/BT12225]
leaf_area Leaf area Pérez-Harguindeguy 2013 [https://doi.org/10.1071/BT12225]
leaf_length Leaf length Pérez-Harguindeguy 2013 [https://doi.org/10.1071/BT12225]
leaf_thickness Leaf thickness Pérez-Harguindeguy 2013 [https://doi.org/10.1071/BT12225]
leaf_dry_mass Leaf dry mass Pérez-Harguindeguy 2013 [https://doi.org/10.1071/BT12225]
leaf_fresh_mass Leaf fresh mass Pérez-Harguindeguy 2013 [https://doi.org/10.1071/BT12225]
leaf_mass_per_area Leaf mass per area Pérez-Harguindeguy 2013 [https://doi.org/10.1071/BT12225]; Wright 2004 [https://doi.org/10.1038/nature02403]
leaf_lamina_mass_per_area Leaf lamina mass per area Pérez-Harguindeguy 2013 [https://doi.org/10.1071/BT12225]
leaf_fresh_mass_per_area Leaf fresh mass per leaf area Pérez-Harguindeguy 2013 [https://doi.org/10.1071/BT12225]
leaf_type Leaf type Pérez-Harguindeguy 2013 [https://doi.org/10.1071/BT12225]; Burrows 2001 [https://doi.org/10.1086/319579]
fruit_dry_mass Fruit dry mass Pérez-Harguindeguy 2013 [https://doi.org/10.1071/BT12225]; Kew Seed Information Database 2022 [https://data.kew.org/sid/sidsearch.html]
fruit_length Fruit length Pérez-Harguindeguy 2013 [https://doi.org/10.1071/BT12225]; Kew Seed Information Database 2022 [https://data.kew.org/sid/sidsearch.html]
fruit_width Fruit width Pérez-Harguindeguy 2013 [https://doi.org/10.1071/BT12225]; Kew Seed Information Database 2022 [https://data.kew.org/sid/sidsearch.html]
fruit_height Fruit breadth Pérez-Harguindeguy 2013 [https://doi.org/10.1071/BT12225]; Kew Seed Information Database 2022 [https://data.kew.org/sid/sidsearch.html]

Deprecated trait names

For AusTraits users, if you have used an old version of AusTraits, previous names used for trait concepts are documented under deprecated_trait_name.

You can extract all trait names that have changed, with 10 of them displayed:

deprecated_trait_names <- 
  APD_traits %>%
  select(trait, label, deprecated_trait_name) %>%
  filter(!is.na(deprecated_trait_name))
trait label deprecated_trait_name
leaf_chlorophyll_A_B_ratio Ratio of leaf chlorophyll A content to leaf chlorophyll B content chlorophyll_A_B_ratio
leaf_rubisco_per_leaf_dry_mass Leaf rubisco content per unit leaf dry mass cell_rubisco_concentration
seed_protein_per_seed_dry_mass Seed protein content per unit seed dry mass seed_protein_content
seed_oil_per_seed_dry_mass Seed oil content per unit seed dry mass seed_oil_content
leaf_ash_per_dry_mass Leaf ash content per unit leaf dry mass leaf_ash_content_per_dry_mass
bark_ash_per_dry_mass Bark ash content per unit bark dry mass bark_ash_content_per_dry_mass
plant_diameter_breast_height Stem diameter at breast height basal_diameter
stem_count Stem count stem_count_categorical
plant_spinescence Plant spinescence spinescence
seedling_hypocotyl_hairs Hypocotyl hairiness hypocotyl_type
seedling_first_node_leaf_type Seedling first true leaf type seedling_first_leaf

Or look up a specific trait name that is no longer used:

deprecated_fire_traits <-
  APD_traits %>%
  select(trait, label, deprecated_trait_name) %>%
  filter(str_detect(deprecated_trait_name, "fire"))
trait label deprecated_trait_name
resprouting_capacity Post-fire resprouting capacity fire_response
resprouting_capacity_proportion_individuals Post-fire proportion resprouting individuals fire_response_numeric
resprouting_capacity_juvenile Post-fire resprouting capacity of juvenile plants fire_response_juvenile
resprouting_capacity_stem_ratio Post-fire to pre-fire stem ratio fire_response_stem_ratio
resprouting_capacity_non_fire_disturbance Plant vegetative response to disturbances other than fire regeneration_non_fire_disturbance
post_fire_recruitment Post-fire recruitment fire_and_establishing
fire_time_from_fire_to_fruiting Time from fire to fruiting time_from_fire_to_fruit

Labelling your own data with APD identifiers

The reason the definitions carry identifiers is so that a dataset can point at them. Recording https://w3id.org/APD/traits/trait_0011211 alongside your leaf_area column says which of the several possible meanings of “leaf area” you measured, and lets anyone — or any pipeline — retrieve the definition, the expected unit and the allowed range without asking you.

APD_traits carries both forms of identifier: identifier is the bare trait_0011211, and Entity is the resolvable URI. Matching your column names against trait, falling back to deprecated_trait_name for names that have since been renamed:

my_traits <- tibble::tibble(
  column = c("leaf_area", "seed_dry_mass", "N_to_P_ratio", "leaf_thickness_mm")
)

deprecated <-
  APD_traits %>%
  select(trait, deprecated_trait_name) %>%
  filter(!is.na(deprecated_trait_name)) %>%
  mutate(deprecated_trait_name = str_split(deprecated_trait_name, "; ")) %>%
  unnest_longer(deprecated_trait_name)

my_traits_labelled <-
  my_traits %>%
  left_join(deprecated, by = c(column = "deprecated_trait_name")) %>%
  mutate(trait = coalesce(trait, column)) %>%
  left_join(
    APD_traits %>% select(trait, APD_identifier = identifier, APD_URI = Entity),
    by = "trait"
    ) %>%
  select(column, trait, APD_identifier, APD_URI)
column trait APD_identifier APD_URI
leaf_area leaf_area trait_0011211 https://w3id.org/APD/traits/trait_0011211
seed_dry_mass seed_dry_mass trait_0012610 https://w3id.org/APD/traits/trait_0012610
N_to_P_ratio leaf_NP_ratio trait_0000091 https://w3id.org/APD/traits/trait_0000091
leaf_thickness_mm leaf_thickness_mm NA NA

N_to_P_ratio resolves through its deprecated name to the current concept, leaf_NP_ratio. leaf_thickness_mm does not match at all — it is a column name carrying a unit rather than a trait concept, and the APD concept it belongs to (leaf_thickness) has to be chosen by reading the definition. Unmatched rows are the useful output of this exercise: each one is either a trait the APD does not yet define, in which case please tell us, or a column whose meaning was never as obvious as its name suggested.