diff --git a/.gitignore b/.gitignore index 28eb002..9a75db4 100644 --- a/.gitignore +++ b/.gitignore @@ -3,4 +3,5 @@ dist/ spectrophore/__pycache__/ uamc_spectrophore.egg-info/ spectrophore/spectrophore_notebook.ipynb -spectrophore/.ipynb_checkpoints/ \ No newline at end of file +spectrophore/.ipynb_checkpoints/ +__pycache__/ \ No newline at end of file diff --git a/README.md b/README.md index bdaa645..978b59c 100644 --- a/README.md +++ b/README.md @@ -70,7 +70,7 @@ Check the installation by opening a `python` session and entering: ```python >>> from spectrophore import spectrophore >>> spectrophore.__version__ -'1.0.1' +'1.1.0' ``` @@ -103,7 +103,7 @@ Calculate spectrophores optional arguments: -h, --help show this help message and exit -n {none,mean,all,std}, --norm {none,mean,all,std} - normalization setting (default: none) + normalization setting (default: all) -s {none,unique,mirror,all}, --stereo {none,unique,mirror,all} stereo setting (default: none) -a {1,2,3,4,5,6,9,10,12,15,18,20,30,36,45,60,90,180}, --accuracy {1,2,3,4,5,6,9,10,12,15,18,20,30,36,45,60,90,180} @@ -134,24 +134,24 @@ Once you have installed all required tools and the `uamc-spectrophore` package, >>> from rdkit.Chem import AllChem >>> mol = Chem.MolFromSmiles("c1ncncc1") >>> mol = Chem.AddHs(mol) ->>> AllChem.EmbedMolecule(mol) +>>> AllChem.EmbedMolecule(mol, randomSeed=1) 0 ->>> calculator = spectrophore.SpectrophoreCalculator() +>>> calculator = spectrophore.SpectrophoreCalculator(normalization='none') Probes initialised: 48 number of probes in total -Only using 12 probes +12 probes are used due to the imposed stereo flag >>> calculator.calculate(mol) -array([ 2.79612877e+00, 1.67804299e+00, 2.09592537e+00, 1.56546211e+00, - 3.52116032e+00, 3.46776209e+00, 2.62841820e+00, 2.60869245e+00, - 2.51220245e+00, 3.93695578e+00, 3.80399099e+00, 2.38644040e+00, - 4.03731656e+00, 1.29366764e+00, 5.21337207e-01, 1.23693624e-02, - -1.46207663e+00, 5.63430303e+00, -5.07664172e-01, -5.76536023e-01, - 2.05383248e+00, -1.47519328e+00, 5.24238115e+00, 2.35758470e+00, - 9.59050950e+01, 2.72358109e+01, 9.49020528e+00, -2.42285499e+00, - -3.54603042e+01, 1.17303747e+02, -1.52150804e+01, -1.72464368e+01, - 3.35391951e+01, -3.54603042e+01, 1.06633861e+02, 5.19670971e+01, - 1.83474518e+00, 6.12021101e-01, 1.28260191e-01, -1.10206015e-01, - -7.59982097e-01, 2.61648795e+00, -3.23001423e-01, -3.69624105e-01, - 7.91595688e-01, -7.59982097e-01, 2.39011308e+00, 1.15975591e+00]) +array([ 1.40924502, 2.02165046, 1.60116436, 3.03469596, + 2.41507857, 5.08722611, 2.28581149, 1.72504948, + 3.43664362, 3.98129377, 5.09220782, 2.98450003, + 0.64177653, 0.80248703, 4.87071751, 4.87075576, + 2.87898807, 4.10470357, 1.94134559, 3.59602651, + 4.90197306, 4.13912579, 4.53947967, 5.76613547, + 44.7911691 , 71.551798 , 106.82237198, 106.82056914, + 49.73713312, 61.66294048, 23.50814953, 81.88458225, + 77.47027889, 67.52201764, 57.44200226, 112.96883394, + 0.67946222, 1.16072246, 2.47007244, 2.47010285, + 1.02031206, 1.14833662, 0.51142376, 1.74329957, + 1.80947322, 1.30153977, 1.24314761, 2.51634169]) ``` In the example shown, the first three lines import the required modules: module `spectrophore` for the calculation of spectrophores, module `Chem` to generate a RDKit molecule from a smiles string, and module `AllChem` to generate a 3D-conformation from the molecule. Next, a molecule is created from a smiles string (line 4), and a conformation is then generated at the 6'th line after adding hydrogen atoms on the 5'th line. Finally, on lines 7 and 8, a `SpectrophoreCalculator` object is generated and this object is then used to calculate a `spectrophore` descriptor (line 8), which consists in its default form of 4 * 12 numbers. @@ -175,48 +175,52 @@ In the example shown, the first three lines import the required modules: module If a molecule contains more than one 3D-conformation, then one may specify which conformation should be used for the calculation of `spectrophores`. As an example, consider the following code: ```python +>>> calculator = spectrophore.SpectrophoreCalculator(normalization='none') +Probes initialised: 48 number of probes in total +12 probes are used due to the imposed stereo flag >>> aspirin = Chem.MolFromSmiles("CC(Oc1ccccc1C(O)=O)=O") ->>> cids = AllChem.EmbedMultipleConfs(aspirin, numConfs=3) +>>> mol = Chem.AddHs(mol) +>>> cids = AllChem.EmbedMultipleConfs(aspirin, numConfs=3, randomSeed=1) >>> print(len(cids)) 3 >>> for i in range(len(cids)): calculator.calculate(aspirin, i) ... -array([ 2.76333116e+00, 1.88272478e+00, 2.41594407e+00, 1.94137378e+00, - 4.24987797e+00, 3.31974773e+00, 2.69228201e+00, 2.63096102e+00, - 2.50042479e+00, 3.39582797e+00, 3.38116752e+00, 2.91764355e+00, - 1.84611805e+01, 3.72834082e+00, 4.30004028e+00, 3.98508974e+00, - -5.72096326e-01, 1.06385182e+01, 3.90295711e-01, 1.00220548e+00, - 4.90389286e+00, -6.85082335e-01, 1.05008383e+01, 5.36045725e+00, - 2.53150467e+02, 8.69746911e+01, 4.62911497e+01, 4.05631990e+01, - -1.85953640e+01, 2.49890738e+02, 1.83589314e+00, -1.13820244e+00, - 1.05522169e+02, -1.91212970e+01, 2.45247412e+02, 1.34650560e+02, - 7.69015379e+00, 2.66531515e+00, 1.41281704e+00, 1.23772227e+00, - -5.72965434e-01, 7.56310105e+00, 4.82452251e-02, -4.02931606e-02, - 3.15069834e+00, -5.87971255e-01, 7.41740150e+00, 4.12861256e+00]) -array([ 2.68627622e+00, 1.83634338e+00, 2.32891112e+00, 1.88955203e+00, - 4.15781984e+00, 3.26182940e+00, 2.62326816e+00, 2.58397849e+00, - 2.44327492e+00, 3.36734898e+00, 3.34772731e+00, 2.85710289e+00, - 1.77853239e+01, 3.67164582e+00, 4.15154181e+00, 3.83242016e+00, - -5.67838738e-01, 1.05490695e+01, 3.79239626e-01, 9.99403083e-01, - 4.89491453e+00, -6.78547495e-01, 1.04110889e+01, 5.28024565e+00, - 2.38736866e+02, 8.40744401e+01, 4.28507882e+01, 3.71381291e+01, - -1.84811217e+01, 2.45651168e+02, 1.39771377e+00, -1.54160197e+00, - 1.03879971e+02, -1.89940228e+01, 2.40980957e+02, 1.31583317e+02, - 7.24363945e+00, 2.58010744e+00, 1.30258311e+00, 1.12788219e+00, - -5.70649605e-01, 7.45225558e+00, 3.40850493e-02, -5.45057478e-02, - 3.10737509e+00, -5.85184094e-01, 7.30536160e+00, 4.04229515e+00]) -array([ 2.91469475e+00, 1.93172622e+00, 2.43339676e+00, 1.94337237e+00, - 4.34287437e+00, 3.42072192e+00, 2.74090844e+00, 2.70491554e+00, - 2.55278863e+00, 3.53028262e+00, 3.52315311e+00, 2.97409546e+00, - 1.84625592e+01, 3.73065078e+00, 4.32493133e+00, 4.00600516e+00, - -5.65341277e-01, 1.06834328e+01, 4.06627497e-01, 1.05469332e+00, - 4.96638708e+00, -6.75702313e-01, 1.05473789e+01, 5.34733478e+00, - 2.46382770e+02, 8.56744422e+01, 4.42393367e+01, 3.85624404e+01, - -1.85359724e+01, 2.47716551e+02, 1.51078638e+00, -1.53106741e+00, - 1.04196592e+02, -1.90381597e+01, 2.43050756e+02, 1.33308450e+02, - 7.47357302e+00, 2.62967431e+00, 1.34786441e+00, 1.17423161e+00, - -5.71793341e-01, 7.51242068e+00, 3.92631649e-02, -5.22361423e-02, - 3.11897607e+00, -5.86099546e-01, 7.36595668e+00, 4.09366717e+00]) +array([ 2.96462985, 3.10789424, 2.92701307, 4.73480129, + 7.50700756, 6.7752696 , 4.69460938, 4.98432913, + 6.56649102, 8.24607551, 10.16534187, 6.63522774, + 4.85850723, 8.00209372, 6.81008801, 8.81632779, + 15.71507174, 19.57181297, 10.92897534, 14.39582906, + 17.00322879, 18.44783421, 25.71436069, 15.14679154, + 72.95486358, 98.34447259, 169.3500435 , 182.39792935, + 131.36937557, 131.15881671, 65.37049347, 130.03636659, + 162.26216635, 149.89674859, 179.36647984, 198.56950862, + 2.24635125, 3.15646299, 5.16635242, 5.61258427, + 4.05891392, 4.40971427, 2.20378948, 4.40347814, + 4.95831891, 5.23932504, 5.46180745, 6.26469512]) +array([ 2.86370938, 3.11908114, 2.9662985 , 4.77096845, + 7.39310395, 7.31580198, 4.90127635, 5.10262032, + 6.54896831, 8.57209314, 10.4252182 , 6.48236019, + 4.78703499, 8.0880778 , 6.63117671, 8.7416472 , + 16.06779332, 19.49238064, 10.81952934, 14.26088777, + 16.78952893, 18.33067086, 25.61064224, 14.16513261, + 69.21313429, 96.67400647, 170.67855437, 184.54777123, + 119.22878554, 135.03753518, 59.88890451, 119.4956808 , + 173.35099255, 145.16651515, 180.47798998, 187.6085509 , + 2.19625495, 3.10844742, 5.21008164, 5.67473542, + 3.85068934, 4.43502882, 2.10609961, 4.09882807, + 5.17161401, 5.10314635, 5.38430731, 5.95512953]) +array([ 3.03098509, 3.43547073, 2.87682353, 4.70654369, + 7.55577361, 6.44795641, 4.55689165, 4.95357717, + 6.48715747, 8.70650427, 8.51842619, 6.36629528, + 4.92845349, 9.35540521, 6.61796667, 8.52382953, + 15.45974411, 19.28477464, 10.79250878, 13.99183075, + 16.79567856, 18.5976027 , 24.08439853, 13.11722779, + 77.63923352, 120.10923123, 169.49598685, 166.18620528, + 131.14177781, 144.46258022, 72.46953874, 149.309445 , + 140.3545568 , 155.59245541, 130.84980794, 174.86938246, + 2.44134022, 3.88011509, 5.14895684, 4.83463651, + 4.07958148, 4.01362515, 2.4914236 , 4.58399527, + 4.27013576, 5.33584991, 4.63150519, 5.6371141 ]) ``` One can easily visualise `spectrophores` by plotting the actual values. For example, consider the following snippet: @@ -225,7 +229,7 @@ One can easily visualise `spectrophores` by plotting the actual values. For exam >>> import matplotlib.pyplot as plt >>> mol = Chem.MolFromSmiles("CC(CCC1=CC=CC=C1Cl)N1CCOCC1") >>> mol = Chem.AddHs(mol) ->>> cids = AllChem.EmbedMultipleConfs(mol, numConfs = 10) +>>> cids = AllChem.EmbedMultipleConfs(mol, numConfs = 10, randomSeed = 1) >>> spectrophores = [] >>> for cid in cids: spectrophores.append(calculator.calculate(mol, cid)) ... @@ -235,22 +239,24 @@ One can easily visualise `spectrophores` by plotting the actual values. For exam [] [] >>> plt.legend(loc='upper left') +>>> plt.grid() >>> plt.suptitle("Spectrophores calculated for three molecular conformations") ->>> plt.savefig("exampleplot1.png") +>>> plt.savefig("spectrophore/images/exampleplot1.png") ``` which generates the following plot: -![Three conformations](exampleplot1.png) +![Three conformations](spectrophore/images/exampleplot1.png) Similarly, one can easily compare the `spectrophores` from two different molecules, and quantify the difference: ```python >>> plt.close() +>>> spectrophores = [] >>> mols = [Chem.MolFromSmiles("ClC(Br)(I)F"), Chem.MolFromSmiles("CC(CCC1=CC=CC=C1Cl)N1CCOCC1")] >>> for i in range(2): ... mols[i] = Chem.AddHs(mols[i]) -... AllChem.EmbedMolecule(mols[i]) +... AllChem.EmbedMolecule(mols[i], randomSeed=1) ... spectrophores.append(calculator.calculate(mols[i])) ... 0 @@ -259,13 +265,14 @@ Similarly, one can easily compare the `spectrophores` from two different molecul ... [] [] ->>> plt.savefig("exampleplot2.png") +>>> plt.grid() +>>> plt.savefig("spectrophore/images/exampleplot2.png") >>> from scipy.spatial import distance >>> distance.euclidean(spectrophores[0],spectrophores[1]) -2162.512188773051 +2060.6541853196104 ``` -![Two molecules](exampleplot2.png) +![Two molecules](spectrophore/images/exampleplot2.png) From the last example, it is clear that the actual `spectrophore` values may differ a lot depending on the type of molecule. Also, the absolute values are depending on the property type, with some properties leading to large values (e.g. shape deviation) and others very small. For this reason, a number of normalisation methods are provided as shown below. @@ -278,33 +285,29 @@ The `resolution()` method controls the smallest distance between the molecule an ```python >>> mol = Chem.MolFromSmiles("ClC(Br)(I)F") ->>> AllChem.EmbedMolecule(mol) +>>> AllChem.EmbedMolecule(mol, randomSeed=1) 0 ->>> calculator = spectrophore.SpectrophoreCalculator() # Default of 3.0 +>>> calculator = spectrophore.SpectrophoreCalculator(normalization='none') # Default of 3.0 Probes initialised: 48 number of probes in total -Only using 12 probes ->>> spec = calculator.calculate(mol) ->>> print(spec[0]) -0.30117366411301427 ->>> calculator = spectrophore.SpectrophoreCalculator(resolution = 3.0) +12 probes are used due to the imposed stereo flag +>>> print(calculator.calculate(mol)[0]) +2.986999574231686 +>>> calculator = spectrophore.SpectrophoreCalculator(normalization='none', resolution = 3.0) Probes initialised: 48 number of probes in total -Only using 12 probes ->>> spec = calculator.calculate(mol) ->>> print(spec[0]) -0.30117366411301427 ->>> calculator = spectrophore.SpectrophoreCalculator(resolution = 5.0) +12 probes are used due to the imposed stereo flag +>>> print(calculator.calculate(mol)[0]) +2.986999574231686 +>>> calculator = spectrophore.SpectrophoreCalculator(normalization='none', resolution = 5.0) Probes initialised: 48 number of probes in total -Only using 12 probes ->>> spec = calculator.calculate(mol) ->>> print(spec[0]) -0.07899008784089182 +12 probes are used due to the imposed stereo flag +>>> print(calculator.calculate(mol)[0]) +1.3418808308942443 >>> calculator.resolution(10.0) ->>> spec = calculator.calculate(mol) ->>> print(spec[0]) -0.009178129128602913 +>>> print(calculator.calculate(mol)[0]) +0.33471846966269136 ``` -The larger the resolution value (e.g. 5.0 versus 3.0 A), the smaller the interaction energies and corresponding `spectrophore` values. +The larger the resolution value (e.g. 10.0 *versus* 3.0 A), the smaller the interaction energies and corresponding `spectrophore` values. Calling the `resolution()` method without an argument returns the current resolution value: @@ -319,24 +322,23 @@ Calling the `resolution()` method without an argument returns the current resolu The `accuracy()` method controls the angular stepsize by which the molecule is rotated within the cages. By default this value is set to 20°. This parameter can be modified either at class creation, or using the `accuracy()` method later on. The accuracy should be an integer fraction of 180, hence 180 modulus *accuracy* should be equal to 0. The smaller the accuracy value (meaning smaller angular stepsizes), the longer the computation time: ```python ->>> calculator = spectrophore.SpectrophoreCalculator(accuracy = 20.0) # Default +>>> calculator = spectrophore.SpectrophoreCalculator(accuracy = 20.0, normalization = 'none') # Default Probes initialised: 48 number of probes in total -Only using 12 probes ->>> spec = calculator.calculate(mol) ->>> print(spec[0]) -0.2947654850479195 ->>> calculator = spectrophore.SpectrophoreCalculator() +12 probes are used due to the imposed stereo flag +>>> print(calculator.calculate(mol)[0]) +2.986999574231686 +>>> calculator = spectrophore.SpectrophoreCalculator(normalization = 'none') Probes initialised: 48 number of probes in total -Only using 12 probes ->>> spec = calculator.calculate(mol) ->>> print(spec[0]) -0.2947654850479195 ->>> calculator = spectrophore.SpectrophoreCalculator(accuracy = 2.0) +12 probes are used due to the imposed stereo flag +>>> print(calculator.calculate(mol)[0]) +2.986999574231686 +>>> calculator = spectrophore.SpectrophoreCalculator(accuracy = 2.0, normalization = 'none') Probes initialised: 48 number of probes in total Only using 12 probes ->>> spec = calculator.calculate(mol) ->>> print(spec[0]) -0.30442130872737927 +>>> print(calculator.calculate(mol)[0]) +3.031550037295078 +>>> 100.0 * (3.031550037295078 - 2.986999574231686) / 3.031550037295078 +1.469560538843759 ``` Calling the `accuracy()` method without an argument returns the current accuracy value: @@ -354,45 +356,51 @@ With the `normalization()` method, one can specify the type of `spectrophore` no - `normalization("none")`: no normalization is applied and the `spectrophore` values are the raw calculated interaction energies (multiplied by -100), - `normalization("mean")`: for each property, the average value is calculated and each of the individual `spectrophore` property value are reduced by these mean values. This centers the calculated values around 0, - `normalization("std")`: for each property, the standard deviation is calculated and each of the individual `spectrophore` property value is divided by these standard deviations, -- `normalization("all")`: each spectrophore value is normalized by mean and standard deviation. +- `normalization("all")`: each spectrophore value is normalized by mean and standard deviation. This is the fefault option. -The default value is "none", but a setting of "all" is also a good choice: +The default value is "all". ```python +>>> calculator.accuracy(20) >>> calculator.normalization("none") >>> spec = calculator.calculate(mol) >>> print(spec[:12]) -[0.293261 0.45461287 0.4156776 1.10858653 2.80451603 1.23886813 - 1.15383657 1.08827509 1.10487316 2.76474151 1.62110108 1.22473783] +[2.98699957 2.70232233 1.80297059 4.46890589 7.37554531 7.25227472 + 4.11233399 4.05599379 5.90845924 8.56495646 9.32825451 6.22968839] +>>> sum(spec[:12]) +64.78870479507654 >>> calculator.normalization("mean") >>> spec = calculator.calculate(mol) -print(spec[:12]) -[-0.97949629 -0.81814442 -0.85707968 -0.16417076 1.53175875 -0.03388915 - -0.11892071 -0.18448219 -0.16788413 1.49198423 0.3483438 -0.04801945] +>>> print(spec[:12]) +[-2.41205916 -2.69673641 -3.59608814 -0.93015285 1.97648657 1.85321599 + -1.28672475 -1.34306494 0.5094005 3.16589773 3.92919578 0.83062966] >>> sum(spec[:12]) --3.774758283725532e-15 +-1.7763568394002505e-15 >>> calculator.normalization("std") >>> spec = calculator.calculate(mol) >>> print(spec[:12]) -[0.37955444 0.58838486 0.53799271 1.43479337 3.62975819 1.60341096 - 1.49335846 1.4085052 1.42998733 3.57827982 2.09811777 1.58512275] +[1.2924119 1.16923804 0.78010746 1.9336016 3.19124336 3.13790677 + 1.77932044 1.75494322 2.55646607 3.70587655 4.03613957 2.69545517] +>>> sum(spec[:12]) +28.03271016057212 >>> calculator.normalization("all") >>> spec = calculator.calculate(mol) >>> print(spec[:12]) -[-1.26771772 -1.05888729 -1.10927945 -0.21247878 1.98248603 -0.04386119 - -0.15391369 -0.23876695 -0.21728483 1.93100767 0.45084561 -0.0621494 ] +[-1.04364728 -1.16682114 -1.55595172 -0.40245758 0.85518418 0.80184759 + -0.55673874 -0.58111596 0.22040689 1.36981737 1.70008039 0.35939599] >>> sum(spec[:12]) --5.044575868140555e-15 +0.0 ``` Using a normalization over 'all' makes it more easier to compare `spectrophores` between molecules: ```python +>>> plt.close() >>> mols = [Chem.MolFromSmiles("ClC(Br)(I)F"), Chem.MolFromSmiles("CC(CCC1=CC=CC=C1Cl)N1CCOCC1")] >>> spectrophores = [] >>> for i in range(2): ... mols[i] = Chem.AddHs(mols[i]) -... AllChem.EmbedMolecule(mols[i]) +... AllChem.EmbedMolecule(mols[i], randomSeed = 1) ... spectrophores.append(calculator.calculate(mols[i])) ... 0 @@ -401,13 +409,15 @@ Using a normalization over 'all' makes it more easier to compare `spectrophores` ... [] [] ->>> plt.savefig("exampleplot3.png") +>>> plt.legend() +>>> plt.grid() +>>> plt.savefig("spectrophore/images/exampleplot3.png") >>> from scipy.spatial import distance >>> distance.euclidean(spectrophores[0],spectrophores[1]) -9.072753455280592 +8.374486663568376 ``` -![Two molecules](exampleplot3.png) +![Two molecules](spectrophore/images/exampleplot3.png) The same holds true when comparing `spectrophores` from different conformations: @@ -416,7 +426,7 @@ The same holds true when comparing `spectrophores` from different conformations: >>> spectrophores = [] >>> mol = Chem.MolFromSmiles("CC(CCC1=CC=CC=C1Cl)N1CCOCC1") >>> mol = Chem.AddHs(mol) ->>> cids = AllChem.EmbedMultipleConfs(mol, numConfs = 10) +>>> cids = AllChem.EmbedMultipleConfs(mol, numConfs = 10, randomSeed = 1) >>> calculator.normalization("all") >>> for cid in cids: spectrophores.append(calculator.calculate(mol, cid)) ... @@ -427,17 +437,24 @@ The same holds true when comparing `spectrophores` from different conformations: [] >>> plt.legend(loc='upper left') >>> plt.suptitle("Spectrophores calculated for three molecular conformations") ->>> plt.savefig("exampleplot4.png") +>>> plt.savefig("spectrophore/images/exampleplot4.png") +>>> from scipy.spatial import distance +>>> distance.euclidean(spectrophores[0],spectrophores[1]) +5.974719598137992 +>>> distance.euclidean(spectrophores[0],spectrophores[2]) +6.081919289368958 +>>> distance.euclidean(spectrophores[1],spectrophores[2]) +3.7508923029079013 ``` -![Three conformations](exampleplot4.png) +![Three conformations](spectrophore/images/exampleplot4.png) #### `stereo()` The `stereo()` method specifies the kind of cages to be used. The reason for this is that some of the cages that are used to calculate `spectrophores` have a stereospecific distribution of the interaction points: -![Stereo cages](exampleplot5.png) +![Stereo cages](spectrophore/images/exampleplot5.png) There are four possibilities: - `stereo("none")`: no stereospecificity (default). `Spectrophores` are generated using cages that are not stereospecific. For most applications, these `spectrophores` will suffice, @@ -476,7 +493,20 @@ meaning that the first *n* values (with *n* being the number of probes) are calc -## 4. Reference and citation +## 4. Release updates + +- 1.0.1: First official release on PyPi + +- 1.1.0: + - Updated and optimised the NumPy code + - Bug fixes + - Introduced Numba + - Made the 'all' normalization method the default one + - Added a test suite + + + +## 5. Reference and citation If you use the `spectrophore` technology in your own research work, please cite as follows: diff --git a/exampleplot1.png b/exampleplot1.png deleted file mode 100644 index c599c37..0000000 Binary files a/exampleplot1.png and /dev/null differ diff --git a/exampleplot2.png b/exampleplot2.png deleted file mode 100644 index 7c5810d..0000000 Binary files a/exampleplot2.png and /dev/null differ diff --git a/exampleplot3.png b/exampleplot3.png deleted file mode 100644 index a035304..0000000 Binary files a/exampleplot3.png and /dev/null differ diff --git a/exampleplot4.png b/exampleplot4.png deleted file mode 100644 index 6ed0235..0000000 Binary files a/exampleplot4.png and /dev/null differ diff --git a/run_tests.sh b/run_tests.sh new file mode 100755 index 0000000..4338650 --- /dev/null +++ b/run_tests.sh @@ -0,0 +1,3 @@ +#!/bin/bash + +python -m unittest -v tests diff --git a/setup.py b/setup.py index 347d041..1c7a51f 100755 --- a/setup.py +++ b/setup.py @@ -1,21 +1,43 @@ #!/usr/bin/env python from setuptools import setup, find_packages +import codecs +import os.path + + + +def read(rel_path): + here = os.path.abspath(os.path.dirname(__file__)) + with codecs.open(os.path.join(here, rel_path), 'r') as fp: + return fp.read() + + +def get_version(rel_path): + for line in read(rel_path).splitlines(): + if line.startswith('__version__'): + delim = '"' if '"' in line else "'" + return line.split(delim)[1] + else: + raise RuntimeError("Unable to find version string.") + with open("README.md", "r") as fh: long_description = fh.read() + setup( name = "uamc-spectrophore", - version = "1.1.0", + version = get_version("spectrophore/__init__.py"), author = "Hans De Winter", author_email = "hans.dewinter@uantwerpen.be", description = ("Python implementation of the spectrophore descriptor"), long_description = long_description, long_description_content_type="text/markdown", url = "https://github.com/UAMCAntwerpen/spectrophore", - download_url = "https://github.com/UAMCAntwerpen/spectrophore/releases/tag/1.0.1", - packages = find_packages(include=['spectrophore']), + download_url = "https://github.com/UAMCAntwerpen/spectrophore/releases/tag/1.1.0", + packages = ['spectrophore'], + package_dir = {'spectrophore': 'spectrophore'}, + package_data = {'spectrophore': ['images/*']}, keywords = ['uamc', 'spectrophore', 'rdkit', 'cheminformatics'], classifiers = [ "Development Status :: 5 - Production/Stable", diff --git a/spectrophore/__init__.py b/spectrophore/__init__.py index e313b24..41e3013 100644 --- a/spectrophore/__init__.py +++ b/spectrophore/__init__.py @@ -1 +1,2 @@ __all__ = ["spectrophore"] +__version__ = "1.1.0" diff --git a/spectrophore/images/exampleplot1.png b/spectrophore/images/exampleplot1.png new file mode 100644 index 0000000..00e096d Binary files /dev/null and b/spectrophore/images/exampleplot1.png differ diff --git a/spectrophore/images/exampleplot2.png b/spectrophore/images/exampleplot2.png new file mode 100644 index 0000000..d2b87e5 Binary files /dev/null and b/spectrophore/images/exampleplot2.png differ diff --git a/spectrophore/images/exampleplot3.png b/spectrophore/images/exampleplot3.png new file mode 100644 index 0000000..f6a26ab Binary files /dev/null and b/spectrophore/images/exampleplot3.png differ diff --git a/spectrophore/images/exampleplot4.png b/spectrophore/images/exampleplot4.png new file mode 100644 index 0000000..c4e221c Binary files /dev/null and b/spectrophore/images/exampleplot4.png differ diff --git a/exampleplot5.png b/spectrophore/images/exampleplot5.png similarity index 100% rename from exampleplot5.png rename to spectrophore/images/exampleplot5.png diff --git a/spectrophore/spectrophore.py b/spectrophore/spectrophore.py index f7a11ec..f0191da 100755 --- a/spectrophore/spectrophore.py +++ b/spectrophore/spectrophore.py @@ -5,7 +5,6 @@ # of Antwerp __all__ = ['SpectrophoreCalculator'] -__version__ = "1.1.0" # Numba support from numba import njit @@ -234,11 +233,11 @@ class SpectrophoreCalculator: # self.BOX[i][2] z-coordinate of the i'th box point (1-12) #################################################### - def __init__(self, resolution=3.0, accuracy=20, stereo='none', normalization='none'): + def __init__(self, resolution=3.0, accuracy=20, stereo='none', normalization='all'): # Initiate PARMS self.PARMS = np.array([ - 0, # 0 Normalisation + 3, # 0 Normalisation 20, # 1 Accuracy 0, # 2 Stereo 0, # 3 BeginProbe @@ -743,7 +742,7 @@ def __processCommandline(): parser.add_argument('-n', '--norm', dest = 'norm', help = 'normalization setting', - default = 'none', + default = 'all', choices = ['none','mean','all','std']) parser.add_argument('-s', '--stereo', dest = 'stereo', @@ -813,4 +812,3 @@ def __processCommandline(): if spec is not None: of.write("%s\n" % (spec)) of.close() - diff --git a/tests.py b/tests.py new file mode 100755 index 0000000..48af271 --- /dev/null +++ b/tests.py @@ -0,0 +1,345 @@ +#!/usr/bin/env python + +import unittest + +from spectrophore import spectrophore +from rdkit import Chem +from rdkit.Chem import AllChem + +import numpy as np + + +class Tests(unittest.TestCase): + + def test_spectrophore_creation_default(self): + """ + Test that a spectrophore calculator can be created + """ + calculator = spectrophore.SpectrophoreCalculator() + self.assertIsInstance(calculator, spectrophore.SpectrophoreCalculator) + + + def test_spectrophore_creation_normalization_1(self): + """ + Test the normalization default setting + """ + calculator = spectrophore.SpectrophoreCalculator() + self.assertEqual(calculator.normalization(), "all") + + + def test_spectrophore_creation_normalization_2(self): + """ + Test the normalization 'all' setting + """ + calculator = spectrophore.SpectrophoreCalculator(normalization='all') + self.assertEqual(calculator.normalization(), "all") + + + def test_spectrophore_creation_normalization_3(self): + """ + Test the normalization 'none' setting + """ + calculator = spectrophore.SpectrophoreCalculator(normalization='none') + self.assertEqual(calculator.normalization(), "none") + + + def test_spectrophore_creation_normalization_4(self): + """ + Test the normalization 'std' setting + """ + calculator = spectrophore.SpectrophoreCalculator(normalization='std') + self.assertEqual(calculator.normalization(), "std") + + + def test_spectrophore_creation_normalization_5(self): + """ + Test the normalization 'mean' setting + """ + calculator = spectrophore.SpectrophoreCalculator(normalization='mean') + self.assertEqual(calculator.normalization(), "mean") + + + def test_spectrophore_creation_stereo_1(self): + """ + Test the stereo default setting + """ + calculator = spectrophore.SpectrophoreCalculator() + self.assertEqual(calculator.stereo(), "none") + + + def test_spectrophore_creation_stereo_2(self): + """ + Test the stereo 'none' setting + """ + calculator = spectrophore.SpectrophoreCalculator(stereo="none") + self.assertEqual(calculator.stereo(), "none") + + + def test_spectrophore_creation_stereo_3(self): + """ + Test the stereo 'unique' setting + """ + calculator = spectrophore.SpectrophoreCalculator(stereo="unique") + self.assertEqual(calculator.stereo(), "unique") + + + def test_spectrophore_creation_stereo_4(self): + """ + Test the stereo 'mirror' setting + """ + calculator = spectrophore.SpectrophoreCalculator(stereo="mirror") + self.assertEqual(calculator.stereo(), "mirror") + + + def test_spectrophore_creation_stereo_5(self): + """ + Test the stereo 'all' setting + """ + calculator = spectrophore.SpectrophoreCalculator(stereo="all") + self.assertEqual(calculator.stereo(), "all") + + + def test_spectrophore_creation_resolution_1(self): + """ + Test the resolution default setting + """ + calculator = spectrophore.SpectrophoreCalculator() + self.assertEqual(calculator.resolution(), 3.0) + + + def test_spectrophore_creation_resolution_2(self): + """ + Test the resolution setting + """ + calculator = spectrophore.SpectrophoreCalculator(resolution=5.0) + self.assertEqual(calculator.resolution(), 5.0) + + + def test_spectrophore_creation_accuracy_1(self): + """ + Test the accuracy default setting + """ + calculator = spectrophore.SpectrophoreCalculator() + self.assertEqual(calculator.accuracy(), 20) + + + def test_spectrophore_creation_accuracy_2(self): + """ + Test the accuracy setting + """ + calculator = spectrophore.SpectrophoreCalculator(accuracy=30) + self.assertEqual(calculator.accuracy(), 30) + + + def test_spectrophore_run_1(self): + """ + Test the output data + """ + mol = Chem.MolFromSmiles("ClC(F)(Br)I") + AllChem.EmbedMolecule(mol, randomSeed = 1) + calculator = spectrophore.SpectrophoreCalculator(accuracy=20, normalization="all", stereo="none", resolution=3.0) + spec = calculator.calculate(mol) + refe = np.array( + [-1.10319109,-1.07507620,-1.36544508,-0.42381262, 0.59894784, 0.56994993, + -0.55262759,-0.57715614, 0.42761176, 1.05092946, 2.21811155, 0.23175817, + -1.63061581,-1.49627106,-0.92949955,-0.32289585, 0.48718168, 0.55379588, + -0.51246375,-0.16559990, 0.87225420, 1.48597513, 1.52055110, 0.13758795, + -1.52330889,-1.24327825,-0.27087133,-0.07694924, 0.31983545, 0.36887293, + -0.88575512,-0.79157141, 0.14561522, 1.10584918, 2.16577390, 0.68578756, + -1.66401726,-1.40570784,-0.42076108,-0.08906513, 0.00725977, 0.67331657, + -0.78097254,-0.28257457, 0.08920660, 1.33439735, 1.94594202, 0.59297611]) + np.testing.assert_allclose(spec, refe, rtol=1e-5) + + + def test_spectrophore_run_2(self): + """ + Test the output data + """ + mol = Chem.MolFromSmiles("ClC(F)(Br)I") + AllChem.EmbedMolecule(mol, randomSeed = 1) + calculator = spectrophore.SpectrophoreCalculator(accuracy=10, normalization="all", stereo="none", resolution=3.0) + spec = calculator.calculate(mol) + refe = np.array( + [-1.09706685,-1.07194684,-1.37179309,-0.44025359, 0.59403602, 0.57050793, + -0.55358716,-0.59205748, 0.43895745, 1.06219895, 2.20188373, 0.25912093, + -1.68271362,-1.55463831,-0.86471250,-0.25011503, 0.43485924, 0.53341893, + -0.57047323,-0.12031136, 0.84752376, 1.44546425, 1.49617920, 0.28551867, + -1.59199956,-1.30398008,-0.28732486, 0.12322232, 0.27585675, 0.23474463, + -1.00496457,-0.56038389, 0.15567317, 0.84030459, 2.11543153, 1.00341998, + -1.70066565,-1.44577692,-0.52701561, 0.13723203,-0.06601790, 0.63088907, + -0.84543821,-0.15673933, 0.05657921, 1.35649453, 1.75872797, 0.80173082]) + np.testing.assert_allclose(spec, refe, rtol=1e-5) + + + def test_spectrophore_run_3(self): + """ + Test the output data + """ + mol = Chem.MolFromSmiles("ClC(F)(Br)I") + AllChem.EmbedMolecule(mol, randomSeed = 1) + calculator = spectrophore.SpectrophoreCalculator(accuracy=20, normalization="none", stereo="none", resolution=3.0) + spec = calculator.calculate(mol) + refe = np.array( + [ 2.51490484, 2.59537645, 1.76427065, 4.45944989, 7.38683701, 7.30383802, + 4.09075036, 4.02054376, 6.89643184, 8.68051745,12.02127412, 6.33585163, + 3.59122485, 4.19542870, 6.74443436, 9.47258186,13.11583520,13.41542677, + 8.62001669,10.18000672,14.84766542,17.60782202,17.76332445,11.54356774, + 13.47567667,15.82870969,23.99962104,25.62910378,28.96319414,29.37524476, + 18.83289419,19.62429819,27.49926162,35.56788651,44.47418983,32.03820547, + 1.57047230, 1.89561423, 3.13539671, 3.55291250, 3.67415958, 4.51254555, + 2.68198757, 3.30933627, 3.77730855, 5.34466806, 6.11443796, 4.41141857]) + np.testing.assert_allclose(spec, refe, rtol=1e-5) + + + def test_spectrophore_run_4(self): + """ + Test the output data + """ + mol = Chem.MolFromSmiles("ClC(F)(Br)I") + AllChem.EmbedMolecule(mol, randomSeed = 1) + calculator = spectrophore.SpectrophoreCalculator(accuracy=20, normalization="mean", stereo="none", resolution=3.0) + spec = calculator.calculate(mol) + refe = np.array( + [-3.15759900e+00,-3.07712739e+00,-3.90823319e+00,-1.21305395e+00, + 1.71433317e+00, 1.63133419e+00,-1.58175347e+00,-1.65196008e+00, + 1.22392800e+00, 3.00801362e+00, 6.34877029e+00, 6.63347792e-01, + -7.33355305e+00,-6.72934920e+00,-4.18034354e+00,-1.45219604e+00, + 2.19105731e+00, 2.49064887e+00,-2.30476121e+00,-7.44771182e-01, + 3.92288752e+00, 6.68304412e+00, 6.83854655e+00, 6.18789846e-01, + -1.28000138e+01,-1.04469808e+01,-2.27606945e+00,-6.46586715e-01, + 2.68750365e+00, 3.09955427e+00,-7.44279631e+00,-6.65139230e+00, + 1.22357113e+00, 9.29219602e+00, 1.81984993e+01, 5.76251498e+00, + -2.09454919e+00,-1.76940726e+00,-5.29624776e-01,-1.12108989e-01, + 9.13809562e-03, 8.47524067e-01,-9.83033918e-01,-3.55685215e-01, + 1.12287064e-01, 1.67964657e+00, 2.44941647e+00, 7.46397080e-01]) + np.testing.assert_allclose(spec, refe, rtol=1e-5) + + + def test_spectrophore_run_5(self): + """ + Test the output data + """ + mol = Chem.MolFromSmiles("ClC(F)(Br)I") + AllChem.EmbedMolecule(mol, randomSeed = 1) + calculator = spectrophore.SpectrophoreCalculator(accuracy=20, normalization="std", stereo="none", resolution=3.0) + spec = calculator.calculate(mol) + refe = np.array( + [0.87864881,0.90676371,0.61639482,1.55802728,2.58078774,2.55178984, + 1.42921231,1.40468377,2.40945166,3.03276937,4.19995146,2.21359808, + 0.79850899,0.93285374,1.49962525,2.10622895,2.91630648,2.98292068, + 1.91666105,2.26352490,3.30137900,3.91509993,3.94967590,2.56671275, + 1.60371843,1.88374908,2.85615599,3.05007809,3.44686277,3.49590025, + 2.24127220,2.33545591,3.27264254,4.23287650,5.29280122,3.81281489, + 1.24766371,1.50597313,2.49091989,2.82261584,2.91894074,3.58499754, + 2.13070843,2.62910640,3.00088757,4.24607832,4.85762299,3.50465708]) + np.testing.assert_allclose(spec, refe, rtol=1e-5) + + + def test_spectrophore_run_6(self): + """ + Test the output data + """ + mol = Chem.MolFromSmiles("ClC(F)(Br)I") + AllChem.EmbedMolecule(mol, randomSeed = 1) + calculator = spectrophore.SpectrophoreCalculator(accuracy=20, normalization="all", stereo="unique", resolution=3.0) + spec = calculator.calculate(mol) + refe = np.array( + [-2.03921899,-1.04517342,-0.28499011,-1.29917805,-0.47926903,-1.22532822, + -0.89542927, 0.10037913, 1.06592355, 0.19154231, 0.02370325, 0.49968536, + 1.39211832, 1.20631878, 0.05983865, 0.52852503, 0.42327740, 1.77727531, + -2.00962557,-0.94052749,-1.05069265,-0.57476055,-0.59438612,-1.40042448, + -0.65892811, 0.06031672, 1.12082133, 0.22931550,-0.47580130, 0.02467334, + 1.60509384, 0.99574236, 0.49127697, 0.72111261, 1.28871180, 1.16808180, + -1.89353923,-0.37359974,-0.85411562,-0.32538559,-0.53902770,-1.41911805, + -1.11538883, 0.53695328, 1.66420002, 0.46439284,-0.92596599, 0.23159390, + 1.91784546, 0.20877391, 0.11192487, 0.66190005, 0.52831513, 1.12024128, + -2.14066262,-0.16366780,-1.13408345,-0.16928469,-0.69858810,-1.12002024, + -1.27966436, 0.14968130, 0.95374096, 0.92985097,-0.76864761, 0.01253743, + 1.78150756, 0.22270588, 0.57046401, 0.91541664, 0.82401849, 1.11469565]) + np.testing.assert_allclose(spec, refe, rtol=1e-5) + + + def test_spectrophore_run_7(self): + """ + Test the output data + """ + mol = Chem.MolFromSmiles("ClC(F)(Br)I") + AllChem.EmbedMolecule(mol, randomSeed = 1) + calculator = spectrophore.SpectrophoreCalculator(accuracy=20, normalization="all", stereo="mirror", resolution=3.0) + spec = calculator.calculate(mol) + refe = np.array( + [-1.90921713,-0.98252904,-0.90366253,-0.91434369,-0.74867565,-0.80129392, + -0.95162298, 0.28901830, 1.35555346, 0.64547353,-0.54970129,-0.27716388, + 1.64987831, 0.88433158, 0.14506460, 0.87131347, 0.77244895, 1.42512791, + -2.31299993,-0.82483996,-0.85101572,-0.52132848,-0.41838436,-1.46410667, + -0.65312759, 0.24702886, 1.19228061, 0.12813404,-0.36024007, 0.28587791, + 1.71346271, 0.32608845, 0.47657839, 0.78201641, 0.90884304, 1.34573237, + -2.23400905,-0.77962677,-0.73147309,-0.17699684,-0.45110149,-1.23282715, + -0.95921007, 0.31719927, 1.71804647, 0.29338296,-0.65229095, 0.41400049, + 1.74454209, 0.28271240, 0.37067729, 0.65412822, 0.09683844, 1.32600779, + -2.50565022,-0.70145335,-0.98193163,-0.22953142,-0.69302100,-1.01641870, + -0.75447023, 0.30909326, 1.05843658, 0.16536189,-0.36628141, 0.89948652, + 1.78925164, 0.43424018, 0.19778535, 0.55352457, 0.41453461, 1.42704334]) + np.testing.assert_allclose(spec, refe, rtol=1e-5) + + + def test_spectrophore_run_8(self): + """ + Test the output data + """ + mol = Chem.MolFromSmiles("ClC(F)(Br)I") + AllChem.EmbedMolecule(mol, randomSeed = 1) + calculator = spectrophore.SpectrophoreCalculator(accuracy=20, normalization="all", stereo="all", resolution=3.0) + spec = calculator.calculate(mol) + refe = np.array( + [-1.88686588,-1.02863665,-0.37231710,-1.24793665,-0.54005171,-1.18417691, + -0.89935202,-0.03960081, 0.79402138, 0.03910675,-0.10580048, 0.30514826, + 1.07564820, 0.91523443,-0.07460224, 0.33004757, 0.23917990, 1.40818123, + -1.98487173,-0.96017665,-0.87296917,-0.88477998,-0.70159080,-0.75977402, + -0.92600195, 0.44585017, 1.62518262, 0.84000428,-0.48157282,-0.18021172, + 1.95063541, 1.10412407, 0.28667186, 1.08972916, 0.98040869, 1.70211530, + -2.04385246,-0.93105785,-1.04572572,-0.55034117,-0.57076887,-1.40975190, + -0.63794884, 0.11069319, 1.21454310, 0.28659935,-0.44733722, 0.07359299, + 1.71860896, 1.08435187, 0.55926780, 0.79849735, 1.38929565, 1.26373522, + -2.25678837,-0.83561989,-0.86061731,-0.54577138,-0.44746143,-1.44610916, + -0.67163738, 0.18799734, 1.09069733, 0.07445472,-0.39193458, 0.22509754, + 1.58841773, 0.26349796, 0.40721340, 0.69890172, 0.82001908, 1.23724125, + -1.90478601,-0.36869716,-0.85431853,-0.31997074,-0.53588280,-1.42532411, + -1.11836776, 0.55153048, 1.69075421, 0.47819908,-0.92693231, 0.24292665, + 1.94709464, 0.21986420, 0.12198614, 0.67780480, 0.54280054, 1.14101591, + -2.21871209,-0.78006430,-0.73243159,-0.18395404,-0.45509324,-1.22836166, + -0.95770475, 0.30489552, 1.69058741, 0.28133687,-0.65410609, 0.40064949, + 1.71679638, 0.27078175, 0.35779498, 0.63817935, 0.08691871, 1.30279007, + -2.13624368,-0.10707831,-1.10310208,-0.11284343,-0.65611452,-1.08866776, + -1.25252470, 0.21453969, 1.03981754, 1.01529712,-0.72802282, 0.07377676, + 1.88942791, 0.28949131, 0.64642637, 1.00048188, 0.90667184, 1.20501963, + -2.48907143,-0.74066938,-1.01247387,-0.28334165,-0.73249780,-1.04589442, + -0.79204671, 0.23862606, 0.96479593, 0.09933958,-0.41586263, 0.81076140, + 1.67301052, 0.35990281, 0.13076035, 0.47549833, 0.34080663, 1.32200352]) + np.testing.assert_allclose(spec, refe, rtol=1e-5) + + + def test_spectrophore_run_9(self): + """ + Test the output data + """ + mol = Chem.MolFromSmiles("ClC(F)(Br)I") + AllChem.EmbedMolecule(mol, randomSeed = 1) + calculator = spectrophore.SpectrophoreCalculator(accuracy=20, normalization="all", stereo="none", resolution=5.0) + spec = calculator.calculate(mol) + refe = np.array( + [-1.17696999,-1.16754104,-1.37535841,-0.38849771, 0.62028062, 0.50084625, + -0.46682031,-0.47735307, 0.44754847, 1.03628022, 2.18767882, 0.25990616, + -1.70774136,-1.62467284,-0.87070400,-0.20418283, 0.64592735, 0.47249982, + -0.51501546,-0.12306470, 0.88154932, 1.35987348, 1.42435165, 0.26117956, + -1.64621639,-1.46510089,-0.17857477, 0.06535166, 0.33775689, 0.34624943, + -0.85367692,-0.64890728, 0.26991872, 1.00050675, 2.02104921, 0.75164359, + -1.76818132,-1.57525892,-0.35909169, 0.07542518, 0.09415803, 0.56238827, + -0.72335774,-0.16622585, 0.11416589, 1.21297226, 1.85346106, 0.67954482]) + np.testing.assert_allclose(spec, refe, rtol=1e-5) + + + + +if __name__ == '__main__': + unittest.main() \ No newline at end of file