Genomics Research · Northern Arizona University

Reviving NASP

I worked with Dr. Jason Sahl, Associate Professor of Biology at Northern Arizona University and Assistant Director of its Pathogen and Microbiome Institute, on NASP, a genomic analysis tool he published as part of his federally funded pathogen-detection research. Researchers use it to compare bacterial genomes, for example to tell how closely related outbreak samples are. Its install package had been broken for years. I found out why, fixed it, and got the fixes shipped to bioconda, the main software channel for bioinformatics.

6+Years without a new builduntil my first fix was merged
25Logged test runseach in a clean Linux container
4Root causes foundplus a hidden build blacklist
100%Identical outputto the expected results, byte for byte
Merged · Oct 27, 2026

Pull request #1: packaging fixes

Got the package building and installing again, and shipped the first new NASP builds since August 2020.

View on GitHub →
In review · all checks passing

Pull request #2: code fixes

Updates NASP's code so it runs on current Python and current samtools, and pins the Java version GATK needs.

View on GitHub →
The problem

It installed perfectly and didn't work

Running conda install nasp finished without a single error. Every quick check I could run without actually using the tool also passed. But the first time NASP tried to process an alignment, it crashed.

Every alignment in NASP passes through a tool called samtools, and the samtools version the package pinned couldn't even start. So the pipeline died before it processed a single read, and nobody had been able to publish a fixed build since 2020.

The lesson that shaped the whole project: a dry run only checks that packages fit together. It never runs them. From then on I tested by actually running things.

$ conda install nasp
done
$ samtools --version
samtools: error while loading shared
libraries: libncurses.so.5: cannot open
shared object file: No such file or
directory
$ ldd $(which samtools) | grep ncurses
  libncurses.so.5 => not found
The real output from a fresh install (test run 10)
Diagnosis

What was actually broken

Root cause 1 · The crash

A samtools build missing a library

The recipe pinned samtools below 1.3, which picked version 1.2. That build needs a system library (ncurses) but never declared it, so nothing installed it and the program couldn't load.

Fix: pin samtools 1.1 instead. Its build declares the library correctly and still understands NASP's commands. I tested this directly against four samtools versions.

Root cause 2 · No new builds

One line of shell broke every build

The build script overwrote NASP's Go module file with a one-line version that dropped a dependency. Older Go versions quietly fixed that. Go 1.16 made it a hard error, so the build broke without anyone changing NASP.

Fix: delete that one line.

Root cause 3 · Hidden

A blacklist nobody remembered

When that build failure hit bioconda's 2021 mass rebuild, NASP was added to a list of recipes the system stops trying to build. That's why the failure stayed invisible for years.

Fix: remove NASP from the blacklist.

Root cause 4 · Modern Python

A removed Python module

NASP found its own bundled files with pkg_resources, which setuptools deleted. I pinned down exactly when: version 81.0.0 has it, 82.0.0 doesn't.

Fix: a temporary version pin, then a real code fix using Python's built-in importlib.resources at all 4 places NASP used it.

Root cause 5 · Modern samtools

The fix that silently failed

NASP sorts alignments with an old samtools command that newer versions reject. The obvious replacement looked fine, but when I tested it on samtools 1.1 it wrote no output file and still reported success. A small extra flag (-T) makes it work on 1.1, 1.9, and 1.24. This is why I tested every fix instead of trusting it.

Proof

The receipts

Same answer, byte for byte

  • Ran the full pipeline on NASP's own example dataset: alignment, SNP calling, an external genome, and the duplicate-region check
  • Ran it three ways: the original code, my fixed code, and my fixed code on the newest samtools
  • All three produced output byte-identical to each other and to the expected results in the repository: 3,977 positions and the same 5 SNPs

How I tested

  • Every test ran in a fresh Ubuntu container with nothing carried over, and every run's raw output is saved
  • No claim without a command behind it. That rule disproved 8 assumptions, including the starting premise of the whole project
  • Caught two mistakes in my own method: Linux versions solved from a Mac came out stale, and a piped command was hiding a failure. I re-ran both
  • Checked the recipes with bioconda's own linter and build tools before submitting
Judgment

What I left out on purpose

Some problems aren't packaging bugs. Fixing them would change which SNPs NASP reports, so they're research decisions for the lab, not for me.

Retired, with approval

The SAMtools SNP caller

Its 2013-era command fails on every bcftools version still packaged. Rewriting it would change results, so with Dr. Sahl's approval I removed it from the menu instead.

Needs validation

Moving to GATK 4

NASP's caller doesn't exist in GATK 4. Its replacement calls SNPs differently, so switching would need scientific revalidation.

Untested

MUMmer 4

It looks compatible on paper, but its defaults changed. MUMmer 3.23 works, so I left it rather than guess.

Process

How the project ran

  1. Sep 1Committed to a full diagnosis within two weeks
  2. Sep 15Delivered the diagnosis: 18 test runs, a dependency audit, and a 10-step plan
  3. Oct 7–9Wrote and validated the fixes
  4. Oct 12Dr. Sahl approved submitting. Opened pull request #1
  5. Oct 27Pull request #1 merged by a bioconda maintainer
  6. Oct 29–30Opened pull request #2 with the code fixes, and added a Java fix after Dr. Sahl reported a problem on the lab's cluster

I worked directly with Dr. Sahl from start to finish. I committed to a deadline, delivered a full written diagnosis, brought him the decisions that affected the science, and shipped the fixes once he approved them.

I set the rules for the project, made the scope and shipping decisions, and opened both pull requests. One is already merged into bioconda, the main software channel for bioinformatics.