High-performance molecular operations using RDKit's C++ core through nanobind bindings
Project description
RDTools
High-performance molecular operations using RDKit C++ with numpy arrays.
RDTools provides fast molecular descriptor calculations, SMILES validation, and fingerprint generation by exposing RDKit's C++ core through pybind11 bindings. This allows for efficient processing of large numpy arrays of SMILES strings.
Features
- Fast Molecular Descriptors: Calculate molecular weight, LogP, TPSA in parallel
- SMILES Validation: Efficiently validate large arrays of SMILES strings
- Fingerprint Generation: Morgan fingerprints as numpy bit vectors
- TensorFlow Integration: Custom TensorFlow operations for data pipelines (tf.data compatible)
- Batch Processing: Optimized for large datasets with batch processing utilities
- NumPy Integration: Native support for numpy arrays with proper error handling
Installation
System Requirements
- Operating System: Linux (Ubuntu/Debian recommended), macOS, or Windows
- Python: 3.12 or later (specified in pyproject.toml)
- Memory: At least 4GB RAM recommended for building
- Disk Space: ~500MB for dependencies and build artifacts
Dependencies
1. System Dependencies
Ubuntu/Debian (Recommended):
# Update package manager
sudo apt-get update
# Install RDKit C++ libraries and development headers
sudo apt-get install -y python3-rdkit librdkit-dev librdkit1 rdkit-data
# Install build essentials (if not already installed)
sudo apt-get install -y build-essential cmake pkg-config
macOS with Homebrew:
# Install RDKit
brew install rdkit
# Install build tools (usually pre-installed with Xcode)
xcode-select --install
Windows:
# Using conda (recommended for Windows)
conda install -c conda-forge rdkit-dev rdkit
# You'll also need Visual Studio Build Tools
2. Python Dependencies
The build system automatically handles Python dependencies, but here's what gets installed:
Build-time dependencies (handled by pyproject.toml):
scikit-build-core>=0.10- Modern CMake-based Python build backendnanobind>=2.0.0- Fast C++/Python binding librarytensorflow==2.19.0- For TensorFlow custom operations (built automatically when available)
Runtime dependencies:
numpy>=1.20.0- Core numerical operationstensorflow==2.19.0- Required for TensorFlow custom operations
Development dependencies (optional):
pytest>=6.0- Testing frameworkblack- Code formattingisort- Import sorting
Build and Installation
Method 1: Quick Install (Recommended)
# 1. Clone the repository
git clone <repository-url>
cd rdtools
# 2. Install using uv (handles everything automatically)
uv sync
# 3. Build the C++ extension (with verbose output for debugging)
SKBUILD_EDITABLE_VERBOSE=1 uv sync --reinstall
Method 2: Step-by-Step Installation
# 1. Clone and navigate
git clone <repository-url>
cd rdtools
# 2. Create and activate virtual environment (if not using uv)
python -m venv .venv
source .venv/bin/activate # Linux/macOS
# or
.venv\Scripts\activate # Windows
# 3. Install build dependencies
pip install scikit-build-core pybind11 numpy
# 4. Build and install in editable mode
pip install -e .
Method 3: Manual CMake Build (Advanced)
For development or debugging the build process:
# 1. Ensure RDKit is installed (see System Dependencies above)
# 2. Create build directory
mkdir build && cd build
# 3. Configure with CMake
cmake .. \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_CXX_STANDARD=17 \
-DPYTHON_EXECUTABLE=$(which python)
# 4. Build with verbose output
make VERBOSE=1 -j$(nproc) # Linux/macOS
# or
cmake --build . --config Release --verbose # Windows
# 5. The extension will be in: build/_rdtools_core.so (or .pyd on Windows)
Verification
After installation, verify everything works:
# Test basic import
uv run python -c "import rdtools; print('RDTools version:', rdtools.__version__)"
# Test C++ extension loading
uv run python -c "import rdtools; print('Extension available:', rdtools._EXTENSION_AVAILABLE)"
# Run basic functionality test
uv run python -c "
import rdtools
import numpy as np
smiles = np.array(['CCO', 'c1ccccc1'])
result = rdtools.molecular_weights(smiles)
print('Molecular weights:', result)
print('✓ Installation successful!')
"
# Run the comprehensive example
uv run python examples/basic_usage.py
Troubleshooting
RDKit Not Found
Error: "RDKit not found. Please install RDKit or set RDBASE environment variable."
Solution: Install RDKit system packages as shown in System Dependencies above.
CMake Version Too Old
Error: "CMake 3.15 or higher is required"
Solution:
# Ubuntu/Debian
sudo apt-get install cmake
# Verify version
cmake --version
Compilation Errors
Error: Cannot find RDKit headers
Solutions:
- Install development packages:
sudo apt-get install librdkit-dev - Set environment variable:
export RDBASE=/path/to/rdkit - For conda installations:
export RDBASE=$CONDA_PREFIX
Python Version Issues
Error: "requires-python = '>=3.12'"
Solution: Use Python 3.12 or later. Check with: python --version
Import Errors After Build
ImportError: cannot import name '_rdtools_core'
Solutions:
- Rebuild:
SKBUILD_EDITABLE_VERBOSE=1 uv sync --reinstall - Check installation:
find .venv -name "*rdtools*" -type f - Verify RDKit:
python -c "import rdkit; print(rdkit.__version__)"
TensorFlow Custom Ops Errors
ImportError: RDK-Tools TensorFlow ops not available: undefined symbol
Solutions:
- Ensure TensorFlow versions match between build and runtime environments
- Rebuild with correct TensorFlow version:
rm -rf build/ dist/ && uv build - For distribution, use:
uv run auditwheel repair dist/*.whl --exclude "libtensorflow*"
Build Configuration
The build process is configured via pyproject.toml:
[tool.scikit-build]
build-dir = "build/{wheel_tag}" # Separate builds for different Python versions
cmake.version = ">=3.15" # Minimum CMake version
cmake.define.CMAKE_BUILD_TYPE = "Release" # Optimized builds
cmake.define.CMAKE_CXX_STANDARD = "17" # C++17 for RDKit compatibility
Key files:
pyproject.toml- Python packaging and build configurationCMakeLists.txt- CMake build instructions for C++ extensionsrc/cpp/- C++ source code using RDKit and pybind11src/rdtools/__init__.py- Python API wrapper
Quick Start
import numpy as np
import rdtools
# Sample SMILES strings
smiles = np.array(['CCO', 'c1ccccc1', 'CC(=O)O', 'invalid_smiles'])
# Validate SMILES
valid = rdtools.is_valid(smiles)
print(f"Valid: {valid}") # [True, True, True, False]
# Calculate molecular descriptors
descriptors = rdtools.descriptors(smiles)
print(f"Molecular weights: {descriptors['molecular_weight']}")
print(f"LogP values: {descriptors['logp']}")
print(f"TPSA values: {descriptors['tpsa']}")
# Generate fingerprints
fingerprints = rdtools.morgan_fingerprints(smiles, radius=2, nbits=2048)
print(f"Fingerprint shape: {fingerprints.shape}") # (4, 2048)
API Reference
Core Functions
rdtools.molecular_weights(smiles_array)
Calculate molecular weights for SMILES strings.
Parameters:
smiles_array: numpy array or list of SMILES strings
Returns:
- numpy array of molecular weights (float64), NaN for invalid SMILES
rdtools.logp(smiles_array)
Calculate LogP (octanol-water partition coefficient) values.
rdtools.tpsa(smiles_array)
Calculate TPSA (Topological Polar Surface Area) values.
rdtools.is_valid(smiles_array)
Validate SMILES strings.
Returns:
- boolean numpy array indicating validity
rdtools.descriptors(smiles_array)
Calculate multiple descriptors efficiently in a single pass.
Returns:
- Dictionary with keys: 'molecular_weight', 'logp', 'tpsa'
rdtools.canonical_smiles(smiles_array)
Convert SMILES to canonical form.
rdtools.morgan_fingerprints(smiles_array, radius=2, nbits=2048)
Calculate Morgan fingerprints as bit vectors.
Parameters:
radius: fingerprint radius (default: 2)nbits: number of bits (default: 2048)
Returns:
- 2D numpy array of shape (n_molecules, nbits) with dtype uint8
Utility Functions
rdtools.filter_valid(smiles_array)
Filter array to keep only valid SMILES.
rdtools.batch_process(smiles_array, batch_size=1000, **kwargs)
Process large arrays in batches with comprehensive results.
TensorFlow Operations
rdtools.tf_ops.string_process(smiles_tensor)
TensorFlow custom operation for string processing in data pipelines.
Parameters:
smiles_tensor: TensorFlow string tensor
Returns:
- TensorFlow string tensor with processed SMILES
Example:
import tensorflow as tf
import rdtools.tf_ops
# Use in tf.data pipeline
dataset = tf.data.Dataset.from_tensor_slices(["CCO", "c1ccccc1"])
dataset = dataset.map(rdtools.tf_ops.string_process)
Performance
RDTools is optimized for high-throughput molecular processing:
- Batch Processing: Calculate multiple descriptors in a single pass
- C++ Core: Uses RDKit's optimized C++ implementation
- Memory Efficient: Minimal Python overhead with direct numpy array access
- Parallel Ready: Functions are designed to work well with joblib/multiprocessing
Benchmarks
On a modern CPU, RDTools can process:
- ~10,000-50,000 molecules/second for descriptor calculations
- ~5,000-20,000 molecules/second for fingerprint generation
Performance varies by molecule complexity and system specifications.
Examples
See the examples/ directory for detailed usage examples:
basic_usage.py: Comprehensive demonstration of all featuresperformance_comparison.py: Benchmarking against pure Python approaches
Development
Development Setup
-
Clone and install in development mode:
git clone <repository-url> cd rdtools # Install with development dependencies uv sync # Build the C++ extension SKBUILD_EDITABLE_VERBOSE=1 uv sync --reinstall
-
Development workflow:
# Run tests uv run pytest tests/ # Code formatting uv run black src/ uv run isort src/ # Build wheel for distribution uv build uv run auditwheel repair dist/*.whl --exclude "libtensorflow*" # Run examples uv run python examples/basic_usage.py
-
Rebuilding after C++ changes:
# Clean rebuild (if needed) rm -rf build/ SKBUILD_EDITABLE_VERBOSE=1 uv sync --reinstall # Or force rebuild with pip uv run python -m pip install -e . --force-reinstall --no-deps
Testing
Run the test suite to ensure everything works:
# Run all tests
uv run pytest tests/ -v
# Run specific test
uv run pytest tests/test_rdtools.py::TestBasicFunctions::test_molecular_weights -v
# Test with coverage
uv run pytest tests/ --cov=rdtools --cov-report=html
Build Debugging
If you encounter build issues:
# Build with maximum verbosity
SKBUILD_EDITABLE_VERBOSE=1 CMAKE_VERBOSE_MAKEFILE=ON uv sync --reinstall
# Check CMake configuration
cd build/cp312-cp312-linux_x86_64 # (or your platform directory)
cmake .. -DCMAKE_BUILD_TYPE=Debug
# Manual build for debugging
mkdir debug_build && cd debug_build
cmake .. -DCMAKE_BUILD_TYPE=Debug -DCMAKE_VERBOSE_MAKEFILE=ON
make VERBOSE=1
Project Structure
rdtools/
├── src/
│ ├── rdtools/ # Python package
│ │ └── __init__.py # Main API and function wrappers
│ └── cpp/ # C++ source code
│ ├── molecular_ops.hpp # C++ function declarations
│ ├── molecular_ops.cpp # C++ implementations using RDKit
│ └── pybind_module.cpp # pybind11 bindings
├── examples/ # Usage examples and demos
│ └── basic_usage.py # Comprehensive feature demonstration
├── tests/ # Test suite
│ └── test_rdtools.py # Unit tests
├── build/ # Build artifacts (generated)
├── CMakeLists.txt # CMake build configuration
├── pyproject.toml # Project metadata and build config
├── uv.lock # Dependency lock file
└── CLAUDE.md # Development guidelines
Dependencies
Runtime Dependencies
- Python: >= 3.12 (as specified in pyproject.toml)
- NumPy: >= 1.20.0 (for array operations)
System Dependencies
- RDKit: >= 2022.9.1 (C++ libraries and headers required)
librdkit-dev- Development headerslibrdkit1- Runtime librariesrdkit-data- Data filespython3-rdkit- Python bindings (optional, for compatibility testing)
Build Dependencies
- scikit-build-core: >= 0.10 (modern CMake-based build backend)
- nanobind: >= 2.0.0 (fast C++/Python binding library)
- tensorflow: == 2.19.0 (for TensorFlow custom operations)
- CMake: >= 3.15 (build system)
- C++ Compiler: Supporting C++17 standard (GCC 7+, Clang 5+, MSVC 2017+)
Development Dependencies (Optional)
- pytest: >= 6.0 (testing framework)
- black (code formatting)
- isort (import sorting)
- uv (recommended package manager)
License
[Add your license here]
Contributing
[Add contributing guidelines here]
Citation
If you use RDTools in your research, please cite: [Add citation information here]
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distributions
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file rdkit_data_pipeline_tools-0.1.5-cp312-cp312-manylinux_2_39_x86_64.whl.
File metadata
- Download URL: rdkit_data_pipeline_tools-0.1.5-cp312-cp312-manylinux_2_39_x86_64.whl
- Upload date:
- Size: 6.3 MB
- Tags: CPython 3.12, manylinux: glibc 2.39+ x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.8.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c8bf72a4846ca3a85a3e22f662fef5bab9732827aea0393219e707ac6b507432
|
|
| MD5 |
4ec8359a95116ccddf75561809bdb7b3
|
|
| BLAKE2b-256 |
1e442b9aa0149c858912d09d61a0235177b1e00356bef74c754b782477d20134
|