schrodinger.application.pathfinder.synthesis module

A module to support reaction enumeration.


# combinatorial enumeration from a route file
route = route.read_route('route.json')
synthesizer = Synthesizer(route)
# Assuming acids and amines are iterables with the reactants...
for product in synthesizer.synthesizeCombinations([acids, amines]):
    print Chem.MolToSmiles(product)
class schrodinger.application.pathfinder.synthesis.SystematicIterator(synthesizer, reagent_sources, start=0, stop=None, dedup=True)

Bases: object

Generate all combinations (or a slice thereof) of products that can be synthesized by a Synthesizer using the given sets of starting materials.

__init__(synthesizer, reagent_sources, start=0, stop=None, dedup=True)
  • synthesizer (Synthesizer) – Synthesizer

  • reagent_sources (iterable of ReagentSource or iterable of list of Mol.) – List of reagent sources.

  • start (int) – Start yielding from this reagent combination index (counting from zero).

  • stop (int or NoneType) – Stop yielding when this product reagent combination index is reached. None means unlimited.

  • dedup (bool) – skip duplicate products

class schrodinger.application.pathfinder.synthesis.RandomSampleIterator(synthesizer, reagent_sources, size, max_tries=None, dedup=True, prng=<module 'random' from '/scr/buildbot/savedbuilds/2024-1/NB/build-133/internal/lib/python3.8/'>)

Bases: object

Generate a random sample of unique products by repeatedly choosing a random reagent from each reagent source and keeping track of which products have been seen so far. Therefore, it is most efficient when only a fraction of the possible space of reagent combinations is sampled, because otherwise there may be many unproductive duplicates. Also, since it keeps the set of products seen so far, it uses memory proportional to ‘size’, so it is best if that number is not too large (thousands is fine).

__init__(synthesizer, reagent_sources, size, max_tries=None, dedup=True, prng=<module 'random' from '/scr/buildbot/savedbuilds/2024-1/NB/build-133/internal/lib/python3.8/'>)
  • synthesizer (Synthesizer) – Synthesizer

  • reagent_sources (iterable of ReagentSource or iterable of list of Mol.) – List of reagent sources

  • max_tries (int) – maximum number of random attempts to make before giving up, even if not enough products have been synthesized. The default is a function of ‘size’ and the number of reactant combinations.

  • dedup (bool) – skip duplicate products

  • prng (random.Random) – pseudo-random number generator


size: desired sample size (number of products).

class schrodinger.application.pathfinder.synthesis.Synthesizer(route, id_property='s_m_title', allow_multiple_products=False, ncycles=None, keep_labels=False, failed_reaction_handle=None)

Bases: object

A Synthesizer is a “machine” that given a RouteNode, knows how to apply all the reactions in the RouteNode in the right order to a list of starting materials to give the final products.

__init__(route, id_property='s_m_title', allow_multiple_products=False, ncycles=None, keep_labels=False, failed_reaction_handle=None)

Create a synthesizer from a route. The value of id_property is propagated from the starting materials to the product, to make it possible to keep track of where a product came from.

  • route (RouteNode) – synthetic route to apply

  • id_property (str) – name of the property that gets propagated to the product for identification purposes

  • allow_multiple_products (bool) – if True, the synthesis won’t fail if a reaction generates more than one product

  • ncycles (int or None) – how many times to try to apply each reaction; when multiple substitution or polymerization is desired, use ncycles > 1. The default is to use the ncycles specified by each reaction node, or 1 if the node doesn’t specify it either.

  • keep_labels (bool) – keep the frozen atom labels? If so, they are added to the i_reaction_atom_label property.

run(starting_materials, check_frozen=False)

Return the final product of the RouteNode given a list of starting materials.


check_frozen (bool) – if True, only return products for which all frozen atoms from the reactants are still present in the product. This also clears the frozen atom info (currently encoded as isotopes) from the atoms.


list of products (may be empty)

Return type

list of Mol

synthesizeCombinations(reagent_sources, **kwargs)

Create a SystematicIterator using the Synthesizer and the other arguments. See SystematicIterator for details. (This method is redundant but was kept for backward compatibility.)

synthesizeRandomSample(reagent_sources, size, **kwargs)

Crate a RandomSampleIterator using the Synthesizer and the other arguments. See RandomSampleIterator for details. (This method is redundant but was kept for backward compatibility.)


Yield the “labels” (isotopes) from the two atoms in each bond

