Source code for qsarkit.representation.fingerprints._avalon

"""Avalon fingerprints (lazy ``rdkit.Avalon`` toolkit binding)."""

from __future__ import annotations

from typing import TYPE_CHECKING, Any

import numpy as np

from qsarkit.base import require
from qsarkit.representation.fingerprints._base import BaseFingerprintTransformer

if TYPE_CHECKING:  # pragma: no cover
    from rdkit.Chem import Mol


[docs] class AvalonFingerprint(BaseFingerprintTransformer): """Avalon substructure fingerprint. The Avalon cheminformatics toolkit enumerates a fixed, hand-designed set of feature classes (paths, rings, atom pairs at short distances, augmented atoms, ...) and hashes them into a folded bit vector. In the original benchmark it matched or outperformed contemporary path- and circular-based fingerprints on similarity searching. Parameters ---------- n_bits : int, default 512 Width of the folded fingerprint. 512 is the size used in the original publication and the RDKit default. use_counts : bool, default False Return per-feature occurrence counts (``pyAvalonTools.GetAvalonCountFP``) instead of a binary vector. is_query : bool, default False Generate the query flavour of the fingerprint, used when the molecule is a substructure query rather than a full structure. bit_flags : int, default 15761407 Feature-class bitmask; the default is Avalon's ``avalonSSSBits`` similarity setting used by RDKit. Raises ------ OptionalDependencyError If the RDKit build does not include the Avalon toolkit bindings (``rdkit.Avalon.pyAvalonTools``). Conda/PyPI RDKit wheels ship it, but minimal or source builds may omit it. Examples -------- >>> from rdkit import Chem >>> from qsarkit.representation.fingerprints import AvalonFingerprint >>> AvalonFingerprint(n_bits=256).fit_transform([Chem.MolFromSmiles("CCO")]).shape (1, 256) References ---------- - Gedeck, P., Rohde, B. & Bartels, C. (2006). "QSAR - How Good Is It in Practice? Comparison of Descriptor Sets on an Unbiased Cross Section of Corporate Data Sets." J. Chem. Inf. Model., 46(5), 1924-1936. https://doi.org/10.1021/ci050413p - RDKit ``rdkit.Avalon.pyAvalonTools`` documentation: https://www.rdkit.org/docs/source/rdkit.Avalon.pyAvalonTools.html """ _feature_prefix = "Avalon" #: RDKit's default Avalon similarity bit flags (``avalonSimilarityBits``). DEFAULT_BIT_FLAGS = 15761407 def __init__( self, n_bits: int = 512, use_counts: bool = False, is_query: bool = False, bit_flags: int = DEFAULT_BIT_FLAGS, ): self.n_bits = n_bits self.use_counts = use_counts self.is_query = is_query self.bit_flags = bit_flags @property def n_features_out(self) -> int: return int(self.n_bits) def _fingerprint(self, mol: "Mol") -> np.ndarray: from rdkit import DataStructs avalon = require("rdkit.Avalon.pyAvalonTools") n_bits = int(self.n_bits) if self.use_counts: count_vector = avalon.GetAvalonCountFP( mol, nBits=n_bits, isQuery=bool(self.is_query), bitFlags=int(self.bit_flags), ) array = np.zeros(n_bits, dtype=np.uint32) for bit, count in count_vector.GetNonzeroElements().items(): array[bit] = count return array bit_vector = avalon.GetAvalonFP( mol, nBits=n_bits, isQuery=bool(self.is_query), bitFlags=int(self.bit_flags), ) array = np.zeros(n_bits, dtype=np.uint8) DataStructs.ConvertToNumpyArray(bit_vector, array) return array