schrodinger.application.transforms.filters module

class schrodinger.application.transforms.filters.ComplexityFilterConfig(*, reference_smiles: str, max_complexity: int = 1, large_ring_cutoff: int = 6)

Bases: BaseModel

Configuration for ComplexityFilter.

Parameters:
  • reference_smiles – SMILES representation of the reference molecule

  • max_complexity – maximum number of the six fixed complexity descriptors that may exceed the reference values

  • large_ring_cutoff – rings with more atoms than this value are counted as large rings

reference_smiles: str
max_complexity: int
large_ring_cutoff: int
model_config: ClassVar[ConfigDict] = {'frozen': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class schrodinger.application.transforms.filters.ComplexityFilter(*, _config: pydantic.main.BaseModel | None = None, **kwargs)

Bases: PTransformWithConfig

Filter molecules based on their complexity relative to a reference.

Complexity is the number of these six fixed descriptors whose values exceed the corresponding reference values: NumBridgeheadAtoms, NumChiralCenters, NumSpiroAtoms, LargeRingCount, NumNonSpiroCR4, and NumFiveFiveRings. Molecules with complexity less than or equal to max_complexity are retained. The descriptor set is not configurable; large_ring_cutoff controls the definition of LargeRingCount.

Example usage:

from schrodinger.application.transforms.filters import (
    ComplexityFilter)

filtered = (
    mols
    | ComplexityFilter(
        reference_smiles='c1ccccc1',
        max_complexity=1)
)

See ComplexityFilterConfig for available configuration options.

config_class

alias of ComplexityFilterConfig

class schrodinger.application.transforms.filters.RDKitPathTanimotoSimilarityFilterConfig(*, references_path: Path, ignored_smarts: Optional[str] = None, property_family: str = 'autodesigner', threshold: float = 0.1, keep_dissimilar: bool = False)

Bases: AnnotateRDKitPathTanimotoSimilarityConfig

Configuration for RDKitPathTanimotoSimilarityFilter.

Parameters:
  • threshold – inclusive similarity threshold

  • keep_dissimilar – retain scores at or below the threshold instead of scores at or above it

threshold: float
keep_dissimilar: bool
model_config: ClassVar[ConfigDict] = {'frozen': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class schrodinger.application.transforms.filters.RDKitPathTanimotoSimilarityFilter(*, _config: pydantic.main.BaseModel | None = None, **kwargs)

Bases: PTransformWithConfig

Annotate and filter by path-fingerprint similarity to references.

The annotator records the highest Tanimoto similarity across all references using sparse-count RDKit path fingerprints. When ignored_smarts is configured, fingerprint paths containing bonds wholly within the first SMARTS match are excluded.

Example usage:

from schrodinger.application.transforms.filters import (
    RDKitPathTanimotoSimilarityFilter)

filtered = (
    structures
    | RDKitPathTanimotoSimilarityFilter(
        references_path='references.smi',
        threshold=0.5,
        ignored_smarts='c1ccccc1')
)

See RDKitPathTanimotoSimilarityFilterConfig for available configuration options.

config_class

alias of RDKitPathTanimotoSimilarityFilterConfig

class schrodinger.application.transforms.filters.HypothesisFilterConfig(*, hypothesis_path: Path, min_sites_to_match: int = 2)

Bases: BaseModel

Configuration for HypothesisFilter.

Parameters:
  • hypothesis_path – path containing the Phase hypothesis

  • min_sites_to_match – minimum number of hypothesis sites that must match

hypothesis_path: Path
min_sites_to_match: int
model_config: ClassVar[ConfigDict] = {'frozen': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class schrodinger.application.transforms.filters.HypothesisFilter(*, _config: pydantic.main.BaseModel | None = None, **kwargs)

Bases: PTransformWithConfig

Retain structures matching sites in the first Phase hypothesis.

This filter uses the first hypothesis in hypothesis_path and retains a structure when at least min_sites_to_match sites match. Matching uses existing coordinates, so inputs must already be positioned appropriately.

Example usage:

from schrodinger.application.transforms.filters import (
    HypothesisFilter)

matches = (
    structures
    | HypothesisFilter(
        hypothesis_path='hypothesis.phypo',
        min_sites_to_match=3)
)

See HypothesisFilterConfig for available configuration options.

config_class

alias of HypothesisFilterConfig

class schrodinger.application.transforms.filters.SubstructureFilter(filters: List[SingleSmartsFilter])

Bases: PTransform

A PTransform that returns structures or molecules that match every SingleSmartsFilter in filters.

Note: SMARTS patterns in the filters should be compatible with implicit H since structures are converted to Mol objects with implicit H before filtering.

Example usage:

>>> from schrodinger.structutils.filter import SingleSmartsFilter
>>> filters = [SingleSmartsFilter(
...   smarts='Br', min_matches=0, max_matches=1, name='Bromine')]
>>> with beam.Pipeline() as p:
...     output = (p
...     | beam.Create(['CC', 'CBr', 'BrCBr'])
...     | beam.Map(lambda smiles: Chem.MolFromSmiles(smiles))
...     | SubstructureFilter(filters)
...     | beam.Map(lambda mol: Chem.MolToSmiles(mol))
...     | beam.LogElements()
...     )
CC
CBr
Parameters:

filters – The SingleSmartsFilters that must all match.

__init__(filters: List[SingleSmartsFilter])
Parameters:

filters – the SingleSmartsFilters that must all match

classmethod FromFilterFile(path: Union[str, Path]) → Self

Load substructure filters from an optionally encrypted file.

The file should contain one filter per line, with the format::

<smarts> <min_matches> <max_matches>[ <name>]

writeFilterFile(path: pathlib.Path | str) → Path

Write substructure filters to an optionally encrypted file.

normalize(mols: list[rdkit.Chem.rdchem.Mol])

Modify the substructure filter by adjusting the single SMARTS filters to prevent them from rejected the provided molecules.

Parameters:

mols – the molecules to adjust the substructure filter for

exclude(smarts: list[str])

Modify the substructure filter so that any molecule that matches any SMARTS pattern in the smarts argument will be excluded from the output.

Parameters:

smarts – the SMARTS patterns

class schrodinger.application.transforms.filters.HasSubstructureMatch(smarts: str)

Bases: PTransform

A PTransform that keeps molecules or structures that contain a given SMARTS substructure. Uses HasSubstructMatch for early return on first match.

Example usage:

>>> with beam.Pipeline() as p:
...     output = (p
...     | beam.Create(['CC', 'c1ccccc1', 'CCC'])
...     | beam.Map(lambda smiles: Chem.MolFromSmiles(smiles))
...     | HasSubstructureMatch('c1ccccc1')
...     | beam.Map(lambda mol: Chem.MolToSmiles(mol))
...     | beam.LogElements()
...     )
c1ccccc1
Parameters:

smarts – SMARTS pattern that must be present in the molecule.

__init__(smarts: str)
expand(pcoll)
class schrodinger.application.transforms.filters.PropertySpaceFilterConfig(*, property_ranges: dict[typing.Annotated[str, AfterValidator(func=<function _mol_property_validator at 0x7d07c41e5800>)], typing.Annotated[tuple[int | float, int | float], AfterValidator(func=<function _range_validator at 0x7d07c41e5760>)]], uncharge: bool = False)

Bases: BaseModel

Configuration for PropertySpaceFilter.

Parameters:
  • property_ranges – property ranges to filter on

  • uncharge – whether to uncharge inputs before calculating properties

property_ranges: dict[typing.Annotated[str, AfterValidator(func=<function _mol_property_validator at 0x7d07c41e5800>)], typing.Annotated[tuple[int | float, int | float], AfterValidator(func=<function _range_validator at 0x7d07c41e5760>)]]
uncharge: bool
model_config: ClassVar[ConfigDict] = {'frozen': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class schrodinger.application.transforms.filters.PropertySpaceFilter(*, _config: pydantic.main.BaseModel | None = None, **kwargs)

Bases: PTransformWithConfig

A PTransform that returns structures or molecules based on RDKit property ranges, with the option to uncharge the input before filtering.

Parameters:

property_ranges – Dictionary containing property names as keys and lists of two floats as values, representing the minimum and maximum values for the property range.

Possible properties include all rdkit descriptors. This includes all descriptors in the following rdkit modules:

For a comprehensive list of possible properties, see schrodinger.rdkit.descriptors.DESCRIPTORS_DICT.

Example:

>>> property_ranges = {
...     'MolWt': [0, 100], # from rdkit's Lipinski descriptors
...     'NumAromaticRings': [1, 1]
... }
>>> smiles = ['c1ccccc1', 'Brc1ccccc1', 'CC']
>>> with beam.Pipeline() as p:
...     output = (p
...     | beam.Create(smiles)
...     | beam.Map(lambda smiles: Chem.MolFromSmiles(smiles))
...     | PropertySpaceFilter(property_ranges=property_ranges)
...     | beam.Map(lambda mol: Chem.MolToSmiles(mol))
...     | beam.LogElements()
...     )
c1ccccc1
config_class

alias of PropertySpaceFilterConfig

static property_filter_transform_label(property_name: str) → str

Return the Beam step label for a property filter sub-transform.

Parameters:

property_name – the property being filtered on

display_data()

Return display data for the transform based on the configuration.

Automatically generates display data from all fields in the config, converting values to strings for display purposes.

Returns:

Dictionary of configuration data for display

expand(molecules)
class schrodinger.application.transforms.filters.RGroupNormalizedPropertySpaceFilterConfig(*, property_ranges: dict[typing.Annotated[str, AfterValidator(func=<function _mol_property_validator at 0x7d07c41e5800>)], typing.Annotated[tuple[int | float, int | float], AfterValidator(func=<function _range_validator at 0x7d07c41e5760>)]], uncharge: bool = False, to_add: list[schrodinger.molutils.rgroups.RGroup] = <factory>, added: list[schrodinger.molutils.rgroups.RGroup] = <factory>, max_heavy_atom_count: int = 10, zero_minimums: bool = False)

Bases: PropertySpaceFilterConfig

Configuration for RGroupNormalizedPropertySpaceFilter.

Parameters:
  • to_add – R-groups still expected to be added

  • added – R-groups already attached

  • max_heavy_atom_count – maximum allowed heavy atom count for the current molecule before accounting for R-groups already in added

  • zero_minimums – set all normalized lower bounds to zero

to_add: list[RGroup]
added: list[RGroup]
max_heavy_atom_count: int
zero_minimums: bool
model_config: ClassVar[ConfigDict] = {'arbitrary_types_allowed': True, 'frozen': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class schrodinger.application.transforms.filters.RGroupNormalizedPropertySpaceFilter(*, _config: pydantic.main.BaseModel | None = None, **kwargs)

Bases: PTransformWithConfig

A PTransform that normalizes final-product target property ranges around known R-group additions for use with PropertySpaceFilter.

The normalized ranges account for known R-group additions when filtering the current molecules. Only supported normalized property-space ranges are retained; other valid PropertySpaceFilter descriptors are ignored because their contribution cannot be normalized around R-group additions. The normalized ranges are then filtered with PropertySpaceFilter.

config_class

alias of RGroupNormalizedPropertySpaceFilterConfig

display_data() → dict[str, FilterFunnelDisplayData]

Return filter funnel metadata for the nested property filter.

class schrodinger.application.transforms.filters.StructurePropertyFilter(property_ranges: Dict[str, List[float]])

Bases: PTransform

A PTransform that rejects structures that have one or more property values outside the allowed range as defined by the property_ranges.

Properties that are not on the structure will not be used as filters.

__init__(property_ranges: Dict[str, List[float]])
Parameters:

property_ranges – the property ranges to filter on

static property_filter_transform_label(property_name: str) → str

Return the Beam step label for a property filter sub-transform.

Parameters:

property_name – the property being filtered on

display_data()

Returns the display data associated to a pipeline component.

It should be reimplemented in pipeline components that wish to have static display data.

Returns:

Dict[str, Any]: A dictionary containing key:value pairs. The value might be an integer, float or string value; a DisplayDataItem for values that have more data (e.g. short value, label, url); or a HasDisplayData instance that has more display data that should be picked up. For example:

{
  'key1': 'string_value',
  'key2': 1234,
  'key3': 3.14159265,
  'key4': DisplayDataItem('apache.org', url='http://apache.org'),
  'key5': subComponent
}
expand(pcoll)
class schrodinger.application.transforms.filters.FepAmenableConfig(*, fep_references_path: Path, max_hac_diff: int = 10, core_smarts: Optional[str] = None)

Bases: BaseModel

Configuration for FepAmenable.

Parameters:
  • fep_references_path – SMILES file containing FEP references

  • max_hac_diff – maximum heavy-atom difference from the MCS

  • core_smarts – optional invariant core used to avoid MCS calculations

fep_references_path: Path
max_hac_diff: int
core_smarts: Optional[str]
model_config: ClassVar[ConfigDict] = {'frozen': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class schrodinger.application.transforms.filters.FepAmenable(*, _config: pydantic.main.BaseModel | None = None, **kwargs)

Bases: PTransformWithConfig

Retain molecules with a perturbation amenable to FEP calculations.

A molecule is retained if no more than max_hac_diff heavy atoms fall outside the maximum common substructure it shares with at least one reference molecule.

core_smarts can speed up filtering by avoiding the maximum common substructure calculation when possible.

config_class

alias of FepAmenableConfig

expand(pcoll)
validate_mol(mol: Mol, what='Molecule') → None
Raises:

ValueError – if mol is not considered FepAmenable

class schrodinger.application.transforms.filters.DistinctStructures(label: Optional[str] = None)

Bases: PTransform

A PTransform that returns the unique structures based on the SMILES.

expand(pcoll)
class schrodinger.application.transforms.filters.TanimotoFilter(references: Iterable[Mol], threshold: float, ignored_smarts: str = '', larger_is_better: bool = True)

Bases: PTransform

A PTransform that returns molecules that have a better Tanimoto similarity score to at least one molecule in references. What is considered better depends on the larger_is_better parameter.

When ignored_smarts is provided, paths containing a bond whose endpoints are both in the first SMARTS match are excluded. Other paths may include matched atoms, including attachment bonds and paths through a single matched atom. Consequently, a single-atom match masks no paths. If the SMARTS does not match, the fingerprint is unmasked.

Only the first match is used, so the pattern should uniquely identify the intended core.

The larger_is_better parameter determines whether a larger or equal similarity score than the threshold is required to pass the filter. (Default is True)

__init__(references: Iterable[Mol], threshold: float, ignored_smarts: str = '', larger_is_better: bool = True)
Parameters:
  • references – the molecules to compare against

  • ignored_smarts – the SMARTS pattern identifying the core

  • threshold – the Tanimoto similarity threshold

  • larger_is_better – whether a larger similarity score is better

expand(pcoll)
class schrodinger.application.transforms.filters.ChargedNHpKaFilterConfig(*, pka_range: tuple[int | float, int | float], exclude_smarts: Optional[str] = None)

Bases: BaseModel

Configuration for ChargedNHpKaFilter.

Parameters:
  • pka_range – inclusive range of acceptable pKa values

  • exclude_smarts – optional atoms to exclude from the filter

pka_range: tuple[int | float, int | float]
exclude_smarts: Optional[str]
model_config: ClassVar[ConfigDict] = {'frozen': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class schrodinger.application.transforms.filters.ChargedNHpKaFilter(*, _config: pydantic.main.BaseModel | None = None, **kwargs)

Bases: PTransformWithConfig

Retain structures whose relevant pKa values fall within pka_range.

The filter checks hydrogens bonded to formally charged nitrogen atoms. Their pKa values should be stored in the r_epik_H2O_pKa atom property, as LigPrep normally does. A hydrogen without this property is accepted.

config_class

alias of ChargedNHpKaFilterConfig

expand(pcoll)