class schrodinger.application.pathfinder.synthesis.ReagentSource(mols, size, filename, reagent_class, index, has_frozen_atoms=False)

Bases: object

A ReagentSource is just a struct-like object with the following fields:

  • mols: a generator or list of Mol objects;

  • size: (int) the number of molecules in mols;

  • filename: (str) file where the mols came from (or as a special case,

    “SMILES” if they came from the SMILES list hard-coded into the route);

  • reagent_class: (str) name of the reagent class.

  • index: the 1-based index that identifies the starting material in a route.

  • filters: a list of filters to apply to this reagent source. Each filter is

    a callable that takes an iterable of Mol and generating Mol.

  • has_frozen_atoms: if true, the molecules have frozen atoms

__init__(mols, size, filename, reagent_class, index, has_frozen_atoms=False)
schrodinger.application.pathfinder.synthesis.get_reagent_sources(route, r_dict=None, libpath=None)

Return a list of reagent sources given a route and, optionally, a dictionary mapping reagent index to filename/SMILES (e.g,, {1: ‘foo.smi’, 2: ‘CCO’}). The special filename ‘’ (empty string) means use SMILES associated with the node. Values in r_dict take precedence, followed by filename associated with the node, reagent class associated with the node, and SMILES associated with the node.


libpath (list of str) – list of directories to prepend to the standard reagent library search path


reagent sources

Return type

list of ReagentSource


ValueError when no file is found in the search path for a given reagent class or there is neither reagent class nor SMILES.


Create a route for a one-step synthesis given a Reaction.


rxn (Reaction) – reaction object


new route object

Return type



Return a list of unique molecules from ‘mols’, using the canonical SMILES as the comparison key.


mols (iterable of Mol) – molecules to uniquify


unique molecules

Return type

list of Mol


Desalt molecule (keep first largest fragment).


mol (rdkit.Chem.Mol) – molecule to desalt


desalted molecule (original is not modified)

Return type



Return the default neturalization patterns.


list of (query, replacement)

Return type

[(Mol, Mol)]


Neutralize a molecule.


mol (rdkit.Chem.Mol) – molecule to neutralize


neutralized molecule (original is not modified)

Return type


schrodinger.application.pathfinder.synthesis.create_reagent_library(name, input_file, smarts, id_property='s_m_title', properties=None, require_single_match=False, pfx=False, add=False, dedup=True, desalt=False, neutralize=False)

Create a reagent library file for one reagent class by searching through an input file using the provided SMARTS patterns. Writes a file called <name>.csv or <name>.pfx, depending on the value of the pfx flag.

A structure is selected for the library when it matches ANY of the specified patterns.

  • name (str) – name of the reagent class.

  • input_file (str) – name of structure file to process

  • smarts (str or list of str) – SMARTS pattern (or patterns) to search

  • id_property (str) – name of structure property to store as the title of each reagent.

  • properties ((list of str) or None) – properties to store in reaction file. None means “use all properties from the first structure”.

  • require_single_match (bool) – skip input structures matching the SMARTS pattern multiple times

  • pfx (bool) – write pfx library file

  • add (bool) – add new structures to output file if it exists, instead of clobbering

  • dedup (bool) – skip duplicate compunds, identified by canonical SMILES

  • desalt (bool) – keep first largest molecule. This is done _before_ doing the the SMARTS query.

  • neutralize (bool) – neutralize the reactants. This is done _before_ doing the the SMARTS query.


output filename

Return type


schrodinger.application.pathfinder.synthesis.set_prop(mol, name, value)

Set a property for a Mol object, with the property type deduced from the name, which should follow m2io conventions.

  • mol (rdkit.Chem.Mol) – molecule to modify

  • name (str) – property name following m2io convention

  • value (int, bool, float, or str, depending on name) – property value


Check if a molecule is considered a null reagent. The convention is that null reagents are molecules consisting only of a dummy atom.


mol (rdkit.Chem.Mol) – molecule to test


is the molecule a null reagent?

Return type


class schrodinger.application.pathfinder.synthesis.ReactionFailureTracker(output_handle)

Bases: object

Helper class to track failed reactions, and print them out to a csv for easy debugging. It currently also tracks total failures recorded, and is intended to be a convenience class to track and report other statistics.


output_handle (_io.TextIOWrapper) – file handle for output

writeFailure(reaction, reactants)

Write failures into the output file handle provided at construction

  • reaction (reaction.Reaction) – reaction type

  • reactants (list(rdkit.Chem.Mol)) – list of reactants