Install
$ agentstack add skill-mcox3406-claude-comp-chem-skills-mol-ml ✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
About
Molecular ML Skill
Best practices for machine learning with molecular data using RDKit.
Scaffold Splitting
Critical for avoiding data leakage — molecules with the same scaffold in train and test sets lead to overly optimistic performance estimates.
See references/scaffolds.md for complete documentation.
Quick Reference
from rdkit import Chem
from rdkit.Chem.Scaffolds.MurckoScaffold import MurckoScaffoldSmiles
from collections import defaultdict
def get_scaffold(smiles):
"""Extract Murcko scaffold from SMILES."""
mol = Chem.MolFromSmiles(smiles)
if mol is None:
return None
return MurckoScaffoldSmiles(mol=mol, includeChirality=False)
def scaffold_split(smiles_list, test_size=0.2, random_state=42):
"""Split molecules by scaffold to avoid data leakage."""
import random
random.seed(random_state)
# Group by scaffold
scaffold_to_indices = defaultdict(list)
for idx, smi in enumerate(smiles_list):
scaffold = get_scaffold(smi)
scaffold_to_indices[scaffold].append(idx)
# Shuffle scaffolds and split
scaffolds = list(scaffold_to_indices.keys())
random.shuffle(scaffolds)
train_idx, test_idx = [], []
test_count = int(len(smiles_list) * test_size)
for scaffold in scaffolds:
indices = scaffold_to_indices[scaffold]
if len(test_idx) < test_count:
test_idx.extend(indices)
else:
train_idx.extend(indices)
return train_idx, test_idx
Fingerprint Selection
Different fingerprints suit different tasks. See references/fingerprint-selection.md for guidance.
Quick Recommendations
| Task | Recommended FP | Why | |------|---------------|-----| | Similarity search | Morgan2 (ECFP4) | Captures local environment well | | Virtual screening | Morgan2 or RDKit | Both work well | | QSAR modeling | Morgan2 with counts | Count info helps regression | | Scaffold hopping | FCFP (Feature Morgan) | Abstracts to pharmacophore features | | Substructure matching | RDKit FP | Path-based, captures connectivity |
Fingerprint Similarity Varies Dramatically
The same molecule pair gives very different similarity values with different fingerprints:
from rdkit import Chem, DataStructs
from rdkit.Chem import rdFingerprintGenerator
mol1 = Chem.MolFromSmiles('COc1ccc2nc([nH]c2c1)[S@](=O)Cc1ncc(C)c(OC)c1C') # esomeprazole
mol2 = Chem.MolFromSmiles('FC(F)(F)COc1ccnc(c1C)CS(=O)c2[nH]c3ccccc3n2') # lansoprazole
rdk_gen = rdFingerprintGenerator.GetRDKitFPGenerator()
mfp_gen = rdFingerprintGenerator.GetMorganGenerator(radius=2)
rdk_sim = DataStructs.TanimotoSimilarity(
rdk_gen.GetFingerprint(mol1), rdk_gen.GetFingerprint(mol2))
mfp_sim = DataStructs.TanimotoSimilarity(
mfp_gen.GetFingerprint(mol1), mfp_gen.GetFingerprint(mol2))
# RDKit FP: ~0.79, Morgan2: ~0.43
Always specify the fingerprint type when reporting similarity values.
Common Pitfalls
1. Scaffold Leakage
Problem: Random splits put similar molecules in train and test.
Solution: Use scaffold-based splits.
2. Ignoring Fingerprint Type for Similarity
Problem: Reporting "Tanimoto similarity = 0.6" without specifying the fingerprint.
Solution: "Tanimoto similarity using Morgan2 = 0.6"
3. Using Bit Fingerprints for Regression
Problem: Bit fingerprints lose count information important for QSAR.
Solution: Use count fingerprints or count simulation:
# Count fingerprints
fp = gen.GetCountFingerprintAsNumPy(mol)
# Or bit with count simulation
gen = rdFingerprintGenerator.GetMorganGenerator(
radius=2, fpSize=4096, countSimulation=True)
4. Not Handling Parse Failures
Problem: Some SMILES fail to parse, causing index misalignment.
Solution: Track valid indices:
valid_fps = []
valid_indices = []
for idx, smi in enumerate(smiles_list):
mol = Chem.MolFromSmiles(smi)
if mol is not None:
valid_fps.append(gen.GetFingerprintAsNumPy(mol))
valid_indices.append(idx)
5. Feature Matrix Shape Issues
Problem: Ragged arrays when some molecules fail.
Solution: Filter first, then stack:
import numpy as np
fps = [gen.GetFingerprintAsNumPy(Chem.MolFromSmiles(s))
for s in smiles_list if Chem.MolFromSmiles(s) is not None]
X = np.vstack(fps) # shape: (n_valid, fp_size)
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: mcox3406
- Source: mcox3406/claude-comp-chem-skills
- License: MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet — be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.