mirror of
https://github.com/openbabel/openbabel.git
synced 2025-02-25 18:55:23 -06:00
* fingerprint.cpp/.h: Changed the FindFingerprint method to
accept const string& instead of string&. This is necessary for access to this function from Python. * scripts/python/pybel.py, testpybel.py, pybelapi.html: Added a method to Molecule for calculating a molecular fingerprint, handled by a new Fingerprint class.
This commit is contained in:
10
ChangeLog
10
ChangeLog
@@ -1,3 +1,13 @@
|
||||
2006-12-13 Noel O'Boyle <baoilleach@gmail.com>
|
||||
|
||||
* fingerprint.cpp/.h: Changed the FindFingerprint method to accept
|
||||
const string& instead of string&. This is necessary for access to this
|
||||
function from Python.
|
||||
|
||||
* scripts/python/pybel.py, testpybel.py, pybelapi.html: Added a method
|
||||
to Molecule for calculating a molecular fingerprint, handled by a new
|
||||
Fingerprint class.
|
||||
|
||||
2006-12-15 Geoffrey Hutchison <babel@geoffhutchison.net>
|
||||
|
||||
* configure.in, configure, Doxyfile: Bump to 2.1.0b4 for upcoming snapshot.
|
||||
|
||||
@@ -58,7 +58,7 @@ public:
|
||||
static bool GetNextFPrt(std::string& id, OBFingerprint*& pFPrt);
|
||||
|
||||
/// \return a pointer to a fingerprint (the default if ID is empty), or NULL if not available
|
||||
static OBFingerprint* FindFingerprint(std::string& ID);
|
||||
static OBFingerprint* FindFingerprint(const std::string& ID);
|
||||
|
||||
/// \return the Tanimoto coefficient between two vectors (vector<unsigned int>& SeekPositions)
|
||||
static double Tanimoto(const std::vector<unsigned int>& vec1, const std::vector<unsigned int>& vec2);
|
||||
|
||||
@@ -120,7 +120,7 @@ class Molecule(object):
|
||||
(refer to the Open Babel library documentation for more info).
|
||||
|
||||
Methods:
|
||||
write()
|
||||
write(), calcfp()
|
||||
|
||||
The original Open Babel molecule can be accessed using the attribute:
|
||||
OBMol
|
||||
@@ -175,6 +175,23 @@ class Molecule(object):
|
||||
for atom in self.atoms:
|
||||
yield atom
|
||||
|
||||
def calcfp(self, fptype=""):
|
||||
"""Calculate a molecular fingerprint.
|
||||
|
||||
Optional parameters:
|
||||
fptype -- the name of the Open Babel fingerprint type.
|
||||
|
||||
If fptype is not specified, the default Open Babel fingerprint
|
||||
type is used. See the Open Babel library documentation for more
|
||||
details.
|
||||
"""
|
||||
fp = ob.vectorUnsignedInt()
|
||||
fingerprinter = ob.OBFingerprint.FindFingerprint(fptype)
|
||||
if fingerprinter is None:
|
||||
raise ValueError, "%s is not a recognised Open Babel Fingerprint type" % fptype
|
||||
fingerprinter.GetFingerprint(self.OBMol, fp)
|
||||
return Fingerprint(fp)
|
||||
|
||||
def write(self, format="SMI", filename=None, overwrite=False):
|
||||
"""Write the molecule to a file or return a string.
|
||||
|
||||
@@ -272,6 +289,54 @@ class Atom(object):
|
||||
"""
|
||||
return "Atom: %d %s" % (self.atomicnum, self.coords.__str__())
|
||||
|
||||
def findbits(fp, bitsperint):
|
||||
"""Find which bits are set in a list/vector.
|
||||
|
||||
This function is used by the Fingerprint class.
|
||||
|
||||
>>> findbits([13, 71], 8)
|
||||
[1, 3, 4, 9, 10, 11, 15]
|
||||
"""
|
||||
ans = []
|
||||
start = 1
|
||||
for x in fp:
|
||||
i = start
|
||||
while x > 0:
|
||||
if x % 2:
|
||||
ans.append(i)
|
||||
x >>= 1
|
||||
i += 1
|
||||
start += bitsperint
|
||||
return ans
|
||||
|
||||
class Fingerprint(object):
|
||||
"""A Molecular Fingerprint.
|
||||
|
||||
Required parameters:
|
||||
obFingerprint -- a vector calculated by OBFingerprint.FindFingerprint()
|
||||
|
||||
Attributes:
|
||||
fp -- the original obFingerprint
|
||||
bits -- a list of bits set in the Fingerprint
|
||||
|
||||
Methods:
|
||||
The "|" operator can be used to calculate the Tanimoto coeff. For example,
|
||||
given two Fingerprints 'a', and 'b', the Tanimoto coefficient is given by:
|
||||
tanimoto = a | b
|
||||
"""
|
||||
def __init__(self, obFingerprint):
|
||||
self.fp = obFingerprint
|
||||
def __or__(self, other):
|
||||
return ob.OBFingerprint.Tanimoto(self.fp, other.fp)
|
||||
def __getattr__(self, attr):
|
||||
if attr == "bits":
|
||||
# Create a bits attribute on-the-fly
|
||||
return findbits(self.fp, ob.OBFingerprint.Getbitsperint())
|
||||
else:
|
||||
raise AttributeError, "Molecule has no attribute %s" % attr
|
||||
def __str__(self):
|
||||
return ", ".join([str(x) for x in self.fp])
|
||||
|
||||
class Smarts(object):
|
||||
"""A Smarts Pattern Matcher
|
||||
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
</font></dt><dd>
|
||||
<dl>
|
||||
<dt><font face="helvetica, arial"><a href="pybel.html#Atom">Atom</a>
|
||||
</font></dt><dt><font face="helvetica, arial"><a href="pybel.html#Fingerprint">Fingerprint</a>
|
||||
</font></dt><dt><font face="helvetica, arial"><a href="pybel.html#Molecule">Molecule</a>
|
||||
</font></dt><dt><font face="helvetica, arial"><a href="pybel.html#Outputfile">Outputfile</a>
|
||||
</font></dt><dt><font face="helvetica, arial"><a href="pybel.html#Smarts">Smarts</a>
|
||||
@@ -80,6 +81,42 @@ Data and other attributes defined here:<br>
|
||||
|
||||
<dl><dt><strong>__weakref__</strong> = <attribute '__weakref__' of 'Atom' objects><dd><tt>list of weak references to the <a href="__builtin__.html#object">object</a> (if defined)</tt></dl>
|
||||
|
||||
</td></tr></table> <p>
|
||||
<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
|
||||
<tr bgcolor="#ffc8d8">
|
||||
<td colspan=3 valign=bottom> <br>
|
||||
<font color="#000000" face="helvetica, arial"><a name="Fingerprint">class <strong>Fingerprint</strong></a>(<a href="__builtin__.html#object">__builtin__.object</a>)</font></td></tr>
|
||||
|
||||
<tr bgcolor="#ffc8d8"><td rowspan=2><tt> </tt></td>
|
||||
<td colspan=2><tt>A Molecular <a href="#Fingerprint">Fingerprint</a>.<br>
|
||||
<br>
|
||||
Required parameters:<br>
|
||||
obFingerprint -- a vector calculated by OBFingerprint.FindFingerprint()<br>
|
||||
<br>
|
||||
Attributes:<br>
|
||||
fp -- the original obFingerprint<br>
|
||||
bits -- a list of bits set in the <a href="#Fingerprint">Fingerprint</a><br>
|
||||
<br>
|
||||
Methods:<br>
|
||||
The "|" operator can be used to calculate the Tanimoto coeff. For example,<br>
|
||||
given two Fingerprints 'a', and 'b', the Tanimoto coefficient is given by:<br>
|
||||
tanimoto = a | b<br> </tt></td></tr>
|
||||
<tr><td> </td>
|
||||
<td width="100%">Methods defined here:<br>
|
||||
<dl><dt><a name="Fingerprint-__getattr__"><strong>__getattr__</strong></a>(self, attr)</dt></dl>
|
||||
|
||||
<dl><dt><a name="Fingerprint-__init__"><strong>__init__</strong></a>(self, obFingerprint)</dt></dl>
|
||||
|
||||
<dl><dt><a name="Fingerprint-__or__"><strong>__or__</strong></a>(self, other)</dt></dl>
|
||||
|
||||
<dl><dt><a name="Fingerprint-__str__"><strong>__str__</strong></a>(self)</dt></dl>
|
||||
|
||||
<hr>
|
||||
Data and other attributes defined here:<br>
|
||||
<dl><dt><strong>__dict__</strong> = <dictproxy object><dd><tt>dictionary for instance variables (if defined)</tt></dl>
|
||||
|
||||
<dl><dt><strong>__weakref__</strong> = <attribute '__weakref__' of 'Fingerprint' objects><dd><tt>list of weak references to the <a href="__builtin__.html#object">object</a> (if defined)</tt></dl>
|
||||
|
||||
</td></tr></table> <p>
|
||||
<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
|
||||
<tr bgcolor="#ffc8d8">
|
||||
@@ -100,7 +137,7 @@ Attributes:<br>
|
||||
(refer to the Open Babel library documentation for more info).<br>
|
||||
<br>
|
||||
Methods:<br>
|
||||
<a href="#Molecule-write">write</a>()<br>
|
||||
<a href="#Molecule-write">write</a>(), <a href="#Molecule-calcfp">calcfp</a>()<br>
|
||||
<br>
|
||||
The original Open Babel molecule can be accessed using the attribute:<br>
|
||||
OBMol<br> </tt></td></tr>
|
||||
@@ -121,6 +158,15 @@ This allows constructions such as the following:<b
|
||||
|
||||
<dl><dt><a name="Molecule-__str__"><strong>__str__</strong></a>(self)</dt></dl>
|
||||
|
||||
<dl><dt><a name="Molecule-calcfp"><strong>calcfp</strong></a>(self, fptype<font color="#909090">=''</font>)</dt><dd><tt>Calculate a molecular fingerprint.<br>
|
||||
<br>
|
||||
Optional parameters:<br>
|
||||
fptype -- the name of the Open Babel fingerprint type.<br>
|
||||
<br>
|
||||
If fptype is not specified, the default Open Babel fingerprint<br>
|
||||
type is used. See the Open Babel library documentation for more<br>
|
||||
details.</tt></dd></dl>
|
||||
|
||||
<dl><dt><a name="Molecule-write"><strong>write</strong></a>(self, format<font color="#909090">='SMI'</font>, filename<font color="#909090">=None</font>, overwrite<font color="#909090">=False</font>)</dt><dd><tt>Write the molecule to a file or return a string.<br>
|
||||
<br>
|
||||
Optional parameters:<br>
|
||||
@@ -160,8 +206,7 @@ Optional parameters:<br>
|
||||
overwrite (default is False) -- if the output file already exists,<br>
|
||||
should it be overwritten?<br>
|
||||
Methods:<br>
|
||||
<a href="#Outputfile-write">write</a>(molecule)<br>
|
||||
<a href="#Outputfile-close">close</a>()<br> </tt></td></tr>
|
||||
<a href="#Outputfile-write">write</a>(molecule)<br> </tt></td></tr>
|
||||
<tr><td> </td>
|
||||
<td width="100%">Methods defined here:<br>
|
||||
<dl><dt><a name="Outputfile-__init__"><strong>__init__</strong></a>(self, format, filename, overwrite<font color="#909090">=False</font>)</dt></dl>
|
||||
@@ -221,7 +266,13 @@ Data and other attributes defined here:<br>
|
||||
<font color="#ffffff" face="helvetica, arial"><big><strong>Functions</strong></big></font></td></tr>
|
||||
|
||||
<tr><td bgcolor="#eeaa77"><tt> </tt></td><td> </td>
|
||||
<td width="100%"><dl><dt><a name="-readfile"><strong>readfile</strong></a>(format, filename)</dt><dd><tt>Iterate over the molecules in a file.<br>
|
||||
<td width="100%"><dl><dt><a name="-findbits"><strong>findbits</strong></a>(fp, bitsperint)</dt><dd><tt>Find which bits are set in a list/vector.<br>
|
||||
<br>
|
||||
This function is used by the <a href="#Fingerprint">Fingerprint</a> class.<br>
|
||||
<br>
|
||||
>>> <a href="#-findbits">findbits</a>([13, 71], 8)<br>
|
||||
[1, 3, 4, 9, 10, 11, 15]</tt></dd></dl>
|
||||
<dl><dt><a name="-readfile"><strong>readfile</strong></a>(format, filename)</dt><dd><tt>Iterate over the molecules in a file.<br>
|
||||
<br>
|
||||
Required parameters:<br>
|
||||
format<br>
|
||||
|
||||
@@ -2,6 +2,39 @@ import os
|
||||
import unittest
|
||||
import pybel
|
||||
|
||||
class Test_fingerprint(unittest.TestCase):
|
||||
"""Test the Fingerprint class"""
|
||||
def setUp(self):
|
||||
self.mols = [pybel.readstring("smi", "CCCC"),
|
||||
pybel.readstring("smi", "CCCN")]
|
||||
|
||||
def testTanimoto(self):
|
||||
"""Test the calculation of the Tanimoto coefficient"""
|
||||
fps = [x.calcfp() for x in self.mols]
|
||||
self.assertEqual(fps[0] | fps[1], 1/3.)
|
||||
fps = [x.calcfp("FP3") for x in self.mols]
|
||||
self.assertEqual(fps[0] | fps[1], 0.)
|
||||
|
||||
def teststringrepr(self):
|
||||
"""Test the string representation and corner cases."""
|
||||
self.assertRaises(ValueError, self.mols[0].calcfp, "Nosuchname")
|
||||
self.assertRaises(AttributeError, self.accesstest)
|
||||
self.assertEqual(str(self.mols[0].calcfp()),
|
||||
'0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1073741824, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0')
|
||||
|
||||
def accesstest(self):
|
||||
# Should raise AttributeError
|
||||
return self.mols[0].calcfp().nosuchname
|
||||
|
||||
def testbits(self):
|
||||
"""Test whether the bits are set correctly."""
|
||||
bits = [x.calcfp().bits for x in self.mols]
|
||||
self.assertEqual(bits[0], [261, 385, 671])
|
||||
bits = [set(x) for x in bits]
|
||||
# Calculate the Tanimoto coefficient the old-fashioned way
|
||||
tanimoto = len(bits[0] & bits[1]) / float(len(bits[0] | bits[1]))
|
||||
self.assertEqual(tanimoto, 1/3.)
|
||||
|
||||
class Test_readstring(unittest.TestCase):
|
||||
"""Test the ability to read and write to a string"""
|
||||
def setUp(self):
|
||||
@@ -154,7 +187,8 @@ class Test_cornercases(unittest.TestCase):
|
||||
self.assertEqual(atom.atomicnum, 0)
|
||||
|
||||
if __name__=="__main__":
|
||||
testgroups = [Test_readstring, Test_readfile, Test_cornercases, Test_atoms, Test_smarts]
|
||||
testgroups = [Test_readstring, Test_readfile, Test_atoms,
|
||||
Test_smarts, Test_cornercases, Test_fingerprint]
|
||||
for testgroup in testgroups:
|
||||
print "\n=== %s ===" % testgroup.__doc__
|
||||
suite = unittest.makeSuite(testgroup)
|
||||
|
||||
@@ -65,7 +65,7 @@ namespace OpenBabel
|
||||
return true;
|
||||
}
|
||||
|
||||
OBFingerprint* OBFingerprint::FindFingerprint(string& ID)
|
||||
OBFingerprint* OBFingerprint::FindFingerprint(const string& ID)
|
||||
{
|
||||
if(ID.empty())
|
||||
return _pDefault;
|
||||
|
||||
Reference in New Issue
Block a user