stk.rotaxane.NRotaxane

class stk.rotaxane.NRotaxane(axle, cycles, repeating_unit, num_repeating_units, orientations=None, random_seed=None, num_processes=1, optimizer=<stk._internal.optimizers.null.NullOptimizer object>)[source]

Bases: TopologyGraph

Represents [n]rotaxane topology graphs.

Axle and cycle building blocks do not require functional groups.

This class assumes one axle with (n-1) macrocycles threaded on it. The macrocycles are spaced evenly along the axle in repeating patterns. The threaded macrocycles can be described analogously to monomers in linear polymers, in terms of a repeating unit, except that no bonds are formed between them.

Examples

Construction

import stk

cycle = stk.ConstructedMolecule(
    topology_graph=stk.macrocycle.Macrocycle(
        building_blocks=(
            stk.BuildingBlock(
                smiles='[Br]CC[Br]',
                functional_groups=[stk.BromoFactory()],
            ),
        ),
        repeating_unit='A',
        num_repeating_units=5,
    ),
)
axle = stk.ConstructedMolecule(
    topology_graph=stk.polymer.Linear(
        building_blocks=(
            stk.BuildingBlock('BrCCBr', [stk.BromoFactory()]),
            stk.BuildingBlock('BrCNCBr', [stk.BromoFactory()]),
        ),
        repeating_unit='AB',
        num_repeating_units=7,
    )
)
rotaxane = stk.ConstructedMolecule(
    topology_graph=stk.rotaxane.NRotaxane(
        axle=stk.BuildingBlock.init_from_molecule(axle),
        cycles=(
            stk.BuildingBlock.init_from_molecule(cycle),
        ),
        repeating_unit='A',
        num_repeating_units=3,
    ),
)

Suggested Optimization

For NRotaxane topologies, there is no need to use an optimizer, so stick with NullOptimizer. However, it is recommended that all building blocks be optimized prior to construction.

Defining the Orientation of Each Building Block

The orientations parameter allows the direction of each cycle along the axle to be flipped

import stk

cycle1 = stk.ConstructedMolecule(
    topology_graph=stk.macrocycle.Macrocycle(
        building_blocks=(
            stk.BuildingBlock(
                smiles='BrCCBr',
                functional_groups=[stk.BromoFactory()],
            ),
            stk.BuildingBlock(
                smiles='BrCNCBr',
                functional_groups=[stk.BromoFactory()],
            ),
        ),
        repeating_unit='AB',
        num_repeating_units=5,
        optimizer=stk.MCHammer(),
    ),
)
cycle2 = stk.ConstructedMolecule(
    topology_graph=stk.macrocycle.Macrocycle(
        building_blocks=(
            stk.BuildingBlock(
                smiles='BrCCCBr',
                functional_groups=[stk.BromoFactory()],
            ),
            stk.BuildingBlock(
                smiles='BrCCNCBr',
                functional_groups=[stk.BromoFactory()],
            ),
        ),
        repeating_unit='AB',
        num_repeating_units=5,
        optimizer=stk.MCHammer(),
    ),
)
axle = stk.ConstructedMolecule(
    topology_graph=stk.polymer.Linear(
        building_blocks=(
            stk.BuildingBlock('BrCCBr', [stk.BromoFactory()]),
        ),
        repeating_unit='A',
        num_repeating_units=2,
    ),
)
rotaxane1 = stk.ConstructedMolecule(
    topology_graph=stk.rotaxane.NRotaxane(
        axle=stk.BuildingBlock.init_from_molecule(axle),
        cycles=(
            stk.BuildingBlock.init_from_molecule(cycle1),
            stk.BuildingBlock.init_from_molecule(cycle2),
        ),
        repeating_unit='AB',
        num_repeating_units=3,
        orientations=(1., 0.5),
    ),
)

In the above example, cycle1 is guaranteed to be flipped, cycle2 has a 50% chance of being flipped, each time it is placed on a node.

Note that whether a building block will be flipped or not is decided during the initialization of NRotaxane

