Skip to content

Commit

Permalink
Add doctests for files in the Classes folder
Browse files Browse the repository at this point in the history
  • Loading branch information
ralf-meyer committed Apr 22, 2023
1 parent 350a722 commit b049930
Show file tree
Hide file tree
Showing 4 changed files with 134 additions and 94 deletions.
5 changes: 5 additions & 0 deletions .github/workflows/CI.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,11 @@ jobs:
run: |
pytest -v --cov=molSimplify --cov-report=xml
- name: Run doctest
# For now only testing the files in the Classes folder
run: |
pytest --doctest-modules molSimplify/Classes
- name: Upload coverage report to codecov
uses: codecov/codecov-action@v3
with:
Expand Down
130 changes: 70 additions & 60 deletions molSimplify/Classes/mol3D.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ class mol3D:
Example instantiation of an octahedral iron-ammonia complex from an XYZ file:
>>> complex_mol = mol3D()
>>> complex_mol.readfromxyz('fe_nh3_6.xyz')
>>> complex_mol.readfromxyz('fe_nh3_6.xyz') # doctest: +SKIP
"""

Expand Down Expand Up @@ -127,18 +127,7 @@ def __init__(self, name='ABC', loc='', use_atom_specific_cutoffs=False):
def __repr__(self):
return f"mol3D({self.make_formula(latex=False)})"

Returns
-------
method_string : string
String of methods available in mol3D class.
"""

method_string = "\nClass mol3D has the following methods:\n"
for method in dir(self):
if callable(getattr(self, method)):
method_string += method + '\n'
return method_string

@deprecated("Preliminary testing showed this function is unreliable at best")
def ACM(self, idx1, idx2, idx3, angle):
"""
Performs angular movement on mol3D class. A submolecule is
Expand All @@ -154,8 +143,6 @@ def ACM(self, idx1, idx2, idx3, angle):
Index of anchor atom 2.
angle : float
New bond angle in degrees.
>>> complex_mol.ACM(2, 1, 0, 180) # Make atom 2 form a 180 degree angle with atoms 1 and 0.
"""

