Thursday, June 05, 2025

A metabarcoding mess and the importance of just looking at the data

How to cite: Page, R. (2025). A metabarcoding mess and the importance of just looking at the data. https://doi.org/10.59350/q2v8n-wc488

Here I summarise a few posts on Bluesky where I raised concerns about some metadabarcoding datasets that were highlighted by GBIF:

>3.4 million insect records based on DNA metabarcoding of bulk samples from #Sweden and #Madagascar have been mobilized to GBIF thanks to collaborative efforts of research institutions led by the #NaturhistoriskaRiksmuseet link

Looking at these datasets it’s clear that something is wrong.

Data

The datasets discussed are for CO1 Amplicon Sequence Variants from Madagascar, which are part of the Insect Biome Atlas project. The data is described in Miraldo et al. https://doi.org/10.1038/s41597-025-05151-0. There are two datasets for Madagascar:

  • CO1 Amplicon Sequence Variants of leaf litter arthropod communities collected at Malaise traps from the Insect Biome Atlas project in Madagascar https://doi.org/10.15468/pad7pc
  • CO1 Amplicon Sequence Variants of bulk arthropod samples (mild lysis) collected with Malaise traps from the Insect Biome Atlas project in Madagascar https://doi.org/10.15468/6u5rum

In case the data changes in the future I’ve made snapshots of the two datasets and uploaded them to Zenodo doi:10.5281/zenodo.15599342. The files I downloaded (https://doi.org/10.15468/dl.kwjyjt and https://doi.org/10.15468/dl.2p3z5q) are the GBIF annotated archives, hence they include the mapping between the taxonomic names and GBIF’s backbone taxonomy.

Problem

In browsing the data on GBIF I noticed some striking distribution patterns: insects normally found in Europe and/or North America were also turning up in Madagascar, based solely on these metabarcoding datasets. For example, Helina impuncta.

Helina impuncta

Metadata barcoding data can be a complicated beast, especially if you try and navigate the multiple databases that house metadata on the sampling program and the output of sequencing machines. For example, GBIF occurrence 5162479277 is linked to ENA record ERR12944764 which in turn has multiple identifier links:

Study Accession Sample Accession Experiment Accession Run Accession Tax Id
PRJEB61109 SAMEA115499645 ERX12317105 ERR12944764 1234904

What’s nice about the GBIF datasets that they wrap all this up into a single package that we can explore. BLASTing a few sequences in these datasets suggests that the identifications of these sequences were probably correct, so the source of the problematic maps lies elsewhere.

Lots of maps

I wrote a simple PHP script to read the GBIF dataset, aggregate the GBIF taxon ids (i.e., the GBIF taxa that the sequences were mapped to) and draw a map for each taxon (code is on GitHub) . These maps use GBIF’s maps API to retrieve a tile (256 x 256 pixels) showing the distribution of each taxon on a global map (i.e., zoom level 0 on a tiled web map). I overlay that on a GBIF base map tile (see Base Map Tiles), and dump the output as HTML.

This is crude but gives a quick visual overview of the data. For the litter datasets there are a lot of these Euro-Madagascar distributions:

litter

For the malaise trap data the results look much more like what I’d expect, lots of taxa restricted to Madagascar.

malaise

But there are still examples of the problematic pattern mentioned above.

What happened?

In the paper describing the data there is a paragraph discussing contamination:

As part of data clean-up, it is usually advised to remove ASVs present in negative controls, or the maximum number of reads for those, from the entire dataset71. However, after careful inspection of our negative controls, we noticed that only a few ASVs were persistently showing up in control samples. The majority of ASVs seemed to be arthropod sequences that were present in the bulk samples, and also sporadically present in negative controls in relatively small numbers. This was presumably due to DNA spreading between samples through tiny droplets during sample processing, or to low-level of “index hopping”, leading to incorrect assignment of reads during sequencing, despite the use of double-unique indexes in library preparation72. link

The paper goes on to discuss possible examples of contamination. Looking at the results I suspect there has been a lot more contamination than the authors allow, especially for the litter dataset.

Summary

These results are preliminary, and I’ve contacted the authors of the paper to see if we can find out what happened. But for me the most obvious conclusions are:

  • Metabarcoding has the potential to generate a lot of spurious records that may negatively impact databases such as GBIF.
  • One of the great features of GBIF is that it enables you to simply look at the data. In an age of automated pipelines and big data I think visualisation is increasingly important. It’s often an easy way to discover that something is not as it should be.

References

Miraldo, A., Sundh, J., Iwaszkiewicz-Eggebrecht, E. et al. Data of the Insect Biome Atlas: a metabarcoding survey of the terrestrial arthropods of Sweden and Madagascar. Sci Data 12, 835 (2025). https://doi.org/10.1038/s41597-025-05151-0

Page, R. (2025). Snapshot of Insect Biome Atlas data for Madagascar from GBIF [Data set]. Zenodo. https://doi.org/10.5281/zenodo.15599342

Written with StackEdit.

Friday, May 16, 2025

Tracking changes in DNA barcode BINs

Following on from releasing BOLD View I’ve started to explore how the classifcation of DNA barcodes changes over time. BOLD uses the RESL algorithm described in Ratnasingham & Hebert (2013, 2016) to cluster barcodes into “BINs”. As the number of DNA barcodes grows over time these clusters may change. For example, some clusters may increase in size as barcodes are added, and some clusters may be merged as sequences of intermediate similarity are found that link those BINs. Within the public-facing BOLD portal there is no way to see the history of a BIN (Meier et al., 2022), so I decided to explore this. I downloaded of data packages from BOLD for the period 2022-2024, as well as the BARCODE 500K data for 2016. BOLD issues regular releases of its data, querterly releases are persistent and received a DOI. More regular releases don’t get a DOI and seem to disappear from the web site, but I have a copy of the release for 06-Sep-2024, which I used to create BOLD View.

The data packages I’ve used to infer version history are listed below.

Dataset DOI
iBOLD.31-Dec-2016 10.5883/dp-ibold.31-dec-2016
BOLD_Public.30-Mar-2022 10.5883/dp-bold_public.30-mar-2022
BOLD_Public.06-Jul-2022 10.5883/dp-bold_public.06-jul-2022
BOLD_Public.28-Sep-2022 10.5883/dp-bold_public.28-sep-2022
BOLD_Public.30-Dec-2022 10.5883/dp-bold_public.30-dec-2022
BOLD_Public.31-Mar-2023 10.5883/dp-bold_public.31-mar-2023
BOLD_Public.30-Jun-2023 10.5883/dp-bold_public.30-jun-2023
BOLD_Public.29-Sep-2023 10.5883/dp-bold_public.29-sep-2023
BOLD_Public.29-Dec-2023 10.5883/dp-bold_public.29-dec-2023
BOLD_Public.29-Mar-2024 10.5883/dp-bold_public.29-mar-2024
BOLD_Public.19-Jul-2024 10.5883/dp-bold_public.19-jul-2024
BOLD_Public.06-Sep-2024 no DOI

Versioning

I am only interested in a few of the fields in the data, namely ,bin_uri, identification, identification_method, and identified_by. Note that field names can change between data packages, so we may have to translate field names, or assemble a field’s value from other fields (e.g., taxonomic classification). Rather than store all the data I used Tuple-versioning , so that we store values for processid and the various data fields, together values for valid_from and valid_to. The first time a combination of values is found we set valid_from to the YYYY-MM-DD date of the corresponding data package, and valid_to to NULL. Note that we may have multiple barcodes for a given processid (e.g., for different genes) so we index on both processid and marker_code. We also compute a MD5 hash of the data for a barcode to enable fast lookup of a particular set of values. The hash is not sufficient to identify an edit as the same set of values may have more than one period of validity. For example, a barcode may be in one BIN, then move to another, then move back again.

When we load the first data package (iBOLD.31-Dec-2016) all rows in the database will have NULL values for valid_to. This signals that those values for the data are currently valid. We then add the remaining data packages from oldest to most recent. For each barcode, if the data for a barcode in the current package is the same as that already in the database (i.e., for which valid_to is NULL) we do nothing. But if the data has changed we do the following:

  • set valid_to for the most recent row to the YYYY-MM-DD data of the current data package
  • add a new row with valid_from set to the same date, and valid_to set to NULL.

At the end of this process we have a list of values for the selected fields for each barcode, together with the time span that those values were valid.

Queries

There are two kinds of queries I’ve explored so far. The first is tracking the changes for an individual barcode, the other is the history of a BIN.

Barcode histories

Here is the history for XAF587-05

2022-03-30 - 2022-09-28

  • identification: Poanes hobomok
  • identified_by: Paul Hebert

2022-09-28 - 2024-07-19

  • identification: Lon hobomok
  • identified_by: Paul Hebert

2024-07-19 -

  • identification: Lon hobomok
  • identified_by: Paul D.N. Hebert

This examples shows that we need to be careful when counting edits to a barcode. We could simply record these as changes in identification and identifier, but is a little more complicated. Poanes hobomok and Lon hobomok are synonyms (Cong et al., 2019), so we’ve not changed the taxonomic identification, merely the name. In the absence of a single authoritative source of taxonomic names and synonyms I use TAXMATCH-like rules to “stem” the species names (Boyle, 2013), so that if two values of identification have the same species epithet (taking into account possible change in gender of the genus name) I treat these as changes in name, not identification. The other change is from “Paul Hebert” to “Paul D.N. Hebert”, which is clearly the same person. I compute the Levenshtein distance between values of identified_by and treat any value > 5 as a different name (5 was chosen so that “Paul Hebert” to “Paul D.N. Hebert” would be the same).

BINs

For BINs reconstruct the history by taking a BIN and finding all barcodes that have, at any point in time, been a member of that BIN. So far the best way I’ve come with to visualise the changes in a BIN is to create a “storyline” (see Liu et al., 2013) where the composition of each BIN is shown at each timeslice.

For example, here is the history of BIN BOLD:ABX0491 which contains barcocdes identifiers as Rhamma, Rhamma anosma, and Rhamma bilix (Prieto, et al. 2021).

The vertical columns are time slices, barcodes in the same BIN are grouped together in coloured rectangles, and the history of each barcode can be traced from left to right. You can see cases where barcodes have moved between BINs (BOLD:ABX0491 gobbled up two smaller BINs). There are also barcodes that were (for one time slice) not in any BIN.

This visualisation has been challenging to create, I ended up using # Graphviz as implememted in (https://dreampuf.github.io/GraphvizOnline).

Summary

This is still early stages, but it looks promising. The next step would be to incorporate it into BOLD View. It might also be interetsing to develop measures of stability of barcode clustering based on how often members move around.

References

  • Boyle, B., Hopkins, N., Lu, Z., Raygoza Garay, J. A., Mozzherin, D., Rees, T., Matasci, N., Narro, M. L., Piel, W. H., Mckay, S. J., Lowry, S., Freeland, C., Peet, R. K., & Enquist, B. J. (2013). The taxonomic name resolution service: an online tool for automated standardization of plant names. BMC Bioinformatics, 14(1). https://doi.org/10.1186/1471-2105-14-16
  • Cong, Q., Zhang, J., Shen, J., & Grishin, N. V. (2019). Fifty new genera of Hesperiidae (Lepidoptera). Insecta Mundi, 2019, 0731. https://doi.org/10.5281/zenodo.3677235
  • Hebert, P., & Ratnasingham, S. (2016). Systems, methods, and computer program products for merging a new nucleotide or amino acid sequence into operational taxonomic units (United States Patent US20160103958A1). [https://patents.google.com/patent/US20160103958A1)
  • Liu, S., Wu, Y., Wei, E., Liu, M., & Liu, Y. (2013). StoryFlow: Tracking the Evolution of Stories. IEEE Transactions on Visualization and Computer Graphics, 19(12), 2436–2445. https://doi.org/10.1109/TVCG.2013.196
  • Meier, R., Blaimer, B.B., Buenaventura, E., Hartop, E., von Rintelen, T., Srivathsan, A. and Yeo, D. (2022), A re-analysis of the data in Sharkey et al.’s (2021) minimalist revision reveals that BINs do not deserve names, but BOLD Systems needs a stronger commitment to open science. Cladistics, 38: 264-275. https://doi.org/10.1111/cla.12489
  • Prieto, C., Faynel, C., Robbins, R., & Hausmann, A. (2021). Congruence between morphology-based species and Barcode Index Numbers (BINs) in Neotropical Eumaeini (Lycaenidae). PeerJ, 9, e11843. https://doi.org/10.7717/peerj.11843
  • Ratnasingham, S., & Hebert, P. D. N. (2013). A DNA-Based Registry for All Animal Species: The Barcode Index Number (BIN) System. PLOS ONE, 8(7), e66213. https://doi.org/10.1371/journal.pone.0066213

Written with StackEdit.

Friday, April 11, 2025

Future interfaces for the Biodiversity Heritage Library

On Wednesday this week (April 9th, 2025) I gave a talk entitled “Future interface(s) for BHL” (the slides are on FigShare) at BHL Day 2025. My goal was to introduce “BHL-Light”, an exploration of an alternative interface to the Biodiversity Heritage Library (BHL). As some readers may already know, BHL is coming to a crossroads, and so this presentation felt a bit more urgent than my usual “here’s yet another web site I made”.

BHL-Light

BHL-Light is my attempt to explore other ways of navigating BHL. The current interface is somewhat dated, and I wanted to start from scratch and see what might be possible to create, even for someone with my somewhat limited skills. BHL-Light has only a very small subset of BHL’s content, I’m putting scalability issues to one side so that I can have some fun.

The tech (TL;DR BHL was not harmed in the making of this)

Under the hood, BHL-Light stores BHL metadata, OCR text, and layout information as JSON documents in CouchDB (one of my favourite databases for exploring new ideas).

BHL serves its images from Internet Archive, which is not always available. BHL recently uploaded images to AWS, but the images there are not currently viewable on the web. So I ended up creating my own image server. I used Hetzner’s S3-compatible object storage for the image files, added imgproxy to resize images as needed, and finally put all this behind a Cloudflare CDN to speed up image delivery (and reduce traffic to the S3 store, which becomes a real consideration when one is paying for all of this).

To view BHL content (e.g., books, journal volumes) I wrote my own viewer, modelled loosely on Google Books. I expressly wanted to avoid IIIF because I find IIIF viewers a terrible way to view documents, and for me BHL is all about the text.

The web site itself is a few PHP scripts to glue everything together, and I’ve tried to avoid using Javascript unless absolutely necessary. HTML + CSS is really powerful these days, so you can do a lot without resorting to Javascript.

Tour

In building BHL-Light I’ve wanted a simple interface to concentrate on displaying content as much as possible. I also wanted a cleaner interface, one that is responsive (AKA "mobile friendly").

BHL has some extraordinary content. It has works both old and new.

Text

The viewer I built makes it easy to scroll through an item, and also makes text selectable (something you currently can’t do in BHL. This means you can interact with text in the browser, such as using Google Chrome to translate part of the text.

It also opens up the possibility of annotation using Hypothes.is.

Geotagging and maps

I also demonstrated pages that had been geotagged. These tags can be extracted and used to create an interactive map.

I still haven’t decided on the best way to interact with the map. For example, should we use the map to search for content geographically, or should we search for content and display those results on a map, or both? I ran out of time to resolve this, so for now if you click on the map you see a H3 hexagon that encloses where you click. The idea is that then the page would display BHL content within that area. Other idea ideas include something like Frankenplace or JournalMap.

Document layout

For me one of the most exciting areas for the future is adding document layout information to BHL content, such that not only can we identify articles, but figures, tables, references, etc. In this way BHL could finally offer something akin to what Plazi can deliver: structured text about species. This has seemed a challenging task, but recent AI developments have been a game changer. In particular, Datalab have released powerful and simple-to-use tools that do a very good job of retrieving document structure from scanned pages. I have started to use this on BHL content and display the results on BHL-Light. For example, Datalab makes it almost trivial to identify and extract figures from scanned pages. Below is a comparsion of document layout for a page as inferred from a born-digital PDF by Plazi, and the same page in BHL where it is simply an image, but Datalab's methods have inferred which bits are text, figures, captions, etc.

One unexpected consequence of building my own image server (see above) is that the task of displaying figures by cropping page images becomes almost trivial. This idea was inspired in part by Smits et al.’s approach of cropping Internet Archive images.

What’s next?

There is much to do. BHL-Light is missing many features. It doesn’t make it easy to find content such as articles found by BioStor, the project I started over a decade ago to find articles in BHL. Search is rudimentary at best, and I haven’t tackled taxonomic names yet (but have ideas for this).

For me BHL-Light is a fun way to explore BHL, and its development has made me even more aware of all the work done to create the current and maintain the BHL portal. Apart from being a play thing for me, I am curious as to whether BHL-Light might be a way to have “BHL-mini” portals, rather like GBIF hosted portals. In this way, we could have views of BHL focused on a particular taxon, institution, person, etc., or localised by language and/or country. Perhaps we could de-extinct past projects such as BHL-Europe?

References

Page, R.D. Extracting scientific articles from a large digital archive: BioStor and the Biodiversity Heritage Library. BMC Bioinformatics 12, 187 (2011). https://doi.org/10.1186/1471-2105-12-187

Page, Roderic (2025). Future interface(s) for BHL. figshare. Presentation. https://doi.org/10.6084/m9.figshare.28777868.v1

Smits, T., Warner, B., Fyfe, P., & Lee, B. C. G. (2025). A Fully-Searchable Multimodal Dataset of the Illustrated London News, 1842–1890. Journal of Open Humanities Data, 11(1), 10. https://doi.org/10.5334/johd.284

Written with StackEdit.

Wednesday, February 26, 2025

BOLD View: exploring DNA barcodes

For a while now I’ve been exploring ways to navigate through DNA barcodes. Over the years I’ve built various “toys” to explore barcodes, such as Displaying a million DNA barcodes on Google Maps using CouchDB, built a small scale browser using Elastic search that had some succes, and discovered that Postgres can search for DNA sequences and it’s really fast. At the same time, I’ve bemoaned the challenges of getting barcode data into GBIF, and the current state of BOLD’s data exports.

Over the last few months I’ve been getting a project to the point where it’s usable, and today I’ve released a live version called BOLD view. Why make a portal to DNA barcodes when BOLD have themselves recently released a new version of their own portal you might ask? There are two reasons. Making my own forces me to explore the barcode data in some detail, which is eye-opening in places. The second reason is that I want to be able to explore the barcode data at various levels and in different ways. For example, I want an interactive global map of barcodes.

I want to see a DNA barcode in context, including a phylogeny that includes barcodes both within and outside the BIN the barcode belongs too.

I want to make the imagery more visible.

I want to be able to navigate the taxonomy underlying the barcodes using tools such as summary trees.

I want to be able to input a DNA search and quickly search for matches.

I also want to be able to connect the barcodes to the science behind them (who created the barcodes and what questions were they addressing?).

Abve all, I just want to be able to explore the data. I don’t want donut charts and dashboards. I want to be able to see the data and the connections. There is still much to be done, in particular I want to visualise sequence alignments. We can have a global map, and a global taxonomy, where is the global alignment?

I hope to work on BOLD view further, but for now it is out the door and my spotlight will inevitably turn elsewhere.

Written with StackEdit.