Orienting two torsionsΒΆ

Can also be found here.

This comes from an issue in automating the alignment of functional groups either side of imine bonds, where ETKDG just happens to give the configuration I do not want.

import stk
import bbprepared

building_block = stk.BuildingBlock(
    smiles="C1=CC=NC(=C1)C=NBr",
    functional_groups=[
        stk.SmartsFunctionalGroupFactory(
            smarts="[#6]~[#7X2]~[#35]",
            bonders=(1,),
            deleters=(),
        ),
        stk.SmartsFunctionalGroupFactory(
            smarts="[#6]~[#7X2]~[#6]",
            bonders=(1,),
            deleters=(),
        ),
    ],
)

ensemble = bbprepared.generators.ETKDG(num_confs=100).generate_conformers(
    building_block
)

Here, we use two distinct torsional selection processes either side of the imine to get the configuration we want. This benefits from processes occuring in the same order over the same ensemble.

# Select the C-C-N-Br torsion.
process1 = bbprepared.TargetTorsion(
    ensemble=ensemble,
    selector=bbprepared.selectors.BySmartsSelector(
        smarts="[#6]~[#6]~[#7]~[#35]",
        selected_indices=(0, 1, 2, 3),
    ),
    target_value=180,
)
p1_by_id = process1.get_all_scores_by_id()

# Select the N-C-C-N torsion.
process2 = bbprepared.TargetTorsion(
    ensemble=ensemble,
    selector=bbprepared.selectors.BySmartsSelector(
        smarts="[#7]~[#6]~[#6]~[#7]",
        selected_indices=(0, 1, 2, 3),
    ),
    target_value=0,
)
p2_by_id = process2.get_all_scores_by_id()

Then you can iterate over the ensemble with the selections and compute the scores.

best_score = float("inf")
best_conformer = bbprepared.Conformer(
    molecule=ensemble.get_base_molecule().clone(),
    conformer_id=-1,
    source=None,
    permutation=None,
)
for conformer in ensemble.yield_conformers():
    p1score = p1_by_id[conformer.conformer_id]
    p2score = p2_by_id[conformer.conformer_id]
    sum_score = p1score + p2score
    if sum_score < best_score:
        best_conformer = bbprepared.Conformer(
            molecule=conformer.molecule.clone(),
            conformer_id=conformer.conformer_id,
            source=conformer.source,
            permutation=conformer.permutation,
        )
        best_score = sum_score

# Get the best conformer as an stk.BuildingBlock.
best_bb = best_conformer.molecule

The desired conformation: