"""Classes of topologies of precursors."""
from collections import abc
from dataclasses import dataclass
import numpy as np
import stk
from .beads import CgBead, periodic_table, string_to_atom_number
[docs]
@dataclass
class LinearPrecursor:
composition: abc.Sequence[int]
present_beads: abc.Sequence[CgBead]
binder_beads: abc.Sequence[CgBead]
placer_beads: abc.Sequence[CgBead]
def __post_init__(self) -> None:
atoms = [
stk.Atom(
i, string_to_atom_number(self.present_beads[i].element_string)
)
for i in range(len(self.present_beads))
]
coordinates = [np.array([0, 0, 0])]
bonds = []
for i in range(self.composition[0]):
coordinates.append(np.array([1 * (i + 1), 0, 0]))
bonds.append(stk.Bond(atoms[i], atoms[i + 1], order=1))
model = stk.BuildingBlock.init(
atoms=tuple(atoms),
bonds=tuple(bonds),
position_matrix=np.array(coordinates),
)
if self.composition[0] == 0:
new_fgs = (
stk.GenericFunctionalGroup(
atoms=(atoms[0],),
bonders=(atoms[0],),
deleters=(),
placers=(atoms[0],),
),
stk.GenericFunctionalGroup(
atoms=(atoms[0],),
bonders=(atoms[0],),
deleters=(),
placers=(atoms[0],),
),
)
elif self.composition[0] == 1:
new_fgs = (
stk.GenericFunctionalGroup(
atoms=(atoms[0], atoms[1]),
bonders=(atoms[0],),
deleters=(),
placers=(atoms[0], atoms[1]),
),
stk.GenericFunctionalGroup(
atoms=(atoms[0], atoms[1]),
bonders=(atoms[1],),
deleters=(),
placers=(atoms[0], atoms[1]),
),
)
else:
new_fgs = ( # type: ignore[assignment]
stk.SmartsFunctionalGroupFactory(
smarts=(
f"[{self.placer_beads[0].element_string}]"
f"[{self.binder_beads[0].element_string}]"
),
bonders=(1,),
deleters=(),
placers=(0, 1),
),
)
self.building_block = stk.BuildingBlock.init_from_molecule(
molecule=model,
functional_groups=new_fgs,
)
[docs]
def get_building_block(self) -> stk.BuildingBlock:
return self.building_block
[docs]
@dataclass
class TrianglePrecursor:
present_beads: abc.Sequence[CgBead]
binder_beads: abc.Sequence[CgBead]
placer_beads: abc.Sequence[CgBead]
def __post_init__(self) -> None:
_x = 2 * np.sqrt(3) / 4
_y = 2
coordinates = np.array(
(
np.array([0, _x, 0]),
np.array([_y / 2, -_x, 0]),
np.array([-_y / 2, -_x, 0]),
)
)
atoms = [
stk.Atom(
i, string_to_atom_number(self.present_beads[i].element_string)
)
for i in range(len(self.present_beads))
]
bonds = [
stk.Bond(atoms[0], atoms[1], order=1),
stk.Bond(atoms[1], atoms[2], order=1),
stk.Bond(atoms[2], atoms[0], order=1),
]
model = stk.BuildingBlock.init(
atoms=tuple(atoms),
bonds=tuple(bonds),
position_matrix=coordinates,
)
new_fgs = (
stk.SmartsFunctionalGroupFactory(
smarts=(
f"[{self.placer_beads[0].element_string}]"
f"[{self.binder_beads[0].element_string}]"
f"[{self.placer_beads[1].element_string}]"
),
bonders=(1,),
deleters=(),
placers=(0, 1, 2),
),
)
self.building_block = stk.BuildingBlock.init_from_molecule(
molecule=model,
functional_groups=new_fgs,
)
[docs]
def get_building_block(self) -> stk.BuildingBlock:
return self.building_block
[docs]
@dataclass
class SquarePrecursor:
present_beads: abc.Sequence[CgBead]
binder_beads: abc.Sequence[CgBead]
placer_beads: abc.Sequence[CgBead]
def __post_init__(self) -> None:
coordinates = np.array(
(
np.array([1, 1, 0]),
np.array([1, -1, 0]),
np.array([-1, -1, 0]),
np.array([-1, 1, 0]),
)
)
atoms = [
stk.Atom(
i, string_to_atom_number(self.present_beads[i].element_string)
)
for i in range(len(self.present_beads))
]
bonds = [
stk.Bond(atoms[0], atoms[1], order=1),
stk.Bond(atoms[1], atoms[2], order=1),
stk.Bond(atoms[2], atoms[3], order=1),
stk.Bond(atoms[3], atoms[0], order=1),
]
model = stk.BuildingBlock.init(
atoms=tuple(atoms),
bonds=tuple(bonds),
position_matrix=coordinates,
)
new_fgs = (
stk.SmartsFunctionalGroupFactory(
smarts=(
f"[{self.placer_beads[0].element_string}]"
f"[{self.binder_beads[0].element_string}]"
f"[{self.placer_beads[1].element_string}]"
),
bonders=(1,),
deleters=(),
placers=(0, 1, 2),
),
)
self.building_block = stk.BuildingBlock.init_from_molecule(
molecule=model,
functional_groups=new_fgs,
)
[docs]
def get_building_block(self) -> stk.BuildingBlock:
return self.building_block
[docs]
class Precursor:
"""Define model precursors."""
def __init__(self) -> None:
"""Initialize a precursor."""
self._bead_set: dict[str, CgBead]
self._building_block: stk.BuildingBlock
self._name: str
raise NotImplementedError
[docs]
def get_bead_set(self) -> dict[str, CgBead]:
"""Get beads in precursor."""
return self._bead_set
[docs]
def get_building_block(self) -> stk.BuildingBlock:
"""Get building block defined by precursor."""
return self._building_block
[docs]
def get_name(self) -> str:
"""Get name of precursor."""
return self._name
[docs]
class Single(Precursor):
"""A single bead Precursor."""
def __init__(self, bead: CgBead) -> None:
"""Initialize a precursor."""
self._bead = bead
self._name = f"S1{bead.bead_type}"
self._bead_set = {bead.bead_type: bead}
self._building_block = stk.BuildingBlock(
smiles=f"[{bead.element_string}]",
functional_groups=(
stk.SingleAtom(
stk.Atom(
0,
charge=0,
atomic_number=periodic_table()[bead.element_string],
)
),
),
position_matrix=np.array([[0, 0, 0]]),
)
[docs]
class FourC0Arm(Precursor):
"""A `FourC0Arm` Precursor."""
def __init__(self, bead: CgBead) -> None:
"""Initialize a precursor."""
self._bead = bead
self._name = f"4C0{bead.bead_type}"
self._bead_set = {bead.bead_type: bead}
four_c_bb = stk.BuildingBlock(
smiles=f"[Br][{bead.element_string}]([Br])([Br])[Br]",
position_matrix=np.array(
[
[-2, 0, -1],
[0, 0, 1],
[0, -2, -1],
[2, 0, 1],
[0, 2, 1],
]
),
)
new_fgs = stk.SmartsFunctionalGroupFactory(
smarts=(f"[{bead.element_string}][Br]"),
bonders=(0,),
deleters=(1,),
placers=(0, 1),
)
self._building_block = stk.BuildingBlock.init_from_molecule(
molecule=four_c_bb,
functional_groups=(new_fgs,),
)
[docs]
class FourC1Arm(Precursor):
"""A `FourC1Arm` Precursor."""
def __init__(self, bead: CgBead, abead1: CgBead) -> None:
"""Initialize a precursor."""
self._bead = bead
self._abead1 = abead1
self._name = f"4C1{bead.bead_type}{abead1.bead_type}"
self._bead_set = {
bead.bead_type: bead,
abead1.bead_type: abead1,
}
factories = (stk.BromoFactory(placers=(0, 1)),)
four_c_bb = stk.BuildingBlock(
smiles=f"[Br][{bead.element_string}]([Br])([Br])[Br]",
functional_groups=factories,
position_matrix=np.array(
[
[-2, 0, -1],
[0, 0, 1],
[0, -2, -1],
[2, 0, -1],
[0, 2, -1],
]
),
)
const_mol = stk.ConstructedMolecule(
topology_graph=stk.small.NCore(
core_building_block=four_c_bb,
arm_building_blocks=stk.BuildingBlock(
smiles=f"[{abead1.element_string}][Br]",
functional_groups=factories,
position_matrix=np.array([[-3, 0, 0], [0, 0, 0]]),
),
repeating_unit="AAAA",
),
)
new_fgs = (
stk.SmartsFunctionalGroupFactory(
smarts=(f"[{bead.element_string}][{abead1.element_string}]"),
bonders=(1,),
deleters=(),
),
)
self._building_block = stk.BuildingBlock.init_from_molecule(
molecule=const_mol,
functional_groups=new_fgs,
)
[docs]
class ThreeC0Arm(Precursor):
"""A `ThreeC0Arm` Precursor."""
def __init__(
self,
bead: CgBead,
deleter_bead: CgBead | None = None,
) -> None:
"""Initialize a precursor."""
self._bead = bead
deleter_string = (
deleter_bead.element_string if deleter_bead is not None else "Br"
)
self._name = f"3C0{bead.bead_type}"
self._bead_set = {
bead.bead_type: bead,
}
if deleter_bead is not None:
self._bead_set[deleter_bead.bead_type] = deleter_bead
three_c_bb = stk.BuildingBlock(
smiles=(
f"[{deleter_string}][{bead.element_string}]"
f"([{deleter_string}])[{deleter_string}]"
),
position_matrix=np.array(
[
[-2, 0, 0],
[0, 0, 1],
[-1.2, 1, 0],
[-1.2, -1, 0],
]
),
)
new_fgs = stk.SmartsFunctionalGroupFactory(
smarts=f"[{bead.element_string}][{deleter_string}]",
bonders=(0,),
deleters=(1,),
placers=(0, 1),
)
self._building_block = stk.BuildingBlock.init_from_molecule(
molecule=three_c_bb,
functional_groups=(new_fgs,),
)
[docs]
class ThreeC1Arm(Precursor):
"""A `ThreeC1Arm` Precursor."""
def __init__(self, bead: CgBead, abead1: CgBead) -> None:
"""Initialize a precursor."""
self._bead = bead
self._abead1 = abead1
self._name = f"3C1{bead.bead_type}{abead1.bead_type}"
self._bead_set = {
bead.bead_type: bead,
abead1.bead_type: abead1,
}
factories = (stk.BromoFactory(placers=(0, 1)),)
three_c_bb = stk.BuildingBlock(
smiles=f"[Br][{bead.element_string}]([Br])[Br]",
functional_groups=factories,
position_matrix=np.array(
[
[-2, 0, 0],
[0, 0, 0.5],
[-1.2, 1, 0],
[-1.2, -1, 0],
]
),
)
const_mol = stk.ConstructedMolecule(
topology_graph=stk.small.NCore(
core_building_block=three_c_bb,
arm_building_blocks=stk.BuildingBlock(
smiles=f"[{abead1.element_string}][Br]",
functional_groups=factories,
position_matrix=np.array([[-3, 0, 0], [0, 0, 0]]),
),
repeating_unit="AAA",
),
)
new_fgs = stk.SmartsFunctionalGroupFactory(
smarts=f"[{bead.element_string}][{abead1.element_string}]",
bonders=(1,),
deleters=(),
)
self._building_block = stk.BuildingBlock.init_from_molecule(
molecule=const_mol,
functional_groups=(new_fgs,),
)
[docs]
class ThreeC2Arm(Precursor):
"""A `ThreeC2Arm` Precursor."""
def __init__(self, bead: CgBead, abead1: CgBead, abead2: CgBead) -> None:
"""Initialize a precursor."""
self._bead = bead
self._abead1 = abead1
self._abead2 = abead2
self._name = f"3C2{bead.bead_type}{abead1.bead_type}{abead2.bead_type}"
self._bead_set = {
bead.bead_type: bead,
abead1.bead_type: abead1,
abead2.bead_type: abead2,
}
factories = (stk.BromoFactory(placers=(0, 1)),)
three_c_bb = stk.BuildingBlock(
smiles=f"[Br][{bead.element_string}]([Br])[Br]",
functional_groups=factories,
position_matrix=np.array(
[
[-2, 0, 0],
[0, 0, 0],
[-1.2, 1, 0],
[-1.2, -1, 0],
]
),
)
new_fgs = stk.SmartsFunctionalGroupFactory(
smarts=f"[{abead1.element_string}][{abead2.element_string}]",
bonders=(0,),
deleters=(),
)
const_mol = stk.ConstructedMolecule(
topology_graph=stk.small.NCore(
core_building_block=three_c_bb,
arm_building_blocks=stk.BuildingBlock(
smiles=f"[{abead1.element_string}][{abead2.element_string}]",
functional_groups=new_fgs,
position_matrix=np.array([[-3, 0, 0], [0, 0, 0]]),
),
repeating_unit="AAA",
),
)
new_fgs = stk.SmartsFunctionalGroupFactory(
smarts=f"[{abead1.element_string}][{abead2.element_string}]",
bonders=(1,),
deleters=(),
)
self._building_block = stk.BuildingBlock.init_from_molecule(
molecule=const_mol,
functional_groups=(new_fgs,),
)
[docs]
class TwoC0Arm(Precursor):
"""A `TwoC0Arm` Precursor."""
def __init__(self, bead: CgBead) -> None:
"""Initialize a precursor."""
self._bead = bead
self._name = f"2C0{bead.bead_type}"
self._bead_set = {bead.bead_type: bead}
core_c_bb = stk.BuildingBlock(
smiles=f"[Br][{bead.element_string}][Br]",
position_matrix=np.array([[-3, 0, 0], [0, 0, 0], [3, 0, 0]]),
)
new_fgs = stk.SmartsFunctionalGroupFactory(
smarts=f"[Br][{bead.element_string}]",
bonders=(1,),
deleters=(0,),
placers=(0, 1),
)
self._building_block = stk.BuildingBlock.init_from_molecule(
molecule=core_c_bb,
functional_groups=(new_fgs,),
)
[docs]
class TwoC1Arm(Precursor):
"""A `TwoC1Arm` Precursor."""
def __init__(self, bead: CgBead, abead1: CgBead) -> None:
"""Initialize a precursor."""
self._bead = bead
self._abead1 = abead1
self._name = f"2C1{bead.bead_type}{abead1.bead_type}"
self._bead_set = {
bead.bead_type: bead,
abead1.bead_type: abead1,
}
new_fgs = stk.SmartsFunctionalGroupFactory(
smarts=f"[{abead1.element_string}][{bead.element_string}]",
bonders=(0,),
deleters=(),
placers=(0, 1),
)
self._building_block = stk.BuildingBlock(
smiles=f"[{abead1.element_string}][{bead.element_string}][{abead1.element_string}]",
functional_groups=new_fgs,
position_matrix=np.array([[-3, 0, 0], [0, 0, 0], [3, 0, 0]]),
)
[docs]
class TwoC2Arm(Precursor):
"""A `TwoC2Arm` Precursor."""
def __init__(self, bead: CgBead, abead1: CgBead, abead2: CgBead) -> None:
"""Initialize a precursor."""
self._bead = bead
self._abead1 = abead1
self._abead2 = abead2
self._name = f"2C2{bead.bead_type}{abead1.bead_type}{abead2.bead_type}"
self._bead_set = {
bead.bead_type: bead,
abead1.bead_type: abead1,
abead2.bead_type: abead2,
}
new_fgs = stk.SmartsFunctionalGroupFactory(
smarts=f"[{abead2.element_string}X1][{abead1.element_string}]",
bonders=(0,),
deleters=(),
placers=(0, 1),
)
self._building_block = stk.BuildingBlock(
smiles=(
f"[{abead2.element_string}][{abead1.element_string}]"
f"[{bead.element_string}][{abead1.element_string}]"
f"[{abead2.element_string}]"
),
functional_groups=new_fgs,
position_matrix=np.array(
[
[-8, 0, 0],
[-3, 0, 0],
[0, 0, 0],
[3, 0, 0],
[8, 0, 0],
]
),
)
[docs]
class TwoC3Arm(Precursor):
"""A `TwoC3Arm` Precursor."""
def __init__(
self,
bead: CgBead,
abead1: CgBead,
abead2: CgBead,
abead3: CgBead,
) -> None:
"""Initialize a precursor."""
self._bead = bead
self._abead1 = abead1
self._abead2 = abead2
self._abead3 = abead3
self._name = (
f"2C3{bead.bead_type}{abead1.bead_type}"
f"{abead2.bead_type}{abead3.bead_type}"
)
self._bead_set = {
bead.bead_type: bead,
abead1.bead_type: abead1,
abead2.bead_type: abead2,
abead3.bead_type: abead3,
}
new_fgs = stk.SmartsFunctionalGroupFactory(
smarts=f"[{abead3.element_string}X1][{abead2.element_string}]",
bonders=(0,),
deleters=(),
placers=(0, 1),
)
self._building_block = stk.BuildingBlock(
smiles=(
f"[{abead3.element_string}]"
f"[{abead2.element_string}][{abead1.element_string}]"
f"[{bead.element_string}][{abead1.element_string}]"
f"[{abead2.element_string}][{abead3.element_string}]"
),
functional_groups=new_fgs,
position_matrix=np.array(
[
[-12, 0, 0],
[-8, 0, 0],
[-3, 0, 0],
[0, 0, 0],
[3, 0, 0],
[8, 0, 0],
[12, 0, 0],
]
),
)
[docs]
class SixBead(Precursor):
"""A Precursor."""
def __init__(self, bead: CgBead, abead1: CgBead, abead2: CgBead) -> None:
"""Initialize a precursor."""
self._bead = bead
self._abead1 = abead1
self._abead2 = abead2
self._name = f"6C2{bead.bead_type}{abead1.bead_type}{abead2.bead_type}"
self._bead_set = {
bead.bead_type: bead,
abead1.bead_type: abead1,
abead2.bead_type: abead2,
}
new_fgs = stk.SmartsFunctionalGroupFactory(
smarts=f"[{abead2.element_string}X1][{abead1.element_string}]",
bonders=(0,),
deleters=(),
placers=(0, 1),
)
self._building_block = stk.BuildingBlock(
smiles=(
f"[{abead2.element_string}][{abead1.element_string}]"
f"[{bead.element_string}][{bead.element_string}]"
f"[{abead1.element_string}][{abead2.element_string}]"
),
functional_groups=new_fgs,
position_matrix=np.array(
[
[-6, 3, 0.2],
[-4, 2, 0],
[-2, 0.1, 0],
[2, 0, 0],
[4, 2, 0],
[6, 3, 0.2],
]
),
)
[docs]
class StericSixBead(Precursor):
"""A Precursor."""
def __init__(
self,
bead: CgBead,
abead1: CgBead,
abead2: CgBead,
ibead: CgBead,
) -> None:
"""Initialize a precursor."""
self._bead = bead
self._abead1 = abead1
self._abead2 = abead2
self._ibead = ibead
self._name = (
f"6S2{bead.bead_type}{abead1.bead_type}{abead2.bead_type}"
f"{ibead.bead_type}"
)
self._bead_set = {
bead.bead_type: bead,
abead1.bead_type: abead1,
abead2.bead_type: abead2,
ibead.bead_type: ibead,
}
new_fgs = stk.SmartsFunctionalGroupFactory(
smarts=f"[{abead2.element_string}X1][{abead1.element_string}]",
bonders=(0,),
deleters=(),
placers=(0, 1),
)
self._building_block = stk.BuildingBlock(
smiles=(
f"[{abead2.element_string}][{abead1.element_string}]"
f"[{bead.element_string}][{ibead.element_string}]"
f"[{bead.element_string}]"
f"[{abead1.element_string}][{abead2.element_string}]"
),
functional_groups=new_fgs,
position_matrix=np.array(
[
[-6, 3, 0.2],
[-4, 2, 0],
[-2, 0.1, 0],
[0, 0.1, 0],
[2, 0, 0],
[4, 2, 0],
[6, 3, 0.2],
]
),
)
[docs]
class StericSevenBead(Precursor):
"""A Precursor."""
def __init__(
self,
bead: CgBead,
abead1: CgBead,
abead2: CgBead,
ibead: CgBead,
sbead: CgBead,
) -> None:
"""Initialize a precursor."""
self._bead = bead
self._abead1 = abead1
self._abead2 = abead2
self._ibead = ibead
self._sbead = sbead
self._name = (
f"7S2{bead.bead_type}{abead1.bead_type}{abead2.bead_type}"
f"{ibead.bead_type}{sbead.bead_type}"
)
self._bead_set = {
bead.bead_type: bead,
abead1.bead_type: abead1,
abead2.bead_type: abead2,
sbead.bead_type: sbead,
ibead.bead_type: ibead,
}
new_fgs = stk.SmartsFunctionalGroupFactory(
smarts=f"[{abead2.element_string}X1][{abead1.element_string}]",
bonders=(0,),
deleters=(),
placers=(0, 1),
)
self._building_block = stk.BuildingBlock(
smiles=(
f"[{abead2.element_string}][{abead1.element_string}]"
f"[{bead.element_string}][{ibead.element_string}]"
f"([{sbead.element_string}])[{bead.element_string}]"
f"[{abead1.element_string}][{abead2.element_string}]"
),
functional_groups=new_fgs,
position_matrix=np.array(
[
[-6, 3, 0.2],
[-4, 2, 0],
[-2, 0.1, 0],
[0, 0.1, 0],
[0, 1, 0],
[2, 0, 0],
[4, 2, 0],
[6, 3, 0.2],
]
),
)
[docs]
class StericTwoC1Arm(Precursor):
"""A `TwoC1Arm` Precursor with a steric bead."""
def __init__(
self,
bead: CgBead,
abead1: CgBead,
steric_bead: CgBead,
) -> None:
"""Initialize a precursor."""
self._bead = bead
self._abead1 = abead1
self._name = (
f"s2C1{bead.bead_type}{abead1.bead_type}{steric_bead.bead_type}"
)
self._bead_set = {
bead.bead_type: bead,
abead1.bead_type: abead1,
steric_bead.bead_type: steric_bead,
}
new_fgs = stk.SmartsFunctionalGroupFactory(
smarts=f"[{abead1.element_string}][{bead.element_string}]",
bonders=(0,),
deleters=(),
placers=(0, 1),
)
self._building_block = stk.BuildingBlock(
smiles=f"[{abead1.element_string}][{bead.element_string}]"
f"([{steric_bead.element_string}])[{abead1.element_string}]",
functional_groups=new_fgs,
position_matrix=np.array(
[[-3, 0, 0], [0, 0, 0], [0, 1, 0], [3, 0, 0]]
),
)