fastnntpy 0.2.4
Fast NeighbourNet (Rust) with Python bindings
Requires Python: >=3.9

[![DOI](https://zenodo.org/badge/1037785550.svg)](https://doi.org/10.5281/zenodo.16907379)

# fast-nnt
fast-nnt (read Fast Ent) is a simple Rust implementation of the Neighbour Net algorithm with both R and Python bindings.

### Introduction

Fast-NNT is a Rust implementation of the NeighbourNet algorithm, designed for efficient phylogenetic analysis. It constructs split trees from distance matrices, providing a fast and reliable tool for researchers in evolutionary biology. R and Python bindings are provided so that users can easily integrate Fast-NNT into their existing workflows.

**Why does this exist when SplitsTree is available?**

Well, SplitsTree4/6 are GUI-based applications, while Fast-NNT is a command-line tool that can be easily integrated into automated workflows and pipelines. It's meant to be lightweight and simple to use, you provide a simple input and it generates the nexus file. You can then use this file in R or Python to generate your own plots. This is perfect for people who love to manually beautify their visualizations.

Additionally, we provide R and Python bindings that allow you pass in memory data matrices directly with a single command and get results without having to write intermediate files. For installation instructions, please refer to the respective documentation for R and Python.

**How do the results compare to SplitsTree?**

Fast-NNT aims to produce results that are consistent with those generated by SplitsTree, but there may be differences due to the underlying implementations and algorithms used. Users are encouraged to compare the output from Fast-NNT with that of SplitsTree to assess any discrepancies and determine the best tool for their specific needs.

![Comparison to SplitsTree4](images/IMG_5077.png)

### Installation
Install Rust via [rustup](https://rustup.rs/).

#### Python
You can install the Python package via pip:
```bash
pip install fastnntpy
```

#### R
You can install the R package via:
```R
install.packages("fastnntr")

# Or if CRAN is unavailable and you have Rust on your machine, i think this will work
devtools::install_github("rhysnewell/fast-nnt", subdir = "fastnntr")
```

If you are developing locally and have changed the R bindings:
```R
rextendr::document()
devtools::load_all()
```

#### CLI

```bash
cargo install fast-nnt
```

Alternatively, you can build from source. Clone and install this repo via:
```bash
git clone https://github.com/rhysnewell/fast-nnt.git
cd fast-nnt
cargo install --path .
```

### Usage

For `Python` and `R`, complete usage examples can be found in `test/python` and `test/R`. But a brief summary is as follows.

#### Ordering and inference methods
Fast-NNT exposes two knobs that match the algorithmic choices in SplitsTree:
- Ordering (`ordering_method` / `-O`): the cycle construction step. Options are `splitstree4` (SplitsTree4-style ordering) and `huson2023` (the improved ordering from Bryant & Huson 2023). The default is `huson2023`.
- Inference (`inference_method` / `--inference`): the split-weight solver. Options are `active-set` (active-set NNLS, default) and `splitstree4` (SplitsTree4-style optimizer).
- For SplitsTree6-style defaults, use `ordering_method="splitstree4"` with `inference_method="active-set"` (or `-O splits-tree4 --inference active-set` in the CLI).
- For SplitsTree4-style defaults, use `ordering_method="splitstree4"` with `inference_method="splitstree4"` (or `-O splits-tree4 --inference splitstree4` in the CLI).

#### Python
Read data in via `numpy`, `pandas`, or `polars`:

```
import fastnntpy as fn
import pandas as pd
data = pd.read_csv("test/data/large/large_dist_matrix.csv")
n = fn.run_neighbour_net(
    data,
    ordering_method="huson2023",
    inference_method="active-set",
)
print("Labels")
print(len(n.get_labels()))
print("Splits Records")
print(len(n.get_splits_records()))
print("Node Translations")
print(len(n.get_node_translations()))
print("Node Positions")
print(len(n.get_node_positions()))
print("Graph Edges")
print(len(n.get_graph_edges()))
```

#### R
Read your distance matrix in using your preferred method (e.g., `data.table`):
```
library(fastnntr)
library(data.table)
data <- fread("test/data/large/large_dist_matrix.csv", header=TRUE)
# Load network
Nnet <- fastnntr::run_neighbournet_networkx(
  data,
  ordering_method="huson2023",
  inference_method="active-set"
)
```

The `run_neighbournet_networkx` function will return an object almost identical to that produced by `phangorn`, so should be compatible with existing workflows.

#### CLI
Required input is a symmetrical distance matrix, ideally with a header row indicating the taxa labels. Can be separated by any delimiter.

To generate a split nexus file (mostly) identical to SplitsTree4 and SplitsTree6:
```
fast_nnt neighbour_net -t 4 -i test/data/large_dist_matrix.csv -d output_dir -o prefix -O splits-tree4
```

Use the new Huson 2023 ordering algorithm (default):
```
fast_nnt neighbour_net -t 4 -i test/data/large_dist_matrix.csv -d output_dir -o prefix -O huson2023
```

Select the split-weight inference method:
```
fast_nnt neighbour_net -t 4 -i test/data/large_dist_matrix.csv -d output_dir -o prefix --inference active-set
fast_nnt neighbour_net -t 4 -i test/data/large_dist_matrix.csv -d output_dir -o prefix --inference splitstree4
```

### Output

The output will include a nexus file containing the split network and network layout.



### Citations

If you use this tool in your work, please cite the original authors work:
- Bryant & Huson 2023: D. Bryant and DH Huson, NeighborNet- improved algorithms and implementation. Front. Bioinform. 3, 2023.
- Bryant & Moulton 2004: D. Bryant and V. Moulton. Neighbor-net: An agglomerative method for the construction of phylogenetic networks. Molecular Biology and Evolution, 21(2):255– 265, 2004.

You can also cite this repository directly:
- Newell, R. J. P., & McMaster, E. S. (2025). Fast-NNT: Fast NeighbourNet Split Trees For Unrooted Phylogenetic Analysis (v0.2.0). Zenodo. https://doi.org/10.5281/zenodo.16907379