# graph1 will always construct the same [n]rotaxane.
graph1 = stk.rotaxane.NRotaxane(
    axle=stk.BuildingBlock.init_from_molecule(axle),
    cycles=(
        stk.BuildingBlock.init_from_molecule(cycle1),
        stk.BuildingBlock.init_from_molecule(cycle2),
    ),
    repeating_unit='AB',
    num_repeating_units=5,
    orientations=(0.65, 0.45),
)
# rotaxane2 and rotaxane3 are guaranteed to be the same as they
# used the same topology graph.
rotaxane2 = stk.ConstructedMolecule(graph1)
rotaxane3 = stk.ConstructedMolecule(graph1)

# graph2 may lead to a different [n]rotaxane, despite
# being initialized with the same parameters.
graph2 = stk.rotaxane.NRotaxane(
    axle=stk.BuildingBlock.init_from_molecule(axle),
    cycles=(
        stk.BuildingBlock.init_from_molecule(cycle1),
        stk.BuildingBlock.init_from_molecule(cycle2),
    ),
    repeating_unit='AB',
    num_repeating_units=5,
    orientations=(0.65, 0.45)
)

# rotaxane4 and rotaxane5 are guaranteed to be the same because
# they used the same topology graph. However, they may be
# different to rotaxane2 and rotaxane3.
rotaxane4 = stk.ConstructedMolecule(graph2)
rotaxane5 = stk.ConstructedMolecule(graph2)

The random_seed parameter can be used to get reproducible results

# rotaxane6 and rotaxane7 are guaranteed to be the same,
# because graph3 and graph4 used the same random seed.

graph3 = stk.rotaxane.NRotaxane(
    axle=stk.BuildingBlock.init_from_molecule(axle),
    cycles=(
        stk.BuildingBlock.init_from_molecule(cycle1),
        stk.BuildingBlock.init_from_molecule(cycle2),
    ),
    repeating_unit='AB',
    num_repeating_units=5,
    orientations=(0.65, 0.45),
    random_seed=4,
)
rotaxane6 = stk.ConstructedMolecule(graph3)

graph4 = stk.rotaxane.NRotaxane(
    axle=stk.BuildingBlock.init_from_molecule(axle),
    cycles=(
        stk.BuildingBlock.init_from_molecule(cycle1),
        stk.BuildingBlock.init_from_molecule(cycle2),
    ),
    repeating_unit='AB',
    num_repeating_units=5,
    orientations=(0.65, 0.45),
    random_seed=4,
)
rotaxane7 = stk.ConstructedMolecule(graph4)

Using Numbers to Define the Repeating Unit

The repeating unit can also be specified through the indices of the building blocks

import stk

cycle1 = stk.ConstructedMolecule(
    topology_graph=stk.macrocycle.Macrocycle(
        building_blocks=(
            stk.BuildingBlock(
                smiles='BrCCBr',
                functional_groups=[stk.BromoFactory()],
            ),
            stk.BuildingBlock(
                smiles='BrCNCBr',
                functional_groups=[stk.BromoFactory()],
            ),
        ),
        repeating_unit='AB',
        num_repeating_units=5,
        optimizer=stk.MCHammer(),
    ),
)
cycle2 = stk.ConstructedMolecule(
    topology_graph=stk.macrocycle.Macrocycle(
        building_blocks=(
            stk.BuildingBlock(
                smiles='BrCCCBr',
                functional_groups=[stk.BromoFactory()],
            ),
            stk.BuildingBlock(
                smiles='BrCCNCBr',
                functional_groups=[stk.BromoFactory()],
            ),
        ),
        repeating_unit='AB',
        num_repeating_units=5,
        optimizer=stk.MCHammer(),
    ),
)
cycle3 = stk.ConstructedMolecule(
    topology_graph=stk.macrocycle.Macrocycle(
        building_blocks=(
            stk.BuildingBlock(
                smiles='BrCCNNCBr',
                functional_groups=[stk.BromoFactory()],
            ),
            stk.BuildingBlock(
                smiles='BrCCNNNCBr',
                functional_groups=[stk.BromoFactory()],
            ),
        ),
        repeating_unit='AB',
        num_repeating_units=5,
        optimizer=stk.MCHammer(),
    ),
)
axle = stk.ConstructedMolecule(
    topology_graph=stk.polymer.Linear(
        building_blocks=(
            stk.BuildingBlock('BrCCBr', [stk.BromoFactory()]),
        ),
        repeating_unit='A',
        num_repeating_units=2,
    ),
)

