Source code for synkit.Rule.Compose.seq_comp
from typing import List, Dict, Optional
from synkit.IO.chem_converter import smart_to_gml
from synkit.Rule.Compose.compose_rule import ComposeRule
from synkit.Rule.Compose.rule_mapping import RuleMapping
[docs]
class SeqComp:
"""A class for generating pairwise mappings between sequential chemical
reaction rules.
This class takes a list of reaction SMARTS strings, converts them to
their corresponding GML representations, composes candidate reaction
rules for each consecutive pair, and computes a mapping between the
rules using a rule mapping algorithm.
"""
def __init__(self) -> None:
"""Initialize an instance of the SeqComp class."""
pass
[docs]
@staticmethod
def sequence_map(smarts: List[str]) -> Dict[str, Optional[dict]]:
"""Generate pairwise mapping dictionaries between consecutive reaction
SMARTS strings.
This function processes a list of reaction SMARTS strings by:
1. Converting each SMARTS string to its GML representation.
2. For each consecutive pair, composing candidate rules using ComposeRule().get_rule_comp().
3. Using the first candidate (if available) and the original GMLs to compute a mapping
using RuleMapping().fit().
4. Storing the resulting mapping in a dictionary with keys in the format "i:i+1".
Parameters:
- smarts (List[str]): The list of reaction SMARTS strings.
Returns:
- Dict[str, Optional[dict]]:
A dictionary where each key is a string "i:i+1" representing the consecutive pair indices,
and the corresponding value is the mapping dictionary produced by RuleMapping().fit()
for that pair, or None if no valid mapping could be computed.
"""
# Convert each SMARTS string to its GML representation.
gml_list = [smart_to_gml(s, sanitize=True, reindex=False) for s in smarts]
mappings: Dict[str, Optional[dict]] = {}
# Process each consecutive pair in the list.
for i in range(len(gml_list) - 1):
# Get the consecutive SMARTS and GML representations.
smart_a = smarts[i]
smart_b = smarts[i + 1]
rule_a = gml_list[i]
rule_b = gml_list[i + 1]
# Compose candidate rules between smart_a and smart_b.
candidate_rules = ComposeRule().get_rule_comp(smart_a, smart_b)
# If no candidate rule is found, assign None for this pair.
if not candidate_rules:
mappings[f"{i}:{i+1}"] = None
continue
# Try to compute the mapping using the first candidate rule.
try:
mapping_result = RuleMapping().fit(rule_a, rule_b, candidate_rules[0])
except Exception as e:
print(f"Error computing mapping for pair {i}:{i+1}: {e}")
mapping_result = None
mappings[f"{i}:{i+1}"] = mapping_result
return mappings