Tree-based visualization for high-dimensional data. Organizes similar items into interactive tree structures. Ideal for chemical space, protein embeddings, single-cell data, or any high-dimensional dataset.
![]() |
![]() |
Most dimensionality reduction tools (UMAP, t-SNE) produce point clouds. TMAP produces a tree, a connected structure where every point is linked to its neighbors through branches. This makes the layout itself explorable: you can follow branches, trace paths between any two points, and discover how regions connect.
For example, in a TMAP of pet breed images, following the branch from terriers toward cats reveals that the bridge between the two groups runs through chihuahuas and sphynx cats (the bald ones) which is both hilarious and logical; both are small, short-haired, big-eyed. The tree doesn't just cluster similar things it also shows you how dissimilar things are connected.
Because the layout is a tree, you get operations that point clouds can't support:
path = model.path(idx_a, idx_b) # nodes along the tree path
d = model.distance(idx_a, idx_b) # sum of edge weights along the path
pseudotime = model.distances_from(idx) # tree distance from one point to all otherspip install tmap2Optional extras:
pip install rdkit # chemistry helpers (fingerprints_from_smiles, molecular_properties)
pip install jupyter-scatter # notebook interactive widgets
pip install biopython # protein helpers (ProtParam properties, PDB parsing)Note: The import name is
tmap, nottmap2.
from tmap.utils import fingerprints_from_smiles
from tmap import TMAP
smiles = [...] # Your smiles list
# Get Binary fingerprints (Need Jaccard distance)
fps = fingerprints_from_smiles(smiles, fp_type="morgan", radius=2, n_bits=2048)
model = TMAP(metric="jaccard", n_neighbors=20, seed=42).fit(fps)
model.write_html("map.html") # Save in html file
# model.show() # See in Jupyter Notebook # embeddings (use cosine / euclidean distances)
X = np.random.random((1000, 128)).astype(np.float32)
model = TMAP(metric="cosine", n_neighbors=20).fit(X)
# model.write_html("tmap.html") # Save in html file
model.show() # See in Jupyter Notebook - Tree structure: follow branches, trace paths, compute pseudotime
- Deterministic: same input + seed = same output
- Multiple metrics:
jaccard,cosine,euclidean,precomputed - Incremental:
add_points()andtransform()for adding new data into an existing TMAP - Model persistence:
save()/load() - Three viz backends: interactive HTML, jupyter-scatter, matplotlib
Notebook widgets: color switching, categorical filtering, and lasso selection with pandas-backed metadata:
Adding colors is quite simple. Just pass the name of the layout (e.g. Molecular Weight, Age, Protein Lenght ...), a list of values for each node and matplotlib color.
If the data is categorical (e.g. Age or Heavy Atom Count) pass categorical=True so that categorical colors like tab10 become available.
To add labels (i.e. data that is not needed for coloring the nodes) just pass a name for the labels and the list of values.
model = TMAP(metric="jaccard").fit(X)
viz = model.to_tmapviz()
viz.add_color_layout("Molecular Weight", mw.tolist(), categorical=False)
viz.add_color_layout("Scaffold", scaffolds, categorical=True, color="tab10")
viz.add_label("SMILES", smiles_list)
viz.show(width=1000, height=620, controls=True) # to see in jupyter notebook
# viz.write_html("mytmap.html") # to save and see as HTML in the browserHere SMILES are added as label which will not trigger the 2D image of the structure. If you want to see the structures add smiles via
add_smiles(smiles_list)
If you save using viz.write_html("name.html") the Interactive HTML becomes available which supports lasso selection, light/dark theme, filter and search panels, pinned metadata cards, binary mode for large datasets.
Alternatively, you can see it with matplotlib by using Static plots matplotlib for publication figures: model.plot_static(color_by=labels)
Built-in helpers for common scientific workflows:
from tmap.utils.chemistry import fingerprints_from_smiles, molecular_properties
from tmap.utils.proteins import fetch_uniprot, sequence_properties
from tmap.utils.singlecell import from_anndata| Domain | Metric | Utilities |
|---|---|---|
| Chemoinformatics | jaccard |
fingerprints_from_smiles, molecular_properties, murcko_scaffolds |
| Proteins | cosine / euclidean |
fetch_uniprot, fetch_alphafold, read_fasta, sequence_properties |
| Single-cell | cosine / euclidean |
from_anndata, cell_metadata, marker_scores |
| Generic embeddings | cosine / euclidean / precomputed |
No domain utils needed |
| Notebook | Topic |
|---|---|
| 01 Quickstart | Shortest end-to-end walkthrough on a small molecule table |
| 02 Cheminformatics | SMILES → fingerprints → interactive molecular map |
| 03 Continuous Embeddings | Cosine and euclidean on MNIST: when to use each |
| 04 What's New | add_points, transform, tree paths, save/load, external kNN |
| 05 Single-Cell | RNA-seq with PBMC 3k, pseudotime, UMAP comparison |
| 06 FAQ | Troubleshooting and common questions |
| 07 MinHash Deep Dive | Encoding methods and when to use each |
| 08 Notebook Widgets | Coloring, tooltips, lasso selection with jupyter-scatter |
| 09 Card Configuration | Pinned card layout, fields, and links |
| 10 Protein Analysis | FASTA, ESM embeddings, AlphaFold |
| 11 USearch Jaccard | Native binary Jaccard backend (high recall, low memory) |
| 12 Legacy LSH Pipeline | Lower-level MinHash + LSHForest + layout workflow |
For direct control over indexing, hashing, and layout, see the legacy pipeline notebook. The main building blocks:
from tmap.index import USearchIndex # dense / binary kNN
from tmap import MinHash, LSHForest # Jaccard on sets / strings
from tmap.layout import LayoutConfig, layout_from_lsh_forestYour Data
├─→ Binary matrix ─────────→ USearch (Jaccard / cosine / euclidean)
└─→ Sets / strings ───────→ MinHash → LSHForest
↓
k-NN Graph → MST → OGDF Tree Layout → Interactive Visualization
git clone https://github.com/afloresep/tmap2.git
cd tmap2
pip install ".[dev]"
pytest -vMIT License - see LICENSE for details.
Based on the original TMAP by Daniel Probst and Jean-Louis Reymond.


