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")Using the APD: exploring and extracting trait definitions and metadata
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.jsonAccept 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 |
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.csvQuerying 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:exactMatchagainst, and how often - the trait hierarchy as a hierarchy, following
skos:broaderupwards, 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")):
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.