install
source · Clone the upstream repo
git clone https://github.com/mdbabumiamssm/LLMs-Universal-Life-Science-and-Clinical-Skills-
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/mdbabumiamssm/LLMs-Universal-Life-Science-and-Clinical-Skills- "$T" && mkdir -p ~/.claude/skills && cp -r "$T/Skills/Drug_Discovery/Chemoinformatics/reaction-enumeration" ~/.claude/skills/mdbabumiamssm-llms-universal-life-science-and-clinical-skills-reaction-enumerati && rm -rf "$T"
manifest:
Skills/Drug_Discovery/Chemoinformatics/reaction-enumeration/SKILL.mdsource content
<!--
# COPYRIGHT NOTICE
# This file is part of the "Universal Biomedical Skills" project.
# Copyright (c) 2026 MD BABU MIA, PhD <md.babu.mia@mssm.edu>
# All Rights Reserved.
#
# This code is proprietary and confidential.
# Unauthorized copying of this file, via any medium is strictly prohibited.
#
# Provenance: Authenticated by MD BABU MIA
-->
name: bio-reaction-enumeration description: Enumerates chemical libraries through reaction SMARTS transformations using RDKit. Generates virtual compound libraries from building blocks using defined chemical reactions with product validation. Use when creating combinatorial libraries or enumerating products from synthetic routes. tool_type: python primary_tool: RDKit measurable_outcome: Execute skill workflow successfully with valid output within 15 minutes. allowed-tools:
- read_file
- run_shell_command
Reaction Enumeration
Generate virtual compound libraries using reaction SMARTS.
Reaction SMARTS Basics
from rdkit import Chem from rdkit.Chem import AllChem # Define reaction (reactants >> products with atom mapping) # Amide coupling: carboxylic acid + amine -> amide amide_rxn = AllChem.ReactionFromSmarts( '[C:1](=[O:2])O.[N:3]>>[C:1](=[O:2])[N:3]' ) # Validate reaction definition n_errors = amide_rxn.Validate() if n_errors[0] == 0: print('Reaction is valid') # Run reaction acid = Chem.MolFromSmiles('CC(=O)O') amine = Chem.MolFromSmiles('CCN') products = amide_rxn.RunReactants((acid, amine)) # products is a tuple of tuples: ((product1,), (product2,), ...) for prod_set in products: for prod in prod_set: Chem.SanitizeMol(prod) print(Chem.MolToSmiles(prod))
Common Reaction SMARTS
REACTIONS = { 'amide_coupling': '[C:1](=[O:2])O.[N:3]>>[C:1](=[O:2])[N:3]', 'reductive_amination': '[C:1]=O.[N:2]>>[C:1][N:2]', 'suzuki': '[c:1][Br].[c:2][B](O)O>>[c:1][c:2]', 'buchwald': '[c:1][Br].[N:2]>>[c:1][N:2]', 'ester_formation': '[C:1](=[O:2])O.[O:3]>>[C:1](=[O:2])[O:3]', 'michael_addition': '[C:1]=[C:2]C(=O).[C:3]>>[C:1][C:2]([C:3])C(=O)', }
Combinatorial Library Enumeration
from rdkit import Chem from rdkit.Chem import AllChem from itertools import product def enumerate_library(rxn_smarts, reactant_lists, deduplicate=True): ''' Enumerate products from combinatorial reaction. Args: rxn_smarts: Reaction SMARTS string reactant_lists: List of lists of SMILES for each reactant position deduplicate: Remove duplicate products Returns: List of unique product SMILES ''' rxn = AllChem.ReactionFromSmarts(rxn_smarts) # Validate reaction if rxn.Validate()[0] != 0: raise ValueError('Invalid reaction SMARTS') products = [] seen = set() # Generate all combinations for reactants in product(*reactant_lists): mols = [Chem.MolFromSmiles(s) for s in reactants] if None in mols: continue try: prods = rxn.RunReactants(tuple(mols)) for prod_set in prods: for prod in prod_set: try: Chem.SanitizeMol(prod) smiles = Chem.MolToSmiles(prod) if deduplicate: if smiles not in seen: seen.add(smiles) products.append(smiles) else: products.append(smiles) except Exception: continue # Skip invalid products except Exception: continue return products # Example: Amide library acids = ['CC(=O)O', 'c1ccccc1C(=O)O', 'OC(=O)CC(=O)O'] amines = ['CCN', 'c1ccc(N)cc1', 'NCCN'] products = enumerate_library( '[C:1](=[O:2])O.[N:3]>>[C:1](=[O:2])[N:3]', [acids, amines] ) print(f'Generated {len(products)} unique products')
Multi-Step Synthesis
def multi_step_enumeration(building_blocks, reaction_sequence): ''' Enumerate products from multi-step synthesis. Args: building_blocks: Dict of {step: [smiles_list]} reaction_sequence: List of reaction SMARTS ''' current = building_blocks[0] for step, rxn_smarts in enumerate(reaction_sequence): next_bbs = building_blocks.get(step + 1, []) if not next_bbs: break current = enumerate_library(rxn_smarts, [current, next_bbs]) print(f'Step {step + 1}: {len(current)} intermediates') return current
Product Validation
from rdkit import Chem from rdkit.Chem import AllChem, Descriptors def validate_products(smiles_list, mw_max=500, remove_reactive=True): ''' Validate and filter enumerated products. ''' valid = [] reactive_smarts = [ '[N+]([O-])=O', # Nitro '[Cl,Br,I]', # Halogens (optional) 'C#N', # Nitrile ] reactive_patterns = [Chem.MolFromSmarts(s) for s in reactive_smarts] for smiles in smiles_list: mol = Chem.MolFromSmiles(smiles) if mol is None: continue # Check MW if Descriptors.MolWt(mol) > mw_max: continue # Check reactive groups if remove_reactive: has_reactive = any(mol.HasSubstructMatch(p) for p in reactive_patterns) if has_reactive: continue # Check valence try: Chem.SanitizeMol(mol) except Exception: continue valid.append(smiles) return valid
Reaction Templates
def apply_template(core_smiles, r_groups, attachment_smarts='[*:1]'): ''' Apply R-group decoration to a core scaffold. Args: core_smiles: Core with attachment point (e.g., '*c1ccccc1') r_groups: List of R-group SMILES attachment_smarts: SMARTS for attachment point ''' products = [] for rg in r_groups: # Simple string replacement for single attachment product_smiles = core_smiles.replace('*', rg, 1) mol = Chem.MolFromSmiles(product_smiles) if mol: try: Chem.SanitizeMol(mol) products.append(Chem.MolToSmiles(mol)) except Exception: continue return products # Example: Decorate benzene core core = '*c1ccccc1' r_groups = ['C', 'CC', 'C(=O)O', 'O'] decorated = apply_template(core, r_groups)
Related Skills
- molecular-io - Save enumerated libraries
- molecular-descriptors - Filter by properties
- admet-prediction - Screen for drug-likeness