SmileSherlock Practical Guide (v1.7.0)
Welcome to the comprehensive tutorial for SmileSherlock. This guide is designed to take you from basic lookups to advanced, multithreaded batch processing using both the Command Line Interface (CLI) and the Python API.
Table of Contents
- SmileSherlock Practical Guide (v1.7.0)
- Table of Contents
- 1. System Management
- 2. Single Compound Lookups
- CLI Examples
- 3. Batch Processing \& File I/O
- CLI Examples
- Python API Examples
- 4. Chemical Structure Downloads
- Python API Examples
- 5. Advanced SMILES Validation (Python API)
- 6. Fingerprint Generation
- CLI Examples
- Python API Examples
- 7. Similarity Search
- CLI Examples
- Python API Examples
- 8. Substructure Search\n - CLI\n - Python API\n- 9. Drug-Likeness Filtering (ADMET)
- CLI Examples
- Python API Examples
- 10. Standardization Pipeline
- Python API
- 11. Tautomer Enumeration
- CLI
- Python API
- 12. IUPAC Identifier Generation
- Python API
- 13. Advanced Cheminformatics
- 13.1 Reaction SMILES Validation
- 13.2 Multiple Conformer Generation
- 13.3 Murcko Scaffold Extraction
- 13.4 Stereochemistry Analysis
- 13.5 R-Group Decomposition
- 13.6 SMILES Augmentation
- 13.7 Atom Mapping
- Learn More
1. System Management
SmileSherlock manages local SQLite caches and logs to ensure high performance and respect for PubChem's rate limits.
CLI Commands
Check your environment paths, active threads, and database size:
smilesherlock status
Initialize the database schema and storage directories (Run this once after installation):
smilesherlock init
Keep your tool up-to-date. This smart command automatically checks PyPI (or GitHub if you cloned the source) and safely applies updates:
smilesherlock update
If your local database gets corrupted or you want to clear your cache completely, perform a factory reset:
smilesherlock reinstall -y
2. Single Compound Lookups
SmileSherlock's "Smart Auto-Routing" automatically detects if your input is a SMILES string, an InChIKey, a PubChem CID, or a Chemical Name.
CLI Examples
Basic Lookups:
# Lookup by SMILES
smilesherlock lookup "CC(=O)OC1=CC=CC=C1C(=O)O"
# Lookup by Common/IUPAC Name
smilesherlock lookup "Aspirin"
smilesherlock lookup "benzene"
Advanced CLI Flags:
# Bypass the local SQLite cache to force a fresh network request
smilesherlock lookup "Caffeine" --no-cache
# Force the engine to treat the input specifically as a CID
smilesherlock lookup 2244 --cid
# Output raw JSON instead of a rich table (ideal for piping into `jq` or other scripts)
smilesherlock lookup "Ibuprofen" --json
Python API Examples
from smilesherlock import lookup, lookup_by_name
# 1. Smart Auto-Detect Lookup
compound = lookup("c1ccccc1")
print(f"Name: {compound.iupac_name}, MW: {compound.molecular_weight}")
# 2. Explicit Lookup by Name (Bypasses SMILES validation checks)
drug = lookup_by_name("Amoxicillin")
print(f"CID: {drug.cid}, Formula: {drug.molecular_formula}")
# 3. Accessing detailed properties (PubChemCompound model)
if drug:
print(f"H-Bond Donors: {drug.hbond_donor_count}")
print(f"XLogP: {drug.xlogp}")
print(f"InChIKey: {drug.inchikey}")
3. Batch Processing & File I/O
Process hundreds of compounds in seconds. SmileSherlock uses multithreading (concurrent.futures) combined with a strict rate limiter to fetch data as fast as possible without getting banned by PubChem.
Supported Input Formats: .csv, .tsv, .xlsx, .smi, .sdf, .txt
(SmileSherlock automatically detects the column containing SMILES/Names!)
CLI Examples
# Basic batch processing (auto-generates a CSV output and a .log report)
smilesherlock batch input_data.csv
# Output to an Excel file and keep duplicate entries (duplicates are removed by default)
smilesherlock batch raw_smiles.txt --format xlsx --keep-duplicates
# Specify a custom output path and export as JSON
smilesherlock batch data.sdf --output /my_project/clean_data.json --format json
Python API Examples
from smilesherlock import lookup_file, lookup
# 1. Process a file directly in your script
results = lookup_file(
input_file="messy_data.csv",
output_file="clean_results.xlsx",
output_format="xlsx",
remove_duplicates=True
)
print(f"Successfully processed {len(results)} unique compounds.")
# 2. Custom loop for lists (No file needed)
my_chemicals = ["Aspirin", "c1ccccc1", "Invalid_Chemical_Name"]
valid_compounds = []
for chem in my_chemicals:
data = lookup(chem, use_cache=True)
if data and data.cid:
valid_compounds.append(data)
4. Chemical Structure Downloads & Generation
Download physical structure files from PubChem or generate 2D/3D conformations offline from SMILES using RDKit with built-in resume logic.
Supported Formats: sdf, mol, pdb, png (generation supports sdf, mol, pdb)
Supported Dimensions: 2d, 3d
Downloaded and generated files are skipped automatically unless --force is used.
# Download a single 3D SDF file by its PubChem CID
smilesherlock download 2244 --format sdf --3d
# Generate all 3D structures locally from SMILES using RDKit (--gen all)
smilesherlock download "CC(=O)OC1=CC=CC=C1C(=O)O" --gen all --3d --format sdf
# Generate 2D MOL structure locally from SMILES
smilesherlock download "c1ccccc1" --gen all --2d --format mol
# Batch download with fallback to local generation (--gen missing)
smilesherlock download -i my_compounds.csv --gen missing --format sdf --3d --output-dir ./structures/
# Batch generate all structures offline from file
smilesherlock download -i my_compounds.smi --gen all --format pdb --3d --output-dir ./3d_models/
# Force overwrite existing files (disables resume logic)
smilesherlock download -i my_compounds.csv --format sdf --force
Python API Examples
from smilesherlock import download_structure
# Download a single structure programmatically
status = download_structure(
cid=2244,
format="sdf",
dimension="3d",
output_dir="my_structures",
force=False
)
print(f"Download status: {status}")
5. Advanced SMILES Validation (Python API)
If you only need to validate SMILES strings and calculate RDKit descriptors locally without querying the PubChem internet database, you can use the core SMILES engine directly.
from smilesherlock import validate_smiles
# Validate a complex SMILES string
result = validate_smiles("CC(=O)OC1=CC=CC=C1C(=O)O")
if result.is_valid:
print(f"Standardized SMILES: {result.canonical_smiles}")
print(f"Exact Mass: {result.molecular_weight}")
print(f"Heavy Atoms: {result.heavy_atom_count}")
print(f"TPSA: {result.tpsa}")
print(f"Calculated LogP: {result.logp}")
else:
print(f"Invalid SMILES! Error: {result.error_message}")
Learn More
- README.md — Installation and Quick Start
- API Documentation — Python API reference
- GitHub Issues — Bug reports and feature requests
- Discussions — Community support
6. Fingerprint Generation
Generate molecular fingerprints offline from SMILES strings. Useful for ML model preparation, similarity search, and database indexing.
CLI
# Single compound - ECFP4 (default)
smilesherlock fingerprint "CC(=O)OC1=CC=CC=C1C(=O)O" --type ecfp4
# MACCS keys (167-bit)
smilesherlock fingerprint "CCO" --type maccs
# All fingerprint types at once
smilesherlock fingerprint "CC(=O)OC1=CC=CC=C1C(=O)O" --type all
# Batch file - save to CSV
smilesherlock fingerprint --file compounds.smi --type ecfp4 --bits 2048 --output fingerprints.csv
# Custom bit size
smilesherlock fingerprint "CC(=O)OC1=CC=CC=C1C(=O)O" --type rdkit --bits 1024
Supported fingerprint types:
| Type | Algorithm | Default Bits | Use Case |
|---|---|---|---|
ecfp4 |
Morgan (radius=2) | 2048 | General ML, virtual screening |
ecfp6 |
Morgan (radius=3) | 2048 | More specific substructures |
fcfp4 |
Feature Morgan (radius=2) | 2048 | Pharmacophore-based |
maccs |
MACCS Keys | 167 (fixed) | Structural keys, scaffold analysis |
rdkit |
Daylight-style RDKit | 2048 | General purpose |
atompair |
Atom Pair | 2048 | 3D-aware searches |
torsion |
Topological Torsion | 2048 | Conformer-sensitive searches |
Python API
from smilesherlock import compute_fingerprint
# Single fingerprint
fp = compute_fingerprint("CC(=O)OC1=CC=CC=C1C(=O)O", fp_type="ecfp4")
print(f"Type: {fp.fingerprint_type}, On bits: {fp.n_on_bits}, Density: {fp.density:.4f}")
print(f"Bit string: {fp.bit_string}")
# All fingerprint types
fps = compute_fingerprint("CCO", fp_type="all")
for fp in fps:
print(f"{fp.fingerprint_type:12s}: {fp.n_on_bits} bits on / {fp.n_bits}")
7. Similarity Search
Search a compound library to find structurally similar compounds using Tanimoto similarity.
CLI
# Search against a library file, default threshold 0.5, top 10
smilesherlock similar "CC(=O)OC1=CC=CC=C1C(=O)O" --file library.smi
# Custom threshold and top-N
smilesherlock similar "CC(=O)OC1=CC=CC=C1C(=O)O" --file library.csv --threshold 0.3 --top 20
# Use MACCS fingerprints instead of ECFP4
smilesherlock similar "CCO" --file compounds.smi --fp-type maccs --top 5
# Save results to CSV
smilesherlock similar "CC(=O)OC1=CC=CC=C1C(=O)O" --file library.smi --output hits.csv
# Higher bit resolution
smilesherlock similar "CCO" --file library.smi --fp-type ecfp6 --bits 4096 --top 10
Python API
from smilesherlock import compute_similarity
# Library as list of SMILES
library = ["CCO", "CCCO", "CC(=O)OC1=CC=CC=C1C(=O)O", "c1ccccc1", "CN1C=NC2=C1C(=O)N(C(=O)N2C)C"]
hits = compute_similarity(
query_smiles="CC(=O)OC1=CC=CC=C1C(=O)O",
library=library,
fp_type="ecfp4",
threshold=0.1,
top_n=5,
)
for hit in hits:
print(f"Rank {hit.rank}: {hit.hit} (Tanimoto={hit.similarity:.4f})")
8. Substructure Search
Search a compound library for molecules that contain a specific substructural fragment or functional group. This is highly useful for identifying compounds with a required pharmacophore or structural alert.
CLI
# Search using a SMARTS query (default). This searches for a carboxylic acid.
smilesherlock substructure "C(=O)[OH]" --file library.csv
# Search using a SMILES query (e.g. benzene ring)
smilesherlock substructure "c1ccccc1" --file compounds.smi --smiles-query
# Save only the matching compounds to a new CSV file
smilesherlock substructure "[#9,#17,#35,#53]" --file library.csv --output halogens_only.csv
Python API
from smilesherlock import substructure_search
library = [
"CCO",
"CC(=O)OC1=CC=CC=C1C(=O)O",
"c1ccccc1",
"CN1C=NC2=C1C(=O)N(C(=O)N2C)C"
]
# Query for carboxylic acid using SMARTS
hits = substructure_search("C(=O)[OH]", library, is_smarts=True)
print(f"Found {len(hits)} matches:")
for hit in hits:
print(f"- {hit.smiles} (Atoms matched: {hit.match_indices})")
9. Drug-Likeness Filtering (ADMET)
Evaluate compounds against standard drug-likeness rules and PAINS alerts.
CLI
# Single compound - all rules (default)
smilesherlock filter "CC(=O)OC1=CC=CC=C1C(=O)O"
# Specific rules only
smilesherlock filter "CC(=O)OC1=CC=CC=C1C(=O)O" --rules lipinski,veber,pains
# Batch: keep only compounds that pass all rules
smilesherlock filter --file compounds.csv --rules lipinski --output drug_like.csv
# Batch: keep only PAINS-free compounds (--rules pains keeps clean ones)
smilesherlock filter --file compounds.csv --rules pains --output no_pains.csv
# Batch: keep only PAINS-flagged compounds for investigation (--fail inverts)
smilesherlock filter --file compounds.csv --rules pains --fail --output pains_hits.csv
# Add QED minimum threshold
smilesherlock filter --file compounds.csv --rules lipinski,veber --qed-min 0.5 --output output.csv
Available filter rules:
| Rule | Criteria | Use Case |
|---|---|---|
lipinski |
MW<=500, LogP<=5, HBD<=5, HBA<=10 | Oral drug candidates |
veber |
RotBonds<=10, TPSA<=140 A^2 | Oral bioavailability |
ghose |
MW 160-480, LogP -0.4 to 5.6, Atoms 20-70, MR 40-130 | Drug-like space |
egan |
TPSA<=131.6, LogP<=5.88 | Passive permeability |
ro3 |
MW<=300, LogP<=3, HBD<=3, HBA<=3 | Lead-like fragments |
pains |
RDKit PAINS catalog | Frequent hitter detection |
qed |
0-1 score (info only) | Overall drug-likeness score |
Python API
from smilesherlock import apply_filters
# All rules at once
result = apply_filters("CC(=O)OC1=CC=CC=C1C(=O)O")
print(f"MW: {result.molecular_weight:.2f} g/mol")
print(f"LogP: {result.logp:.2f}")
print(f"QED: {result.qed_score:.4f}")
print(f"Lipinski: {'PASS' if result.lipinski.passed else 'FAIL'} — {result.lipinski.details}")
print(f"PAINS: {'PASS' if result.pains.passed else 'FAIL'} — {result.pains.details}")
print(f"Overall: {'PASS' if result.passes_all else 'FAIL'}")
# Specific rules only
result = apply_filters("CC(=O)OC1=CC=CC=C1C(=O)O", rules=["lipinski", "pains"])
# Batch filtering
import csv
library = ["CC(=O)OC1=CC=CC=C1C(=O)O", "CN1C=NC2=C1C(=O)N(C(=O)N2C)C", "c1ccccc1"]
passing = [smi for smi in library if apply_filters(smi, rules=["lipinski"]).passes_all]
print(f"Drug-like compounds: {len(passing)}/{len(library)}")
10. Standardization Pipeline
Clean up "dirty" SMILES from databases using RDKit's MolStandardize:
# Single compound: strip salts, neutralize, canonicalize tautomers
smilesherlock standardize "[Na+].[OH-].CC(=O)[O-]"
# Output: CC(=O)O
# Show exactly what each step changed
smilesherlock standardize "[Na+].[OH-].CC(=O)[O-]" --show-diff
# Apply only specific steps
smilesherlock standardize "O=C([O-])c1ccccc1" --steps neutralize,canonical
# Batch process a CSV file
smilesherlock standardize --file compounds.csv --output standardized.csv --show-diff
Available steps (applied in order):
| Step | Description |
|---|---|
fragment |
Salt stripping — keeps the largest organic fragment |
neutralize |
Neutralizes charged atoms (e.g., carboxylate → carboxylic acid) |
tautomer |
Canonicalize tautomers to a single stable form |
canonical |
Generate canonical RDKit SMILES string |
Python API
from smilesherlock import standardize_smiles
result = standardize_smiles("[Na+].[OH-].CC(=O)[O-]")
print(result.output_smiles) # CC(=O)O
print(result.changed) # True
# Inspect per-step changes
for step in result.step_results:
if step.changed:
print(f"{step.step}: {step.input_smiles} -> {step.output_smiles}")
# Custom pipeline
result = standardize_smiles("O=C([O-])c1ccccc1", steps=["neutralize", "canonical"])
11. Tautomer Enumeration
Different tautomers of a single molecule can exhibit vastly different binding affinities to a target protein. Enumerating plausible tautomeric states is a critical preparation step for structure-based virtual screening and molecular docking.
CLI
# Single compound
smilesherlock tautomers "Oc1nc(O)c2nc[nH]c2n1"
# Restrict the maximum number of tautomers generated
smilesherlock tautomers "Oc1nc(O)c2nc[nH]c2n1" --max 50
# Batch process a CSV file
# NOTE: The output CSV will "explode" the dataset, meaning if an input SMILES
# produces 15 tautomers, the output CSV will contain 15 rows for that input.
smilesherlock tautomers --file ligands.csv --output all_tautomers.csv
Python API
from smilesherlock import enumerate_tautomers
# Enumerate tautomers
result = enumerate_tautomers("Oc1nc(O)c2nc[nH]c2n1", max_tautomers=100)
if result.success:
print(f"Generated {result.num_tautomers} tautomers.")
print(f"Canonical tautomer: {result.canonical_tautomer}")
# Iterate through them
for t_smi in result.tautomers:
is_canonical = (t_smi == result.canonical_tautomer)
print(f"{t_smi} (Canonical: {is_canonical})")
else:
print(f"Error: {result.error}")
12. IUPAC Identifier Generation
Generate systematic identifiers from SMILES, fully offline.
# Offline: InChI, InChIKey, Formula, MW
smilesherlock iupacname "CC(=O)OC1=CC=CC=C1C(=O)O"
# With IUPAC preferred name (fetched from PubChem on first use, then cached offline)
smilesherlock iupacname "CCO" --online
# Batch processing
smilesherlock iupacname --file compounds.smi --online --output identifiers.csv
| Output | Source | Requires Network? |
|---|---|---|
| Canonical SMILES | RDKit | No |
| Molecular Formula | RDKit | No |
| Exact MW | RDKit | No |
| InChI | RDKit | No |
| InChIKey | RDKit | No |
| IUPAC Name | PubChem (cached) | First time only |
Python API
from smilesherlock import get_iupac_name
# Fully offline — InChI, formula, MW
result = get_iupac_name("CCO")
print(result.inchi) # InChI=1S/C2H6O/c1-2-3/h3H,2H2,1H3
print(result.inchikey) # LFQSCWFLJHTTHZ-UHFFFAOYSA-N
print(result.molecular_formula) # C2H6O
print(result.molecular_weight) # 46.0419
# Fetch IUPAC name (network on first call, cache thereafter)
result = get_iupac_name("CCO", use_online=True)
print(result.iupac_name) # ethanol
print(result.iupac_name_source) # pubchem (or 'cache' on repeat calls)
13. Advanced Cheminformatics
13.1 Reaction SMILES Validation
Validate Reaction SMILES (SMIRKS) syntax, confirming the number of reactants, agents (catalysts), and products.
smilesherlock reaction "CC(=O)O.OCC>>CC(=O)OCC.O"
13.2 Multiple Conformer Generation
Generate multiple optimized 3D conformers using the ETKDG algorithm. The output must be saved as a multi-model .sdf file, ready for 3D virtual screening.
smilesherlock conformers "CCO" --num-conformers 100 --output out.sdf
13.3 Murcko Scaffold Extraction
Remove side chains and extract the core ring framework. Highly useful for clustering High-Throughput Screening (HTS) hits.
# Single
smilesherlock scaffold "CC(=O)OC1=CC=CC=C1C(=O)O"
# Batch
smilesherlock scaffold --file hits.csv --output scaffolds.csv
13.4 Stereochemistry Analysis
Identify stereocenters (R/S) and unassigned chiral atoms (?). Use --chiral-flag to return a system error code if unassigned stereochemistry is detected (useful for strict CI pipelines).
smilesherlock stereo "C[C@H](O)CC" --chiral-flag
13.5 R-Group Decomposition
Decompose a library of molecules against a core SMARTS scaffold.
smilesherlock rgroup --core "c1ccccc1" --smiles "Cc1ccccc1,c1ccccc1F"
13.6 SMILES Augmentation
Generate a set of unique uncanonical SMILES representing the same molecule, highly useful for deep learning model augmentation.
smilesherlock augment "CC(=O)OC1=CC=CC=C1C(=O)O" --num 10
13.7 Atom Mapping
Assign map indices to every atom, useful for reaction tracking and graph networks.
smilesherlock atommap "CCO"