---
title: Fingerprints & Similarity
description: >-
  Calculate Morgan, RDKit, and pattern fingerprints for similarity searching and
  substructure screening.
---

Fingerprints let you encode molecular structure as bit vectors for similarity searching and substructure screening across a library. The fingerprint type (Morgan, RDKit topological, or pattern), its radius and bit count, and the similarity metric are what most affect which compounds surface as hits.

## Common fingerprints

- Morgan: `AllChem.GetMorganFingerprintAsBitVect(mol, radius=2, nBits=2048)`
- RDKit topological: `Chem.RDKFingerprint(mol, fpSize=2048)`
- Pattern: `Chem.PatternFingerprint(mol)`

```python
from rdkit import Chem, DataStructs
from rdkit.Chem import AllChem

query = Chem.MolFromSmiles("c1ccccc1O")
library = [Chem.MolFromSmiles(s) for s in ["c1ccccc1", "CCO", "CCN"]]

query_fp = AllChem.GetMorganFingerprintAsBitVect(query, radius=2, nBits=2048)
scores: list[float] = []

for mol in library:
    fp = AllChem.GetMorganFingerprintAsBitVect(mol, radius=2, nBits=2048)
    scores.append(DataStructs.TanimotoSimilarity(query_fp, fp))

print(scores)
```

## Substructure screening

1. Precompute pattern fingerprints for the library.
2. Filter by `HasSubstructMatch` only on candidates that pass fingerprint
   screening.

```python
pattern = Chem.MolFromSmarts("c1ccc(cc1)O")
hits = []
for mol in library:
    if not mol.HasSubstructMatch(pattern):
        continue
    hits.append(mol)
```

## Batch performance tips

- Use bit vectors (`ExplicitBitVect`) and avoid converting to hex strings during
  scoring.
- Chunk large libraries and parallelize scoring if CPU allows.
- Persist fingerprints to disk (e.g., `.fp` via
  `DataStructs.BitVectToBinaryText`) to skip recompute.