# r1 and r2 are different ways to write the same thing.
r1 = stk.ConstructedMolecule(
    topology_graph=stk.rotaxane.NRotaxane(
        axle=stk.BuildingBlock.init_from_molecule(axle),
        cycles=(
            stk.BuildingBlock.init_from_molecule(cycle1),
            stk.BuildingBlock.init_from_molecule(cycle2),
            stk.BuildingBlock.init_from_molecule(cycle3),
        ),
        repeating_unit='ACB',
        num_repeating_units=3,
    ),
)
r2 = stk.ConstructedMolecule(
    topology_graph=stk.rotaxane.NRotaxane(
        axle=stk.BuildingBlock.init_from_molecule(axle),
        cycles=(
            stk.BuildingBlock.init_from_molecule(cycle1),
            stk.BuildingBlock.init_from_molecule(cycle2),
            stk.BuildingBlock.init_from_molecule(cycle3),
        ),
        repeating_unit=(0, 2, 1),
        num_repeating_units=3,
    ),
)
Parameters:
  • axle (BuildingBlock) – The axle of the rotaxane.

  • cycles (list[BuildingBlock]) – The cycles threaded onto the axle.

  • repeating_unit (str | list[int]) –

    A string specifying the repeating unit of the cycles. For example, 'AB' or 'ABB'. The first cycle in cycles is 'A' and so on.

    The repeating unit can also be specified by the indices of cycles, for example 'ABB' can be written as [0, 1, 1].

  • num_repeating_units (int) – The number of repeating units threaded along the axle.

  • orientations (list[float] | None) –

    For each character in the repeating unit, a value between 0 and 1 (both inclusive) must be given in a tuple. It indicates the probability that each cycle will have its orientation along the axle flipped. If 0 then the cycle is guaranteed not to flip. If 1 it is guaranteed to flip. This allows the user to create head-to-head or head-to-tail chains, as well as chain with a preference for head-to-head or head-to-tail if a number between 0 and 1 is chosen. If None, then defaults to 0 in every case.

    It is also possible to supply an orientation for every cycle vertex in the final topology graph. In this case, the length of orientations must be equal to len(repeating_unit)*num_repeating_units.

  • random_seed (int | Generator | None) – The random seed to use when choosing random orientations.

  • num_processes (int) – The number of parallel processes to create during construct().

  • optimizer (Optimizer) – Used to optimize the structure of the constructed molecule.

Raises:

ValueError – If the length of orientations is not equal in length to repeating_unit or to the total number of vertices.

Methods

clone

Return a clone.

construct

Construct a ConstructedMolecule.

get_building_blocks

Yield the building blocks.

get_num_building_block

Get the number of times building_block is present.

with_building_blocks

Return a clone holding different building blocks.

clone()[source]

Return a clone.

Returns:

The clone.

Return type:

Self

construct()

Construct a ConstructedMolecule.

Returns:

The data describing the ConstructedMolecule.

Return type:

ConstructionResult

get_building_blocks()

Yield the building blocks.

Building blocks are yielded in an order based on their position in the topology graph. For two equivalent topology graphs, but with different building blocks, equivalently positioned building blocks will be yielded at the same time.

Yields:

A building block of the topology graph.

Return type:

Iterator[BuildingBlock]

get_num_building_block(building_block)

Get the number of times building_block is present.

Parameters:

building_block (BuildingBlock) – The building block whose frequency in the topology graph is desired.

Returns:

The number of times building_block is present in the topology graph.

Return type:

int

with_building_blocks(building_block_map)

Return a clone holding different building blocks.

Parameters:

building_block_map (dict[BuildingBlock, BuildingBlock]) – Maps a building block in the current topology graph to the building block which should replace it in the clone. If a building block should be not replaced in the clone, it can be omitted from the map.

Returns:

The clone.

Return type:

Self