Library#
Block 1 — describe the combinatorial library. See the guide.
Pipeline#
- class TACTICS.library_enumeration.synthesis_pipeline.SynthesisPipeline(config)[source]#
Synthesis pipeline for single-step, multi-step, and alternative-SMARTS reactions.
This is the main entry point for: - ThompsonSampler compound generation - Full library enumeration - Reagent validation and compatibility detection
- Variables:
config – ReactionConfig defining the synthesis
reagent_file_list – List of reagent file paths
Example
>>> from TACTICS.library_enumeration import SynthesisPipeline >>> from TACTICS.library_enumeration.smarts_toolkit import ReactionDef, ReactionConfig >>> >>> config = ReactionConfig( ... reactions=[ReactionDef(reaction_smarts="...", step_index=0)], ... reagent_file_list=["acids.smi", "amines.smi"] ... ) >>> pipeline = SynthesisPipeline(config) >>> result = pipeline.enumerate_single(reagent_mols, reagent_keys)
- __init__(config)[source]#
Initialize pipeline from ReactionConfig.
- Parameters:
config (ReactionConfig) – ReactionConfig with reactions and reagent files
- property reactions: List[ReactionDef]#
Get all ReactionDef objects.
- enumerate_single(reagent_mols, reagent_keys=None, store_intermediates=False)[source]#
Enumerate a single product from reagent molecules.
Used by ThompsonSampler for individual compound generation.
- Parameters:
- Returns:
EnumerationResult with product or error details
- Return type:
- enumerate_single_from_smiles(smiles_list, reagent_keys=None, store_intermediates=False)[source]#
Enumerate a single product from SMILES strings.
- enumerate(reagent_mols, reagent_keys=None, store_intermediates=False)[source]#
Alias for enumerate_single (backward compatibility).
- Return type:
- enumerate_from_smiles(smiles_list, reagent_keys=None, store_intermediates=False)[source]#
Alias for enumerate_single_from_smiles (backward compatibility).
- Return type:
- enumerate_library(n_jobs=1, show_progress=True)[source]#
Enumerate entire combinatorial library.
Generates all possible products from reagent files.
- Parameters:
- Returns:
List of EnumerationResult for all products
- Return type:
- auto_detect_compatibility(reagent_lists=None, deprotect=False, desalt=False)[source]#
Automatically detect which reagents work with which patterns.
This runs validation for each pattern and builds a compatibility map used during enumeration for routing.
- Parameters:
- Returns:
AutoDetectionResult with full compatibility information
- Return type:
- register_compatibility(position, reagent_key, compatible_patterns, step_index=0)[source]#
Manually register reagent-pattern compatibility.
- get_compatible_patterns(reagent_keys, step_index=0)[source]#
Find a pattern compatible with all given reagents.
- prepare_worker_data()[source]#
Prepare serializable data for multiprocessing workers.
- Returns:
Dict that workers can use to reconstruct the pipeline
- Return type:
Reaction definition#
Configuration classes for the SMARTS toolkit.
This module provides validated Pydantic configuration for: - Single reaction definitions (ReactionDef) - Multi-step synthesis pipelines (ReactionConfig) - Deprotection specifications (DeprotectionSpec) - Step input mappings (StepInput)
The configuration system supports three modes: 1. Single SMARTS: One ReactionDef with step_index=0 2. Alternative SMARTS: Multiple ReactionDef with same step_index, marked with step_modes 3. Multi-step: Multiple ReactionDef with different step_index values
- class TACTICS.library_enumeration.smarts_toolkit.config.InputSource(value)[source]#
Source of input for a reaction step.
- class TACTICS.library_enumeration.smarts_toolkit.config.ProtectingGroupInfo(name, smarts, deprotection_smarts=None)[source]#
Definition of a protecting group for detection and optional removal.
- Variables:
Example
>>> boc = ProtectingGroupInfo( ... name="Boc", ... smarts="[NX3][C](=O)OC(C)(C)C", ... deprotection_smarts="[N:1][C](=O)OC(C)(C)C>>[N:1]" ... )
- class TACTICS.library_enumeration.smarts_toolkit.config.StepInput(*, source, file_index=None, step_index=None)[source]#
Configuration for one input to a reaction step.
Specifies where the input comes from: - REAGENT_FILE: From one of the original reagent files - PREVIOUS_STEP: From the output of a previous reaction step
Example
>>> # Input from first reagent file >>> input1 = StepInput(source=InputSource.REAGENT_FILE, file_index=0) >>> # Input from step 0's output >>> input2 = StepInput(source=InputSource.PREVIOUS_STEP, step_index=0)
Fields
- Parameters:
source (InputSource) – Default: required.
file_index (int | None) – Index into reagent_file_list (for REAGENT_FILE source). Default:
None.step_index (int | None) – Index of previous step to use output from (for PREVIOUS_STEP source). Default:
None.
- class TACTICS.library_enumeration.smarts_toolkit.config.DeprotectionSpec(*, group, target)[source]#
Deprotection to apply to a reactant or product.
Specifies which protecting group to remove and the target molecule. The target can be: - An integer (0, 1, 2, …): Index of the reactant to deprotect BEFORE the reaction - The string “product”: Apply deprotection to the product AFTER the reaction
Multiple DeprotectionSpec can be applied to a single reaction.
Examples
>>> # Remove Boc from the first reactant (before reaction) >>> deprot = DeprotectionSpec(group="Boc", target=0) >>> >>> # Remove Fmoc from the product (after reaction) >>> deprot = DeprotectionSpec(group="Fmoc", target="product")
Fields
- Parameters:
- class TACTICS.library_enumeration.smarts_toolkit.config.ReactionDef(*, reaction_smarts, step_index=0, pattern_id=None, description=None, deprotections=<factory>)[source]#
Definition of a single chemical reaction with built-in validation.
This is the fundamental building block for all synthesis configurations. Every reaction must specify a step_index (0 for single-step reactions, 0/1/2… for sequences).
Validation is built-in: call validate() to check reagent compatibility.
Example
>>> rxn = ReactionDef( ... reaction_smarts="[C:1](=O)O.[N:2]H2>>[C:1](=O)[N:2]", ... step_index=0, ... description="Amide coupling" ... ) >>> result = rxn.validate(reagent_files=["acids.smi", "amines.smi"]) >>> print(rxn.coverage_stats)
Fields
- Parameters:
reaction_smarts (str) – Reaction SMARTS string. Default: required.
step_index (int) – Step index (0 = first step). Default:
0.pattern_id (str | None) – Identifier for this pattern (for alternatives). Default:
None.description (str | None) – Human-readable description. Default:
None.deprotections (List[DeprotectionSpec]) – Deprotections to apply before this reaction executes. Default: computed.
- validate_reaction(reagent_files=None, reagent_smiles=None, protecting_groups=None, deprotect=False, desalt=False, test_reactions=False)[source]#
Validate this reaction against reagent files or SMILES lists.
- Parameters:
reagent_files (List[str] | None) – Paths to reagent .smi files
reagent_smiles (List[List[Tuple[str, str]]] | None) – Direct SMILES lists as [(smiles, name), …] per position (useful for validating against intermediates)
protecting_groups (List[ProtectingGroupInfo] | None) – Custom protecting group definitions
deprotect (bool) – Remove protecting groups before checking compatibility
desalt (bool) – Remove salt fragments before checking compatibility
test_reactions (bool) – Actually run reaction on sample combinations
- Returns:
ValidationResult with comprehensive compatibility information
- Return type:
Example
>>> rxn = ReactionDef(reaction_smarts="[C:1](=O)O.[N:2]>>[C:1](=O)[N:2]") >>> result = rxn.validate_reaction(reagent_files=["acids.smi", "amines.smi"]) >>> print(f"Coverage: {result.coverage_stats}")
- visualize_template_match(smiles, position, highlight_color=(0.0, 0.8, 0.0), size=(400, 300))[source]#
Visualize which atoms in a molecule match the reaction template.
This is the primary troubleshooting tool for understanding why a reagent or intermediate doesn’t work with the reaction.
- Parameters:
- Returns:
IPython Image for Jupyter display, or PIL Image
- Return type:
- get_reactant_template(position)[source]#
Get the RDKit mol template for a reactant position.
- Parameters:
position (int) – Reactant position (0-indexed)
- Returns:
RDKit Mol object representing the reactant pattern
- Return type:
Mol | None
- property coverage_stats: Dict[int, float]#
Coverage percentage per position.
- Returns:
Dict mapping position to coverage percentage (0-100)
- Raises:
ValueError – If validate_reaction() hasn’t been called
- property validation_result: ValidationResult | None#
Get the cached validation result.
- class TACTICS.library_enumeration.smarts_toolkit.config.ReactionConfig(*, reactions, reagent_file_list=<factory>, step_inputs=None, step_modes=None, protecting_groups=None)[source]#
Container for synthesis configuration.
Rules: - Every ReactionDef must have a step_index - step_inputs is REQUIRED when len(reactions) > 1 - step_modes is only used to mark steps with alternative SMARTS patterns - pattern_ids are auto-generated for alternatives if not provided
Examples
# Single reaction (simplest case) >>> config = ReactionConfig( … reactions=[ReactionDef(reaction_smarts=”…”, step_index=0)], … reagent_file_list=[“acids.smi”, “amines.smi”] … )
# Alternatives at step 0 >>> config = ReactionConfig( … reactions=[ … ReactionDef(reaction_smarts=”…”, step_index=0, pattern_id=”primary”), … ReactionDef(reaction_smarts=”…”, step_index=0, pattern_id=”secondary”), … ], … reagent_file_list=[“amines.smi”, “acids.smi”], … step_inputs={0: [StepInput(…), StepInput(…)]}, … step_modes={0: “alternative”} … )
# Multi-step sequence >>> config = ReactionConfig( … reactions=[ … ReactionDef(reaction_smarts=”…”, step_index=0), … ReactionDef(reaction_smarts=”…”, step_index=1), … ], … reagent_file_list=[“bb1.smi”, “bb2.smi”, “bb3.smi”], … step_inputs={ … 0: [StepInput(source=InputSource.REAGENT_FILE, file_index=0), …], … 1: [StepInput(source=InputSource.PREVIOUS_STEP, step_index=0), …], … } … )
Fields
- Parameters:
reactions (List[ReactionDef]) – Default: required.
step_inputs (Dict[int, List[StepInput]] | None) – Mapping of step_index to input sources (required if multiple reactions). Default:
None.step_modes (Dict[int, Literal['alternative']] | None) – Mark steps with alternative SMARTS patterns. Default:
None.protecting_groups (List[ProtectingGroupInfo] | None) – Custom protecting group definitions. Default:
None.
- validate_config()[source]#
Validate the configuration: 1. Require step_inputs when multiple reactions 2. Auto-generate pattern_ids for alternatives 3. Validate step_modes references valid step indices 4. Validate step_inputs references valid file/step indices
- get_reactions_for_step(step_index)[source]#
Get all ReactionDef objects for a step (including alternatives).
- Parameters:
step_index (int) – The step index
- Returns:
List of ReactionDef objects for that step
- Return type:
- get_primary_reaction(step_index)[source]#
Get the primary reaction for a step.
Returns the reaction with pattern_id=’primary’, or the first one if not found.
- Parameters:
step_index (int) – The step index
- Returns:
The primary ReactionDef or None if step doesn’t exist
- Return type:
ReactionDef | None
- get_inputs_for_step(step_index)[source]#
Get the input configuration for a step.
For single-reaction configs without step_inputs, auto-generates inputs from reagent_file_list.
Validation result#
- class TACTICS.library_enumeration.smarts_toolkit._validator.ValidationResult(compatible_reagents=<factory>, incompatible_reagents=<factory>, invalid_smiles=<factory>, duplicate_smiles=<factory>, protected_reagents=<factory>, multi_fragment_reagents=<factory>, coverage_stats=<factory>, reaction_success_rate=0.0, error_messages=<factory>, warnings=<factory>)[source]#
Comprehensive results from SMARTS validation.
- Variables:
compatible_reagents (Dict[int, List[Tuple[str, str]]]) – {position: [(smiles, name), …]} - Reagents that match template
incompatible_reagents (Dict[int, List[Tuple[str, str]]]) – {position: [(smiles, name), …]} - Reagents that don’t match
invalid_smiles (Dict[int, List[Tuple[str, str]]]) – {position: [(smiles, name), …]} - Unparseable SMILES
duplicate_smiles (Dict[int, List[Tuple[str, str]]]) – {position: [(smiles, name), …]} - Duplicate entries
protected_reagents (Dict[int, List[Tuple[str, str, List[str]]]]) – {position: [(smiles, name, [groups]), …]} - With protecting groups
multi_fragment_reagents (Dict[int, List[Tuple[str, str, List[str]]]]) – {position: [(smiles, name, [fragments]), …]} - With salts
coverage_stats (Dict[int, float]) – {position: float} - Percent compatible per position (0-100)
reaction_success_rate (float) – float - Percent of test reactions that succeeded
error_messages (List[str]) – List[str] - Critical errors
warnings (List[str]) – List[str] - Non-critical warnings
Enumeration results and helpers#
Enumeration utilities and result dataclasses.
This module provides: - EnumerationResult: Result from product enumeration - EnumerationError: Details about failed enumeration - AutoDetectionResult: Results from SMARTS compatibility detection - Utility functions for reagent processing
- class TACTICS.library_enumeration.enumeration_utils.EnumerationError(step_index, pattern_id, error_type, message, reagent_smiles=<factory>, reagent_names=<factory>, reaction_smarts=None)[source]#
Details about a failed enumeration.
- Variables:
step_index (int) – Which step failed
pattern_id (str | None) – Which pattern was attempted
error_type (Literal['no_compatible_pattern', 'reaction_failed', 'invalid_input', 'deprotection_failed']) – Type of error
message (str) – Human-readable description
reagent_smiles (List[str]) – Input SMILES that failed
reagent_names (List[str]) – Input reagent names for traceability
reaction_smarts (str | None) – The SMARTS pattern that was attempted (if available)
- class TACTICS.library_enumeration.enumeration_utils.EnumerationResult(product=None, product_smiles=None, product_name=None, patterns_used=<factory>, intermediates=None, error=None)[source]#
Complete result from pipeline enumeration.
- Variables:
product (rdkit.Chem.rdchem.Mol | None) – Final product molecule (None if failed)
product_smiles (str | None) – SMILES of final product
product_name (str | None) – Name of product (from reagent keys)
patterns_used (Dict[int, str]) – {step_index: pattern_id} for each step
intermediates (Dict[int, rdkit.Chem.rdchem.Mol] | None) – {step_index: mol} if store_intermediates=True
error (TACTICS.library_enumeration.enumeration_utils.EnumerationError | None) – EnumerationError if failed
- class TACTICS.library_enumeration.enumeration_utils.AutoDetectionResult(pattern_results=<factory>, compatibility_map=<factory>, coverage_by_pattern=<factory>, unmatched_reagents=<factory>, warnings=<factory>)[source]#
Results from automatic SMARTS compatibility detection.
- Variables:
pattern_results (Dict[int, Dict[str, Any]]) – {step_index: {pattern_id: ValidationResult}}
compatibility_map (Dict[Tuple[int, int, str], Set[str]]) – {(step_index, position, reagent_key): {pattern_ids}}
coverage_by_pattern (Dict[int, Dict[str, Dict[int, float]]]) – {step_index: {pattern_id: {position: coverage%}}}
unmatched_reagents (Dict[int, List[str]]) – {position: [reagent_names]} - Reagents matching no patterns
warnings (List[str]) – List of warning messages
- TACTICS.library_enumeration.enumeration_utils.read_reagent_file(file_path)[source]#
Read reagents from a SMILES file.
- TACTICS.library_enumeration.enumeration_utils.results_to_dataframe(results, include_failures=False)[source]#
Convert enumeration results to Polars DataFrame.
- Parameters:
results (List[EnumerationResult]) – List of EnumerationResult
include_failures (bool) – Include failed enumerations
- Returns:
product_name, product_smiles, success
- Return type:
DataFrame with columns
- TACTICS.library_enumeration.enumeration_utils.failures_to_dataframe(results)[source]#
Convert failed enumeration results to a detailed Polars DataFrame for analysis.
- Parameters:
results (List[EnumerationResult]) – List of EnumerationResult (will filter to failures only)
- Returns:
product_name: Attempted product name
step_index: Which step failed
pattern_id: Which pattern was attempted
error_type: Type of error
message: Error message
reagent_names: Semicolon-separated reagent names
reagent_smiles: Semicolon-separated reagent SMILES
reaction_smarts: The SMARTS pattern attempted (if available)
- Return type:
DataFrame with columns
Example
>>> results = pipeline.enumerate_library() >>> failures_df = failures_to_dataframe(results) >>> print(failures_df.group_by("error_type").count())
- TACTICS.library_enumeration.enumeration_utils.summarize_failures(results)[source]#
Generate a summary of enumeration failures.
- Parameters:
results (List[EnumerationResult]) – List of EnumerationResult
- Returns:
total: Total number of results
successes: Number of successful enumerations
failures: Number of failed enumerations
by_error_type: Count per error type
by_step: Count per step index
failure_rate: Percentage of failures
- Return type:
Dictionary with failure statistics
Example
>>> results = pipeline.enumerate_library() >>> summary = summarize_failures(results) >>> print(f"Failure rate: {summary['failure_rate']:.1f}%")
File writing utilities for enumerated chemical libraries.
This module provides functions to write enumeration results to various formats: - CSV: Standard comma-separated values - SMI: SMILES format (SMILES name) - SDF: Structure-Data File format
- TACTICS.library_enumeration.file_writer.write_enumerated_library(results, output_path, format='csv', include_failures=False)[source]#
Write enumerated library to file.
- Parameters:
results (List[EnumerationResult]) – List of EnumerationResult from enumeration
output_path (str) – Output file path
format (Literal['csv', 'smi', 'sdf']) – Output format (csv, smi, sdf)
include_failures (bool) – Include failed enumerations in output
- Returns:
Number of products written
- Return type:
Example
>>> results = pipeline.enumerate_library() >>> n_written = write_enumerated_library(results, "products.csv", format="csv") >>> print(f"Wrote {n_written} products")
- TACTICS.library_enumeration.file_writer.write_products_chunked(results, output_dir, products_per_file=5000, format='smi', file_prefix='products')[source]#
Write products to multiple files with a specified number per file.
- Parameters:
- Returns:
Total number of products written
- Return type:
Product generation utilities for chemical library enumeration.
This module provides functions for: - Single product enumeration from reagents - Batch enumeration (sequential and parallel) - Reaction execution helpers - Deprotection application
These functions are used by SynthesisPipeline for library enumeration.
- TACTICS.library_enumeration.generate_products.enumerate_products(pipeline, combinations, n_jobs=1, show_progress=False)[source]#
Enumerate products from reagent combinations.
- Parameters:
- Returns:
List of EnumerationResult objects
- Return type:
- TACTICS.library_enumeration.generate_products.generate_all_combinations(reagent_files, return_separate_names=False)[source]#
Generate all reagent combinations from files.
- Parameters:
- Returns:
Tuple of (mol_combinations, name_combinations, reagent_name_lists) - mol_combinations: List of tuples of Mol objects - name_combinations: List of product names (reagent names joined by _) - reagent_name_lists: List of [reagent_name, …] lists (only if return_separate_names=True)
- Return type:
Tuple[List[Tuple[Mol, …]], List[str], List[List[str]] | None]
Protecting groups and salts#
Default constants for SMARTS validation.
Provides commonly-used protecting groups and salt fragments for automatic detection during reagent validation.
The protecting groups include SMARTS patterns for detection and optional reaction SMARTS for deprotection. Salt fragments are provided as SMILES patterns for common counterions and salts.
These defaults can be extended by providing additional entries when creating a SMARTSValidator instance.