atidxs_to_move = self.findsubMol(idx1, idx2)
Expand Down Expand Up @@ -233,7 +220,8 @@ def addAtom(self, atom: atom3D, index: Optional[int] = None, auto_populate_BO_di
auto_populate_BO_dict : bool, optional
Populate bond order dictionary with newly added atom. Default is True.
>>> C_atom = atom3D('C',[1, 1, 1])
>>> complex_mol = mol3D()
>>> C_atom = atom3D('C', [1, 1, 1])
>>> complex_mol.addAtom(C_atom) # Add carbon atom at cartesian position 1, 1, 1 to mol3D object.
"""

Expand Down Expand Up @@ -486,7 +474,13 @@ def BCM(self, idx1, idx2, d):
d : float
Bond distance in angstroms.
>>> complex_mol.BCM(1, 0, 1.5) # Set distance between atoms 0 and 1 to be 1.5 angstroms. Move atom 1.
>>> complex_mol = mol3D()
>>> complex_mol.addAtom(atom3D('H', [0, 0, 0]))
>>> complex_mol.addAtom(atom3D('H', [0, 0, 1]))
>>> complex_mol.BCM(1, 0, 0.7) # Set distance between atoms 0 and 1 to be 1.5 angstroms. Move atom 1.
>>> complex_mol.coordsvect()
array([[0. , 0. , 0. ],
[0. , 0. , 0.7]])
"""

bondv = self.getAtom(idx1).distancev(self.getAtom(idx2)) # 1 - 2
Expand Down Expand Up @@ -1626,7 +1620,7 @@ def getBondedAtoms(self, idx):
"""

if len(self.graph): # The graph exists.
if len(self.graph): # The graph exists.
nats = list(np.nonzero(np.ravel(self.graph[idx]))[0])
else:
ratom = self.getAtom(idx)
Expand Down Expand Up @@ -2540,25 +2534,33 @@ def RCAngle(self, idx1, idx2, idx3, anglei, anglef, angleint=1.0, writegeo=False
The directory to which generated reaction coordinate
geoemtries are written, if writegeo=True.
>>> complex_mol.RCAngle(2, 1, 0, 90, 180, 0.5, True, 'rc_geometries') # Generate reaction coordinate
>>> # geometries using the given structure by changing the angle between atoms 2, 1,
>>> # and 0 from 90 degrees to 180 degrees in intervals of 0.5 degrees, and write the
>>> # generated geometries to 'rc_geometries' directory.
>>> complex_mol.RCAngle(2, 1, 0, 180, 90, -0.5) # Generate reaction coordinates
>>> # with the given geometry by changing the angle between atoms 2, 1, and 0 from
>>> # 180 degrees to 90 degrees in intervals of 0.5 degrees, and the generated
>>> # geometries will not be written to a directory.
>>> complex_mol = mol3D()
>>> complex_mol.addAtom(atom3D('O', [0, 0, 0]))
>>> complex_mol.addAtom(atom3D('H', [0, 0, 1]))
>>> complex_mol.addAtom(atom3D('H', [0, 1, 0]))
Generate reaction coordinate geometries using the given structure by changing the angle between atoms 2, 1,
and 0 from 90 degrees to 160 degrees in intervals of 10 degrees
>>> complex_mol.RCAngle(2, 1, 0, 90, 160, 10)
[mol3D(O1H2), mol3D(O1H2), mol3D(O1H2), mol3D(O1H2), mol3D(O1H2), mol3D(O1H2), mol3D(O1H2), mol3D(O1H2)]
Generate reaction coordinates with the given geometry by changing the angle between atoms 2, 1, and 0 from
160 degrees to 90 degrees in intervals of 10 degrees, and the generated geometries will not be written to
a directory.
>>> complex_mol.RCAngle(2, 1, 0, 160, 90, -10)
[mol3D(O1H2), mol3D(O1H2), mol3D(O1H2), mol3D(O1H2), mol3D(O1H2), mol3D(O1H2), mol3D(O1H2), mol3D(O1H2)]
"""
if writegeo:
os.mkdir(dir_name)
temp_list = []
for ang_val in np.arange(anglei, anglef+angleint, angleint):
temp_angle = mol3D()
temp_angle.copymol3D(self)
temp_angle.ACM(idx1, idx2, idx3, ang_val)
temp_list.append(temp_angle)
temp_list = []
for ang_val in np.arange(anglei, anglef+angleint, angleint):
temp_angle = mol3D()
temp_angle.copymol3D(self)
temp_angle.ACM(idx1, idx2, idx3, ang_val)
temp_list.append(temp_angle)
if writegeo:
temp_angle.writexyz(str(dir_name)+"/rc_"+str(str("{:.4f}".format(ang_val)))+'.xyz')
return temp_list
return temp_list

def RCDistance(self, idx1, idx2, disti, distf, distint=0.05, writegeo=False, dir_name='rc_distance_geometries'):
"""
Expand All @@ -2585,26 +2587,34 @@ def RCDistance(self, idx1, idx2, disti, distf, distint=0.05, writegeo=False, dir
The directory to which generated reaction coordinate
geoemtries are written if writegeo=True.
>>> complex_mol.RCDistance(1, 0, 1.0, 3.0, 0.01, True, 'rc_geometries') # Generate reaction coordinate
>>> # geometries using the given structure by changing the distance between atoms 1 and 0
>>> # from 1.0 to 3.0 angstrom (atom 1 is moved) in intervals of 0.01 angstrom, and write
>>> # the generated geometries to 'rc_geometries' directory.
>>> complex_mol.RCDistance(1, 0, 3.0, 1.0, -0.02) # Generate reaction coordinates
>>> # geometries using the given structure by changing the distance between atoms 1 and 0
>>> # from 3.0 to 1.0 angstrom (atom 1 is moved) in intervals of 0.02 angstrom, and
>>> # the generated geometries will not be written to a directory.
>>> complex_mol = mol3D()
>>> complex_mol.addAtom(atom3D('H', [0, 0, 0]))
>>> complex_mol.addAtom(atom3D('H', [0, 0, 1]))
Generate reaction coordinate geometries using the given structure by changing the distance between atoms 1 and 0
from 1.0 to 3.0 angstrom (atom 1 is moved) in intervals of 0.5 angstrom
>>> complex_mol.RCDistance(1, 0, 1.0, 3.0, 0.5)
[mol3D(H2), mol3D(H2), mol3D(H2), mol3D(H2), mol3D(H2)]
Generate reaction coordinates
geometries using the given structure by changing the distance between atoms 1 and 0
from 3.0 to 1.0 angstrom (atom 1 is moved) in intervals of 0.2 angstrom, and
the generated geometries will not be written to a directory.
>>> complex_mol.RCDistance(1, 0, 3.0, 1.0, -0.25)
[mol3D(H2), mol3D(H2), mol3D(H2), mol3D(H2), mol3D(H2), mol3D(H2), mol3D(H2), mol3D(H2), mol3D(H2)]
"""

if writegeo:
os.mkdir(dir_name)
temp_list = []
for dist_val in np.arange(disti, distf+distint, distint):
temp_dist = mol3D()
temp_dist.copymol3D(self)
temp_dist.BCM(idx1, idx2, dist_val)
temp_list.append(temp_dist)
temp_list = []
for dist_val in np.arange(disti, distf+distint, distint):
temp_dist = mol3D()
temp_dist.copymol3D(self)
temp_dist.BCM(idx1, idx2, dist_val)
temp_list.append(temp_dist)
if writegeo:
temp_dist.writexyz(str(dir_name)+"/rc_"+str(str("{:.4f}".format(dist_val)))+'.xyz')
return temp_list
return temp_list

def returnxyz(self):
"""
Expand Down Expand Up @@ -4803,7 +4813,7 @@ def Structure_inspection(self, init_mol=None, catoms_arr=None, num_coord=5, dict
return flag_oct, flag_list, dict_oct_info, flag_oct_loose, flag_list_loose

def get_fcs(self, strict_cutoff=False, catom_list=None):
"""
"""
Get first coordination shell of a transition metal complex.
Parameters
Expand All @@ -4828,7 +4838,7 @@ def get_fcs(self, strict_cutoff=False, catom_list=None):
return fcs

def get_bo_dict_from_inds(self, inds):
"""
"""
Recreate bo_dict with correct indices
Parameters
Expand Down Expand Up @@ -4860,7 +4870,7 @@ def get_bo_dict_from_inds(self, inds):
return new_bo_dict

def create_mol_with_inds(self, inds):
"""
"""
Create molecule with indices.
Parameters
Expand Down Expand Up @@ -4889,7 +4899,7 @@ def create_mol_with_inds(self, inds):
return molnew

def make_formula(self, latex=True):
"""
"""
Get a chemical formula from the mol3D class instance.
Parameters
Expand Down Expand Up @@ -4924,7 +4934,7 @@ def make_formula(self, latex=True):
return retstr

def read_smiles(self, smiles, ff="mmff94", steps=2500):
"""
"""
Read a smiles string and convert it to a mol3D class instance.
Parameters
Expand Down Expand Up @@ -4999,7 +5009,7 @@ def get_smiles(self, canonicalize=False, use_mol2=False) -> str:
return smi

def mols_symbols(self):
"""
"""
Store symbols and their frequencies in symbols_dict attributes.
"""
self.symbols_dict = {}
Expand All @@ -5010,7 +5020,7 @@ def mols_symbols(self):
self.symbols_dict[atom.symbol()] += 1

def read_bonder_order(self, bofile):
"""
"""
Get bond order information from file.
Parameters
Expand Down Expand Up @@ -5054,7 +5064,7 @@ def read_bonder_order(self, bofile):
self.bodavrg_dict.update({ii: np.mean(devi)})

def read_charge(self, chargefile):
"""
"""
Get charge information from file.
Parameters
Expand All @@ -5075,7 +5085,7 @@ def read_charge(self, chargefile):
print(("chargefile does not exist.", chargefile))

def get_mol_graph_det(self, oct=True, useBOMat=False):
"""
"""
Get molecular graph determinant.
Parameters
Expand Down Expand Up @@ -5484,7 +5494,7 @@ def get_features(self, lac=True, force_generate=False, eq_sym=False,
return results

def getMLBondLengths(self):
"""
"""
Outputs the metal-ligand bond lengths in the complex.
Returns
Expand All @@ -5511,7 +5521,7 @@ def getMLBondLengths(self):

@deprecated('Using this function might lead to inconsistent behavior.')
def setAtoms(self, atoms):
"""
"""
Set atoms of a mol3D class to atoms.
Parameters
Expand All @@ -5523,7 +5533,7 @@ def setAtoms(self, atoms):
self.natoms = len(atoms)

def setLoc(self, loc):
"""
"""
Sets the conformation of an amino acid in the chain of a protein.
Parameters
Expand Down
6 changes: 2 additions & 4 deletions molSimplify/Classes/monomer3D.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@


class monomer3D:
"""Holds information about a monomer, used to do manipulations. Reads information from structure file (pdb) or is directly built from molsimplify.
"""Holds information about a monomer, used to do manipulations.
Reads information from structure file (pdb) or is directly built from molsimplify.
"""

Expand Down Expand Up @@ -231,9 +232,6 @@ def addAtom(self, atom, index=None):
Index of added atom. Default is None.
auto_populate_BO_dict : bool, optional
Populate bond order dictionary with newly added atom. Default is True.
>>> C_atom = atom3D('C',[1, 1, 1])
>>> complex_mol.addAtom(C_atom) # Add carbon atom at cartesian position 1, 1, 1 to mol3D object.
"""

if index is None:
Expand Down
Loading

0 comments on commit b049930

Please sign in to comment.