28
28
29
29
import tempfile as _tempfile
30
30
31
- from .. import _is_notebook
31
+ from .. import _isVerbose
32
32
from .. import IO as _IO
33
33
from .. import _Utils
34
34
from ..Units .Charge import electron_charge as _electron_charge
35
35
from .._SireWrappers import Molecule as _Molecule
36
36
37
37
38
- def formalCharge (molecule ):
38
+ def formalCharge (molecule , property_map = {} ):
39
39
"""
40
40
Compute the formal charge on a molecule. This function requires that
41
41
the molecule has explicit hydrogen atoms.
@@ -46,6 +46,11 @@ def formalCharge(molecule):
46
46
molecule : :class:`Molecule <BioSimSpace._SireWrappers.Molecule>`
47
47
A molecule object.
48
48
49
+ property_map : dict
50
+ A dictionary that maps system "properties" to their user defined
51
+ values. This allows the user to refer to properties with their
52
+ own naming scheme, e.g. { "charge" : "my-charge" }
53
+
49
54
Returns
50
55
-------
51
56
@@ -58,6 +63,9 @@ def formalCharge(molecule):
58
63
"'molecule' must be of type 'BioSimSpace._SireWrappers.Molecule'"
59
64
)
60
65
66
+ if not isinstance (property_map , dict ):
67
+ raise TypeError ("'property_map' must be of type 'dict'" )
68
+
61
69
from rdkit import Chem as _Chem
62
70
from rdkit import RDLogger as _RDLogger
63
71
@@ -71,15 +79,56 @@ def formalCharge(molecule):
71
79
# Zero the total formal charge.
72
80
formal_charge = 0
73
81
74
- # Run in the working directory.
75
- with _Utils .cd (work_dir ):
76
- # Save the molecule to a PDB file.
77
- _IO .saveMolecules ("tmp" , molecule , "PDB" )
78
-
79
- # Read the ligand PDB into an RDKit molecule.
80
- mol = _Chem .MolFromPDBFile ("tmp.pdb" )
81
-
82
- # Compute the formal charge.
83
- formal_charge = _Chem .rdmolops .GetFormalCharge (mol )
84
-
85
- return formal_charge * _electron_charge
82
+ # Get the fileformat property name.
83
+ property = property_map .get ("fileformat" , "fileformat" )
84
+
85
+ # Preferentially use the file format that the molecule was loaded from.
86
+ try :
87
+ # Get the raw list of formats.
88
+ raw_formats = molecule ._sire_object .property (property ).value ().split ("," )
89
+
90
+ # Remove all formats other than PDB and SDF.
91
+ formats = [f for f in raw_formats if f in ["PDB" , "SDF" ]]
92
+
93
+ if len (formats ) == 0 :
94
+ formats = ["PDB" , "SDF" ]
95
+ elif len (formats ) == 1 :
96
+ if formats [0 ] == "PDB" :
97
+ formats .append ("SDF" )
98
+ else :
99
+ formats .append ("PDB" )
100
+ except :
101
+ formats = ["PDB" , "SDF" ]
102
+
103
+ # List of exceptions.
104
+ exceptions = []
105
+
106
+ # Try going via each format in turn.
107
+ for format in formats :
108
+ try :
109
+ with _Utils .cd (work_dir ):
110
+ # Save the molecule in the given format.
111
+ _IO .saveMolecules ("tmp" , molecule , format )
112
+
113
+ # Load with RDKit.
114
+ if format == "SDF" :
115
+ rdmol = _Chem .MolFromMolFile ("tmp.sdf" )
116
+ else :
117
+ rdmol = _Chem .MolFromPDBFile ("tmp.pdb" )
118
+
119
+ # Compute the formal charge.
120
+ formal_charge = _Chem .rdmolops .GetFormalCharge (rdmol )
121
+
122
+ return formal_charge * _electron_charge
123
+
124
+ except Exception as e :
125
+ exceptions .append (e )
126
+
127
+ # If we got this far, then we failed to compute the formal charge.
128
+ msg = "Failed to compute the formal charge on the molecule."
129
+ if _isVerbose ():
130
+ for e in exceptions :
131
+ msg += "\n \n " + str (e )
132
+ raise RuntimeError (msg )
133
+ else :
134
+ raise RuntimeError (msg ) from None
0 commit comments