Field notesFor developers

58,203 strains in rings: how we drew a family tree that won't stop branching

Cannabis pedigree data is half a century of catalogs, forum posts and contradictions. This is the under-the-hood tour: the dataset, the radial layout, and the rule that keeps conflicting claims side by side.

Pedigree charts are easy when the data is polite: two parents, one child, clean records, everyone shows up on time.

Cannabis pedigree data is not polite. It is half a century of seed catalogs, forum posts, and word of mouth. Sources contradict each other, strains get renamed, clones get sold under three different names, and some "parents" are just a guy's description of a plant he once saw. Data engineers call this a dirty graph. Everyone else calls it Tuesday.

cannalib.org is our attempt to draw that mess honestly. This post is the under-the-hood tour: the dataset, the layout, and the rule that makes the whole thing trustworthy (or at least auditable).

1. The Dataset

MetricLive count
Named strains143,611
In the main catalogue (listings, lineage, grow or effect data)92,344
Strains in the lineage map57,015
Parent-to-child links118,039
Evidence-backed data points7,358,743
Lab test results1,276,466
Sources / seed banks / breeders on real strains1,194 / 211 / 6,124
Strains with a real DNA sample1,017
Cup results (264 competitions, 61 countries, 1988 to 2026)21,141

What goes in:

  1. Seed bank and breeder catalogs. Historical and current listings, kept with their source.
  2. Lab data. 1.27 million test results, with strains where sources disagree on THC (37,014 of them) showing the disagreement rather than resolving it.
  3. Competition records. 21,141 results across 264 competitions. Be careful here: only 9,355 of those results are matched to a specific strain (on 4,333 strains). The rest name a brand, product, or person and are left unmatched rather than guessed.
  4. Recovered public research data. We pulled in archived material from the defunct Open Cannabis Project, plus public mirrors (details and numbers are on the sources page).

And what stays out: 120,822 product and label names (think "Strawberry Cough 0.5g Cartridge") live in a separate ledger so they can't pollute the strain graph. Another 271,392 parent claims are quarantined because they weren't good enough to publish. Garbage in, quarantine out.

2. The Layout: Rings, Because Trees Explode

Classic tree layouts fall over here. One popular parent can have thousands of descendants, and lineages loop back on themselves through backcrosses and self-pollination. (A tree where a node can be its own great-uncle is called a "graph", and it is why you don't get to use your favorite textbook algorithm.)

So the lineage map is radial:

  • Ring 0 (the center): landraces and founders, meaning strains with no recorded parents.
  • Ring N: documented generational distance outward from the founders.
  • Edge confidence: links backed by two or more independent sources are weighted over single-source claims, so consensus lines stand out from lone-wolf stories.

Why rings? Because the question people actually ask is "how far is this thing from its roots?", and a ring is a straight answer to that.

3. Conflict Is a Feature

Most data pipelines force one winner: pick a canonical value, throw away the rest. For botanical history, where the "truth" is often a disputed story, that's editorial bias disguised as engineering.

CannaLib stores competing claims side by side. If Source A says

Strain X = Parent A × Parent B

and Source B says

Strain X = Parent A × Parent C

both edges survive, each with its source. Click a node and you get every claim with its citation.

The record shape looks roughly like this. This is an illustrative sketch, not a live API response; check the API docs for the current schema.

{
"strain": "Example Kush",
"parentage_claims": [
{ "seed_parent": "Lemon Thai", "pollen_donor": "Afghani #1",
"source": "Catalog archive A", "year": 1996 },
{ "seed_parent": "Pakistani Chitral", "pollen_donor": "Unknown indica",
"source": "Community forum log B", "year": 2002 }
],
"awards": [
{ "competition": "Example Cup", "year": 2004,
"category": "Indica", "placement": 1, "verdict": "confirmed" }
]
}

The honesty rules behind it: don't invent (blank stays blank), don't blend (no averaging), don't merge (strains don't silently inherit parent data), don't shred (ranges stay ranges).

4. Try It, Break It

  • Explore the map at cannalib.org/explorer, with deep links like cannalib.org/explorer/#strain=og%20kush.
  • There's a public API at api.cannalib.org with a free tier and paid plans for heavier use.

Obvious experiments: model predictions from pedigree topology, test how well "consensus" edges hold up against DNA, or hunt for cycles we should have caught. If you find a bug in the graph, that is the best kind of bug report. Tell us.

Pull the thread

Fly through the rings yourself, or pull the same graph as JSON. Everything above is checkable in the same CannaLib tools we used.

Live from CannaLibOpen full page →

This opens the real CannaLib page inside the story, so it only loads when you ask.

Same data, as JSON
curl "https://api.cannalib.org/v1/corpus"
CannaLib corpusstrains, aliases, lab tests, DNA panels, cup results

More Strain Stories

Community

Every claim has a receipt. Argue about them here.

Spotted a wrong parent, a missing lab result, or want something from the API? The CannaLib Discord has a corrections forum where every fix comes with a source, and a dev channel for API users.

  • Data corrections with sources, tracked from report to shipped
  • API help, integrations and Home Assistant cards
  • Dataset releases and roadmap votes first
Join the CannaLib Discord (opens Discord in a new tab)

18+ · free · no selling or sourcing, ever