Source: https://github.com/aipoch/medical-research-skills
When to Use
- Screening large compound libraries to quickly triage for drug-like candidates (e.g., Lipinski/Veber + alerts).
- Flagging problematic chemotypes (e.g., PAINS, reactive/toxicophores, curated structural alerts) before follow-up assays.
- Prioritizing lead-optimization candidates with stricter criteria (lead-like rules, demerit systems, complexity caps).
- Enforcing property constraints (MW/logP/TPSA/rotatable bonds) for target-specific design windows (e.g., CNS).
- Identifying molecules containing specific functional groups/scaffolds (e.g., Michael acceptors, hinge binders) for SAR or risk assessment.
Key Features
- Drug-likeness and medchem rule sets: Lipinski (Ro5), Veber, Oprea, CNS, lead-like (soft/strict), Rule of Three, REOS, Golden Triangle, etc.
- PAINS and structural alert filtering: curated alert catalogs and pattern-based screening.
- Curated industrial filter sets: e.g., NIBR filters; Lilly demerit scoring with pass/fail thresholds.
- Functional-group detection via SMARTS-based group matchers (hinge binders, phosphate binders, Michael acceptors, reactive groups, custom patterns).
- Named catalogs of curated structures (functional groups, protecting groups, reagents, fragments) for matching and annotation.
- Molecular complexity metrics (e.g., Bertz/Whitlock/Barone-style) and threshold-based complexity filters.
- Constraint-based filtering for property windows (MW/logP/TPSA/RB, etc.).
- Query language to combine heterogeneous criteria (rules + alerts + numeric thresholds) into a single expression.
Dependencies
medchem (latest)
datamol (latest)
pandas (latest, for tabular workflows)
Example Usage
# End-to-end, runnable example:
# 1) load SMILES
# 2) apply Ro5 + Veber
# 3) apply common structural alerts
# 4) compute complexity and filter
# 5) export a CSV with decisions
import pandas as pd
import datamol as dm
import medchem as mc
smiles_list = [
"CC(=O)OC1=CC=CC=C1C(=O)O", # aspirin
"CN1C=NC2=C1C(=O)N(C(=O)N2C)C", # caffeine
"c1ccccc1", # benzene
]
df = pd.DataFrame({"smiles": smiles_list})
mols = [dm.to_mol(smi) for smi in df["smiles"]]
# 1) Drug-likeness rules
rule_filter = mc.rules.RuleFilters(rule_list=["rule_of_five", "rule_of_veber"])
rule_res = rule_filter(mols=mols, n_jobs=-1, progress=False)
df["passes_rules"] = rule_res["pass"]
# 2) Structural alerts
alerts = mc.structural.CommonAlertsFilters()
alert_res = alerts(mols=mols, n_jobs=-1, progress=False)
df["has_alerts"] = alert_res["has_alerts"]
# 3) Complexity (example threshold)
complex_filter = mc.complexity.ComplexityFilter(max_complexity=500)
complex_res = complex_filter(mols=mols, n_jobs=-1, progress=False)
df["passes_complexity"] = complex_res["pass"]
# 4) Final decision
df["keep"] = df["passes_rules"] & (~df["has_alerts"]) & df["passes_complexity"]
# 5) Save results
df.to_csv("medchem_screening_results.csv", index=False)
print(df)
Implementation Details
Rule evaluation (medchem.rules)
- Rules are implemented as callable checks over SMILES or RDKit-like molecule objects (commonly via
datamol).
RuleFilters(rule_list=[...]) applies multiple rules and returns a structured result (typically including an overall pass plus per-rule details).
- Typical use: start broad (Ro5/Veber), then tighten (CNS/lead-like) as project constraints become clearer.
Structural alerts (medchem.structural)
- Alert systems are primarily SMARTS/pattern-based matchers curated from literature/industrial practice.
CommonAlertsFilters, NIBRFilters, and LillyDemeritsFilters provide different philosophies:
- Common alerts: general-purpose red flags.
- NIBR: curated industrial filter set.
- Lilly demerits: assigns penalties per matched rule; a common convention is reject if total demerits > 100.
Complexity (medchem.complexity)
- Complexity scores approximate synthetic difficulty / structural intricacy using established heuristics (e.g., Bertz/Whitlock/Barone-style metrics).
ComplexityFilter(max_complexity=...) converts a numeric score into a pass/fail gate for library triage.
Constraints (medchem.constraints)
- Property windows (MW/logP/TPSA/rotatable bonds, etc.) are applied as hard filters.
- Use constraints to encode target-specific design hypotheses (e.g., CNS-like space) rather than universal “good/bad” judgments.
Groups and catalogs (medchem.groups, medchem.catalogs)
- Group detection is SMARTS-driven and returns boolean matches and/or match details (substructure hits).
- Named catalogs provide curated sets for consistent annotation and matching across projects.
Parallelization
- Most batch APIs accept
n_jobs; set n_jobs=-1 to use all available CPU cores for large libraries.
1---2name: medchem-23description: Medicinal chemistry screening filters for compound prioritization; use when you need to apply drug-likeness rules, PAINS/structural alerts, and complexity metrics to triage or optimize libraries.4license: MIT5---6> **Source**: [https://github.com/aipoch/medical-research-skills](https://github.com/aipoch/medical-research-skills)78## When to Use910- Screening large compound libraries to quickly triage for drug-like candidates (e.g., Lipinski/Veber + alerts).11- Flagging problematic chemotypes (e.g., PAINS, reactive/toxicophores, curated structural alerts) before follow-up assays.12- Prioritizing lead-optimization candidates with stricter criteria (lead-like rules, demerit systems, complexity caps).13- Enforcing property constraints (MW/logP/TPSA/rotatable bonds) for target-specific design windows (e.g., CNS).14- Identifying molecules containing specific functional groups/scaffolds (e.g., Michael acceptors, hinge binders) for SAR or risk assessment.1516## Key Features1718- **Drug-likeness and medchem rule sets**: Lipinski (Ro5), Veber, Oprea, CNS, lead-like (soft/strict), Rule of Three, REOS, Golden Triangle, etc.19- **PAINS and structural alert filtering**: curated alert catalogs and pattern-based screening.20- **Curated industrial filter sets**: e.g., NIBR filters; **Lilly demerit** scoring with pass/fail thresholds.21- **Functional-group detection** via SMARTS-based group matchers (hinge binders, phosphate binders, Michael acceptors, reactive groups, custom patterns).22- **Named catalogs** of curated structures (functional groups, protecting groups, reagents, fragments) for matching and annotation.23- **Molecular complexity metrics** (e.g., Bertz/Whitlock/Barone-style) and threshold-based complexity filters.24- **Constraint-based filtering** for property windows (MW/logP/TPSA/RB, etc.).25- **Query language** to combine heterogeneous criteria (rules + alerts + numeric thresholds) into a single expression.2627## Dependencies2829- `medchem` (latest)30- `datamol` (latest)31- `pandas` (latest, for tabular workflows)3233## Example Usage3435```python36# End-to-end, runnable example:37# 1) load SMILES38# 2) apply Ro5 + Veber39# 3) apply common structural alerts40# 4) compute complexity and filter41# 5) export a CSV with decisions4243import pandas as pd44import datamol as dm45import medchem as mc4647smiles_list = [48 "CC(=O)OC1=CC=CC=C1C(=O)O", # aspirin49 "CN1C=NC2=C1C(=O)N(C(=O)N2C)C", # caffeine50 "c1ccccc1", # benzene51]5253df = pd.DataFrame({"smiles": smiles_list})54mols = [dm.to_mol(smi) for smi in df["smiles"]]5556# 1) Drug-likeness rules57rule_filter = mc.rules.RuleFilters(rule_list=["rule_of_five", "rule_of_veber"])58rule_res = rule_filter(mols=mols, n_jobs=-1, progress=False)59df["passes_rules"] = rule_res["pass"]6061# 2) Structural alerts62alerts = mc.structural.CommonAlertsFilters()63alert_res = alerts(mols=mols, n_jobs=-1, progress=False)64df["has_alerts"] = alert_res["has_alerts"]6566# 3) Complexity (example threshold)67complex_filter = mc.complexity.ComplexityFilter(max_complexity=500)68complex_res = complex_filter(mols=mols, n_jobs=-1, progress=False)69df["passes_complexity"] = complex_res["pass"]7071# 4) Final decision72df["keep"] = df["passes_rules"] & (~df["has_alerts"]) & df["passes_complexity"]7374# 5) Save results75df.to_csv("medchem_screening_results.csv", index=False)76print(df)77```7879## Implementation Details8081- **Rule evaluation (`medchem.rules`)**82 - Rules are implemented as callable checks over SMILES or RDKit-like molecule objects (commonly via `datamol`).83 - `RuleFilters(rule_list=[...])` applies multiple rules and returns a structured result (typically including an overall `pass` plus per-rule details).84 - Typical use: start broad (Ro5/Veber), then tighten (CNS/lead-like) as project constraints become clearer.8586- **Structural alerts (`medchem.structural`)**87 - Alert systems are primarily **SMARTS/pattern-based** matchers curated from literature/industrial practice.88 - `CommonAlertsFilters`, `NIBRFilters`, and `LillyDemeritsFilters` provide different philosophies:89 - **Common alerts**: general-purpose red flags.90 - **NIBR**: curated industrial filter set.91 - **Lilly demerits**: assigns penalties per matched rule; a common convention is **reject if total demerits > 100**.9293- **Complexity (`medchem.complexity`)**94 - Complexity scores approximate synthetic difficulty / structural intricacy using established heuristics (e.g., Bertz/Whitlock/Barone-style metrics).95 - `ComplexityFilter(max_complexity=...)` converts a numeric score into a pass/fail gate for library triage.9697- **Constraints (`medchem.constraints`)**98 - Property windows (MW/logP/TPSA/rotatable bonds, etc.) are applied as **hard filters**.99 - Use constraints to encode target-specific design hypotheses (e.g., CNS-like space) rather than universal “good/bad” judgments.100101- **Groups and catalogs (`medchem.groups`, `medchem.catalogs`)**102 - Group detection is SMARTS-driven and returns boolean matches and/or match details (substructure hits).103 - Named catalogs provide curated sets for consistent annotation and matching across projects.104105- **Parallelization**106 - Most batch APIs accept `n_jobs`; set `n_jobs=-1` to use all available CPU cores for large libraries.