In wc_rules
, we are essentially constructing graph representations of chemical entities. The basic building blocks of the graph are
To build this graph, one needs to know about :
Objects such as molecules, sites and interactions are derived from generic base classes provided in wc_rules
. To create various types of these objects, one can simply subclass them as often as needed.
Below, we create the type hierarchy
Molecule -> A -> A1
where A
is a subclass of molecule and A1
is a subclass of A
In [1]:
from wc_rules.chem2 import Molecule,Site
class A(Molecule):
pass
class A1(A):
pass
Instances are created by calling the constructor of the class. These constitute the nodes of the graph.
In [2]:
a1_001 = A1()
a1_001
Out[2]:
Instances typically have scalar attributes that can be set during construction. For example, all instances have an id
attribute.
In [3]:
a1_001 = A1(id='instance_001_of_A1')
a1_001.id
Out[3]:
Instances can be type-checked against any parent class.
In [4]:
isinstance(a1_001,A1) and isinstance(a1_001,A) and isinstance(a1_001,Molecule)
Out[4]:
Instances have relations to each other, which constitute the edges of the graph. Relations are managed using pairs of attributes on each of the respective classes. For example, Molecule
has a sites
attribute that holds a list of site instances. Site
has a molecule
attribute that holds a single instance of a molecule.
In [5]:
m,s = Molecule(), Site()
m.sites, s.molecule
Out[5]:
In [6]:
m.sites.append(s)
m.sites
Out[6]:
In [7]:
s.molecule
Out[7]:
The convention for attribute name is typically to use a singular name such as molecule
if it refers to a single instance or a plural name such as sites
if it refers to a list of instances.
wc_rules
provides setters, getters and unsetters for various instance attributes. For example, for the id
attribute, we have get_id()
and set_id(id)
.
In [8]:
m = Molecule()
m.set_id('m_001')
m.get_id()
Out[8]:
Typically, the following naming conventions are followed for getters, setters and unsetters:
Attribute type | Getter | Setter | Unsetter |
---|---|---|---|
Scalar | get_* |
set_* |
|
Object reference | get_* |
set_* |
unset_* |
List of object references | get_* |
add_* |
remove_* |
Setters and unsetters always "return self", so they can be chained indefinitely. For example,
In [9]:
m = Molecule().set_id('m_001').add_sites( Site(), Site() )
m.sites
Out[9]:
Additional points to remember about instance attribute methods:
Molecule.add_sites()
and Site.set_molecule()
will have the same effect of establishing relations between molecules and sites.Class attributes dictate behavior of a class and can be modified during subclassing. For example, the Site
method has the following class attributes:
allowed_to_bind
, a Boolean that indicates whether a bond is allowed on that site type,allowed_molecule_types
, a tuple of Molecule
classes that are allowed to be related to that site. Below, we
Molecule
subclasses A and B, Site
subclasses X1, X2, Y and Z,
In [10]:
class A(Molecule):pass
class B(Molecule):pass
class X1(Site):
allowed_site_types = (A,)
class X2(Site):
allowed_site_types = (A,)
class Y(Site):
allowed_site_types = (B,)
class Z(Site):
allowed_site_types = (B,)
allowed_to_bind = False