Source code for polytop.Junction

from __future__ import annotations
from typing import List

from .Atoms import Atom
from .Bonds import Bond

[docs] class Junction: """ Junctions are the polymerization sites of a monomer topology. They are defined by a name and a list of Bonds. The name should be unique to the Junction such that it can be unambigously identified by its name, thus ensuring that polymers can be built with consistent, desired conformations. :param monomer_atom: the Atom which will remain with this Monomer after polymerisation, and will obtain a new bond. :type monomer_atom: Atom :param residue_atom: the Atom which will be lost during polymerisation, analogous to the leaving atom in a chemical reaction. :type residue_atom: Atom :param name: the unique name of the Junction type, defaults to None. :type name: str, optional :raises ValueError: if a Junction cannot be determined from the two provided atoms (i.e. if they are not bonded). """ #TODO: make name enforcably not optional def __init__(self, monomer_atom: Atom, residue_atom: Atom, name: str = None): """ Junctions are the polymerization sites of a monomer topology. They are defined by a name and a list of Bonds. The name should be unique to the Junction such that it can be unambigously identified by its name, thus ensuring that polymers can be built with consistent, desired conformations. :param monomer_atom: the Atom which will remain with this Monomer after polymerisation, and will obtain a new bond. :type monomer_atom: Atom :param residue_atom: the Atom which will be lost during polymerisation, analogous to the leaving atom in a chemical reaction. :type residue_atom: Atom :param name: the unique name of the Junction type, defaults to None. :type name: str, optional :raises ValueError: if a Junction cannot be determined from the two provided atoms (i.e. if they are not bonded). """ if name is None: name = f"{monomer_atom.atom_name}-{residue_atom.atom_name}" self.name = name self.monomer_atom = monomer_atom self.residue_atom = residue_atom if not residue_atom in monomer_atom.bond_neighbours(): raise ValueError("Junction location cannot be found")
[docs] def named(self, newname: str) -> "Junction": """ Use to name or rename a Junction after it has been created. :param newname: the desired, unique name that will be used to identify this Junction. :type newname: str :return: the Junction object with a name :rtype: Junction Depreciation warning: * This function will be depreciated shortly in favour of enforced setting the name attribute of a Junction when it is created. Instead of: junction = Junction(atomA, atomB).named("name") Use: junction = Junction(atomA, atomB, name="name") """ self.name = newname return self
[docs] def to_dict(self) -> dict: """ Convert this Junction to a dictionary representation. The structure of the dictionary is as below: {"name": self.name, "monomer_atom": self.monomer_atom.atom_name, "residue_atom": self.residue_atom.atom_name} :return: a dictionary containing the names of its Atoms and the unique name of this Junction. :rtype: dict """ return { "name": self.name, "monomer_atom": self.monomer_atom.atom_name, "residue_atom": self.residue_atom.atom_name }
[docs] @classmethod def from_dict(cls, data: dict, atoms: List[Atom]): """ Create a new Junction from a dictionary, such as that created with Junction.to_dict(). The structure of the dictionary is as below: {"name": self.name, "monomer_atom": self.monomer_atom.atom_name, "residue_atom": self.residue_atom.atom_name} :param data: dictionary containing data to make a Junction, generate with 'to_dict()'. :type data: dict :param atoms: list of Atoms. The list may contain more than 2 atoms, as long as the two atoms specified in the data dict are present. :type atoms: List[Atom] :return: a new Junction :rtype: Junction """ name = data["name"] monomer_atom_name = data["monomer_atom"] monomer_atom = next(atom for atom in atoms if atom.atom_name == monomer_atom_name) residue_atom_name = data["residue_atom"] residue_atom = next(atom for atom in atoms if atom.atom_name == residue_atom_name) return cls(monomer_atom,residue_atom,name)
[docs] @classmethod def from_topology(cls, topology: "Topology", monomer_atom_name: str, residue_atom_name: str, residue_id: int = None, name: str = None) -> "Junction": """ Create a new Junction from a monomer or polymer Topology, and the names and shared residue id of the two Atoms used to form the Junction. :param topology: a polymer or monomer Topology. Obtain from the '.topology' attribute of either a Monomer or Polymer. :type topology: Topology :param monomer_atom_name: the name of the Atom which will remain with this Topology after polymerisation, and will obtain a new bond. :type monomer_atom_name: str :param residue_atom_name: the name of the Atom which will be lost during polymerisation, analogous to the leaving atom in a chemical reaction. :type residue_atom_name: str :param residue_id: the id number of the residue both atoms belong to, defaults to None :type residue_id: int, optional :param name: the unique name used to identify the new Junction, defaults to None :type name: str, optional :return: a new Junction :rtype: Junction """ monomer_atom = topology.get_atom(monomer_atom_name, residue_id) residue_atom = topology.get_atom(residue_atom_name, residue_id) return cls(monomer_atom, residue_atom, name)
def __repr__(self) -> str: return f"(\"{self.name}\":{self.monomer_atom.atom_name}-{self.residue_atom.atom_name})"
[docs] class Junctions(list): """ Class used to group and list Junctions of a Monomer or Polymer for RDKit visualisation. Used by the Visualize Class. """
[docs] def add(self, junction: Junction): """ Add a new Junction to the Junction list. :param junction: a Junction to add to the Junction list. :type junction: Junction """ self.append(junction)
[docs] def get_junctions(self) -> "Junctions": """ Getter method to access the list of Junctions. :return: the list of Junction objects (i.e. a 'Junctions' object). :rtype: Junctions """ return self
[docs] def remove(self, junction: Junction): """ Remove a Junction from the list of Junctions. :param junction: the Junction object to be removed from the Junctions. :type junction: Junction """ super().remove(junction)
[docs] def named(self, name: str) -> list[Junction]: """ Returns a list of Junctions with the name provided. :param name: the name of a Junction/s to retrieve. :type name: str :return: list[Junction] :rtype: list """ return [junction for junction in self if junction.name == name]
[docs] def to_dict(self) -> list[dict]: """ Return a list containing the dictionary representations of all of the Junctions in the Junctions list. The structure of each dictionary within the list is as below: {"name": self.name, "monomer_atom": self.monomer_atom.atom_name, "residue_atom": self.residue_atom.atom_name} :return: a list of Junction dictionary representations. :rtype: list[dict] """ return [junction.to_dict() for junction in self]
[docs] @classmethod def from_dict(cls, data: list, atoms: List[Atom]) -> "Junctions": """ Create a new list of Junctions from a list of Junction dictionary representations, such as that created with Junctions.to_dict(). The structure of each dictionary within the list is as below: {"name": self.name, "monomer_atom": self.monomer_atom.atom_name, "residue_atom": self.residue_atom.atom_name} :param data: list of dictionaries containing data to make Junctions, generate with 'to_dict()'. :type data: list :param atoms: list of Atoms. The list may contain more than 2 atoms, as long as the two atoms specified in the data dict are present. :type atoms: List[Atom] :return: a new Junctions (i.e. list of Junction objects) :rtype: Junctions """ junctions = cls() for junction_dict in data: junction = Junction.from_dict(junction_dict, atoms) junctions.add(junction) return junctions
def __repr__(self) -> str: return f"({len(self)}) {','.join(j.__repr__() for j in self)}"