R packages · October 2026

Clusnalyst

A Shiny app for cluster analysis of marker, trait and sequence data. My colleagues and I built the first version at KNUST in 2022. In 2026 I rewrote it as an R package with a live demo.

Clusnalyst's tree step: the seven steps down the left, a table ranking seven clustering methods by cophenetic correlation, and a UPGMA tree of 60 simulated lines coloured by three clusters with bootstrap values on the branches
data types accepted, from band scores to protein sequences
5
errors, warnings and notes from R CMD check
0 / 0 / 0
tests, with one for each bug carried over from 2022
38

Intro

Clusnalyst groups samples by how alike they are, from band scores, SNP genotypes, a sheet of measured traits or a FASTA file. Along with the tree you get bootstrap support for each branch and an estimate of how many groups the data holds. At the end there’s a report to download, plus an R script that repeats the whole analysis.

You can try it in the browser without installing anything.

The Clusnalyst home page: the name in large type, buttons to upload data or try a demo, and a circular tree of the SNP demo coloured by population
Figure 1. The home page. The tree on the right is the SNP demo. You can hover over it.

Where it started

Clusnalyst was our final-year project at KNUST in 2022, built alongside Linkmapper by the same team, which I led. We wrote it to help with teaching systematics. It read 0/1 band scores and letter SNP genotypes, drew a dendrogram and ran silhouette and bootstrap checks. The whole thing was one Shiny file.

What was wrong with it

Four years later I read the old code again and found four bugs that changed results. The options labelled single and complete linkage both ran Ward’s method. The bootstrap resampled columns of the distance matrix instead of the markers, so its support values weren’t valid. Every session shared the same global variables, so two people on the hosted app at once could overwrite each other’s data. And telling it a FASTA file was already aligned made it crash.

Each of those now has a test in the package.

How it works now

  1. Load a table, VCF, HapMap or FASTA file. The app works out the data type and whether markers are in rows or columns. A second table can add population, origin or coordinates for each sample.
  2. Check quality: missing data, minor allele frequency and heterozygosity, with filters. Unaligned sequences are aligned with ClustalOmega, ClustalW or MUSCLE.
  3. Pick a distance. The default depends on the data: Jaccard for bands, allele sharing for SNPs, Gower when some traits are categories, Kimura’s model for DNA.
  4. Build the tree. A table ranks seven methods by cophenetic correlation, so you can see which one keeps your distances best.
  5. Check it, with bootstrap support from resampled markers, the number of groups by silhouette width and the gap statistic, and a Mantel test against geography or a second matrix.
  6. Split the samples into groups and see them on a PCoA or PCA plot.
  7. Download a report, the R script and a session file you can open again later.
The quality check step: sliders for missing data and minor allele frequency on the left, counts of samples and SNPs kept, and histograms of missing data, allele frequency and heterozygosity with the cut-offs drawn as dashed lines
Figure 2. The quality check on the SNP demo. Nothing is removed until you press Apply.
The bootstrap check: 100 replicates, 3 of 58 groups with at least 70% support, a tree with support values on the branches and a histogram of support
Figure 3. Bootstrap support on the SNP demo. Each of the three populations comes back in all 100 replicates, while the median support across the tree is 14%.

The demo data is simulated: 60 lines from three populations, 1,000 SNPs. Both the gap statistic and the silhouette pick three groups. On the PCoA plot the populations sit in separate corners. The average silhouette width is only 0.16, though, which the usual rule of thumb calls no structure at all. Individual genotypes differ at so many markers that this happens even when groups are real, so the app prints a short note under the number explaining it.

The groups step: three clusters of 20 lines each, an average silhouette width of 0.16, and a principal coordinates plot with the three clusters in separate corners inside dashed ellipses
Figure 4. Three groups on the first two principal coordinates.

Run it yourself

The hosted copy takes files up to 30 MB and up to 1,000 bootstrap replicates. Installed locally there are no limits:

install.packages("clusnalyst", repos = c("https://ebenogoe.r-universe.dev", "https://cloud.r-project.org"))
clusnalyst::run_app()

Every step is also an exported function, so the analysis can be scripted. The R script the app writes uses the same functions.

What’s next

SSR data with more than two alleles per locus isn’t handled yet, so that comes first. I’d also like the bootstrap to run in the background on the hosted app, so a long run doesn’t hold up the page.

More work

2026R packages

FounderForge

A Shiny app that turns real marker data into an AlphaSimR founder population without writing R. Load a VCF, HapMap, numeric or PLINK file, check it, filter it and export what newMapPop() needs.

Tools: R · Shiny · golem · AlphaSimR · vcfR · data.table · ggplot2

2026Apps

Plotpin

An Android app for finding a plant again. I built it to walk back to bagged sorghum plants in a crossing block. Now it works for anyone who marks points in a field.

Tools: Kotlin · Jetpack Compose · Room · Paparazzi

2026Machine learning

Colony Counter

An Android app that counts bacterial colonies from plate photos, offline. Two small YOLO models do the counting, in about three quarters of a second a plate on my phone.

Tools: Python · Ultralytics YOLO26 · ONNX Runtime · Kotlin · Jetpack Compose · CVAT

2026Reverse engineering

FF Mod Studio

Tools for modding Freedom Fighters, a game from 2003. There's an editor for its textures and models, plus a Blender addon that sends edits back into the game.

Tools: C++17 · Dear ImGui · miniz · HLSL · Python · Blender

2026R packages

ggWizard

A Shiny wizard for making ggplot2 charts from a CSV or Excel file without writing code. You check and clean the data, pick one of eight chart types and style it, then export it with the R script behind it.

Tools: R · Shiny · golem · ggplot2 · plotly · readxl · DT

2026R packages

Linkmapper

A Shiny app for building genetic linkage maps and mapping QTL without writing code. It began as the final-year project of two colleagues and me at KNUST. Now it's an R package, with a hosted copy that runs in the browser.

Tools: R · Shiny · golem · onemap · R/qtl · ggiraph

2026Codebreaking

The Voynich manuscript

A book about 600 years old, written in a script nobody can read. Here's what's known about it and why no codebreaker has cracked it, with a note on my own work.

Tools: Python · NumPy · SciPy