├── .github ├── ISSUE_TEMPLATE │ ├── bugs.md │ └── feature-request.md └── PULL_REQUEST_TEMPLATE.md ├── .gitignore ├── .travis.yml ├── CONTRIBUTING.md ├── LICENSE ├── README.rst ├── docs ├── Makefile ├── conf.py ├── index.rst ├── introduction.rst ├── matrix.rst ├── mordred.rst ├── refs.bib ├── scripts │ ├── __init__.py │ ├── gen_atomic_props.py │ ├── gen_default_descs.py │ ├── gen_descriptor_doc.py │ ├── gen_descriptor_list_xlsx.py │ └── load_path.py └── subpackages │ ├── mordred.descriptors.rst │ ├── mordred.error.rst │ ├── mordred.surface_area.rst │ └── subpackages.rst ├── examples ├── 010-single_mol-single_desc.py ├── 020-single_mol-multiple_desc.py ├── 030-multiple_mol-multiple_desc.py ├── 110-descriptor-arithmetic.py └── article │ ├── Code2.py │ ├── Code3.py │ ├── Code4.py │ ├── Code5.py │ ├── Code6.py │ ├── Code7.py │ └── Code8.py ├── extra ├── ci │ ├── after_success.sh │ ├── before_install.sh │ ├── bump-dev-version.py │ ├── common.sh │ ├── gen_conda_build_config.py │ ├── get-rdkit-version.py │ ├── install.sh │ └── test_script.sh ├── gen_sdf_file.py ├── id_rsa.enc └── requirements │ ├── rdkit-versions.txt │ ├── requirements-conda.txt │ └── requirements-pip.txt ├── meta.yaml ├── mordred ├── ABCIndex.py ├── AcidBase.py ├── AdjacencyMatrix.py ├── Aromatic.py ├── AtomCount.py ├── Autocorrelation.py ├── BCUT.py ├── BalabanJ.py ├── BaryszMatrix.py ├── BertzCT.py ├── BondCount.py ├── CPSA.py ├── CarbonTypes.py ├── Chi.py ├── Constitutional.py ├── DetourMatrix.py ├── DistanceMatrix.py ├── EState.py ├── EccentricConnectivityIndex.py ├── ExtendedTopochemicalAtom.py ├── FragmentComplexity.py ├── Framework.py ├── GeometricalIndex.py ├── GravitationalIndex.py ├── HydrogenBond.py ├── InformationContent.py ├── KappaShapeIndex.py ├── Lipinski.py ├── LogS.py ├── McGowanVolume.py ├── MoRSE.py ├── MoeType.py ├── MolecularDistanceEdge.py ├── MolecularId.py ├── MomentOfInertia.py ├── PBF.py ├── PathCount.py ├── Polarizability.py ├── RingCount.py ├── RotatableBond.py ├── SLogP.py ├── TopoPSA.py ├── TopologicalCharge.py ├── TopologicalIndex.py ├── VdwVolumeABC.py ├── VertexAdjacencyInformation.py ├── WalkCount.py ├── Weight.py ├── WienerIndex.py ├── ZagrebIndex.py ├── __init__.py ├── __main__.py ├── _atomic_property.py ├── _base │ ├── __init__.py │ ├── calculator.py │ ├── context.py │ ├── descriptor.py │ ├── pandas_module.py │ ├── parallel.py │ ├── result.py │ └── util.py ├── _graph_matrix.py ├── _matrix_attributes.py ├── _util.py ├── _version.py ├── _version.txt ├── data │ ├── allred_rocow_electron_negativity.txt │ ├── ionization_potential.txt │ ├── mass.txt │ ├── mc_gowan_volume.txt │ ├── pauling_electron_negativity.txt │ ├── polarizalibity78.txt │ ├── polarizalibity94.txt │ ├── sanderson_electron_negativity.txt │ └── van_der_waals_radii.txt ├── descriptors │ └── __init__.py ├── error │ └── __init__.py ├── surface_area │ ├── __init__.py │ ├── __main__.py │ ├── _mesh.py │ └── _sasa.py └── tests │ ├── Dummy.py │ ├── __init__.py │ ├── __main__.py │ ├── references │ ├── Aromatic.yaml │ ├── Atom │ │ ├── AtomCount.yaml │ │ └── CarbonTypes.yaml │ ├── Autocorrelation │ │ ├── AATS.yaml │ │ ├── AATSC.yaml │ │ ├── ATS.yaml │ │ ├── ATSC.yaml │ │ ├── GATS.yaml │ │ └── MATS.yaml │ ├── Bond │ │ ├── BondTypes.yaml │ │ ├── HBond.yaml │ │ └── Rotatable.yaml │ ├── CPSA.yaml │ ├── Chi.yaml │ ├── Constitutional.yaml │ ├── DistanceEdge.yaml │ ├── EState.yaml │ ├── ExtendedTopochemicalAtom.yaml │ ├── FragmentComplexity.yaml │ ├── Framework.yaml │ ├── GeometricalIndex.yaml │ ├── GravitationalIndex.yaml │ ├── Indices.yaml │ ├── InformationContent.yaml │ ├── Lipinski.yaml │ ├── LogS.yaml │ ├── Matrix │ │ ├── BCUT.yaml │ │ ├── barysz.yaml │ │ ├── detour.yaml │ │ └── distance.yaml │ ├── MoRSE.yaml │ ├── MolecularId.yaml │ ├── MomentOfInertia.yaml │ ├── PathCount.yaml │ ├── Polarizability.yaml │ ├── Property │ │ ├── McGowanVolume.yaml │ │ ├── Vabc.yaml │ │ └── Weight.yaml │ ├── Ring.yaml │ ├── Smarts.yaml │ ├── TopoPSA.yaml │ ├── TopologicalCharge.yaml │ ├── VAdjMat.yaml │ ├── Walk.yaml │ ├── structures.sdf │ └── structures.smi │ ├── test_ABCIndex.py │ ├── test_ETA.py │ ├── test_SASA.py │ ├── test_SLogP.py │ ├── test_VEA.py │ ├── test_atomic_property.py │ ├── test_attributes.py │ ├── test_base.py │ ├── test_by_references.py │ ├── test_compose_descriptor.py │ ├── test_exceptions.py │ ├── test_import_all_descriptors.py │ ├── test_json.py │ ├── test_mordred_main.py │ ├── test_pandas.py │ ├── test_parallel.py │ ├── test_pickle.py │ └── test_result_type.py ├── setup.cfg └── setup.py /.github/ISSUE_TEMPLATE/bugs.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report or Question 3 | about: Report bug or question about this project 4 | --- 5 | 6 | description 7 | -- 8 | Please fill me. 9 | 10 | minimal reproduction code 11 | -- 12 | 13 | Please fill me if possible. 14 | 15 | environment 16 | -- 17 | ### OS/distribution 18 | 19 | Please fill me. 20 | 21 | ### conda or pip 22 | 23 | Please choose conda or pip. 24 | 25 | ### python version 26 | 27 | Please execute the command and paste result. 28 | 29 | ```.bash 30 | python --version 31 | ``` 32 | 33 | ### library version 34 | 35 | Please execute the command and paste result. 36 | 37 | * conda 38 | 39 | ```.bash 40 | conda list 41 | ``` 42 | 43 | * pip 44 | 45 | ```.bash 46 | python -m pip list 47 | python -c 'import rdkit; print("rdkit " + rdkit.__version__)' 48 | ``` 49 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature-request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | --- 5 | 6 | Summary 7 | -- 8 | Please fill me. 9 | 10 | Reference 11 | -- 12 | Please fill me if implementing descriptor. 13 | 14 | Pseudo code 15 | -- 16 | Please fill me if it is necessary. 17 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | Issue # 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | __pycache__ 2 | *.pyc 3 | *.egg-info/ 4 | .DS_Store 5 | .ipynb_checkpoints 6 | /dist 7 | /.direnv 8 | .eggs/ 9 | /.coverage 10 | /htmlcov 11 | /scripts/id_rsa 12 | /scripts/id_rsa.pub 13 | /docs/_build 14 | /docs/api 15 | /docs/descriptors.rst 16 | /docs/atomic_prop.rst 17 | build/ 18 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: bash 2 | env: 3 | global: 4 | - DOC_REMOTE=git@github.com:mordred-descriptor/documentation.git 5 | - secure: IrmS3kBWNvkC/bFObF0jIHUpdFTasEH8QXXK9mh6M+mfdy34qvpnWffzDcuS2ZD1oyLE1YsMxA9MDVmw/PBY27q1wxmQ1ZQFpBoMDsjmczZ4bI/5oiaAekVktAGc4lX3knmQju2nqqb/MZRB9qmpiPFM3xNRDVikSBdOw92SHwGOIsq5r9Rlp0o5vzj0Qo9HREmlAtpbhtdWpWRU94hnDTgwlQJyd4xBq9Y0CLO45KDV6gkq5sEkfiKQnUzElMPEy8NNGKmK3pLD1PCwLt/42dNSEdIXSw9w/pMWk/fGiS2ebsf+Ch/8jTFTdW3Oq3P/NxJuA8t3aYrdcvDy5lmQHrEr+bf4D/xsMtAVS3igIQHKBBp2fSqwIm+KpMyHmA3//jG76+kmE8j1GpBjctdz4ExbCyRlQFhI3r7qQ/tQ9pHHwcZwx8MX/hzslpNhSuBRTIR/4mi3wckYU2kq7UjKbwuHUkcbMwgkKrH1D2cjhQypOnzEBindd+T9mPQYoewdtSQLAbpPsmJbFE/q9SgG/XjmH4k/mlItFLZiOIKTKFGTkXNY1Wqbht95365O4uSbnmzDEwTSISR0qhtjoDVBMowY/1ZBQUM9/Y9aS5KD5uU8FBUbQ3lR641zD14kGBallpCCRTRxgRt19q5R469jKoBA5eWWzRGp86Q19Ywdnbc= 6 | matrix: 7 | - PYTHON_VERSION=3.7 COVERAGE=true DOCUMENTATION=true ANACONDA_CLOUD=true 8 | - PYTHON_VERSION=3.6 COVERAGE=true 9 | - PYTHON_VERSION=2.7 COVERAGE=true 10 | os: 11 | - linux 12 | - osx 13 | - windows 14 | sudo: false 15 | before_install: travis_retry ./extra/ci/before_install.sh 16 | install: travis_retry ./extra/ci/install.sh 17 | script: travis_retry ./extra/ci/test_script.sh 18 | after_success: travis_retry ./extra/ci/after_success.sh 19 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | Contributing 2 | == 3 | 4 | Pull Request 5 | -- 6 | 1. Open issue and discuss (strongly recommended) 7 | 2. Create Pull Request 8 | 9 | Points 10 | 11 | * one descriptor per one PR 12 | * refer article 13 | * write test 14 | 15 | * check values matching with other software or article (required) 16 | * check invariants (if possible) 17 | 18 | 3. Passing all tests 19 | 4. Review 20 | 5. Merge 21 | 22 | Reporting bugs / Question 23 | -- 24 | Please fill [template](http://github.com/mordred-descriptor/mordred/issues/new?template=bugs.md). 25 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2015-2017, Hirotomo Moriwaki 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 5 | 6 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 7 | 8 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 9 | 10 | 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. 11 | 12 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 13 | -------------------------------------------------------------------------------- /docs/index.rst: -------------------------------------------------------------------------------- 1 | .. mordred documentation master file, created by 2 | sphinx-quickstart on Wed Sep 21 17:22:05 2016. 3 | You can adapt this file completely to your liking, but it should at least 4 | contain the root `toctree` directive. 5 | 6 | Welcome to mordred's documentation! 7 | =================================== 8 | 9 | Contents: 10 | 11 | .. toctree:: 12 | :maxdepth: 3 13 | 14 | introduction.rst 15 | 16 | mordred.rst 17 | 18 | atomic_prop.rst 19 | matrix.rst 20 | descriptors.rst 21 | 22 | Indices and tables 23 | ================== 24 | 25 | * :ref:`genindex` 26 | * :ref:`modindex` 27 | * :ref:`search` 28 | -------------------------------------------------------------------------------- /docs/introduction.rst: -------------------------------------------------------------------------------- 1 | Introduction 2 | ============ 3 | .. include:: ../README.rst 4 | -------------------------------------------------------------------------------- /docs/matrix.rst: -------------------------------------------------------------------------------- 1 | .. _matrix_aggregating_methods: 2 | 3 | Matrix aggregating methods 4 | ========================== 5 | 6 | SpAbs 7 | ----- 8 | .. math:: 9 | {\rm SpAbs} = \sum_{i = 1}^N \left| \lambda_i \right| 10 | 11 | where :math:`\lambda_i` is :math:`i`-th eigenvalue. 12 | 13 | SpMax 14 | ----- 15 | .. math:: 16 | {\rm SpMax} = \max_{i = 1}^N \lambda_i 17 | 18 | SpDiam 19 | ------ 20 | .. math:: 21 | {\rm SpDiam} = {\rm SpMax} - {\rm SpMin} 22 | 23 | SpAD 24 | ---- 25 | .. math:: 26 | {\rm SpAD} = \sum_{i = 1}^N \left| \lambda_i - \bar{\lambda} \right| 27 | 28 | SpMAD 29 | ----- 30 | .. math:: 31 | {\rm SpMAD} = \frac{\rm SpAD}{A} 32 | 33 | where :math:`A` is number of atoms. 34 | 35 | LogEE 36 | ----- 37 | .. math:: 38 | {\rm LogEE} = \log(\sum_{i = 1}^N \exp(\lambda_i)) 39 | 40 | SM1 41 | --- 42 | .. math:: 43 | {\rm SM1} = \sum_{i = 1}^N \lambda_i 44 | 45 | VE1 46 | --- 47 | .. math:: 48 | {\rm VE1} = \sum_{i = 1}^N \left| \ell_i \right| 49 | 50 | where :math:`\ell_i` is eigenvector elements corresponding to leading eigenvalue. 51 | 52 | VE2 53 | --- 54 | .. math:: 55 | {\rm VE2} = \frac{\rm VE1}{A} 56 | 57 | VE3 58 | --- 59 | .. math:: 60 | {\rm VE3} = \log(\frac{A}{10} \cdot {\rm VE1}) 61 | 62 | NaN when :math:`{\rm VE1} = 0`. 63 | 64 | VR1 65 | --- 66 | .. math:: 67 | {\rm VR1} = \sum_{(i, j) \in {\rm bonds}} \left( \ell_i \cdot \ell_j \right)^{-1/2} 68 | 69 | VR2 70 | --- 71 | .. math:: 72 | {\rm VR2} = \frac{\rm VR1}{A} 73 | 74 | VR3 75 | --- 76 | .. math:: 77 | {\rm VR3} = \log(\frac{A}{10} \cdot {\rm VR1}) 78 | 79 | NaN when :math:`{\rm VR1} = 0`. 80 | -------------------------------------------------------------------------------- /docs/mordred.rst: -------------------------------------------------------------------------------- 1 | mordred package 2 | =============== 3 | 4 | .. automodule:: mordred 5 | 6 | .. autoclass:: mordred.Result 7 | :members: 8 | 9 | .. autoclass:: mordred.Descriptor 10 | :members: 11 | 12 | .. autoclass:: mordred.Calculator 13 | :members: 14 | 15 | .. autofunction:: get_descriptors_in_module 16 | .. autofunction:: get_descriptors_from_module 17 | 18 | .. toctree:: 19 | subpackages/subpackages.rst 20 | api/modules.rst 21 | -------------------------------------------------------------------------------- /docs/scripts/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mordred-descriptor/mordred/c9de906f0d7829a9abe80658b19f4f9f9aef6648/docs/scripts/__init__.py -------------------------------------------------------------------------------- /docs/scripts/gen_atomic_props.py: -------------------------------------------------------------------------------- 1 | import load_path 2 | from mordred import _atomic_property as prop 3 | 4 | load_path.nop() 5 | 6 | 7 | print(""" 8 | .. _atomic_properties: 9 | 10 | atomic properties 11 | ================= 12 | """[1:]) 13 | 14 | 15 | for v in prop.getter_list: 16 | print(v.short) 17 | print(" " * 4 + v.long) 18 | -------------------------------------------------------------------------------- /docs/scripts/gen_default_descs.py: -------------------------------------------------------------------------------- 1 | import sys 2 | from distutils.version import StrictVersion 3 | 4 | import load_path 5 | from mordred import Descriptor, __version__, descriptors, get_descriptors_in_module 6 | 7 | load_path.nop() 8 | 9 | prelude = """ 10 | Descriptor List 11 | =============== 12 | preset descriptors 13 | 14 | .. code:: python 15 | 16 | calc = Calculator(descriptors) 17 | 18 | .. csv-table:: Descriptor list 19 | :header: "#", "module", "name", "constructor", "dim", "description" 20 | :widths: 1, 2, 2, 4, 1, 10 21 | 22 | """[1:] 23 | 24 | 25 | class DescriptorInfo(object): 26 | def __init__(self, d): 27 | self.raw = d 28 | 29 | @property 30 | def module(self): 31 | return self.raw.__module__ 32 | 33 | @property 34 | def constructor(self): 35 | return self.raw.__class__.__name__ 36 | 37 | @property 38 | def parameters(self): 39 | return [Descriptor._pretty(p) for p in self.raw.parameters()] 40 | 41 | @property 42 | def dimention(self): 43 | return "3D" if self.raw.require_3D else "2D" 44 | 45 | @property 46 | def description(self): 47 | return self.raw.description() 48 | 49 | def to_rst(self, hide_module=False): 50 | mdl = "" if hide_module else ":py:mod:`~{}`".format(self.module) 51 | desc = self.raw 52 | cnst = ":py:class:`~{}.{}` ({})".format( 53 | self.module, self.constructor, ", ".join(self.parameters)) 54 | info = self.description 55 | dim = self.dimention 56 | 57 | return '{}, {}, "{}", {}, "{}"'.format(mdl, desc, cnst, dim, info) 58 | 59 | 60 | def get_all_descriptors(): 61 | v = StrictVersion(__version__) 62 | for mdl in descriptors.all: 63 | ds = [] 64 | for Desc in get_descriptors_in_module(mdl, submodule=False): 65 | for desc in Desc.preset(v): 66 | ds.append(desc) 67 | 68 | yield ds 69 | 70 | 71 | def main(out): 72 | out.write(prelude) 73 | 74 | i = 0 75 | 76 | for descs in get_all_descriptors(): 77 | first = True 78 | for desc in descs: 79 | i += 1 80 | out.write(" {}, {}\n".format(i, DescriptorInfo(desc).to_rst(not first))) 81 | first = False 82 | 83 | 84 | if __name__ == "__main__": 85 | main(sys.stdout) 86 | -------------------------------------------------------------------------------- /docs/scripts/gen_descriptor_doc.py: -------------------------------------------------------------------------------- 1 | import sys 2 | from itertools import chain 3 | 4 | import load_path 5 | from mordred import descriptors 6 | from mordred._base.descriptor import is_descriptor_class 7 | 8 | load_path.nop() 9 | 10 | 11 | class Generator(object): 12 | def __init__(self, mdl): 13 | self.mdl = mdl 14 | 15 | def header(self): 16 | h = self.mdl.__name__ + ' module' 17 | yield h 18 | yield '=' * len(h) 19 | yield '' 20 | 21 | def descriptor(self, desc): 22 | excludes = set([ 23 | 'as_argument', 'calculate', 'coord', 'dependencies', 'fail', 24 | 'is_descriptor_class', 'mol', 'parameters', 'preset', 25 | 'rethrow_na', 'rethrow_zerodiv' 26 | ]) 27 | docs = [m for m in dir(desc) if m[:1] != '_' if m not in excludes] 28 | 29 | yield '.. autoclass:: {}.{}'.format(self.mdl.__name__, desc.__name__) 30 | yield ' :members: {}'.format(', '.join(docs)) 31 | yield ' :undoc-members:' 32 | yield ' :show-inheritance:' 33 | yield '' 34 | 35 | def member(self, member): 36 | if is_descriptor_class(member): 37 | for line in self.descriptor(member): 38 | yield line 39 | else: 40 | raise ValueError('unknown member {} in {}'.format(member, self.mdl.__name__)) 41 | 42 | def members(self): 43 | for m in self.mdl.__all__: 44 | for line in self.member(getattr(self.mdl, m)): 45 | yield line 46 | 47 | def module(self): 48 | yield '.. automodule:: {}'.format(self.mdl.__name__) 49 | 50 | def print(self, file=sys.stdout): 51 | for line in chain(self.header(), self.module(), self.members()): 52 | print(line, file=file) 53 | 54 | 55 | if __name__ == '__main__': 56 | print('Submodules') 57 | print('----------') 58 | print('') 59 | print('.. toctree::') 60 | 61 | for mdl in descriptors.all: 62 | print(' ' + mdl.__name__) 63 | with open('api/{}.rst'.format(mdl.__name__), 'w') as f: 64 | Generator(mdl).print(file=f) 65 | -------------------------------------------------------------------------------- /docs/scripts/gen_descriptor_list_xlsx.py: -------------------------------------------------------------------------------- 1 | from openpyxl import Workbook 2 | from openpyxl.styles import Font 3 | from gen_default_descs import DescriptorInfo, get_all_descriptors 4 | 5 | 6 | def main(out): 7 | wb = Workbook() 8 | ws = wb.active 9 | ws.title = "descriptors" 10 | 11 | ws.append(["index", "module", "name", "constructor", "dimention", "description"]) 12 | for cell in ws["1:1"]: 13 | cell.font = Font(bold=True) 14 | 15 | i = 0 16 | for descs in get_all_descriptors(): 17 | first = True 18 | for desc in descs: 19 | i += 1 20 | info = DescriptorInfo(desc) 21 | ws.append([ 22 | i, 23 | info.module.split(".")[-1] if first else None, 24 | str(info.raw), 25 | "{}({})".format(info.constructor, ", ".join(info.parameters)), 26 | info.dimention, 27 | info.description, 28 | ]) 29 | first = False 30 | 31 | for cells in ws.columns: 32 | L = max(len(str(cell.value or "")) for cell in cells) 33 | ws.column_dimensions[cells[0].column].width = L + 1 34 | 35 | wb.save(out) 36 | 37 | 38 | if __name__ == "__main__": 39 | import sys 40 | main(sys.argv[1]) 41 | -------------------------------------------------------------------------------- /docs/scripts/load_path.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | 4 | 5 | def nop(): 6 | pass 7 | 8 | 9 | sys.path.insert(0, os.path.abspath(os.path.join(__file__, '..', '..', '..'))) 10 | -------------------------------------------------------------------------------- /docs/subpackages/mordred.descriptors.rst: -------------------------------------------------------------------------------- 1 | mordred.descriptors 2 | =================== 3 | 4 | .. automodule:: mordred.descriptors 5 | :members: 6 | :undoc-members: 7 | :show-inheritance: 8 | -------------------------------------------------------------------------------- /docs/subpackages/mordred.error.rst: -------------------------------------------------------------------------------- 1 | mordred.error 2 | ============= 3 | 4 | .. automodule:: mordred.error 5 | :members: 6 | :undoc-members: 7 | :show-inheritance: 8 | -------------------------------------------------------------------------------- /docs/subpackages/mordred.surface_area.rst: -------------------------------------------------------------------------------- 1 | mordred.surface_area 2 | ==================== 3 | 4 | .. automodule:: mordred.surface_area 5 | :members: 6 | :undoc-members: 7 | :show-inheritance: 8 | -------------------------------------------------------------------------------- /docs/subpackages/subpackages.rst: -------------------------------------------------------------------------------- 1 | Subpackages 2 | ----------- 3 | 4 | .. toctree:: 5 | mordred.error 6 | mordred.descriptors 7 | mordred.surface_area 8 | -------------------------------------------------------------------------------- /examples/010-single_mol-single_desc.py: -------------------------------------------------------------------------------- 1 | from rdkit import Chem 2 | 3 | from mordred import Chi, ABCIndex 4 | 5 | benzene = Chem.MolFromSmiles('c1ccccc1') 6 | 7 | # create descriptor instance 8 | abci = ABCIndex.ABCIndex() 9 | 10 | # calculate descriptor value 11 | result = abci(benzene) 12 | 13 | print(str(abci), result) 14 | 15 | # create descriptor instance with parameter 16 | chi_pc4 = Chi.Chi(type='path_cluster', order=4) 17 | 18 | # calculate 19 | result = chi_pc4(benzene) 20 | 21 | print(str(chi_pc4), result) 22 | -------------------------------------------------------------------------------- /examples/020-single_mol-multiple_desc.py: -------------------------------------------------------------------------------- 1 | from multiprocessing import freeze_support 2 | 3 | from rdkit import Chem 4 | 5 | from mordred import Chi, ABCIndex, RingCount, Calculator, is_missing, descriptors 6 | 7 | if __name__ == "__main__": 8 | freeze_support() 9 | 10 | benzene = Chem.MolFromSmiles("c1ccccc1") 11 | 12 | # Create empty Calculator instance 13 | calc1 = Calculator() 14 | 15 | # Register descriptor instance 16 | calc1.register(Chi.Chi(type="path_cluster", order=4)) 17 | 18 | # Register descriptor class using preset 19 | calc1.register(RingCount.RingCount) 20 | 21 | # Register all descriptors in module 22 | calc1.register(ABCIndex) 23 | 24 | # Calculate descriptors 25 | result = calc1(benzene) 26 | 27 | print(result) 28 | # >>> [0.0, 1, 0, 0, 0, 1, (snip) 29 | 30 | # Calculator constructor can register descriptors 31 | calc2 = Calculator(Chi.Chi) 32 | 33 | # Descriptors module contains all descriptors 34 | calc3 = Calculator(descriptors) 35 | 36 | # User can access all descriptor instances by descriptors property 37 | print(calc3.descriptors) 38 | # >>> (mordred.EccentricConnectivityIndex.EccentricConnectivityIndex(), (snip) 39 | 40 | # Calculate descriptors 41 | result = calc3(benzene) 42 | 43 | # get first missing value 44 | na1 = next(r for r in result if is_missing(r)) 45 | 46 | # get reason 47 | print(na1.error) 48 | # >>> missing 3D coordinate 49 | 50 | # Delete all missing value 51 | result = result.drop_missing() 52 | 53 | # convert to dict 54 | print(result.asdict()) 55 | -------------------------------------------------------------------------------- /examples/030-multiple_mol-multiple_desc.py: -------------------------------------------------------------------------------- 1 | from multiprocessing import freeze_support 2 | 3 | from rdkit import Chem 4 | 5 | from mordred import Calculator, descriptors 6 | 7 | if __name__ == "__main__": 8 | freeze_support() 9 | 10 | mols = [ 11 | Chem.MolFromSmiles("c1ccccc1"), 12 | Chem.MolFromSmiles("c1ccccc1Cl"), 13 | Chem.MolFromSmiles("c1ccccc1C"), 14 | ] 15 | 16 | # Create Calculator 17 | calc = Calculator(descriptors) 18 | 19 | # map method calculate multiple molecules (return generator) 20 | print(list(calc.map(mols))) 21 | 22 | # pandas method calculate multiple molecules (return pandas DataFrame) 23 | print(calc.pandas(mols)) 24 | -------------------------------------------------------------------------------- /examples/110-descriptor-arithmetic.py: -------------------------------------------------------------------------------- 1 | from rdkit import Chem 2 | 3 | from mordred import Chi, ABCIndex 4 | 5 | benzene = Chem.MolFromSmiles('c1ccccc1') 6 | 7 | # create descriptor instance 8 | abci = ABCIndex.ABCIndex() 9 | chi_p2 = Chi.Chi(type='path', order=2) 10 | 11 | # create product term using descriptor arithmetic 12 | abci_x_chi_p2 = abci * chi_p2 13 | 14 | # calculate descriptor value 15 | result = abci_x_chi_p2(benzene) 16 | 17 | print(abci_x_chi_p2, result) 18 | -------------------------------------------------------------------------------- /examples/article/Code2.py: -------------------------------------------------------------------------------- 1 | from rdkit import Chem 2 | 3 | from mordred.RingCount import RingCount 4 | 5 | # Start Code 2 6 | rings = RingCount() 7 | rings6 = RingCount(order=6) 8 | print(rings(Chem.MolFromSmiles("c1ccccc1")), rings(Chem.MolFromSmiles("C1CCCCCC1"))) 9 | print(rings6(Chem.MolFromSmiles("c1ccccc1")), rings6(Chem.MolFromSmiles("C1CCCCCC1"))) 10 | -------------------------------------------------------------------------------- /examples/article/Code3.py: -------------------------------------------------------------------------------- 1 | from rdkit import Chem 2 | 3 | from mordred.RingCount import RingCount 4 | 5 | # Start Code 3 6 | rings50 = RingCount(order=50) 7 | print(rings50(Chem.MolFromSmiles("c1ccccc1")), rings50(Chem.MolFromSmiles("C1CCCCCC1"))) 8 | -------------------------------------------------------------------------------- /examples/article/Code4.py: -------------------------------------------------------------------------------- 1 | from distutils.version import StrictVersion 2 | 3 | from mordred.RingCount import RingCount 4 | 5 | # Start Code 4 6 | presets = list(RingCount.preset(version=StrictVersion("1.0.0"))) 7 | print(len(presets)) 8 | -------------------------------------------------------------------------------- /examples/article/Code5.py: -------------------------------------------------------------------------------- 1 | from multiprocessing import freeze_support 2 | 3 | from rdkit import Chem 4 | 5 | from mordred import Calculator 6 | from mordred.RingCount import RingCount 7 | 8 | # for parallel calculation on windows only 9 | if __name__ == "__main__": 10 | freeze_support() 11 | 12 | # Start Code 5 13 | calc = Calculator() 14 | calc.register(RingCount()) 15 | print(calc(Chem.MolFromSmiles("c1ccccc1"))) 16 | print(list(calc.map([Chem.MolFromSmiles("c1ccccc1"), Chem.MolFromSmiles("CCCCCC")]))) 17 | -------------------------------------------------------------------------------- /examples/article/Code6.py: -------------------------------------------------------------------------------- 1 | from rdkit import Chem 2 | 3 | from mordred import Calculator 4 | from mordred.GeometricalIndex import Radius3D 5 | 6 | # Start Code 6 7 | calc = Calculator(Radius3D) 8 | result = calc(Chem.MolFromSmiles("c1ccccc1")) 9 | err = result[0] 10 | print(repr(err)) 11 | print(err.error) 12 | -------------------------------------------------------------------------------- /examples/article/Code7.py: -------------------------------------------------------------------------------- 1 | from rdkit import Chem 2 | 3 | from mordred import Calculator, descriptors 4 | 5 | # Start Code 7 6 | calc = Calculator(descriptors) 7 | result = calc(Chem.MolFromSmiles("c1ccccc1")) 8 | result_dict = result.drop_missing().asdict() 9 | print(len(result_dict)) 10 | print(result_dict["SLogP"]) 11 | -------------------------------------------------------------------------------- /examples/article/Code8.py: -------------------------------------------------------------------------------- 1 | from rdkit import Chem 2 | 3 | from mordred.SLogP import SLogP 4 | from mordred.Lipinski import Lipinski 5 | 6 | # Start Code 8 7 | slogp = SLogP() 8 | lipinski = Lipinski() 9 | product_term = slogp * lipinski 10 | print(str(product_term)) 11 | print(product_term(Chem.MolFromSmiles("c1ccccc1"))) 12 | -------------------------------------------------------------------------------- /extra/ci/after_success.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | 5 | source ./extra/ci/common.sh 6 | 7 | if [[ -n "$COVERAGE" ]]; then 8 | info coveralls 9 | fi 10 | 11 | if [[ -z "$TRAVIS_TAG" && -z "$APPVEYOR_REPO_TAG_NAME" ]]; then 12 | LABEL=dev 13 | python extra/ci/bump-dev-version.py $(cat mordred/_version.txt) > mordred/_version.txt 14 | else 15 | LABEL=main 16 | fi 17 | 18 | python extra/ci/gen_conda_build_config.py > conda_build_config.yaml 19 | 20 | if [[ -n "$ANACONDA_CLOUD_TOKEN" && -n "$ANACONDA_CLOUD" && "$TRAVIS_OS_NAME" == linux ]]; then 21 | info conda build . 22 | 23 | OUTPUT=`conda build . --output --python $PYTHON_VERSION` 24 | anaconda -t $ANACONDA_CLOUD_TOKEN upload --label $LABEL --force $OUTPUT 25 | fi 26 | 27 | # documentation 28 | if [[ -f ~/.ssh/id_rsa && "$TRAVIS_PULL_REQUEST" == false && -n "$DOCUMENTATION" && "$TRAVIS_OS_NAME" == linux ]]; then 29 | eval $(ssh-agent -s) 30 | ssh-add 31 | ssh-add -l 32 | echo "$SSH_AGENT_PID" 33 | 34 | cd docs 35 | info make html 36 | 37 | rm -rf gh-pages 38 | info git clone -b gh-pages $DOC_REMOTE gh-pages 39 | if [[ -d gh-pages/$TRAVIS_BRANCH ]]; then 40 | info rm -r gh-pages/$TRAVIS_BRANCH 41 | fi 42 | mkdir -p gh-pages/$(dirname $TRAVIS_BRANCH) 43 | info cp -r _build/html gh-pages/$TRAVIS_BRANCH 44 | 45 | cd gh-pages 46 | info git add . 47 | if info git commit -m "update documentation to mordred-descriptor/mordred@$TRAVIS_COMMIT"; then 48 | info git push origin gh-pages 49 | fi 50 | fi 51 | -------------------------------------------------------------------------------- /extra/ci/before_install.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | 5 | if [[ "$TRAVIS_PULL_REQUEST" != "false" ]]; then 6 | echo this is PR 7 | exit 0 8 | fi 9 | 10 | mkdir -p ~/.ssh 11 | chmod 700 ~/.ssh 12 | 13 | openssl aes-256-cbc -K $encrypted_9f3357583363_key -iv $encrypted_9f3357583363_iv -in ./extra/id_rsa.enc -out ~/.ssh/id_rsa -d 14 | chmod 600 ~/.ssh/id_rsa 15 | 16 | echo "StrictHostKeyChecking no" >> ~/.ssh/config 17 | 18 | git config --global user.email "philopon.dependence@gmail.com" 19 | git config --global user.name "philopon" 20 | -------------------------------------------------------------------------------- /extra/ci/bump-dev-version.py: -------------------------------------------------------------------------------- 1 | import sys 2 | from distutils.version import StrictVersion 3 | 4 | 5 | def main(version): 6 | vsn = StrictVersion(version) 7 | if vsn.prerelease: 8 | print(version) 9 | return 10 | 11 | (major, minor, patch) = vsn.version 12 | print("{}.{}.{}a1".format(major, minor, patch + 1)) 13 | 14 | 15 | if __name__ == "__main__": 16 | main(sys.argv[1]) 17 | -------------------------------------------------------------------------------- /extra/ci/common.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | export MINICONDA=$HOME/miniconda 4 | 5 | if [[ "$TRAVIS_OS_NAME" == osx ]]; then 6 | export OS_NAME=MacOSX 7 | elif [[ "$TRAVIS_OS_NAME" == linux ]]; then 8 | export OS_NAME=Linux 9 | elif [[ "$TRAVIS_OS_NAME" == windows ]]; then 10 | export OS_NAME=Windows 11 | fi 12 | 13 | if [[ "$OS_NAME" == Windows ]]; then 14 | export PYTHONIOENCODING=utf-8 15 | chcp.com 65001 16 | export PATH="$MINICONDA:$MINICONDA/Scripts:$MINICONDA/Library/bin:$PATH" 17 | else 18 | export PATH="$HOME/miniconda/bin:$PATH" 19 | fi 20 | 21 | info() { 22 | echo ">>> $@" 23 | "$@" 24 | } 25 | 26 | banner() { 27 | line="==================" 28 | echo "$line $@ $line" 29 | } 30 | -------------------------------------------------------------------------------- /extra/ci/gen_conda_build_config.py: -------------------------------------------------------------------------------- 1 | import numpy 2 | 3 | 4 | def main(): 5 | print('''numpy: 6 | - {}'''.format(numpy.__version__)) 7 | 8 | 9 | if __name__ == "__main__": 10 | main() 11 | -------------------------------------------------------------------------------- /extra/ci/get-rdkit-version.py: -------------------------------------------------------------------------------- 1 | import re 2 | 3 | comment = re.compile(r'^\s*#') 4 | 5 | 6 | def main(data, os, pyver): 7 | d = { 8 | (os, pyver): ver 9 | for os, pyver, ver 10 | in (line.strip().split() for line in open(data) if not comment.match(line)) 11 | } 12 | 13 | print(d[(os, pyver)]) 14 | 15 | 16 | if __name__ == "__main__": 17 | import sys 18 | 19 | main(*sys.argv[1:]) 20 | -------------------------------------------------------------------------------- /extra/ci/install.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | source ./extra/ci/common.sh 5 | 6 | EXTENSION=sh 7 | if [[ "$OS_NAME" == Windows ]]; then 8 | EXTENSION=exe 9 | fi 10 | 11 | MINICONDA_INSTALLER=Miniconda3-latest-${OS_NAME}-x86_64.$EXTENSION 12 | 13 | if [[ ! -f "$MINICONDA_INSTALLER" ]]; then 14 | info wget -q https://repo.continuum.io/miniconda/$MINICONDA_INSTALLER 15 | else 16 | rm -rf $HOME/miniconda 17 | fi 18 | 19 | if [[ "$OS_NAME" == Windows ]]; then 20 | cmd.exe /C "$MINICONDA_INSTALLER /InstallationType=JustMe /RegisterPython=0 /S /D=%UserProfile%\\miniconda" 21 | else 22 | info bash $MINICONDA_INSTALLER -b -p $HOME/miniconda 23 | fi 24 | 25 | rm $MINICONDA_INSTALLER 26 | 27 | # setup conda 28 | hash -r 29 | 30 | info conda config --set always_yes yes --set changeps1 no 31 | info conda config --add channels rdkit 32 | info conda update -y --all 33 | 34 | info conda install python=$PYTHON_VERSION 35 | 36 | RDKIT="rdkit==$(python ./extra/ci/get-rdkit-version.py ./extra/requirements/rdkit-versions.txt $OS_NAME $PYTHON_VERSION)" 37 | info conda install $RDKIT --file ./extra/requirements/requirements-conda.txt 38 | 39 | if [[ "$PYTHON_VERSION" == "2.7" ]]; then 40 | mv ./extra/requirements/requirements-pip.txt ./extra/requirements/requirements-pip.txt.bak 41 | grep -v flake8-black ./extra/requirements/requirements-pip.txt.bak > ./extra/requirements/requirements-pip.txt 42 | fi 43 | info pip install -r ./extra/requirements/requirements-pip.txt 44 | -------------------------------------------------------------------------------- /extra/ci/test_script.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | source ./extra/ci/common.sh 5 | 6 | PYTHON=python 7 | 8 | conda list 9 | 10 | if [[ -n "$COVERAGE" ]]; then 11 | info $PYTHON -m mordred.tests -q --with-coverage 12 | else 13 | info $PYTHON -m mordred.tests -q 14 | fi 15 | 16 | echo "test README.rst" >&2 17 | info $PYTHON -m doctest README.rst 18 | 19 | for example in `find examples -name '*.py'`; do 20 | echo "test $example" >&2 21 | PYTHONPATH=. info $PYTHON $example > /dev/null 22 | done 23 | 24 | info $PYTHON setup.py flake8 25 | -------------------------------------------------------------------------------- /extra/gen_sdf_file.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | from rdkit.Chem import AllChem as Chem 4 | 5 | BASE = os.path.join( 6 | os.path.dirname(__file__), 7 | '..', 'mordred', 'tests', 'references' 8 | ) 9 | 10 | 11 | def main(): 12 | smi = os.path.join(BASE, 'structures.smi') 13 | sdf = os.path.join(BASE, 'structures.sdf') 14 | 15 | writer = Chem.SDWriter(sdf) 16 | for line in open(smi): 17 | smi, name = line.strip().split() 18 | print(name) 19 | mol = Chem.AddHs(Chem.MolFromSmiles(smi)) 20 | mol.SetProp('_Name', name) 21 | 22 | Chem.EmbedMolecule(mol, randomSeed=23216) 23 | while Chem.MMFFOptimizeMolecule(mol) == 1: 24 | pass 25 | 26 | writer.write(mol) 27 | writer.flush() 28 | 29 | 30 | if __name__ == '__main__': 31 | main() 32 | -------------------------------------------------------------------------------- /extra/id_rsa.enc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mordred-descriptor/mordred/c9de906f0d7829a9abe80658b19f4f9f9aef6648/extra/id_rsa.enc -------------------------------------------------------------------------------- /extra/requirements/rdkit-versions.txt: -------------------------------------------------------------------------------- 1 | # updated in 2019.03.2 2 | MacOSX 3.7 2019.03.2.0 3 | MacOSX 3.6 2019.03.2.0 4 | MacOSX 2.7 2018.09.3.0 5 | Linux 3.7 2019.03.2.0 6 | Linux 3.6 2019.03.2.0 7 | Linux 2.7 2018.09.3.0 8 | Windows 3.7 2019.03.1.0 9 | Windows 3.6 2019.03.2.0 10 | Windows 2.7 2017.09.3.0 11 | -------------------------------------------------------------------------------- /extra/requirements/requirements-conda.txt: -------------------------------------------------------------------------------- 1 | networkx 2 | six 3 | numpy 4 | tqdm 5 | pandas 6 | 7 | pyyaml 8 | nose 9 | 10 | pep8 11 | isort 12 | flake8 13 | coverage 14 | coveralls 15 | 16 | sphinx 17 | 18 | conda-build 19 | anaconda-client 20 | -------------------------------------------------------------------------------- /extra/requirements/requirements-pip.txt: -------------------------------------------------------------------------------- 1 | flake8-quotes 2 | flake8-print 3 | flake8-black 4 | flake8-comprehensions 5 | flake8-docstrings 6 | flake8-sorted-keys 7 | flake8-regex 8 | flake8-string-format 9 | sphinx-rtd-theme 10 | sphinxcontrib-bibtex 11 | -------------------------------------------------------------------------------- /meta.yaml: -------------------------------------------------------------------------------- 1 | {% set data = load_setup_py_data(from_recipe_dir=True) %} 2 | 3 | package: 4 | name: {{data["name"]}} 5 | version: {{data["version"]}} 6 | 7 | source: 8 | path: . 9 | 10 | build: 11 | number: 0 12 | noarch: python 13 | script: 14 | - python setup.py install --single-version-externally-managed --record=record.txt 15 | 16 | requirements: 17 | build: 18 | - python 19 | - networkx 20 | - numpy 21 | - six 22 | - rdkit 23 | - enum34 [py27] 24 | 25 | - setuptools 26 | - pyyaml 27 | 28 | run: 29 | - python 30 | - networkx 31 | - numpy 32 | - six 33 | - rdkit 34 | - enum34 [py27] 35 | - tqdm 36 | 37 | test: 38 | imports: 39 | - mordred 40 | 41 | requires: 42 | - nose 43 | - pyyaml 44 | - coveralls 45 | 46 | commands: 47 | - nosetests mordred --with-coverage --cover-package=mordred 48 | -------------------------------------------------------------------------------- /mordred/ABCIndex.py: -------------------------------------------------------------------------------- 1 | r"""ABC Index descriptor. 2 | 3 | References 4 | * http://match.pmf.kg.ac.rs/electronic_versions/Match75/n1/match75n1_233-242.pdf 5 | 6 | """ 7 | 8 | import numpy as np 9 | 10 | from ._base import Descriptor 11 | from ._graph_matrix import DistanceMatrix 12 | 13 | __all__ = ("ABCIndex", "ABCGGIndex") 14 | 15 | 16 | class ABCIndexBase(Descriptor): 17 | __slots__ = () 18 | 19 | @classmethod 20 | def preset(cls, version): 21 | yield cls() 22 | 23 | explicit_hydrogens = False 24 | 25 | def parameters(self): 26 | return () 27 | 28 | def __str__(self): 29 | return self.__class__.__name__[:-5] 30 | 31 | rtype = float 32 | 33 | 34 | class ABCIndex(ABCIndexBase): 35 | r"""atom-bond connectivity index descriptor. 36 | 37 | References: 38 | * :doi:`10.2298/FIL1204733D` 39 | 40 | """ 41 | 42 | since = "1.0.0" 43 | __slots__ = () 44 | 45 | def description(self): 46 | return "atom-bond connectivity index" 47 | 48 | @staticmethod 49 | def _each_bond(bond): 50 | du = bond.GetBeginAtom().GetDegree() 51 | dv = bond.GetEndAtom().GetDegree() 52 | 53 | return np.sqrt((du + dv - 2.0) / (du * dv)) 54 | 55 | def calculate(self): 56 | return np.float(np.sum(self._each_bond(bond) for bond in self.mol.GetBonds())) 57 | 58 | 59 | class ABCGGIndex(ABCIndexBase): 60 | r"""Graovac-Ghorbani atom-bond connectivity index descriptor. 61 | 62 | References: 63 | * Furtula, B. Atom-bond connectivity index versus Graovac-Ghorbani analog. MATCH Commun. Math. Comput. Chem 75, 233-242 (2016). 64 | 65 | """ # noqa: E501 66 | 67 | since = "1.0.0" 68 | __slots__ = () 69 | 70 | def description(self): 71 | return "Graovac-Ghorbani atom-bond connectivity index" 72 | 73 | def dependencies(self): 74 | return {"D": DistanceMatrix(self.explicit_hydrogens)} 75 | 76 | @staticmethod 77 | def _each_bond(bond, D): 78 | u = bond.GetBeginAtomIdx() 79 | v = bond.GetEndAtomIdx() 80 | 81 | nu = np.sum(D[u, :] < D[v, :]) 82 | nv = np.sum(D[v, :] < D[u, :]) 83 | 84 | return np.sqrt((nu + nv - 2.0) / (nu * nv)) 85 | 86 | def calculate(self, D): 87 | return np.float( 88 | np.sum(self._each_bond(bond, D) for bond in self.mol.GetBonds()) 89 | ) 90 | -------------------------------------------------------------------------------- /mordred/AcidBase.py: -------------------------------------------------------------------------------- 1 | """Acid Base descriptor. 2 | 3 | References: 4 | * http://cdk.github.io/cdk/1.5/docs/api/org/openscience/cdk/qsar/descriptors/molecular/AcidicGroupCountDescriptor.html 5 | * http://cdk.github.io/cdk/1.5/docs/api/org/openscience/cdk/qsar/descriptors/molecular/BasicGroupCountDescriptor.html 6 | 7 | """ # noqa: E501 8 | 9 | from abc import abstractproperty 10 | 11 | from rdkit import Chem 12 | 13 | from ._base import Descriptor 14 | 15 | __all__ = ("AcidicGroupCount", "BasicGroupCount") 16 | 17 | 18 | class SmartsCountBase(Descriptor): 19 | __slots__ = ("_mol",) 20 | 21 | @classmethod 22 | def preset(cls, version): 23 | yield cls() 24 | 25 | def _create_smarts(self): 26 | s = ",".join("$(" + s + ")" for s in self.SMARTS) 27 | self._mol = Chem.MolFromSmarts("[" + s + "]") 28 | return self._mol 29 | 30 | @abstractproperty 31 | def SMARTS(self): 32 | pass 33 | 34 | def __str__(self): 35 | return self._name 36 | 37 | def parameters(self): 38 | return () 39 | 40 | def calculate(self): 41 | pat = getattr(self, "_mol", None) or self._create_smarts() 42 | return len(self.mol.GetSubstructMatches(pat)) 43 | 44 | rtype = int 45 | 46 | _extra_docs = ("SMARTS",) 47 | 48 | 49 | class AcidicGroupCount(SmartsCountBase): 50 | r"""acidic group count descriptor.""" 51 | 52 | since = "1.0.0" 53 | __slots__ = () 54 | 55 | def description(self): 56 | return "acidic group count" 57 | 58 | _name = "nAcid" 59 | 60 | SMARTS = ( 61 | "[O;H1]-[C,S,P]=O", 62 | "[*;-;!$(*~[*;+])]", 63 | "[NH](S(=O)=O)C(F)(F)F", 64 | "n1nnnc1", 65 | ) 66 | 67 | 68 | class BasicGroupCount(SmartsCountBase): 69 | r"""basic group count descriptor.""" 70 | 71 | since = "1.0.0" 72 | __slots__ = () 73 | 74 | def description(self): 75 | return "basic group count" 76 | 77 | _name = "nBase" 78 | 79 | SMARTS = ( 80 | "[NH2]-[CX4]", 81 | "[NH](-[CX4])-[CX4]", 82 | "N(-[CX4])(-[CX4])-[CX4]", 83 | "[*;+;!$(*~[*;-])]", 84 | "N=C-N", 85 | "N-C=N", 86 | ) 87 | -------------------------------------------------------------------------------- /mordred/AdjacencyMatrix.py: -------------------------------------------------------------------------------- 1 | from distutils.version import StrictVersion 2 | 3 | from ._base import Descriptor 4 | from ._graph_matrix import AdjacencyMatrix as A 5 | from ._matrix_attributes import SM1, methods, get_method 6 | 7 | __all__ = ("AdjacencyMatrix",) 8 | 9 | 10 | _version_remove_SM1_A = StrictVersion("1.1.0") 11 | 12 | 13 | class AdjacencyMatrix(Descriptor): 14 | r"""adjacency matrix descriptor. 15 | 16 | :type type: :py:class:`str` 17 | :param type: :ref:`matrix_aggregating_methods` 18 | """ 19 | 20 | since = "1.0.0" 21 | __slots__ = ("_type",) 22 | explicit_hydrogens = False 23 | 24 | def description(self): 25 | return "{} of adjacency matrix".format(self._type.__name__) 26 | 27 | @classmethod 28 | def preset(cls, version): 29 | if version >= _version_remove_SM1_A: 30 | return (cls(m) for m in methods if m != SM1) 31 | else: 32 | return map(cls, methods) 33 | 34 | def __str__(self): 35 | return "{}_A".format(self._type.__name__) 36 | 37 | def parameters(self): 38 | return (self._type,) 39 | 40 | def __init__(self, type="SpMax"): 41 | self._type = get_method(type) 42 | 43 | def dependencies(self): 44 | return { 45 | "result": self._type( 46 | A(self.explicit_hydrogens), self.explicit_hydrogens, self.kekulize 47 | ) 48 | } 49 | 50 | def calculate(self, result): 51 | return result 52 | 53 | rtype = float 54 | -------------------------------------------------------------------------------- /mordred/Aromatic.py: -------------------------------------------------------------------------------- 1 | from ._base import Descriptor 2 | 3 | __all__ = ("AromaticAtomsCount", "AromaticBondsCount") 4 | 5 | 6 | class AromaticBase(Descriptor): 7 | __slots__ = () 8 | 9 | @classmethod 10 | def preset(cls, version): 11 | yield cls() 12 | 13 | def __str__(self): 14 | return self._name 15 | 16 | def parameters(self): 17 | return () 18 | 19 | rtype = int 20 | 21 | 22 | class AromaticAtomsCount(AromaticBase): 23 | r"""aromatic atoms count descriptor.""" 24 | 25 | since = "1.0.0" 26 | __slots__ = () 27 | _name = "nAromAtom" 28 | 29 | def description(self): 30 | return "aromatic atoms count" 31 | 32 | def calculate(self): 33 | return sum(1 for a in self.mol.GetAtoms() if a.GetIsAromatic()) 34 | 35 | 36 | class AromaticBondsCount(AromaticBase): 37 | r"""aromatic bonds count descriptor.""" 38 | 39 | since = "1.0.0" 40 | __slots__ = () 41 | _name = "nAromBond" 42 | 43 | def description(self): 44 | return "aromatic bonds count" 45 | 46 | def calculate(self): 47 | return sum(1 for b in self.mol.GetBonds() if b.GetIsAromatic()) 48 | -------------------------------------------------------------------------------- /mordred/AtomCount.py: -------------------------------------------------------------------------------- 1 | from distutils.version import StrictVersion 2 | 3 | from rdkit.Chem import rdMolDescriptors 4 | 5 | from ._base import Descriptor 6 | from ._atomic_property import halogen 7 | 8 | __all__ = ("AtomCount",) 9 | 10 | _desc_conv = { 11 | "Atom": "all", 12 | "Bridgehead": "bridgehead", 13 | "HeavyAtom": "heavy", 14 | "Hetero": "hetero", 15 | "Spiro": "spiro", 16 | "X": "halogen", 17 | } 18 | 19 | 20 | _version_add_Nhetero = StrictVersion("1.1.0") 21 | 22 | 23 | class AtomCount(Descriptor): 24 | r"""atom count descriptor. 25 | 26 | :type type: str 27 | :param type: type to count. 28 | 29 | * "Atom" 30 | * "HeavyAtom" 31 | * "Spiro" 32 | * "Bridgehead" 33 | * "Hetero" 34 | * "X" - all halogen 35 | * element symbol 36 | """ 37 | 38 | since = "1.0.0" 39 | __slots__ = ("_type",) 40 | 41 | def description(self): 42 | return "number of {} atoms".format(_desc_conv.get(self._type, self._type)) 43 | 44 | @classmethod 45 | def preset(cls, version): 46 | if version >= _version_add_Nhetero: 47 | t = [ 48 | "Atom", 49 | "HeavyAtom", 50 | "Spiro", 51 | "Bridgehead", 52 | "Hetero", 53 | "H", 54 | "B", 55 | "C", 56 | "N", 57 | "O", 58 | "S", 59 | "P", 60 | "F", 61 | "Cl", 62 | "Br", 63 | "I", 64 | "X", 65 | ] 66 | else: 67 | t = [ 68 | "Atom", 69 | "HeavyAtom", 70 | "Spiro", 71 | "Bridgehead", 72 | "H", 73 | "B", 74 | "C", 75 | "N", 76 | "O", 77 | "S", 78 | "P", 79 | "F", 80 | "Cl", 81 | "Br", 82 | "I", 83 | "X", 84 | ] 85 | 86 | return map(cls, t) 87 | 88 | @property 89 | def explicit_hydrogens(self): 90 | u"""Require explicit_hydrogens when type is "H" or "Atom".""" 91 | return self._type in {"H", "Atom"} 92 | 93 | def __str__(self): 94 | return "n" + self._type 95 | 96 | def parameters(self): 97 | return (self._type,) 98 | 99 | def __init__(self, type="Atom"): 100 | self._type = type 101 | 102 | def _calc_X(self): 103 | X = halogen 104 | return sum(a.GetAtomicNum() in X for a in self.mol.GetAtoms()) 105 | 106 | def _calc(self): 107 | return sum(a.GetSymbol() == self._type for a in self.mol.GetAtoms()) 108 | 109 | def _calc_all(self): 110 | return self.mol.GetNumAtoms() 111 | 112 | def calculate(self): 113 | if self._type == "X": 114 | return self._calc_X() 115 | elif self._type in ["Atom", "HeavyAtom"]: 116 | return self._calc_all() 117 | elif self._type == "Spiro": 118 | return rdMolDescriptors.CalcNumSpiroAtoms(self.mol) 119 | elif self._type == "Bridgehead": 120 | return rdMolDescriptors.CalcNumBridgeheadAtoms(self.mol) 121 | elif self._type == "Hetero": 122 | return rdMolDescriptors.CalcNumHeteroatoms(self.mol) 123 | else: 124 | return self._calc() 125 | 126 | rtype = int 127 | -------------------------------------------------------------------------------- /mordred/BCUT.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | 3 | from ._base import Descriptor 4 | from ._util import to_ordinal 5 | from ._atomic_property import AtomicProperty, get_properties 6 | 7 | __all__ = ("BCUT",) 8 | 9 | 10 | class BCUTBase(Descriptor): 11 | __slots__ = () 12 | explicit_hydrogens = False 13 | require_connected = True 14 | 15 | 16 | class Burden(BCUTBase): 17 | __slots__ = () 18 | 19 | def parameters(self): 20 | return () 21 | 22 | def calculate(self): 23 | N = self.mol.GetNumAtoms() 24 | 25 | mat = 0.001 * np.ones((N, N)) 26 | 27 | for bond in self.mol.GetBonds(): 28 | a = bond.GetBeginAtom() 29 | b = bond.GetEndAtom() 30 | i = a.GetIdx() 31 | j = b.GetIdx() 32 | 33 | try: 34 | w = bond.GetBondTypeAsDouble() / 10.0 35 | except RuntimeError: 36 | self.fail(ValueError("unknown bond type")) 37 | 38 | if a.GetDegree() == 1 or b.GetDegree() == 1: 39 | w += 0.01 40 | 41 | mat[i, j] = w 42 | mat[j, i] = w 43 | 44 | return mat 45 | 46 | 47 | class BurdenEigenValues(BCUTBase): 48 | __slots__ = ("_prop",) 49 | 50 | def parameters(self): 51 | return (self._prop,) 52 | 53 | def __init__(self, prop): 54 | self._prop = prop 55 | 56 | def dependencies(self): 57 | return {"burden": Burden(), "ps": self._prop} 58 | 59 | def calculate(self, burden, ps): 60 | bmat = burden.copy() 61 | 62 | np.fill_diagonal(bmat, ps) 63 | ev = np.linalg.eig(bmat)[0] 64 | 65 | if np.iscomplexobj(ev): 66 | ev = ev.real 67 | 68 | return np.sort(ev)[-1::-1] 69 | 70 | 71 | class BCUT(BCUTBase): 72 | r"""BCUT descriptor. 73 | 74 | :type prop: :py:class:`str` or :py:class:`function` 75 | :param prop: :ref:`atomic_properties` 76 | 77 | :type nth: int 78 | :param nth: n-th eigen value. 0 is highest, -1 is lowest. 79 | 80 | :returns: NaN when 81 | 82 | * any atomic properties are NaN 83 | * :math:`\left| nth \right| > A` 84 | """ 85 | 86 | since = "1.0.0" 87 | __slots__ = ("_prop", "_nth") 88 | 89 | def description(self): 90 | return "{} {} eigenvalue of Burden matrix weighted by {}".format( 91 | to_ordinal(np.abs(self._nth) if self._nth < 0 else 1 + self._nth), 92 | "lowest" if self._nth < 0 else "heighest", 93 | self._prop.get_long(), 94 | ) 95 | 96 | @classmethod 97 | def preset(cls, version): 98 | return ( 99 | cls(a, n) 100 | for a in get_properties(valence=True, charge=True) 101 | for n in [0, -1] 102 | ) 103 | 104 | def __str__(self): 105 | if self._nth < 0: 106 | return "BCUT{}-{}l".format(self._prop.as_argument, np.abs(self._nth)) 107 | else: 108 | return "BCUT{}-{}h".format(self._prop.as_argument, self._nth + 1) 109 | 110 | def parameters(self): 111 | return self._prop, self._nth 112 | 113 | def __init__(self, prop="m", nth=0): 114 | self._prop = AtomicProperty(self.explicit_hydrogens, prop) 115 | self._nth = nth 116 | 117 | def dependencies(self): 118 | return {"bev": BurdenEigenValues(self._prop)} 119 | 120 | def calculate(self, bev): 121 | try: 122 | return bev[self._nth] 123 | except IndexError: 124 | self.fail(ValueError("nth greater then atom count")) 125 | 126 | rtype = float 127 | -------------------------------------------------------------------------------- /mordred/BalabanJ.py: -------------------------------------------------------------------------------- 1 | import rdkit.Chem.GraphDescriptors as RDKit 2 | 3 | from ._base import Descriptor 4 | from ._graph_matrix import DistanceMatrix 5 | 6 | __all__ = ("BalabanJ",) 7 | 8 | 9 | class BalabanJ(Descriptor): 10 | r"""Balaban's J index descriptor(rdkit wrapper).""" 11 | 12 | since = "1.0.0" 13 | __slots__ = () 14 | 15 | def description(self): 16 | return "Balaban's J index" 17 | 18 | explicit_hydrogens = False 19 | 20 | @classmethod 21 | def preset(cls, version): 22 | yield cls() 23 | 24 | def parameters(self): 25 | return () 26 | 27 | def __str__(self): 28 | return self.__class__.__name__ 29 | 30 | def dependencies(self): 31 | return {"D": DistanceMatrix(self.explicit_hydrogens)} 32 | 33 | def calculate(self, D): 34 | return float(RDKit.BalabanJ(self.mol, dMat=D)) 35 | 36 | rtype = float 37 | -------------------------------------------------------------------------------- /mordred/BaryszMatrix.py: -------------------------------------------------------------------------------- 1 | from __future__ import division 2 | 3 | import numpy as np 4 | from networkx import Graph, floyd_warshall_numpy 5 | 6 | from ._base import Descriptor 7 | from ._atomic_property import AtomicProperty, get_properties 8 | from ._matrix_attributes import methods, get_method 9 | 10 | __all__ = ("BaryszMatrix",) 11 | 12 | 13 | class BaryszMatrixBase(Descriptor): 14 | explicit_hydrogens = False 15 | __slots__ = () 16 | 17 | 18 | class Barysz(BaryszMatrixBase): 19 | __slots__ = ("_prop",) 20 | 21 | hermitian = True 22 | 23 | def parameters(self): 24 | return (self._prop,) 25 | 26 | def __init__(self, prop): 27 | self._prop = prop 28 | 29 | def dependencies(self): 30 | return {"P": self._prop} 31 | 32 | def calculate(self, P): 33 | C = self._prop.carbon 34 | 35 | G = Graph() 36 | 37 | G.add_nodes_from(a.GetIdx() for a in self.mol.GetAtoms()) 38 | 39 | for bond in self.mol.GetBonds(): 40 | i = bond.GetBeginAtomIdx() 41 | j = bond.GetEndAtomIdx() 42 | 43 | pi = bond.GetBondTypeAsDouble() 44 | 45 | with self.rethrow_zerodiv(): 46 | w = (C * C) / (P[i] * P[j] * pi) 47 | 48 | G.add_edge(i, j, weight=w) 49 | 50 | sp = floyd_warshall_numpy(G) 51 | np.fill_diagonal(sp, [1.0 - C / P[a.GetIdx()] for a in self.mol.GetAtoms()]) 52 | return sp 53 | 54 | 55 | class BaryszMatrix(BaryszMatrixBase): 56 | r"""barysz matrix descriptor. 57 | 58 | :type prop: :py:class:`str` or :py:class:`function` 59 | :param prop: :ref:`atomic_properties` 60 | 61 | :type type: str 62 | :param type: :ref:`matrix_aggregating_methods` 63 | 64 | :returns: NaN when any properties are NaN 65 | """ 66 | 67 | since = "1.0.0" 68 | __slots__ = ("_prop", "_type") 69 | 70 | def description(self): 71 | return "{} from Barysz matrix weighted by {}".format( 72 | self._type.description(), self._prop.get_long() 73 | ) 74 | 75 | @classmethod 76 | def preset(cls, version): 77 | return (cls(p, m) for p in get_properties() for m in methods) 78 | 79 | def __str__(self): 80 | return "{}_Dz{}".format(self._type.__name__, self._prop.as_argument) 81 | 82 | def parameters(self): 83 | return self._prop, self._type 84 | 85 | def __init__(self, prop="Z", type="SpMax"): 86 | self._prop = AtomicProperty(self.explicit_hydrogens, prop) 87 | self._type = get_method(type) 88 | 89 | def dependencies(self): 90 | return { 91 | "result": self._type( 92 | Barysz(self._prop), self.explicit_hydrogens, self.kekulize 93 | ) 94 | } 95 | 96 | def calculate(self, result): 97 | return result 98 | 99 | rtype = float 100 | -------------------------------------------------------------------------------- /mordred/BertzCT.py: -------------------------------------------------------------------------------- 1 | import rdkit.Chem.GraphDescriptors as RDKit 2 | 3 | from ._base import Descriptor 4 | from ._graph_matrix import DistanceMatrix 5 | 6 | __all__ = ("BertzCT",) 7 | 8 | 9 | class BertzCT(Descriptor): 10 | r"""Bertz CT descriptor(rdkit wrapper).""" 11 | 12 | since = "1.0.0" 13 | __slots__ = () 14 | explicit_hydrogens = False 15 | 16 | def description(self): 17 | return "Bertz CT" 18 | 19 | @classmethod 20 | def preset(cls, version): 21 | yield cls() 22 | 23 | def __str__(self): 24 | return self.__class__.__name__ 25 | 26 | def parameters(self): 27 | return () 28 | 29 | def dependencies(self): 30 | return {"D": DistanceMatrix(self.explicit_hydrogens)} 31 | 32 | def calculate(self, D): 33 | return float(RDKit.BertzCT(self.mol, dMat=D)) 34 | 35 | rtype = float 36 | -------------------------------------------------------------------------------- /mordred/BondCount.py: -------------------------------------------------------------------------------- 1 | from enum import IntEnum 2 | from itertools import chain 3 | 4 | from rdkit import Chem 5 | 6 | from ._base import Descriptor 7 | from ._util import parse_enum 8 | 9 | __all__ = ("BondCount",) 10 | 11 | 12 | class BondType(IntEnum): 13 | __slots__ = () 14 | 15 | any = 1 16 | heavy = 2 17 | 18 | single = 3 19 | double = 4 20 | triple = 5 21 | 22 | aromatic = 6 23 | multiple = 7 24 | 25 | @property 26 | def as_argument(self): 27 | return self.name 28 | 29 | 30 | bond_types = ( 31 | (BondType.any, ("", "all bonds", lambda _: True)), 32 | (BondType.heavy, ("O", "bonds connecting to heavy atom", lambda _: True)), 33 | ( 34 | BondType.single, 35 | ("S", "single bonds", lambda b: b.GetBondType() == Chem.BondType.SINGLE), 36 | ), 37 | ( 38 | BondType.double, 39 | ("D", "double bonds", lambda b: b.GetBondType() == Chem.BondType.DOUBLE), 40 | ), 41 | ( 42 | BondType.triple, 43 | ("T", "triple bonds", lambda b: b.GetBondType() == Chem.BondType.TRIPLE), 44 | ), 45 | ( 46 | BondType.aromatic, 47 | ( 48 | "A", 49 | "aromatic bonds", 50 | lambda b: b.GetIsAromatic() or b.GetBondType() == Chem.BondType.AROMATIC, 51 | ), 52 | ), 53 | ( 54 | BondType.multiple, 55 | ( 56 | "M", 57 | "multiple bonds", 58 | lambda b: b.GetIsAromatic() or b.GetBondType() != Chem.BondType.SINGLE, 59 | ), 60 | ), 61 | ) 62 | 63 | bond_type_dict = dict(bond_types) 64 | 65 | 66 | class BondCount(Descriptor): 67 | r"""bond count descriptor. 68 | 69 | :type type: str 70 | :param type: one of bond_types 71 | 72 | :type kekulize: bool 73 | :param kekulize: use kekulized structure 74 | """ 75 | 76 | since = "1.0.0" 77 | __slots__ = ("_type", "_bond_name", "_bond_desc", "_check_bond", "kekulize") 78 | 79 | def description(self): 80 | return "number of {} in {}kekulized structure".format( 81 | self._bond_desc, "" if self.kekulize else "non-" 82 | ) 83 | 84 | bond_types = tuple(b.name for b in BondType) 85 | 86 | @classmethod 87 | def preset(cls, version): 88 | return chain( 89 | map(lambda t: cls(t, False), BondType), 90 | map(lambda t: cls(t, True), [BondType.single, BondType.double]), 91 | ) 92 | 93 | def __str__(self): 94 | K = "K" if self.kekulize else "" 95 | return "nBonds{}{}".format(K, self._bond_name) 96 | 97 | @property 98 | def explicit_hydrogens(self): 99 | return self._type in (BondType.any, BondType.single) 100 | 101 | def parameters(self): 102 | return self._type, self.kekulize 103 | 104 | def __init__(self, type="any", kekulize=False): 105 | self._type = parse_enum(BondType, type) 106 | self._bond_name, self._bond_desc, self._check_bond = bond_type_dict[self._type] 107 | self.kekulize = kekulize 108 | 109 | def calculate(self): 110 | return sum(1 for b in self.mol.GetBonds() if self._check_bond(b)) 111 | 112 | rtype = int 113 | 114 | _extra_docs = ("bond_types",) 115 | -------------------------------------------------------------------------------- /mordred/Constitutional.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | 3 | from ._base import Descriptor 4 | from ._atomic_property import AtomicProperty, get_properties 5 | 6 | __all__ = ("ConstitutionalSum", "ConstitutionalMean") 7 | 8 | 9 | class ConstitutionalSum(Descriptor): 10 | r"""sum of constitutional descriptor. 11 | 12 | .. math:: 13 | S_p = \sum^A_{i=1} \frac{p_i}{p_{\rm C}} 14 | 15 | where 16 | :math:`p_i` is atomic property of i-th atom, 17 | :math:`p_{\rm C}` is atomic property of carbon 18 | 19 | :type prop: :py:class:`str` or :py:class:`function` 20 | :param prop: :ref:`atomic_properties` 21 | """ 22 | 23 | since = "1.0.0" 24 | __slots__ = ("_prop",) 25 | 26 | def description(self): 27 | return "sum of constitutional weighted by {}".format(self._prop.get_long()) 28 | 29 | @classmethod 30 | def preset(cls, version): 31 | return map(cls, get_properties()) 32 | 33 | def parameters(self): 34 | return (self._prop,) 35 | 36 | def __init__(self, prop="v"): 37 | self._prop = AtomicProperty(self.explicit_hydrogens, prop) 38 | 39 | _prefix = "S" 40 | 41 | def __str__(self): 42 | return "{}{}".format(self._prefix, self._prop.as_argument) 43 | 44 | def dependencies(self): 45 | return {"P": self._prop} 46 | 47 | def calculate(self, P): 48 | return np.sum(P / self._prop.carbon) 49 | 50 | rtype = float 51 | 52 | 53 | class ConstitutionalMean(ConstitutionalSum): 54 | r"""mean of constitutional descriptor. 55 | 56 | .. math:: 57 | M_p = \frac{S_p}{A} 58 | 59 | :type prop: :py:class:`str` or :py:class:`function` 60 | :param prop: :ref:`atomic_properties` 61 | 62 | :rtype: float 63 | """ 64 | 65 | since = "1.0.0" 66 | __slots__ = ("_prop",) 67 | _prefix = "M" 68 | 69 | def description(self): 70 | return "mean of constitutional weighted by {}".format(self._prop.get_long()) 71 | 72 | @classmethod 73 | def preset(cls, version): 74 | return map(cls, get_properties()) 75 | 76 | def dependencies(self): 77 | return {"S": ConstitutionalSum(self._prop)} 78 | 79 | def calculate(self, S): 80 | return S / self.mol.GetNumAtoms() 81 | -------------------------------------------------------------------------------- /mordred/DistanceMatrix.py: -------------------------------------------------------------------------------- 1 | from distutils.version import StrictVersion 2 | 3 | from ._base import Descriptor 4 | from ._graph_matrix import DistanceMatrix as D 5 | from ._matrix_attributes import SM1, methods, get_method 6 | 7 | __all__ = ("DistanceMatrix",) 8 | 9 | 10 | _version_remove_SM1_D = StrictVersion("1.1.0") 11 | 12 | 13 | class DistanceMatrix(Descriptor): 14 | r"""distance matrix descriptor. 15 | 16 | :type type: str 17 | :param type: :ref:`matrix_aggregating_methods` 18 | """ 19 | 20 | since = "1.0.0" 21 | __slots__ = ("_type",) 22 | explicit_hydrogens = False 23 | 24 | def description(self): 25 | return "{} from distance matrix".format(self._type.description()) 26 | 27 | @classmethod 28 | def preset(cls, version): 29 | if version >= _version_remove_SM1_D: 30 | return (cls(m) for m in methods if m != SM1) 31 | else: 32 | return map(cls, methods) 33 | 34 | def __str__(self): 35 | return "{}_D".format(self._type.__name__) 36 | 37 | def parameters(self): 38 | return (self._type,) 39 | 40 | def __init__(self, type="SpMax"): 41 | self._type = get_method(type) 42 | 43 | def dependencies(self): 44 | return { 45 | "result": self._type( 46 | D(self.explicit_hydrogens), self.explicit_hydrogens, self.kekulize 47 | ) 48 | } 49 | 50 | def calculate(self, result): 51 | return result 52 | 53 | rtype = float 54 | -------------------------------------------------------------------------------- /mordred/EccentricConnectivityIndex.py: -------------------------------------------------------------------------------- 1 | from ._base import Descriptor 2 | from ._graph_matrix import Valence, Eccentricity 3 | 4 | __all__ = ("EccentricConnectivityIndex",) 5 | 6 | 7 | class EccentricConnectivityIndex(Descriptor): 8 | r"""eccentric connectivity index descriptor. 9 | 10 | .. math:: 11 | I_{\rm EC} = \sum^A_i {\boldsymbol E}{\boldsymbol V} 12 | 13 | where 14 | :math:`E` is eccentricity of atoms, 15 | :math:`V` is valences of atoms. 16 | """ 17 | 18 | since = "1.0.0" 19 | __slots__ = () 20 | explicit_hydrogens = False 21 | 22 | def description(self): 23 | return "eccentric connectivity index" 24 | 25 | @classmethod 26 | def preset(cls, version): 27 | yield cls() 28 | 29 | def __str__(self): 30 | return "ECIndex" 31 | 32 | def parameters(self): 33 | return () 34 | 35 | def dependencies(self): 36 | return { 37 | "E": Eccentricity(self.explicit_hydrogens), 38 | "V": Valence(self.explicit_hydrogens), 39 | } 40 | 41 | def calculate(self, E, V): 42 | return int((E.astype("int") * V).sum()) 43 | 44 | rtype = int 45 | -------------------------------------------------------------------------------- /mordred/FragmentComplexity.py: -------------------------------------------------------------------------------- 1 | from __future__ import division 2 | 3 | from ._base import Descriptor 4 | 5 | __all__ = ("FragmentComplexity",) 6 | 7 | 8 | class FragmentComplexity(Descriptor): 9 | r"""fragment complexity descriptor. 10 | 11 | .. math:: 12 | {\rm fragCpx} = \left| B^2 - A^2 + A \right| + \frac{H}{100} 13 | 14 | where 15 | :math:`A` is number of atoms, 16 | :math:`B` is number of bonds, 17 | :math:`H` is number of hetero atoms 18 | 19 | References 20 | * :doi:`10.1021/ci050521b` 21 | 22 | """ 23 | 24 | since = "1.0.0" 25 | __slots__ = () 26 | 27 | def description(self): 28 | return "fragment complexity" 29 | 30 | @classmethod 31 | def preset(cls, version): 32 | yield cls() 33 | 34 | explicit_hydrogens = False 35 | 36 | def parameters(self): 37 | return () 38 | 39 | def __str__(self): 40 | return "fragCpx" 41 | 42 | def calculate(self): 43 | A = self.mol.GetNumAtoms() 44 | B = self.mol.GetNumBonds() 45 | H = sum(1 for a in self.mol.GetAtoms() if a.GetAtomicNum() != 6) 46 | return abs(B ** 2 - A ** 2 + A) + H / 100 47 | 48 | rtype = float 49 | -------------------------------------------------------------------------------- /mordred/Framework.py: -------------------------------------------------------------------------------- 1 | from __future__ import division 2 | 3 | import networkx as nx 4 | 5 | from ._base import Descriptor 6 | from .RingCount import Rings 7 | 8 | __all__ = ("Framework",) 9 | 10 | 11 | class FrameworkCache(Descriptor): 12 | __slots__ = () 13 | 14 | def parameters(self): 15 | return () 16 | 17 | def dependencies(self): 18 | return {"Rs": Rings()} 19 | 20 | def calculate(self, Rs): 21 | G = nx.Graph() 22 | Rd = {i: ("R", Ri) for Ri, R in enumerate(Rs) for i in R} 23 | R = list(set(Rd.values())) 24 | NR = len(R) 25 | 26 | for bond in self.mol.GetBonds(): 27 | a = bond.GetBeginAtomIdx() 28 | b = bond.GetEndAtomIdx() 29 | 30 | a = Rd.get(a, ("A", a)) 31 | b = Rd.get(b, ("A", b)) 32 | 33 | G.add_edge(a, b) 34 | 35 | linkers = set() 36 | for Ri, Rj in ((i, j) for i in range(NR) for j in range(i + 1, NR)): 37 | Ra, Rb = R[Ri], R[Rj] 38 | try: 39 | linkers.update(i for t, i in nx.shortest_path(G, Ra, Rb) if t == "A") 40 | except nx.NetworkXNoPath: 41 | pass 42 | 43 | return linkers, Rs 44 | 45 | 46 | class Framework(Descriptor): 47 | r"""molecular framework ratio descriptor. 48 | 49 | .. math:: 50 | 51 | f_{\rm MF} = \frac{N_{\rm MF}}{N} 52 | 53 | where 54 | :math:`N_{\rm MF}` is number of atoms in molecular framework, 55 | :math:`N` is number of all atoms. 56 | 57 | References 58 | * :doi:`10.1021/jm9602928` 59 | 60 | """ 61 | 62 | since = "1.0.0" 63 | __slots__ = () 64 | 65 | def description(self): 66 | return "molecular framework ratio" 67 | 68 | @classmethod 69 | def preset(cls, version): 70 | yield cls() 71 | 72 | def __str__(self): 73 | return "fMF" 74 | 75 | def parameters(self): 76 | return () 77 | 78 | def dependencies(self): 79 | return {"F": FrameworkCache()} 80 | 81 | def calculate(self, F): 82 | linkers, rings = F 83 | Nmf = len(linkers) + len({i for ring in rings for i in ring}) 84 | N = self.mol.GetNumAtoms() 85 | 86 | return Nmf / N 87 | 88 | rtype = float 89 | -------------------------------------------------------------------------------- /mordred/GeometricalIndex.py: -------------------------------------------------------------------------------- 1 | from __future__ import division 2 | 3 | from ._base import Descriptor 4 | from ._graph_matrix import Radius3D as CRadius3D 5 | from ._graph_matrix import Diameter3D as CDiameter3D 6 | 7 | __all__ = ("Diameter3D", "Radius3D", "GeometricalShapeIndex", "PetitjeanIndex3D") 8 | 9 | 10 | class GeometricalIndexBase(Descriptor): 11 | __slots__ = () 12 | explicit_hydrogens = True 13 | require_3D = True 14 | 15 | @classmethod 16 | def preset(cls, version): 17 | yield cls() 18 | 19 | def parameters(self): 20 | return () 21 | 22 | rtype = float 23 | 24 | 25 | class Radius3D(GeometricalIndexBase): 26 | r"""geometric radius descriptor.""" 27 | 28 | since = "1.0.0" 29 | __slots__ = () 30 | 31 | def description(self): 32 | return "geometric radius" 33 | 34 | def __str__(self): 35 | return "GeomRadius" 36 | 37 | def dependencies(self): 38 | return {"R": CRadius3D(self.explicit_hydrogens)} 39 | 40 | def calculate(self, R): 41 | return R 42 | 43 | 44 | class Diameter3D(GeometricalIndexBase): 45 | r"""geometric diameter descriptor.""" 46 | 47 | since = "1.0.0" 48 | __slots__ = () 49 | 50 | def description(self): 51 | return "geometric diameter" 52 | 53 | def __str__(self): 54 | return "GeomDiameter" 55 | 56 | def dependencies(self): 57 | return {"D": CDiameter3D(self.explicit_hydrogens)} 58 | 59 | def calculate(self, D): 60 | return D 61 | 62 | 63 | class GeometricalShapeIndex(GeometricalIndexBase): 64 | r"""geometrical shape index descriptor. 65 | 66 | .. math:: 67 | 68 | I_{\rm topo} = \frac{D - R}{R} 69 | 70 | where 71 | :math:`R` is geometric radius, 72 | :math:`D` is geometric diameter. 73 | 74 | :returns: NaN when :math:`R = 0` 75 | """ 76 | 77 | since = "1.0.0" 78 | __slots__ = () 79 | 80 | def description(self): 81 | return "geometrical shape index" 82 | 83 | def __str__(self): 84 | return "GeomShapeIndex" 85 | 86 | def dependencies(self): 87 | return { 88 | "D": CDiameter3D(self.explicit_hydrogens), 89 | "R": CRadius3D(self.explicit_hydrogens), 90 | } 91 | 92 | def calculate(self, R, D): 93 | with self.rethrow_zerodiv(): 94 | return (D - R) / (R) 95 | 96 | 97 | class PetitjeanIndex3D(GeometricalShapeIndex): 98 | r"""geometric Petitjean index descriptor. 99 | 100 | .. math:: 101 | 102 | I_{\rm Petitjean} = \frac{D - R}{D} 103 | 104 | where 105 | :math:`R` is geometric radius, 106 | :math:`D` is geometric diameter. 107 | 108 | :returns: NaN when :math:`D = 0` 109 | """ 110 | 111 | since = "1.0.0" 112 | __slots__ = () 113 | 114 | def description(self): 115 | return "geometric Petitjean index" 116 | 117 | def __str__(self): 118 | return "GeomPetitjeanIndex" 119 | 120 | def calculate(self, R, D): 121 | with self.rethrow_zerodiv(): 122 | return (D - R) / (D) 123 | -------------------------------------------------------------------------------- /mordred/GravitationalIndex.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | 3 | from ._base import Descriptor 4 | from ._util import atoms_to_numpy 5 | from ._graph_matrix import AdjacencyMatrix, DistanceMatrix3D 6 | 7 | __all__ = ("GravitationalIndex",) 8 | 9 | 10 | class GravitationalIndex(Descriptor): 11 | since = "1.0.0" 12 | __slots__ = "_heavy", "_pair" 13 | 14 | def description(self): 15 | return "{}{}gravitational index".format( 16 | "heavy atom " if self._heavy else "", "pair " if self._pair else "" 17 | ) 18 | 19 | @classmethod 20 | def preset(cls, version): 21 | return (cls(h, p) for p in [False, True] for h in [True, False]) 22 | 23 | require_3D = True 24 | 25 | @property 26 | def explicit_hydrogens(self): 27 | return not self._heavy 28 | 29 | def __str__(self): 30 | return "GRAV{}{}".format("" if self._heavy else "H", "p" if self._pair else "") 31 | 32 | def parameters(self): 33 | return self._heavy, self._pair 34 | 35 | def __init__(self, heavy=True, pair=False): 36 | self._heavy = heavy 37 | self._pair = pair 38 | 39 | def dependencies(self): 40 | d = {"D": DistanceMatrix3D(self.explicit_hydrogens)} 41 | 42 | if self._pair: 43 | d["A"] = AdjacencyMatrix(self.explicit_hydrogens) 44 | 45 | return d 46 | 47 | def calculate(self, D, A=1.0): 48 | w = atoms_to_numpy(lambda a: a.GetMass(), self.mol) 49 | 50 | w = w[:, np.newaxis] * w 51 | np.fill_diagonal(w, 0) 52 | 53 | D = D.copy() 54 | np.fill_diagonal(D, 1) 55 | 56 | with self.rethrow_zerodiv(): 57 | return 0.5 * np.sum(w * A / D ** 2) 58 | 59 | rtype = float 60 | -------------------------------------------------------------------------------- /mordred/HydrogenBond.py: -------------------------------------------------------------------------------- 1 | from rdkit.Chem import rdMolDescriptors 2 | 3 | from ._base import Descriptor 4 | 5 | __all__ = ("HBondAcceptor", "HBondDonor") 6 | 7 | 8 | class HBondBase(Descriptor): 9 | __slots__ = () 10 | explicit_hydrogens = False 11 | 12 | @classmethod 13 | def preset(cls, version): 14 | yield cls() 15 | 16 | rtype = int 17 | 18 | 19 | class HBondAcceptor(HBondBase): 20 | r"""hydrogen bond acceptor descriptor(rdkit wrapper).""" 21 | 22 | since = "1.0.0" 23 | __slots__ = () 24 | 25 | def description(self): 26 | return "number of hydrogen bond acceptor" 27 | 28 | def __str__(self): 29 | return "nHBAcc" 30 | 31 | def parameters(self): 32 | return () 33 | 34 | def calculate(self): 35 | return rdMolDescriptors.CalcNumHBA(self.mol) 36 | 37 | 38 | class HBondDonor(HBondBase): 39 | r"""hydrogen bond donor descriptor(rdkit wrapper).""" 40 | 41 | since = "1.0.0" 42 | __slots__ = () 43 | 44 | def description(self): 45 | return "number of hydrogen bond donor" 46 | 47 | def __str__(self): 48 | return "nHBDon" 49 | 50 | def parameters(self): 51 | return () 52 | 53 | def calculate(self): 54 | return rdMolDescriptors.CalcNumHBD(self.mol) 55 | -------------------------------------------------------------------------------- /mordred/KappaShapeIndex.py: -------------------------------------------------------------------------------- 1 | from __future__ import division 2 | 3 | from .Chi import ChiCache 4 | from ._base import Descriptor 5 | 6 | __all__ = ("KappaShapeIndex1", "KappaShapeIndex2", "KappaShapeIndex3") 7 | 8 | 9 | class KappaShapeIndexBase(Descriptor): 10 | explicit_hydrogens = False 11 | 12 | __slots__ = ("_order",) 13 | 14 | @classmethod 15 | def preset(cls, version): 16 | yield cls() 17 | 18 | def __str__(self): 19 | return "Kier{}".format(self._order) 20 | 21 | def parameters(self): 22 | return () 23 | 24 | def __init__(self): 25 | self._order = int(self.__class__.__name__[-1]) 26 | 27 | def dependencies(self): 28 | return {"Chi": ChiCache(self._order)} 29 | 30 | def _common(self, Chi): 31 | P = len(Chi.path) 32 | 33 | A = self.mol.GetNumAtoms() 34 | Pmin = A - self._order 35 | 36 | return P, A, Pmin 37 | 38 | rtype = float 39 | 40 | 41 | class KappaShapeIndex1(KappaShapeIndexBase): 42 | r"""Kappa shape index 1 descriptor. 43 | 44 | :returns: NaN when :math:`N_{\rm Chi-path} = 0` 45 | """ 46 | 47 | since = "1.0.0" 48 | __slots__ = () 49 | 50 | def description(self): 51 | return "kappa shape index 1" 52 | 53 | def calculate(self, Chi): 54 | P, A, Pmin = self._common(Chi) 55 | Pmax = 0.5 * A * (A - 1) 56 | 57 | with self.rethrow_zerodiv(): 58 | return 2 * Pmax * Pmin / (P * P) 59 | 60 | 61 | class KappaShapeIndex2(KappaShapeIndexBase): 62 | r"""Kappa shape index 2 descriptor. 63 | 64 | :returns: NaN when :math:`N_{\rm Chi-path} = 0` 65 | """ 66 | 67 | since = "1.0.0" 68 | __slots__ = () 69 | 70 | def description(self): 71 | return "kappa shape index 2" 72 | 73 | def calculate(self, Chi): 74 | P, A, Pmin = self._common(Chi) 75 | Pmax = 0.5 * (A - 1) * (A - 2) 76 | 77 | with self.rethrow_zerodiv(): 78 | return 2 * Pmax * Pmin / (P * P) 79 | 80 | 81 | class KappaShapeIndex3(KappaShapeIndexBase): 82 | r"""Kappa shape index 3 descriptor. 83 | 84 | :returns: NaN when :math:`N_{\rm Chi-path} = 0` 85 | """ 86 | 87 | since = "1.0.0" 88 | __slots__ = () 89 | 90 | def description(self): 91 | return "kappa shape index 3" 92 | 93 | def calculate(self, Chi): 94 | P, A, Pmin = self._common(Chi) 95 | 96 | if A % 2 == 0: 97 | Pmax = 0.25 * (A - 2) ** 2 98 | else: 99 | Pmax = 0.25 * (A - 1) * (A - 3) 100 | 101 | with self.rethrow_zerodiv(): 102 | return 4 * Pmax * Pmin / (P * P) 103 | -------------------------------------------------------------------------------- /mordred/Lipinski.py: -------------------------------------------------------------------------------- 1 | from ._base import Descriptor 2 | from .SLogP import SMR, SLogP 3 | from .Weight import Weight 4 | from .HydrogenBond import HBondDonor, HBondAcceptor 5 | 6 | __all__ = ("Lipinski", "GhoseFilter") 7 | 8 | 9 | class LipinskiLike(Descriptor): 10 | __slots__ = () 11 | 12 | @classmethod 13 | def preset(cls, version): 14 | yield cls() 15 | 16 | def parameters(self): 17 | return () 18 | 19 | def __str__(self): 20 | return self.__class__.__name__ 21 | 22 | rtype = bool 23 | 24 | 25 | class Lipinski(LipinskiLike): 26 | r"""Lipinski rule of 5 descriptor. 27 | 28 | LogP: SLogP 29 | """ 30 | 31 | since = "1.0.0" 32 | __slots__ = () 33 | 34 | def description(self): 35 | return "Lipinski rule of five" 36 | 37 | def dependencies(self): 38 | return { 39 | "HBAcc": HBondAcceptor(), 40 | "HBDon": HBondDonor(), 41 | "LogP": SLogP(), 42 | "MW": Weight(), 43 | } 44 | 45 | def calculate(self, LogP, MW, HBDon, HBAcc): 46 | return HBDon <= 5 and HBAcc <= 10 and MW <= 500 and LogP <= 5 47 | 48 | 49 | class GhoseFilter(LipinskiLike): 50 | r"""Ghose filter descriptor. 51 | 52 | LogP, MR: SLogP, SMR 53 | """ 54 | 55 | since = "1.0.0" 56 | __slots__ = () 57 | 58 | def description(self): 59 | return "Ghose filter" 60 | 61 | def dependencies(self): 62 | return {"LogP": SLogP(), "MR": SMR(), "MW": Weight()} 63 | 64 | def calculate(self, MW, LogP, MR): 65 | return ( 66 | (160 <= MW <= 480) 67 | and (20 <= self.mol.GetNumAtoms() <= 70) 68 | and (-0.4 <= LogP <= 5.6) 69 | and (40 <= MR <= 130) 70 | ) 71 | -------------------------------------------------------------------------------- /mordred/LogS.py: -------------------------------------------------------------------------------- 1 | # flake8: noqa: S1 2 | # -*- coding: UTF-8 -*- 3 | 4 | from __future__ import unicode_literals 5 | 6 | import math 7 | 8 | from rdkit import Chem 9 | 10 | from ._base import Descriptor 11 | from .Weight import Weight 12 | 13 | __all__ = ("LogS",) 14 | 15 | 16 | _smarts_logs = { 17 | "[NH0;X3;v3]": 0.71535, 18 | "[NH2;X3;v3]": 0.41056, 19 | "[nH0;X3]": 0.82535, 20 | "[OH0;X2;v2]": 0.31464, 21 | "[OH0;X1;v2]": 0.14787, 22 | "[OH1;X2;v2]": 0.62998, 23 | "[CH2;!R]": -0.35634, 24 | "[CH3;!R]": -0.33888, 25 | "[CH0;R]": -0.21912, 26 | "[CH2;R]": -0.23057, 27 | "[ch0]": -0.37570, 28 | "[ch1]": -0.22435, 29 | "F": -0.21728, 30 | "Cl": -0.49721, 31 | "Br": -0.57982, 32 | "I": -0.51547, 33 | } 34 | 35 | 36 | _smarts_logs_molecules = [ 37 | (Chem.MolFromSmarts(smarts), log) for smarts, log in _smarts_logs.items() 38 | ] 39 | 40 | 41 | class LogS(Descriptor): 42 | r"""Filter-it™ LogS descriptor. 43 | 44 | http://silicos-it.be.s3-website-eu-west-1.amazonaws.com/software/filter-it/1.0.2/filter-it.html#installation 45 | """ 46 | 47 | __slots__ = () 48 | 49 | since = "1.1.0" 50 | explicit_hydrogens = False 51 | kekulize = False 52 | 53 | @classmethod 54 | def preset(cls, version): 55 | yield cls() 56 | 57 | def dependencies(self): 58 | return {"MW": Weight(exact=False)} 59 | 60 | def description(self): 61 | return "Filter-it™ LogS" 62 | 63 | def __str__(self): 64 | return "FilterItLogS" 65 | 66 | def parameters(self): 67 | return () 68 | 69 | def calculate(self, MW): 70 | logS = 0.89823 - 0.10369 * math.sqrt(MW) 71 | for smarts, log in _smarts_logs_molecules: 72 | logS += len(self.mol.GetSubstructMatches(smarts)) * log 73 | 74 | return logS 75 | 76 | rtype = float 77 | -------------------------------------------------------------------------------- /mordred/McGowanVolume.py: -------------------------------------------------------------------------------- 1 | from ._base import Descriptor 2 | from ._atomic_property import get_mc_gowan_volume 3 | 4 | __all__ = ("McGowanVolume",) 5 | 6 | 7 | class McGowanVolume(Descriptor): 8 | r"""McGowan volume descriptor. 9 | 10 | References 11 | * :doi:`10.1007/BF02311772` 12 | 13 | """ 14 | 15 | since = "1.0.0" 16 | __slots__ = () 17 | 18 | def description(self): 19 | return "McGowan volume" 20 | 21 | @classmethod 22 | def preset(cls, version): 23 | yield cls() 24 | 25 | def __str__(self): 26 | return "VMcGowan" 27 | 28 | def parameters(self): 29 | return () 30 | 31 | def calculate(self): 32 | a = sum(get_mc_gowan_volume(a) for a in self.mol.GetAtoms()) 33 | return a - self.mol.GetNumBonds() * 6.56 34 | 35 | rtype = float 36 | -------------------------------------------------------------------------------- /mordred/MoRSE.py: -------------------------------------------------------------------------------- 1 | from __future__ import division 2 | 3 | from itertools import chain 4 | 5 | import numpy as np 6 | 7 | from ._graph_matrix import DistanceMatrix3D 8 | from ._atomic_property import AtomicProperty 9 | from ._base.descriptor import Descriptor 10 | 11 | __all__ = ("MoRSE",) 12 | 13 | 14 | class MoRSE(Descriptor): 15 | since = "1.0.0" 16 | __slots__ = ("_prop", "_distance") 17 | 18 | require_3D = True 19 | 20 | def description(self): 21 | return "3D-MoRSE{} (distance = {})".format( 22 | "" 23 | if self._prop is None 24 | else " weighted by {}".format(self._prop.get_long()), 25 | self._distance, 26 | ) 27 | 28 | @classmethod 29 | def preset(cls, version): 30 | return chain( 31 | (cls(None, i) for i in range(1, 33)), 32 | (cls("m", i) for i in range(1, 33)), 33 | (cls("v", i) for i in range(1, 33)), 34 | (cls("se", i) for i in range(1, 33)), 35 | (cls("p", i) for i in range(1, 33)), 36 | ) 37 | 38 | def __str__(self): 39 | p = "" if self._prop is None else self._prop.as_argument 40 | return "Mor{:02d}{}".format(self._distance, p) 41 | 42 | def parameters(self): 43 | p = None if self._prop is None else self._prop.as_argument 44 | return p, self._distance 45 | 46 | def __init__(self, prop=None, distance=2): 47 | if prop is None: 48 | self._prop = None 49 | else: 50 | self._prop = AtomicProperty(self.explicit_hydrogens, prop) 51 | 52 | self._distance = distance 53 | 54 | def dependencies(self): 55 | d = {"D": DistanceMatrix3D(self.explicit_hydrogens)} 56 | 57 | if self._prop is not None: 58 | d["A"] = self._prop 59 | 60 | return d 61 | 62 | def calculate(self, D, A=None): 63 | if D.shape[0] <= 1: 64 | self.fail(ValueError("require 2 or more atoms")) 65 | 66 | N = D.shape[0] 67 | 68 | if A is None: 69 | A = np.ones(N) 70 | else: 71 | A = A / self._prop.carbon 72 | 73 | A = A.reshape(1, -1) 74 | 75 | if self._distance == 1: 76 | n = np.ones((N, N), dtype="float") 77 | 78 | else: 79 | with self.rethrow_zerodiv(): 80 | sr = (self._distance - 1) * D 81 | np.fill_diagonal(sr, 1) 82 | n = np.sin(sr) / sr 83 | 84 | np.fill_diagonal(n, 0) 85 | 86 | return np.float(0.5 * A.dot(n).dot(A.T)) 87 | 88 | rtype = float 89 | -------------------------------------------------------------------------------- /mordred/MoeType.py: -------------------------------------------------------------------------------- 1 | from rdkit.Chem import MolSurf 2 | from rdkit.Chem.EState import EState_VSA as RDKit_EState_VSA 3 | 4 | from ._base import Descriptor 5 | 6 | __all__ = ("LabuteASA", "PEOE_VSA", "SMR_VSA", "SlogP_VSA", "EState_VSA", "VSA_EState") 7 | 8 | 9 | class LabuteASA(Descriptor): 10 | r"""Labute's Approximate Surface Area descriptor(rdkit wrapper).""" 11 | 12 | since = "1.0.0" 13 | __slots__ = () 14 | explicit_hydrogens = False 15 | 16 | def description(self): 17 | return "Labute's Approximate Surface Area" 18 | 19 | @classmethod 20 | def preset(cls, version): 21 | yield cls() 22 | 23 | def __str__(self): 24 | return self.__class__.__name__ 25 | 26 | def parameters(self): 27 | return () 28 | 29 | def calculate(self): 30 | return MolSurf.LabuteASA(self.mol) 31 | 32 | rtype = float 33 | 34 | 35 | class MoeTypeBase(Descriptor): 36 | __slots__ = ("_k",) 37 | explicit_hydrogens = False 38 | _module = MolSurf 39 | 40 | @classmethod 41 | def preset(cls, version): 42 | return map(cls, range(1, cls.k_max)) 43 | 44 | def description(self): 45 | return self._fn.__doc__ 46 | 47 | @property 48 | def _fn(self): 49 | return getattr(self._module, str(self)) 50 | 51 | def __str__(self): 52 | return self.__class__.__name__ + str(self._k) 53 | 54 | def parameters(self): 55 | return (self._k,) 56 | 57 | def __init__(self, k=1): 58 | assert 1 <= k <= self.k_max 59 | self._k = k 60 | 61 | def calculate(self): 62 | return self._fn(self.mol) 63 | 64 | rtype = float 65 | 66 | 67 | class PEOE_VSA(MoeTypeBase): 68 | r"""MOE type descriptors using gasteiger charge and surface area contribution(rdkit wrapper). 69 | 70 | :type k: int 71 | :param k: (:math:`1 <= k <= k_{\rm max}`) 72 | """ 73 | 74 | since = "1.0.0" 75 | __slots__ = () 76 | k_max = 14 77 | 78 | 79 | class SMR_VSA(MoeTypeBase): 80 | r"""MOE type descriptors using Wildman-Crippen MR and surface area contribution(rdkit wrapper). 81 | 82 | :type k: int 83 | :param k: (:math:`1 <= k <= k_{\rm max}`) 84 | """ 85 | 86 | since = "1.0.0" 87 | __slots__ = () 88 | k_max = 10 89 | 90 | 91 | class SlogP_VSA(MoeTypeBase): 92 | r"""MOE type descriptors using Wildman-Crippen LogP and surface area contribution(rdkit wrapper). 93 | 94 | :type k: int 95 | :param k: (:math:`1 <= k <= k_{\rm max}`) 96 | """ 97 | 98 | since = "1.0.0" 99 | __slots__ = () 100 | k_max = 12 101 | 102 | 103 | class EState_VSA(MoeTypeBase): 104 | r"""MOE type descriptors using EState indices and surface area contribution(rdkit wrapper). 105 | 106 | :type k: int 107 | :param k: (:math:`1 <= k <= k_{\rm max}`) 108 | """ 109 | 110 | since = "1.0.0" 111 | __slots__ = () 112 | _module = RDKit_EState_VSA 113 | k_max = 11 114 | 115 | 116 | class VSA_EState(MoeTypeBase): 117 | r"""MOE type descriptors using EState indices and surface area contribution(rdkit wrapper). 118 | 119 | :type k: int 120 | :param k: (:math:`1 <= k <= k_{\rm max}`) 121 | """ 122 | 123 | since = "1.0.0" 124 | __slots__ = () 125 | _module = RDKit_EState_VSA 126 | k_max = 10 127 | -------------------------------------------------------------------------------- /mordred/MolecularDistanceEdge.py: -------------------------------------------------------------------------------- 1 | from six import string_types, integer_types 2 | from numpy import product 3 | 4 | from ._base import Descriptor 5 | from ._graph_matrix import Valence, DistanceMatrix 6 | from ._atomic_property import GetAtomicNumber, GetElementSymbol 7 | 8 | __all__ = ("MolecularDistanceEdge",) 9 | 10 | 11 | _sp_dict = {1: "primary", 2: "secondary", 3: "tertiary", 4: "quaternary"} 12 | 13 | 14 | class MolecularDistanceEdge(Descriptor): 15 | r"""molecular distance edge descriptor. 16 | 17 | :type valence1: int 18 | :param valence1: valence of first atom 19 | 20 | :type valence2: int 21 | :param valence2: valence of second atom 22 | 23 | :type element: str or int 24 | :param element: atomic symbol or atomic number 25 | 26 | :returns: NaN when :math:`N_{\rm MDE} = 0` 27 | """ 28 | 29 | since = "1.0.0" 30 | __slots__ = ("_valence1", "_valence2", "_atomic_num") 31 | explicit_hydrogens = False 32 | 33 | def description(self): 34 | return "molecular distance edge between {a} {e} and {b} {e}".format( 35 | a=_sp_dict[self._valence1], 36 | b=_sp_dict[self._valence2], 37 | e=GetElementSymbol(self._atomic_num), 38 | ) 39 | 40 | @classmethod 41 | def preset(cls, version): 42 | return ( 43 | cls(a, b, e) 44 | for e in [6, 8, 7] 45 | for a in range(1, 11 - e) 46 | for b in range(a, 11 - e) 47 | ) 48 | 49 | def __str__(self): 50 | return "MDE{}-{}{}".format( 51 | GetElementSymbol(self._atomic_num), self._valence1, self._valence2 52 | ) 53 | 54 | def parameters(self): 55 | return self._valence1, self._valence2, GetElementSymbol(self._atomic_num) 56 | 57 | def __init__(self, valence1=1, valence2=1, element="C"): 58 | self._valence1 = min(valence1, valence2) 59 | self._valence2 = max(valence1, valence2) 60 | if isinstance(element, integer_types): 61 | self._atomic_num = element 62 | elif isinstance(element, string_types): 63 | self._atomic_num = GetAtomicNumber(element) 64 | else: 65 | raise ValueError("element must be atomic number or atomic symbol") 66 | 67 | def dependencies(self): 68 | return { 69 | "D": DistanceMatrix(self.explicit_hydrogens), 70 | "V": Valence(self.explicit_hydrogens), 71 | } 72 | 73 | def calculate(self, D, V): 74 | N = self.mol.GetNumAtoms() 75 | Dv = [ 76 | D[i, j] 77 | for i in range(N) 78 | for j in range(i + 1, N) 79 | if (V[i] == self._valence1 and V[j] == self._valence2) 80 | or (V[j] == self._valence1 and V[i] == self._valence2) 81 | if self.mol.GetAtomWithIdx(i).GetAtomicNum() 82 | == self.mol.GetAtomWithIdx(j).GetAtomicNum() 83 | == self._atomic_num 84 | ] 85 | n = len(Dv) 86 | 87 | with self.rethrow_zerodiv(): 88 | dx = product(Dv) ** (1.0 / (2.0 * n)) 89 | 90 | return n / (dx ** 2) 91 | 92 | rtype = float 93 | -------------------------------------------------------------------------------- /mordred/MomentOfInertia.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | 3 | from ._base import Descriptor 4 | from ._util import atoms_to_numpy 5 | 6 | __all__ = ("MomentOfInertia",) 7 | 8 | 9 | class MomentOfInertiaBase(Descriptor): 10 | __slots__ = () 11 | require_3D = True 12 | 13 | def _numpy(self): 14 | ws = atoms_to_numpy(lambda a: a.GetMass(), self.mol) 15 | ps = self.coord - np.sum(ws[:, np.newaxis] * self.coord, axis=0) / np.sum(ws) 16 | 17 | return ws, ps 18 | 19 | 20 | class PrincipalAxis(MomentOfInertiaBase): 21 | __slots__ = () 22 | 23 | def parameters(self): 24 | return () 25 | 26 | def calculate(self): 27 | ws, ps = self._numpy() 28 | 29 | i = np.sum( 30 | -ws[:, np.newaxis, np.newaxis] * (ps[:, np.newaxis] * ps[:, :, np.newaxis]), 31 | axis=0, 32 | ) 33 | 34 | diag = np.sum( 35 | ws[:, np.newaxis] * (np.sum(ps ** 2, axis=1)[:, np.newaxis] - ps ** 2), 36 | axis=0, 37 | ) 38 | 39 | np.fill_diagonal(i, diag) 40 | return np.sort(np.linalg.eig(i)[0])[::-1] 41 | 42 | 43 | class MomentOfInertia(MomentOfInertiaBase): 44 | since = "1.0.0" 45 | __slots__ = ("_axis",) 46 | 47 | def description(self): 48 | return "moment of inertia (axis = {})".format(self._axis) 49 | 50 | @classmethod 51 | def preset(cls, version): 52 | return map(cls, cls.axes) 53 | 54 | def __str__(self): 55 | return "MOMI-{}".format(self._axis) 56 | 57 | def parameters(self): 58 | return (self._axis,) 59 | 60 | axes = ("X", "Y", "Z") 61 | _axis_to_index = {a: i for i, a in enumerate(axes)} 62 | 63 | def __init__(self, axis="X"): 64 | assert axis in self.axes 65 | self._axis = axis 66 | 67 | def dependencies(self): 68 | return {"I": PrincipalAxis()} 69 | 70 | def calculate(self, I): 71 | return I[self._axis_to_index[self._axis]] 72 | 73 | rtype = float 74 | -------------------------------------------------------------------------------- /mordred/PBF.py: -------------------------------------------------------------------------------- 1 | from rdkit.Chem.rdMolDescriptors import CalcPBF 2 | 3 | from ._base import Descriptor 4 | 5 | __all__ = ("PBF",) 6 | 7 | 8 | class PBF(Descriptor): 9 | r"""PBF descriptor.""" 10 | 11 | __slots__ = () 12 | since = "1.1.2" 13 | require_3D = True 14 | 15 | @classmethod 16 | def preset(cls, version): 17 | yield cls() 18 | 19 | def description(self): 20 | return self.__class__.__name__ 21 | 22 | def __str__(self): 23 | return self.__class__.__name__ 24 | 25 | def parameters(self): 26 | return () 27 | 28 | def calculate(self): 29 | return CalcPBF(self.get_3D_mol()) 30 | 31 | rtype = float 32 | -------------------------------------------------------------------------------- /mordred/Polarizability.py: -------------------------------------------------------------------------------- 1 | from ._base import Descriptor 2 | from ._atomic_property import polarizability78, polarizability94 3 | 4 | __all__ = ("APol", "BPol") 5 | 6 | 7 | class PolarizabilityBase(Descriptor): 8 | __slots__ = ("_use78",) 9 | 10 | @classmethod 11 | def preset(cls, version): 12 | yield cls() 13 | 14 | def __str__(self): 15 | return self.__class__.__name__.lower() + ("78" if self._use78 else "") 16 | 17 | def parameters(self): 18 | return (self._use78,) 19 | 20 | def __init__(self, use78=False): 21 | self._use78 = use78 22 | 23 | def _get_table(self): 24 | return polarizability78 if self._use78 else polarizability94 25 | 26 | rtype = float 27 | 28 | 29 | class APol(PolarizabilityBase): 30 | r"""atomic polarizability descriptor. 31 | 32 | :type use78: bool 33 | :param use78: use old atomic polarizability data 34 | """ 35 | 36 | since = "1.0.0" 37 | __slots__ = () 38 | 39 | def description(self): 40 | return "atomic polarizability" 41 | 42 | def calculate(self): 43 | table = self._get_table() 44 | return sum(table[a.GetAtomicNum()] for a in self.mol.GetAtoms()) 45 | 46 | 47 | class BPol(PolarizabilityBase): 48 | r"""bond polarizability descriptor. 49 | 50 | :type use78: bool 51 | :param use78: use old atomic polarizability data 52 | """ 53 | 54 | since = "1.0.0" 55 | __slots__ = () 56 | 57 | def description(self): 58 | return "bond polarizability" 59 | 60 | def calculate(self): 61 | table = self._get_table() 62 | 63 | def bond_pol(bond): 64 | a = bond.GetBeginAtom().GetAtomicNum() 65 | b = bond.GetEndAtom().GetAtomicNum() 66 | return abs(table[a] - table[b]) 67 | 68 | return float(sum(bond_pol(b) for b in self.mol.GetBonds())) 69 | -------------------------------------------------------------------------------- /mordred/RotatableBond.py: -------------------------------------------------------------------------------- 1 | from rdkit.Chem.rdMolDescriptors import CalcNumRotatableBonds 2 | 3 | from ._base import Descriptor 4 | from .BondCount import BondCount 5 | 6 | __all__ = ("RotatableBondsCount", "RotatableBondsRatio") 7 | 8 | 9 | class RotatableBondsBase(Descriptor): 10 | __slots__ = () 11 | explicit_hydrogens = False 12 | 13 | @classmethod 14 | def preset(cls, version): 15 | yield cls() 16 | 17 | def parameters(self): 18 | return () 19 | 20 | 21 | class RotatableBondsCount(RotatableBondsBase): 22 | r"""rotatable bonds count descriptor(rdkit wrapper).""" 23 | 24 | since = "1.0.0" 25 | __slots__ = () 26 | 27 | def description(self): 28 | return "rotatable bonds count" 29 | 30 | def __str__(self): 31 | return "nRot" 32 | 33 | def calculate(self): 34 | return CalcNumRotatableBonds(self.mol) 35 | 36 | rtype = int 37 | 38 | 39 | class RotatableBondsRatio(RotatableBondsBase): 40 | r"""rotatable bonds ratio descriptor. 41 | 42 | .. math:: 43 | {\rm RotRatio} = \frac{N_{\rm rotatable bonds}}{N_{\rm bonds}} 44 | 45 | :returns: NaN when :math:`N_{\rm bonds} = 0` 46 | """ 47 | 48 | since = "1.0.0" 49 | __slots__ = () 50 | 51 | def description(self): 52 | return "rotatable bonds ratio" 53 | 54 | def __str__(self): 55 | return "RotRatio" 56 | 57 | def dependencies(self): 58 | return {"nB": BondCount("heavy"), "nRot": RotatableBondsCount()} 59 | 60 | def calculate(self, nRot, nB): 61 | with self.rethrow_zerodiv(): 62 | return float(nRot) / float(nB) 63 | 64 | rtype = float 65 | -------------------------------------------------------------------------------- /mordred/SLogP.py: -------------------------------------------------------------------------------- 1 | r"""Wildman-Crippen LogP/MR descriptor. 2 | 3 | References 4 | * :doi:`10.1021/ci990307l` 5 | 6 | """ 7 | from rdkit.Chem import Crippen 8 | 9 | from ._base import Descriptor 10 | 11 | __all__ = ("SLogP", "SMR") 12 | 13 | 14 | class WildmanCrippenBase(Descriptor): 15 | __slots__ = () 16 | 17 | @classmethod 18 | def preset(cls, version): 19 | yield cls() 20 | 21 | def __str__(self): 22 | return self.__class__.__name__ 23 | 24 | def parameters(self): 25 | return () 26 | 27 | explicit_hydrogens = False 28 | 29 | rtype = float 30 | 31 | 32 | class SLogP(WildmanCrippenBase): 33 | r"""Wildman-Crippen LogP descriptor(rdkit wrapper).""" 34 | 35 | since = "1.0.0" 36 | __slots__ = () 37 | 38 | def description(self): 39 | return "Wildman-Crippen LogP" 40 | 41 | def calculate(self): 42 | return Crippen.MolLogP(self.mol) 43 | 44 | 45 | class SMR(WildmanCrippenBase): 46 | r"""Wildman-Crippen MR descriptor(rdkit wrapper).""" 47 | 48 | since = "1.0.0" 49 | __slots__ = () 50 | 51 | def description(self): 52 | return "Wildman-Crippen MR" 53 | 54 | def calculate(self): 55 | return Crippen.MolMR(self.mol) 56 | -------------------------------------------------------------------------------- /mordred/TopologicalCharge.py: -------------------------------------------------------------------------------- 1 | from itertools import chain 2 | 3 | import numpy as np 4 | from six import integer_types 5 | 6 | from ._base import Descriptor 7 | from ._graph_matrix import DistanceMatrix, AdjacencyMatrix 8 | 9 | __all__ = ("TopologicalCharge",) 10 | 11 | 12 | class ChargeTermMatrix(Descriptor): 13 | __slots__ = () 14 | explicit_hydrogens = False 15 | 16 | def parameters(self): 17 | return () 18 | 19 | def dependencies(self): 20 | return { 21 | "A": AdjacencyMatrix(self.explicit_hydrogens), 22 | "D": DistanceMatrix(self.explicit_hydrogens), 23 | } 24 | 25 | def calculate(self, A, D): 26 | D2 = D.copy() 27 | D2[D2 != 0] **= -2 28 | np.fill_diagonal(D2, 0) 29 | 30 | M = A.dot(D2) 31 | return M - M.T 32 | 33 | 34 | class TopologicalCharge(Descriptor): 35 | r"""topological charge descriptor. 36 | 37 | :type type: str 38 | :param type: 39 | * "raw": sum of order-distance atom pairs coefficient 40 | * "mean": mean of order-distance atom pairs coefficient 41 | * "global": sum of mean-topoCharge over 0 to order 42 | 43 | :type order: int 44 | :param order: int 45 | 46 | References 47 | * :doi:`10.1021/ci00019a008` 48 | 49 | """ 50 | 51 | since = "1.0.0" 52 | __slots__ = ("_type", "_order") 53 | 54 | explicit_hydrogens = False 55 | 56 | tc_types = ("global", "mean", "raw") 57 | 58 | def description(self): 59 | return "{}-ordered {} topological charge".format(self._order, self._type) 60 | 61 | @classmethod 62 | def preset(cls, version): 63 | return chain( 64 | (cls(t, o) for t in ("raw", "mean") for o in range(1, 11)), 65 | [cls("global", 10)], 66 | ) 67 | 68 | def __str__(self): 69 | if self._type == "global": 70 | return "JGT{}".format(self._order) 71 | elif self._type == "mean": 72 | return "JGI{}".format(self._order) 73 | else: 74 | return "GGI{}".format(self._order) 75 | 76 | def parameters(self): 77 | return self._type, self._order 78 | 79 | def __init__(self, type="global", order=10): 80 | assert type in self.tc_types 81 | assert type == "global" or isinstance(order, integer_types) 82 | 83 | self._type = type 84 | self._order = order 85 | 86 | def dependencies(self): 87 | return {"CT": ChargeTermMatrix(), "D": DistanceMatrix(self.explicit_hydrogens)} 88 | 89 | def calculate(self, CT, D): 90 | D = D * np.tri(*D.shape) 91 | D[D == 0] = np.inf 92 | 93 | f = D <= self._order if self._type == "global" else D == self._order 94 | 95 | CT = CT[f] 96 | 97 | if self._type == "raw": 98 | return np.abs(CT).sum() 99 | 100 | # create frequency vector 101 | Df = D[f] 102 | C = Df.copy() 103 | for i in np.unique(Df): 104 | C[Df == i] = len(Df[Df == i]) 105 | 106 | return np.abs(CT / C).sum() 107 | 108 | rtype = float 109 | -------------------------------------------------------------------------------- /mordred/TopologicalIndex.py: -------------------------------------------------------------------------------- 1 | from __future__ import division 2 | 3 | from ._base import Descriptor 4 | from ._graph_matrix import Radius as CRadius 5 | from ._graph_matrix import Diameter as CDiameter 6 | 7 | __all__ = ("Diameter", "Radius", "TopologicalShapeIndex", "PetitjeanIndex") 8 | 9 | 10 | class TopologicalIndexBase(Descriptor): 11 | __slots__ = () 12 | explicit_hydrogens = False 13 | 14 | @classmethod 15 | def preset(cls, version): 16 | yield cls() 17 | 18 | def parameters(self): 19 | return () 20 | 21 | rtype = int 22 | 23 | 24 | class Radius(TopologicalIndexBase): 25 | r"""radius descriptor.""" 26 | 27 | since = "1.0.0" 28 | __slots__ = () 29 | 30 | def description(self): 31 | return "topological radius" 32 | 33 | def __str__(self): 34 | return "Radius" 35 | 36 | def dependencies(self): 37 | return {"R": CRadius(self.explicit_hydrogens)} 38 | 39 | def calculate(self, R): 40 | return int(R) 41 | 42 | 43 | class Diameter(TopologicalIndexBase): 44 | r"""diameter descriptor.""" 45 | 46 | since = "1.0.0" 47 | __slots__ = () 48 | 49 | def description(self): 50 | return "topological diameter" 51 | 52 | def __str__(self): 53 | return "Diameter" 54 | 55 | def dependencies(self): 56 | return {"D": CDiameter(self.explicit_hydrogens)} 57 | 58 | def calculate(self, D): 59 | return int(D) 60 | 61 | 62 | class TopologicalShapeIndex(TopologicalIndexBase): 63 | r"""topological shape index descriptor. 64 | 65 | .. math:: 66 | 67 | I_{\rm topo} = \frac{D - R}{R} 68 | 69 | where 70 | :math:`R` is graph radius, 71 | :math:`D` is graph diameter. 72 | 73 | :returns: NaN when :math:`R = 0` 74 | """ 75 | 76 | since = "1.0.0" 77 | __slots__ = () 78 | 79 | def description(self): 80 | return "topological shape index" 81 | 82 | def __str__(self): 83 | return "TopoShapeIndex" 84 | 85 | def dependencies(self): 86 | return { 87 | "D": CDiameter(self.explicit_hydrogens), 88 | "R": CRadius(self.explicit_hydrogens), 89 | } 90 | 91 | def calculate(self, R, D): 92 | with self.rethrow_zerodiv(): 93 | return (D - R) / R 94 | 95 | rtype = float 96 | 97 | 98 | class PetitjeanIndex(TopologicalShapeIndex): 99 | r"""Petitjean index descriptor. 100 | 101 | .. math:: 102 | 103 | I_{\rm Petitjean} = \frac{D - R}{D} 104 | 105 | where 106 | :math:`R` is graph radius, 107 | :math:`D` is graph diameter. 108 | 109 | :returns: NaN when :math:`D = 0` 110 | """ 111 | 112 | since = "1.0.0" 113 | __slots__ = () 114 | 115 | def description(self): 116 | return "Petitjean index" 117 | 118 | def __str__(self): 119 | return "PetitjeanIndex" 120 | 121 | def calculate(self, R, D): 122 | with self.rethrow_zerodiv(): 123 | return (D - R) / D 124 | -------------------------------------------------------------------------------- /mordred/VdwVolumeABC.py: -------------------------------------------------------------------------------- 1 | from math import pi 2 | 3 | from ._base import Descriptor 4 | from .BondCount import BondCount 5 | from .RingCount import RingCount 6 | from ._atomic_property import GetAtomicNumber 7 | 8 | __all__ = ("VdwVolumeABC",) 9 | 10 | 11 | bondi_radii = { 12 | "H": 1.20, 13 | "C": 1.70, # noqa: S001 14 | "N": 1.55, 15 | "O": 1.52, 16 | "F": 1.47, # noqa: S001 17 | "Cl": 1.75, # noqa: S001 18 | "Br": 1.85, # noqa: S001 19 | "P": 1.80, 20 | "S": 1.80, 21 | "As": 1.85, # noqa: S001 22 | "B": 2.13, 23 | "Si": 2.10, 24 | "Se": 1.90, # noqa: S001 25 | } 26 | 27 | 28 | atom_contrib = { 29 | GetAtomicNumber(s): 4.0 / 3.0 * pi * r ** 3 for s, r in bondi_radii.items() 30 | } 31 | 32 | 33 | class VdwVolumeABC(Descriptor): 34 | r"""van der waals volume(ABC) descriptor. 35 | 36 | :returns: NaN when any atoms are non-compat_atoms 37 | 38 | References 39 | * :doi:`10.1021/jo034808o` 40 | 41 | """ 42 | 43 | since = "1.0.0" 44 | __slots__ = () 45 | 46 | def description(self): 47 | return "ABC van der waals volume" 48 | 49 | compat_atoms = tuple(bondi_radii) 50 | 51 | @classmethod 52 | def preset(cls, version): 53 | yield cls() 54 | 55 | def __str__(self): 56 | return "Vabc" 57 | 58 | def parameters(self): 59 | return () 60 | 61 | def dependencies(self): 62 | return { 63 | "NRA": RingCount(None, False, False, False, None), 64 | "NRa": RingCount(None, False, False, True, None), 65 | "Nb": BondCount(), 66 | } 67 | 68 | def calculate(self, Nb, NRa, NRA): 69 | try: 70 | ac = sum(atom_contrib[a.GetAtomicNum()] for a in self.mol.GetAtoms()) 71 | except KeyError: 72 | self.fail(ValueError("unknown atom type")) 73 | 74 | return ac - 5.92 * Nb - 14.7 * NRa - 3.8 * NRA 75 | 76 | rtype = float 77 | -------------------------------------------------------------------------------- /mordred/VertexAdjacencyInformation.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | 3 | from ._base import Descriptor 4 | 5 | __all__ = ("VertexAdjacencyInformation",) 6 | 7 | 8 | class VertexAdjacencyInformation(Descriptor): 9 | r"""vertex adjacency information descriptor. 10 | 11 | .. math:: 12 | {\rm VAdjMat} = 1 + \log_2(m) 13 | 14 | where :math:`m` is number of heavy-heavy bonds. 15 | 16 | :returns: :math:`m = 0` 17 | """ 18 | 19 | since = "1.0.0" 20 | __slots__ = () 21 | 22 | def description(self): 23 | return "vertex adjacency information" 24 | 25 | @classmethod 26 | def preset(cls, version): 27 | yield cls() 28 | 29 | explicit_hydrogens = False 30 | 31 | def __str__(self): 32 | return "VAdjMat" 33 | 34 | def parameters(self): 35 | return () 36 | 37 | def calculate(self): 38 | m = sum( 39 | 1 40 | for b in self.mol.GetBonds() 41 | if b.GetBeginAtom().GetAtomicNum() != 1 42 | and b.GetEndAtom().GetAtomicNum() != 1 43 | ) 44 | 45 | with self.rethrow_zerodiv(): 46 | return 1 + np.log2(m) 47 | 48 | rtype = float 49 | -------------------------------------------------------------------------------- /mordred/WalkCount.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | 3 | from ._base import Descriptor 4 | from ._graph_matrix import AdjacencyMatrix 5 | 6 | __all__ = ("WalkCount",) 7 | 8 | 9 | class WalkCount(Descriptor): 10 | r"""walk count descriptor. 11 | 12 | :type order: int 13 | :param order: walk length 14 | 15 | :type total: bool 16 | :param total: sum of walk count over 1 to order 17 | 18 | :type self_returning: bool 19 | :param self_returning: use self returning walk only 20 | """ 21 | 22 | since = "1.0.0" 23 | __slots__ = ("_order", "_total", "_self_returning") 24 | 25 | explicit_hydrogens = False 26 | 27 | def description(self): 28 | return "{}walk count (leg-{}{})".format( 29 | "total " if self._total else "", 30 | self._order, 31 | ", only self returning walk" if self._self_returning else "", 32 | ) 33 | 34 | @classmethod 35 | def preset(cls, version): 36 | for start, sr in [(1, False), (2, True)]: 37 | for l in range(start, 11): 38 | yield cls(l, False, sr) 39 | 40 | yield cls(10, True, sr) 41 | 42 | def __str__(self): 43 | T = "{}SRW{:02d}" if self._self_returning else "{}MWC{:02d}" 44 | return T.format("T" if self._total else "", self._order) 45 | 46 | def parameters(self): 47 | return self._order, self._total, self._self_returning 48 | 49 | def __init__(self, order=1, total=False, self_returning=False): 50 | self._order = order 51 | self._total = total 52 | self._self_returning = self_returning 53 | 54 | def dependencies(self): 55 | if self._total: 56 | d = {} 57 | d["W"] = self.__class__(self._order, False, self._self_returning) 58 | 59 | if self._order > 1: 60 | d["T"] = self.__class__(self._order - 1, True, self._self_returning) 61 | 62 | return d 63 | 64 | return {"An": AdjacencyMatrix(self.explicit_hydrogens, order=self._order)} 65 | 66 | def calculate(self, An=None, T=None, W=None): 67 | if self._total: 68 | if self._order == 1: 69 | return self.mol.GetNumAtoms() + W 70 | 71 | return T + W 72 | 73 | if self._self_returning: 74 | return np.log(An.trace() + 1) 75 | 76 | else: 77 | if self._order == 1: 78 | return 0.5 * An.sum() 79 | 80 | return np.log(An.sum() + 1) 81 | 82 | rtype = float 83 | -------------------------------------------------------------------------------- /mordred/Weight.py: -------------------------------------------------------------------------------- 1 | from rdkit.Chem.Descriptors import MolWt, ExactMolWt 2 | 3 | from ._base import Descriptor 4 | 5 | __all__ = ("Weight",) 6 | 7 | 8 | class Weight(Descriptor): 9 | r"""molecular weight descriptor. 10 | 11 | :type averaged: bool 12 | :param averaged: averaged by number of atom 13 | """ 14 | 15 | def description(self): 16 | return "{}{}molecular weight".format( 17 | "averaged " if self._averaged else "", "exact " if self._exact else "" 18 | ) 19 | 20 | since = "1.0.0" 21 | __slots__ = ("_averaged", "_exact") 22 | explicit_hydrogens = True 23 | 24 | @classmethod 25 | def preset(cls, version): 26 | yield cls(True, False) 27 | yield cls(True, True) 28 | 29 | def __str__(self): 30 | return "{}{}MW".format( 31 | "A" if self._averaged else "", "" if self._exact else "a" 32 | ) 33 | 34 | def parameters(self): 35 | return self._exact, self._averaged 36 | 37 | def __init__(self, exact=True, averaged=False): 38 | self._averaged = averaged 39 | self._exact = exact 40 | 41 | def calculate(self): 42 | w = ExactMolWt(self.mol) if self._exact else MolWt(self.mol) 43 | if self._averaged: 44 | w /= self.mol.GetNumAtoms() 45 | 46 | return w 47 | 48 | rtype = float 49 | -------------------------------------------------------------------------------- /mordred/WienerIndex.py: -------------------------------------------------------------------------------- 1 | from ._base import Descriptor 2 | from ._graph_matrix import DistanceMatrix 3 | 4 | __all__ = ("WienerIndex",) 5 | 6 | 7 | class WienerIndex(Descriptor): 8 | r"""Wiener index. 9 | 10 | :type polarity: bool 11 | :param polarity: use polarity Wiener index 12 | """ 13 | 14 | __slots__ = ("_polarity",) 15 | since = "1.0.0" 16 | explicit_hydrogens = False 17 | 18 | def description(self): 19 | return "Wiener {}index".format("polarity " if self._polarity else "") 20 | 21 | @classmethod 22 | def preset(cls, version): 23 | yield cls(False) 24 | yield cls(True) 25 | 26 | def __str__(self): 27 | return "WPol" if self._polarity else "WPath" 28 | 29 | def parameters(self): 30 | return (self._polarity,) 31 | 32 | def __init__(self, polarity=False): 33 | self._polarity = polarity 34 | 35 | def dependencies(self): 36 | return {"D": DistanceMatrix(self.explicit_hydrogens)} 37 | 38 | def calculate(self, D): 39 | if self._polarity: 40 | return int(0.5 * (D == 3).sum()) 41 | else: 42 | return int(0.5 * D.sum()) 43 | 44 | rtype = int 45 | -------------------------------------------------------------------------------- /mordred/ZagrebIndex.py: -------------------------------------------------------------------------------- 1 | from ._base import Descriptor 2 | from ._graph_matrix import Valence 3 | 4 | __all__ = ("ZagrebIndex",) 5 | 6 | 7 | class ZagrebIndex(Descriptor): 8 | r"""Zagreb index descriptor. 9 | 10 | .. math:: 11 | 12 | {}^\lambda M_1 = \sum_{atoms} d_i^\lambda 13 | 14 | {}^\lambda M_2 = \sum_{edges} \left(d_i \cdot d_j \right)^\lambda 15 | 16 | where 17 | :math:`d_i` is degree of i-th atom 18 | 19 | :type version: int 20 | :param version: Zagreb index version. 1 or 2. 21 | 22 | :type variable: int 23 | :param variable: lambda value. 24 | 25 | :returns: NaN when valence of any atoms are 0 26 | """ 27 | 28 | since = "1.0.0" 29 | __slots__ = ("_version", "_variable") 30 | explicit_hydrogens = False 31 | 32 | def description(self): 33 | if self._variable == 1: 34 | return "Zagreb index (version {})".format(self._version) 35 | elif self._variable == -1: 36 | return "modified Zagreb index (version {})".format(self._version) 37 | else: 38 | return "Zagreb like index (lambda = {}, version {})".format( 39 | self._variable, self._version 40 | ) 41 | 42 | @classmethod 43 | def preset(cls, version): 44 | return (cls(v, x) for x in [1, -1] for v in [1, 2]) 45 | 46 | def __str__(self): 47 | if self._variable in {1, -1}: 48 | m = "" if self._variable == 1 else "m" 49 | return "{}Zagreb{}".format(m, self._version) 50 | 51 | return "Zagreb{}_{}".format(self._version, self._variable) 52 | 53 | def parameters(self): 54 | return self._version, self._variable 55 | 56 | def __init__(self, version=1, variable=1): 57 | assert version in {1, 2} 58 | self._version = version 59 | self._variable = variable 60 | 61 | def dependencies(self): 62 | return {"V": Valence(self.explicit_hydrogens)} 63 | 64 | def calculate(self, V): 65 | V = V.astype("float") 66 | 67 | if self._version == 1: 68 | with self.rethrow_zerodiv(): 69 | return (V ** (self._variable * 2)).sum() 70 | else: 71 | return float( 72 | sum( 73 | (V[b.GetBeginAtomIdx()] * V[b.GetEndAtomIdx()]) ** self._variable 74 | for b in self.mol.GetBonds() 75 | ) 76 | ) 77 | 78 | rtype = float 79 | -------------------------------------------------------------------------------- /mordred/__init__.py: -------------------------------------------------------------------------------- 1 | r"""modred descriptor calculator.""" 2 | 3 | from ._base import ( 4 | Result, 5 | Calculator, 6 | Descriptor, 7 | is_missing, 8 | get_descriptors_in_module, 9 | get_descriptors_from_module, 10 | ) 11 | from ._version import __version__ 12 | 13 | __all__ = ( 14 | "__version__", 15 | "Descriptor", 16 | "Calculator", 17 | "get_descriptors_from_module", 18 | "get_descriptors_in_module", 19 | "is_missing", 20 | "Result", 21 | ) 22 | -------------------------------------------------------------------------------- /mordred/_base/__init__.py: -------------------------------------------------------------------------------- 1 | """Mordred base package.""" 2 | 3 | from .util import is_missing 4 | from ..error import MissingValueBase 5 | from .result import Result 6 | from .parallel import parallel 7 | from .calculator import ( 8 | Calculator, 9 | get_descriptors_in_module, 10 | get_descriptors_from_module, 11 | ) 12 | from .descriptor import ( 13 | Descriptor, 14 | ConstDescriptor, 15 | UnaryOperatingDescriptor, 16 | BinaryOperatingDescriptor, 17 | ) 18 | 19 | __all__ = ( 20 | "Descriptor", 21 | "Calculator", 22 | "get_descriptors_from_module", 23 | "get_descriptors_in_module", 24 | "is_missing", 25 | "Result", 26 | ) 27 | 28 | 29 | def _Descriptor__call__(self, mol, id=-1): 30 | r"""Calculate single descriptor value. 31 | 32 | :type id: int 33 | :param id: conformer id 34 | 35 | :returns: descriptor result 36 | :rtype: scalar 37 | """ 38 | v = Calculator(self)(mol, id)[0] 39 | if isinstance(v, MissingValueBase): 40 | raise v.error 41 | 42 | return v 43 | 44 | 45 | def _from_json(obj, descs): 46 | name = obj.get("name") 47 | args = obj.get("args") or {} 48 | if name is None: 49 | raise ValueError("invalid json: {}".format(obj)) 50 | 51 | if name == UnaryOperatingDescriptor.__name__: 52 | return UnaryOperatingDescriptor( 53 | args["name"], args["operator"], _from_json(args["value"]) 54 | ) 55 | 56 | elif name == BinaryOperatingDescriptor.__name__: 57 | return BinaryOperatingDescriptor( 58 | args["name"], 59 | args["operator"], 60 | _from_json(args["left"]), 61 | _from_json(args["right"]), 62 | ) 63 | 64 | cls = descs.get(name) 65 | if cls is None: 66 | raise ValueError("unknown class: {}".format(name)) 67 | 68 | instance = cls(**(obj.get("args") or {})) 69 | return instance 70 | 71 | 72 | @classmethod 73 | def _Descriptor_from_json(self, obj): 74 | """Create Descriptor instance from json dict. 75 | 76 | Parameters: 77 | obj(dict): descriptor dict 78 | 79 | Returns: 80 | Descriptor: descriptor 81 | 82 | """ 83 | descs = getattr(self, "_all_descriptors", None) 84 | 85 | if descs is None: 86 | from mordred import descriptors 87 | 88 | descs = {cls.__name__: cls for cls in get_descriptors_in_module(descriptors)} 89 | descs[ConstDescriptor.__name__] = ConstDescriptor 90 | self._all_descriptors = descs 91 | 92 | return _from_json(obj, descs) 93 | 94 | 95 | Descriptor.__call__ = _Descriptor__call__ 96 | Descriptor.from_json = _Descriptor_from_json 97 | Calculator._parallel = parallel 98 | -------------------------------------------------------------------------------- /mordred/_base/context.py: -------------------------------------------------------------------------------- 1 | from rdkit import Chem 2 | 3 | from .._util import conformer_to_numpy 4 | from ..error import Missing3DCoordinate 5 | 6 | 7 | class Context(object): 8 | __slots__ = "_mols", "_coords", "n_frags", "name", "_stack", "config" 9 | 10 | def __init__(self, mols, coords, n_frags, name, config): 11 | self._mols = mols 12 | self._coords = coords 13 | self.n_frags = n_frags 14 | self.name = name 15 | self.config = config 16 | 17 | def __reduce_ex__(self, version): 18 | return ( 19 | self.__class__, 20 | (self._mols, self._coords, self.n_frags, self.name, self.config), 21 | ) 22 | 23 | def __str__(self): 24 | return self.name 25 | 26 | __tf = {True, False} 27 | 28 | @classmethod 29 | def from_query(cls, mol, require_3D, explicit_hydrogens, kekulizes, id, config): 30 | if not isinstance(mol, Chem.Mol): 31 | raise TypeError("{!r} is not rdkit.Chem.Mol instance".format(mol)) 32 | 33 | n_frags = len(Chem.GetMolFrags(mol)) 34 | 35 | if mol.HasProp("_Name"): 36 | name = mol.GetProp("_Name") 37 | else: 38 | name = Chem.MolToSmiles(Chem.RemoveHs(mol, updateExplicitCount=True)) 39 | 40 | mols, coords = {}, {} 41 | 42 | for eh, ke in ((eh, ke) for eh in explicit_hydrogens for ke in kekulizes): 43 | m = Chem.AddHs(mol) if eh else Chem.RemoveHs(mol, updateExplicitCount=True) 44 | 45 | if ke: 46 | Chem.Kekulize(m) 47 | 48 | if require_3D: 49 | try: 50 | conf = m.GetConformer(id) 51 | if conf.Is3D(): 52 | coords[eh, ke] = conformer_to_numpy(conf) 53 | except ValueError: 54 | pass 55 | 56 | m.RemoveAllConformers() 57 | mols[eh, ke] = m 58 | 59 | return cls(mols, coords, n_frags, name, config) 60 | 61 | @classmethod 62 | def from_calculator(cls, calc, mol, id): 63 | return cls.from_query( 64 | mol, 65 | calc._require_3D, 66 | calc._explicit_hydrogens, 67 | calc._kekulizes, 68 | id, 69 | calc._config, 70 | ) 71 | 72 | def get_coord(self, desc): 73 | try: 74 | return self._coords[desc.explicit_hydrogens, desc.kekulize] 75 | except KeyError: 76 | desc.fail(Missing3DCoordinate()) 77 | 78 | def get_mol(self, desc): 79 | return self._mols[desc.explicit_hydrogens, desc.kekulize] 80 | 81 | def reset(self): 82 | self._stack = [] 83 | 84 | def add_stack(self, d): 85 | self._stack.append(d) 86 | 87 | def get_stack(self): 88 | return self._stack 89 | -------------------------------------------------------------------------------- /mordred/_base/pandas_module.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | from pandas import Series, DataFrame 3 | 4 | from .util import is_missing 5 | 6 | __all__ = ("MordredDataFrame", "Series") 7 | 8 | 9 | class MordredDataFrame(DataFrame): 10 | @property 11 | def _constructor(self): 12 | return self.__class__ 13 | 14 | def fill_missing(self, value=np.nan, inplace=False): 15 | t = self if inplace else self.copy() 16 | 17 | t[t.applymap(is_missing)] = value 18 | return t 19 | -------------------------------------------------------------------------------- /mordred/_base/parallel.py: -------------------------------------------------------------------------------- 1 | from itertools import islice 2 | from collections import deque 3 | from multiprocessing import Pool, Manager 4 | 5 | from .._util import Capture 6 | from .context import Context 7 | 8 | calculator = None 9 | 10 | 11 | def worker(calc_proxy, cxt): 12 | global calculator 13 | if calculator is None: 14 | calculator = calc_proxy[0] 15 | 16 | with Capture() as capture: 17 | r = list(calculator._calculate(cxt)) 18 | 19 | return r, capture.result 20 | 21 | 22 | class MolPool(object): 23 | def __init__(self, calc, nproc): 24 | self.pool = Pool(nproc) 25 | self.mgr = Manager() 26 | self.calc = calc 27 | self.calc_proxy = self.mgr.list([calc]) 28 | self.nproc = nproc 29 | 30 | def __enter__(self): 31 | self.mgr.__enter__() 32 | return self 33 | 34 | def __exit__(self, *args, **kwargs): 35 | self.pool.terminate() 36 | self.mgr.__exit__(*args, **kwargs) 37 | 38 | def map(self, mols, id): 39 | return MolIterator(self, mols, id, self.nproc * 2 + 10) 40 | 41 | def submit(self, mol, id): 42 | cxt = Context.from_calculator(self.calc, mol, id) 43 | return self.pool.apply_async(worker, (self.calc_proxy, cxt)) 44 | 45 | 46 | class MolIterator(object): 47 | def __init__(self, pool, mols, id, buf): 48 | self.pool = pool 49 | self.futures = deque() 50 | self.mols = iter(mols) 51 | self.id = id 52 | 53 | for mol in islice(self.mols, buf): 54 | self.submit(mol) 55 | 56 | def submit(self, mol): 57 | self.futures.append((mol, self.pool.submit(mol, self.id))) 58 | 59 | def __iter__(self): 60 | return self 61 | 62 | def __next__(self): 63 | try: 64 | self.submit(next(self.mols)) 65 | except StopIteration: 66 | pass 67 | 68 | try: 69 | mol, fut = self.futures.popleft() 70 | return mol, fut.get() 71 | except IndexError: 72 | raise StopIteration 73 | 74 | next = __next__ 75 | 76 | 77 | def parallel(calc, mols, nproc, nmols, quiet, ipynb, id): 78 | with MolPool(calc, nproc) as pool, calc._progress(quiet, nmols, ipynb) as bar: 79 | for mol, (r, err) in pool.map(mols, id): 80 | for e in err: 81 | e = e.rstrip() 82 | if not e: 83 | continue 84 | 85 | bar.write(e) 86 | 87 | yield calc._wrap_result(mol, r) 88 | bar.update() 89 | -------------------------------------------------------------------------------- /mordred/_base/util.py: -------------------------------------------------------------------------------- 1 | from ..error import MissingValueBase 2 | 3 | 4 | def is_missing(v): 5 | """Check argument is either MissingValue or not. 6 | 7 | >>> from mordred.error import Missing, Error 8 | >>> is_missing(1) 9 | False 10 | >>> is_missing(Missing(ValueError("missing"), ())) 11 | True 12 | >>> is_missing(Error(ValueError("error"), ())) 13 | True 14 | 15 | Parameters: 16 | v(any): value 17 | 18 | Returns: 19 | bool 20 | 21 | """ 22 | return isinstance(v, MissingValueBase) 23 | -------------------------------------------------------------------------------- /mordred/_util.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function 2 | 3 | import os 4 | import sys 5 | 6 | import numpy as np 7 | 8 | 9 | def parse_enum(enum, v): 10 | if isinstance(v, enum): 11 | return v 12 | else: 13 | return enum[v] 14 | 15 | 16 | def atoms_to_numpy(f, mol, dtype="float"): 17 | return np.fromiter((f(a) for a in mol.GetAtoms()), dtype, mol.GetNumAtoms()) 18 | 19 | 20 | def conformer_to_numpy(conf): 21 | return np.array([list(conf.GetAtomPosition(i)) for i in range(conf.GetNumAtoms())]) 22 | 23 | 24 | class Capture(object): 25 | def __init__(self, target="stderr"): 26 | self.target = target 27 | self.orig = getattr(sys, target) 28 | self.result = [] 29 | 30 | def write(self, text): 31 | self.result.append(text) 32 | 33 | def flush(self): 34 | pass 35 | 36 | def __enter__(self): 37 | setattr(sys, self.target, self) 38 | return self 39 | 40 | def __exit__(self, *args): 41 | setattr(sys, self.target, self.orig) 42 | 43 | 44 | class DummyBar(object): 45 | def __init__(self, *args, **kwargs): 46 | pass 47 | 48 | def __enter__(self): 49 | return self 50 | 51 | def __exit__(self, *args, **kws): 52 | pass 53 | 54 | def update(self, *args, **kws): 55 | pass 56 | 57 | @classmethod 58 | def write(cls, s, file=sys.stdout, end="\n"): 59 | print(s, file=file, end=end) # noqa: T003 60 | 61 | 62 | class NotebookWrapper(object): 63 | def __init__(self, **kwargs): 64 | from tqdm import tqdm_notebook 65 | 66 | self.bar = tqdm_notebook(**kwargs) 67 | 68 | def __enter__(self): 69 | return self 70 | 71 | def __exit__(self, *args): 72 | pass 73 | 74 | def update(self, *args, **kwargs): 75 | self.bar.update(*args, **kwargs) 76 | 77 | def write(self, *args, **kwargs): 78 | self.bar.update(*args, **kwargs) 79 | 80 | 81 | def PathType(string): 82 | if not os.path.isfile(string): 83 | raise ValueError("file not exists: {}".format(string)) 84 | 85 | return string 86 | 87 | 88 | def module_prog(pkg): 89 | return "{} -m {}".format(os.path.basename(sys.executable), pkg) 90 | 91 | 92 | def to_ordinal(n): 93 | r"""Int to ordinal string. 94 | 95 | >>> to_ordinal(1) 96 | 'first' 97 | >>> to_ordinal(2) 98 | 'second' 99 | >>> to_ordinal(3) 100 | 'third' 101 | >>> to_ordinal(4) 102 | '4-th' 103 | >>> to_ordinal(104) 104 | '104-th' 105 | 106 | """ 107 | if n == 1: 108 | return "first" 109 | elif n == 2: 110 | return "second" 111 | elif n == 3: 112 | return "third" 113 | else: 114 | return "{}-th".format(n) 115 | -------------------------------------------------------------------------------- /mordred/_version.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | 4 | def get_version(): 5 | with open(os.path.join(os.path.dirname(__file__), "_version.txt")) as f: 6 | return f.read().strip() 7 | 8 | 9 | __version__ = get_version() 10 | -------------------------------------------------------------------------------- /mordred/_version.txt: -------------------------------------------------------------------------------- 1 | 1.2.0 2 | -------------------------------------------------------------------------------- /mordred/data/allred_rocow_electron_negativity.txt: -------------------------------------------------------------------------------- 1 | # http://www.chm.davidson.edu/ronutt/che115/electroneg.htm 2 | 3 | # 1 4 | 2.20 # 1 H 5 | - # 2 He 6 | 7 | # 2 8 | 0.97 # 3 Li 9 | 1.47 # 4 Be 10 | 2.01 # 5 B 11 | 2.50 # 6 C 12 | 3.07 # 7 N 13 | 3.50 # 8 O 14 | 4.10 # 9 F 15 | - # 10 Ne 16 | 17 | # 3 18 | 1.01 # 11 Na 19 | 1.23 # 12 Mg 20 | 1.47 # 13 Al 21 | 1.74 # 14 Si 22 | 2.06 # 15 P 23 | 2.44 # 16 S 24 | 2.83 # 17 Cl 25 | - # 18 Ar 26 | 27 | # 4 28 | 0.91 # 19 K 29 | 1.04 # 20 Ca 30 | 1.20 # 21 Sc 31 | 1.32 # 22 Ti 32 | 1.45 # 23 V 33 | 1.56 # 24 Cr 34 | 1.60 # 25 Mn 35 | 1.64 # 26 Fe 36 | 1.70 # 27 Co 37 | 1.75 # 28 Ni 38 | 1.75 # 29 Cu 39 | 1.66 # 30 Zn 40 | 1.82 # 31 Ga 41 | 2.02 # 32 Ge 42 | 2.20 # 33 As 43 | 2.48 # 34 Se 44 | 2.74 # 35 Br 45 | - # 36 Kr 46 | 47 | # 5 48 | 0.89 # 37 Rb 49 | 0.99 # 38 Sr 50 | 1.11 # 39 Y 51 | 1.22 # 40 Zr 52 | 1.23 # 41 Nb 53 | 1.30 # 42 Mo 54 | 1.36 # 43 Tc 55 | 1.42 # 44 Ru 56 | 1.45 # 45 Rh 57 | 1.35 # 46 Pd 58 | 1.42 # 47 Ag 59 | 1.46 # 48 Cd 60 | 1.49 # 49 In 61 | 1.72 # 50 Sn 62 | 1.82 # 51 Sb 63 | 2.01 # 52 Te 64 | 2.21 # 53 I 65 | - # 54 Xe 66 | 67 | # 6 68 | 0.86 # 55 Cs 69 | 0.97 # 56 Ba 70 | 71 | # Lanthanoid 72 | 1.08 # 57 La 73 | - # 58 Ce 74 | - # 59 Pr 75 | - # 60 Nd 76 | - # 61 Pm 77 | - # 62 Sm 78 | - # 63 Eu 79 | - # 64 Gd 80 | - # 65 Tb 81 | - # 66 Dy 82 | - # 67 Ho 83 | - # 68 Er 84 | - # 69 Tm 85 | - # 70 Yb 86 | - # 71 Lu 87 | 88 | # 6 cont. 89 | 1.23 # 72 Hf 90 | 1.33 # 73 Ta 91 | 1.40 # 74 W 92 | 1.46 # 75 Re 93 | 1.52 # 76 Os 94 | 1.55 # 77 Ir 95 | 1.44 # 78 Pt 96 | 1.42 # 79 Au 97 | 1.44 # 80 Hg 98 | 1.44 # 81 Tl 99 | 1.55 # 82 Pb 100 | 1.67 # 83 Bi 101 | 1.76 # 84 Po 102 | 1.90 # 85 At 103 | -------------------------------------------------------------------------------- /mordred/data/ionization_potential.txt: -------------------------------------------------------------------------------- 1 | # Handbook of Chemistry and Physics, 94th Edition, 2013-2014, pg10-197 2 | 3 | # 1 4 | 13.598443 # 1 H 5 | 24.587387 # 2 He 6 | 7 | # 2 8 | 5.391719 # 3 Li 9 | 9.32270 # 4 Be 10 | 8.29802 # 5 B 11 | 11.26030 # 6 C 12 | 14.5341 # 7 N 13 | 13.61805 # 8 O 14 | 17.4228 # 9 F 15 | 21.56454 # 10 Ne 16 | 17 | # 3 18 | 5.139076 # 11 Na 19 | 7.646235 # 12 Mg 20 | 5.985768 # 13 Al 21 | 8.15168 # 14 Si 22 | 10.48669 # 15 P 23 | 10.36001 # 16 S 24 | 12.96763 # 17 Cl 25 | 15.759610 # 18 Ar 26 | 27 | # 4 28 | 4.3406633 # 19 K 29 | 6.11316 # 20 Ca 30 | 6.56149 # 21 Sc 31 | 6.82812 # 22 Ti 32 | 6.74619 # 23 V 33 | 6.76651 # 24 Cr 34 | 7.43402 # 25 Mn 35 | 7.9024 # 26 Fe 36 | 7.88101 # 27 Co 37 | 7.6398 # 28 Ni 38 | 7.72638 # 29 Cu 39 | 9.394199 # 30 Zn 40 | 5.999301 # 31 Ga 41 | 7.89943 # 32 Ge 42 | 9.7886 # 33 As 43 | 9.75239 # 34 Se 44 | 11.8138 # 35 Br 45 | 13.99961 # 36 Kr 46 | 47 | # 5 48 | 4.177128 # 37 Rb 49 | 5.69485 # 38 Sr 50 | 6.2173 # 39 Y 51 | 6.63390 # 40 Zr 52 | 6.75885 # 41 Nb 53 | 7.09243 # 42 Mo 54 | 7.28 # 43 Tc 55 | 7.36050 # 44 Ru 56 | 7.45890 # 45 Rh 57 | 8.3369 # 46 Pd 58 | 7.57623 # 47 Ag 59 | 8.99382 # 48 Cd 60 | 5.78636 # 49 In 61 | 7.34392 # 50 Sn 62 | 8.60839 # 51 Sb 63 | 9.0096 # 52 Te 64 | 10.45126 # 53 I 65 | 12.12984 # 54 Xe 66 | 67 | # 6 68 | 3.893905 # 55 Cs 69 | 5.211664 # 56 Ba 70 | 71 | # Lanthanoid 72 | 5.5769 # 57 La 73 | 5.5387 # 58 Ce 74 | 5.473 # 59 Pr 75 | 5.5250 # 60 Nd 76 | 5.582 # 61 Pm 77 | 5.6437 # 62 Sm 78 | 5.67038 # 63 Eu 79 | 6.14980 # 64 Gd 80 | 5.8638 # 65 Tb 81 | 5.9389 # 66 Dy 82 | 6.0215 # 67 Ho 83 | 6.1077 # 68 Er 84 | 6.18431 # 69 Tm 85 | 6.25416 # 70 Yb 86 | 5.42586 # 71 Lu 87 | 88 | # 6 cont. 89 | 6.82507 # 72 Hf 90 | 7.54957 # 73 Ta 91 | 7.86403 # 74 W 92 | 7.83352 # 75 Re 93 | 8.43823 # 76 Os 94 | 8.96702 # 77 Ir 95 | 8.9588 # 78 Pt 96 | 9.22553 # 79 Au 97 | 10.4375 # 80 Hg 98 | 6.108194 # 81 Tl 99 | 7.41663 # 82 Pb 100 | 7.2855 # 83 Bi 101 | 8.414 # 84 Po 102 | - # 85 At 103 | 10.7485 # 86 Rn 104 | 105 | # 7 106 | 4.072741 # 87 Fr 107 | 5.278423 # 88 Ra 108 | 109 | # Actinoid 110 | 5.17 # 89 Ac 111 | 6.3067 # 90 Th 112 | 5.89 # 91 Pa 113 | 6.1941 # 92 U 114 | 6.2657 # 93 Np 115 | 6.0260 # 94 Pu 116 | 5.9738 # 95 Am 117 | 5.9914 # 96 Cm 118 | 6.1979 # 97 Bk 119 | 6.2817 # 98 Cf 120 | 6.42 # 99 Es 121 | 6.50 # 100 Fm 122 | 6.58 # 101 Md 123 | 6.65 # 102 No 124 | 4.9 # 103 Lr 125 | 126 | # 7 cont. 127 | 6.0 # 104 Rf 128 | -------------------------------------------------------------------------------- /mordred/data/mass.txt: -------------------------------------------------------------------------------- 1 | # Handbook of Chemistry and Physics, 94th Edition, 2013-2014, pg1-11 2 | 1.008 # 1 H 3 | 4.002602 # 2 He 4 | 5 | # 2 6 | 6.94 # 3 Li 7 | 9.012182 # 4 Be 8 | 10.81 # 5 B 9 | 12.011 # 6 C 10 | 14.007 # 7 N 11 | 15.999 # 8 O 12 | 18.9984032 # 9 F 13 | 20.1797 # 10 Ne 14 | 15 | # 3 16 | 22.98976928 # 11 Na 17 | 24.3050 # 12 Mg 18 | 26.9815386 # 13 Al 19 | 28.085 # 14 Si 20 | 30.973762 # 15 P 21 | 32.06 # 16 S 22 | 35.45 # 17 Cl 23 | 39.948 # 18 Ar 24 | 25 | # 4 26 | 39.0983 # 19 K 27 | 40.078 # 20 Ca 28 | 44.955912 # 21 Sc 29 | 47.867 # 22 Ti 30 | 50.9415 # 23 V 31 | 51.9961 # 24 Cr 32 | 54.938045 # 25 Mn 33 | 55.845 # 26 Fe 34 | 58.933195 # 27 Co 35 | 58.6934 # 28 Ni 36 | 63.546 # 29 Cu 37 | 65.38 # 30 Zn 38 | 69.723 # 31 Ga 39 | 72.63 # 32 Ge 40 | 74.92160 # 33 As 41 | 78.96 # 34 Se 42 | 79.904 # 35 Br 43 | 83.798 # 36 Kr 44 | 45 | # 5 46 | 85.4678 # 37 Rb 47 | 87.62 # 38 Sr 48 | 88.90585 # 39 Y 49 | 91.224 # 40 Zr 50 | 92.90638 # 41 Nb 51 | 95.96 # 42 Mo 52 | 98 # 43 Tc 53 | 101.07 # 44 Ru 54 | 102.90550 # 45 Rh 55 | 106.42 # 46 Pd 56 | 107.8682 # 47 Ag 57 | 112.411 # 48 Cd 58 | 114.818 # 49 In 59 | 118.710 # 50 Sn 60 | 121.760 # 51 Sb 61 | 127.60 # 52 Te 62 | 126.90447 # 53 I 63 | 131.293 # 54 Xe 64 | 65 | # 6 66 | 132.9054519 # 55 Cs 67 | 137.327 # 56 Ba 68 | 69 | # Lanthanoid 70 | 138.90547 # 57 La 71 | 140.116 # 58 Ce 72 | 140.90765 # 59 Pr 73 | 144.242 # 60 Nd 74 | 145 # 61 Pm 75 | 150.36 # 62 Sm 76 | 151.964 # 63 Eu 77 | 157.25 # 64 Gd 78 | 158.92535 # 65 Tb 79 | 162.500 # 66 Dy 80 | 164.93032 # 67 Ho 81 | 167.259 # 68 Er 82 | 168.93421 # 69 Tm 83 | 173.054 # 70 Yb 84 | 174.9668 # 71 Lu 85 | 86 | # 6 cont. 87 | 178.49 # 72 Hf 88 | 180.94788 # 73 Ta 89 | 183.84 # 74 W 90 | 186.207 # 75 Re 91 | 190.23 # 76 Os 92 | 192.217 # 77 Ir 93 | 195.084 # 78 Pt 94 | 196.966569 # 79 Au 95 | 200.59 # 80 Hg 96 | 204.38 # 81 Tl 97 | 207.2 # 82 Pb 98 | 208.98040 # 83 Bi 99 | 210 # 84 Po 100 | 210 # 85 At 101 | 222 # 86 Rn 102 | 103 | # 7 104 | 223 # 87 Fr 105 | 226 # 88 Ra 106 | 107 | # Actinoid 108 | 227 # 89 Ac 109 | 232.03806 # 90 Th 110 | 231.03588 # 91 Pa 111 | 238.02891 # 92 U 112 | 237 # 93 Np 113 | 244 # 94 Pu 114 | 243 # 95 Am 115 | 247 # 96 Cm 116 | 247 # 97 Bk 117 | 251 # 98 Cf 118 | 252 # 99 Es 119 | 257 # 100 Fm 120 | 258 # 101 Md 121 | 259 # 102 No 122 | 262 # 103 Lr 123 | 124 | # 7 cont. 125 | 261 # 104 Rf 126 | 262 # 105 Db 127 | 266 # 106 Sg 128 | 264 # 107 Bh 129 | 269 # 108 Hs 130 | 268 # 109 Mt 131 | 271 # 110 Ds 132 | -------------------------------------------------------------------------------- /mordred/data/mc_gowan_volume.txt: -------------------------------------------------------------------------------- 1 | # 1 2 | 8.71 # 1 H 3 | 6.75 # 2 He 4 | 5 | # 2 6 | 22.23 # 3 Li 7 | 20.27 # 4 Be 8 | 18.31 # 5 B 9 | 16.35 # 6 C 10 | 14.39 # 7 N 11 | 12.43 # 8 O 12 | 10.47 # 9 F 13 | 8.51 # 10 Ne 14 | 15 | # 3 16 | 32.71 # 11 Na 17 | 30.75 # 12 Mg 18 | 28.79 # 13 Al 19 | 26.83 # 14 Si 20 | 24.87 # 15 P 21 | 22.91 # 16 S 22 | 20.95 # 17 Cl 23 | 18.99 # 18 Ar 24 | 25 | # 4 26 | 51.89 # 19 K 27 | 50.28 # 20 Ca 28 | 48.68 # 21 Sc 29 | 47.07 # 22 Ti 30 | 45.47 # 23 V 31 | 43.86 # 24 Cr 32 | 42.26 # 25 Mn 33 | 40.65 # 26 Fe 34 | 39.05 # 27 Co 35 | 37.44 # 28 Ni 36 | 35.84 # 29 Cu 37 | 34.23 # 30 Zn 38 | 32.63 # 31 Ga 39 | 31.02 # 32 Ge 40 | 29.42 # 33 As 41 | 27.81 # 34 Se 42 | 26.21 # 35 Br 43 | 24.60 # 36 Kr 44 | 45 | # 5 46 | 60.22 # 37 Rb 47 | 58.61 # 38 Sr 48 | 57.01 # 39 Y 49 | 55.40 # 40 Zr 50 | 53.80 # 41 Nb 51 | 52.19 # 42 Mo 52 | 50.59 # 43 Tc 53 | 48.98 # 44 Ru 54 | 47.38 # 45 Rh 55 | 45.77 # 46 Pd 56 | 44.17 # 47 Ag 57 | 42.56 # 48 Cd 58 | 40.96 # 49 In 59 | 39.35 # 50 Sn 60 | 37.75 # 51 Sb 61 | 36.14 # 52 Te 62 | 34.54 # 53 I 63 | 32.93 # 54 Xe 64 | 65 | # 6 66 | 77.25 # 55 Cs 67 | 76.00 # 56 Ba 68 | 69 | # Lanthanoid 70 | 74.75 # 57 La 71 | 73.49 # 58 Ce 72 | 72.24 # 59 Pr 73 | 70.99 # 60 Nd 74 | 69.74 # 61 Pm 75 | 68.49 # 62 Sm 76 | 67.23 # 63 Eu 77 | 65.98 # 64 Gd 78 | 64.73 # 65 Tb 79 | 63.48 # 66 Dy 80 | 62.23 # 67 Ho 81 | 60.97 # 68 Er 82 | 59.72 # 69 Tm 83 | 58.47 # 70 Yb 84 | 57.22 # 71 Lu 85 | 86 | # 6 cont. 87 | 55.97 # 72 Hf 88 | 54.71 # 73 Ta 89 | 53.46 # 74 W 90 | 52.21 # 75 Re 91 | 50.96 # 76 Os 92 | 49.71 # 77 Ir 93 | 48.45 # 78 Pt 94 | 47.20 # 79 Au 95 | 45.95 # 80 Hg 96 | 44.70 # 81 Tl 97 | 43.45 # 82 Pb 98 | 42.19 # 83 Bi 99 | 40.94 # 84 Po 100 | 39.69 # 85 At 101 | 38.44 # 86 Rn 102 | 103 | # 7 104 | 75.59 # 87 Fr 105 | 74.34 # 88 Ra 106 | 107 | # Actinoid 108 | 73.09 # 89 Ac 109 | 71.83 # 90 Th 110 | 70.58 # 91 Pa 111 | 69.33 # 92 U 112 | 68.08 # 93 Np 113 | 66.83 # 94 Pu 114 | 65.57 # 95 Am 115 | 64.32 # 96 Cm 116 | 63.07 # 97 Bk 117 | 61.82 # 98 Cf 118 | 60.57 # 99 Es 119 | 59.31 # 100 Fm 120 | 58.06 # 101 Md 121 | 56.81 # 102 No 122 | 55.56 # 103 Lr 123 | -------------------------------------------------------------------------------- /mordred/data/pauling_electron_negativity.txt: -------------------------------------------------------------------------------- 1 | # https://github.com/cdk/cdk/blob/master/misc/extra/src/main/resources/org/openscience/cdk/config/data/electroneg-pauling.txt 2 | 3 | # 1 4 | 2.2 # 1 H 5 | - # 2 He 6 | 7 | # 2 8 | 0.98 # 3 Li 9 | 1.57 # 4 Be 10 | 2.04 # 5 B 11 | 2.55 # 6 C 12 | 3.04 # 7 N 13 | 3.44 # 8 O 14 | 3.98 # 9 F 15 | - # 10 Ne 16 | 17 | # 3 18 | 0.93 # 11 Na 19 | 1.31 # 12 Mg 20 | 1.61 # 13 Al 21 | 1.9 # 14 Si 22 | 2.19 # 15 P 23 | 2.58 # 16 S 24 | 3.16 # 17 Cl 25 | - # 18 Ar 26 | 27 | # 4 28 | 0.82 # 19 K 29 | 1.0 # 20 Ca 30 | 1.36 # 21 Sc 31 | 1.54 # 22 Ti 32 | 1.63 # 23 V 33 | 1.66 # 24 Cr 34 | 1.55 # 25 Mn 35 | 1.83 # 26 Fe 36 | 1.88 # 27 Co 37 | 1.91 # 28 Ni 38 | 1.9 # 29 Cu 39 | 1.65 # 30 Zn 40 | 1.81 # 31 Ga 41 | 2.01 # 32 Ge 42 | 2.18 # 33 As 43 | 2.55 # 34 Se 44 | 2.96 # 35 Br 45 | 3.0 # 36 Kr 46 | 47 | # 5 48 | 0.82 # 37 Rb 49 | 0.95 # 38 Sr 50 | 1.22 # 39 Y 51 | 1.33 # 40 Zr 52 | 1.6 # 41 Nb 53 | 2.16 # 42 Mo 54 | 1.9 # 43 Tc 55 | 2.2 # 44 Ru 56 | 2.28 # 45 Rh 57 | 2.2 # 46 Pd 58 | 1.93 # 47 Ag 59 | 1.69 # 48 Cd 60 | 1.78 # 49 In 61 | 1.96 # 50 Sn 62 | 2.05 # 51 Sb 63 | 2.1 # 52 Te 64 | 2.66 # 53 I 65 | 2.6 # 54 Xe 66 | 67 | # 6 68 | 0.79 # 55 Cs 69 | 0.89 # 56 Ba 70 | 71 | # Lanthanoid 72 | 1.1 # 57 La 73 | 1.12 # 58 Ce 74 | 1.13 # 59 Pr 75 | 1.14 # 60 Nd 76 | - # 61 Pm 77 | 1.17 # 62 Sm 78 | - # 63 Eu 79 | 1.2 # 64 Gd 80 | - # 65 Tb 81 | 1.22 # 66 Dy 82 | 1.23 # 67 Ho 83 | 1.24 # 68 Er 84 | 1.25 # 69 Tm 85 | - # 70 Yb 86 | 1.27 # 71 Lu 87 | 88 | # 6 cont. 89 | 1.3 # 72 Hf 90 | 1.5 # 73 Ta 91 | 2.36 # 74 W 92 | 1.9 # 75 Re 93 | 2.2 # 76 Os 94 | 2.2 # 77 Ir 95 | 2.28 # 78 Pt 96 | 2.54 # 79 Au 97 | 2.0 # 80 Hg 98 | 1.62 # 81 Tl 99 | 2.33 # 82 Pb 100 | 2.02 # 83 Bi 101 | 2.0 # 84 Po 102 | 2.2 # 85 At 103 | - # 86 Rn 104 | 105 | # 7 106 | 0.7 # 87 Fr 107 | 0.9 # 88 Ra 108 | 109 | # Actinoid 110 | 1.1 # 89 Ac 111 | 1.3 # 90 Th 112 | 1.5 # 91 Pa 113 | 1.38 # 92 U 114 | 1.36 # 93 Np 115 | 1.28 # 94 Pu 116 | 1.3 # 95 Am 117 | 1.3 # 96 Cm 118 | 1.3 # 97 Bk 119 | 1.3 # 98 Cf 120 | 1.3 # 99 Es 121 | 1.3 # 100 Fm 122 | 1.3 # 101 Md 123 | 1.3 # 102 No 124 | -------------------------------------------------------------------------------- /mordred/data/polarizalibity78.txt: -------------------------------------------------------------------------------- 1 | # Handbook of Chemistry and Physics, 78th Edition 2 | 3 | # 1 4 | 0.666793 # 1 H 5 | 0.204956 # 2 He 6 | 7 | # 2 8 | 24.3 # 3 Li 9 | 5.6 # 4 Be 10 | 3.03 # 5 B 11 | 1.76 # 6 C 12 | 1.1 # 7 N 13 | 0.802 # 8 O 14 | 0.557 # 9 F 15 | 0.3956 # 10 Ne 16 | 17 | # 3 18 | 23.6 # 11 Na 19 | 10.6 # 12 Mg 20 | 6.8 # 13 Al 21 | 5.38 # 14 Si 22 | 3.63 # 15 P 23 | 2.9 # 16 S 24 | 2.18 # 17 Cl 25 | 1.6411 # 18 Ar 26 | 27 | # 4 28 | 43.4 # 19 K 29 | 22.8 # 20 Ca 30 | 17.8 # 21 Sc 31 | 14.6 # 22 Ti 32 | 12.4 # 23 V 33 | 11.6 # 24 Cr 34 | 9.4 # 25 Mn 35 | 8.4 # 26 Fe 36 | 7.5 # 27 Co 37 | 6.8 # 28 Ni 38 | 6.1 # 29 Cu 39 | 7.1 # 30 Zn 40 | 8.12 # 31 Ga 41 | 6.07 # 32 Ge 42 | 4.31 # 33 As 43 | 3.77 # 34 Se 44 | 3.05 # 35 Br 45 | 2.4844 # 36 Kr 46 | 47 | # 5 48 | 47.3 # 37 Rb 49 | 27.6 # 38 Sr 50 | 22.7 # 39 Y 51 | 17.9 # 40 Zr 52 | 15.7 # 41 Nb 53 | 12.8 # 42 Mo 54 | 11.4 # 43 Tc 55 | 9.6 # 44 Ru 56 | 8.6 # 45 Rh 57 | 4.8 # 46 Pd 58 | 7.2 # 47 Ag 59 | 7.2 # 48 Cd 60 | 10.2 # 49 In 61 | 7.7 # 50 Sn 62 | 6.6 # 51 Sb 63 | 5.5 # 52 Te 64 | 5.35 # 53 I 65 | 4.044 # 54 Xe 66 | 67 | # 6 68 | 59.6 # 55 Cs 69 | 39.7 # 56 Ba 70 | 71 | # Lanthanoid 72 | 31.1 # 57 La 73 | 29.6 # 58 Ce 74 | 28.2 # 59 Pr 75 | 31.4 # 60 Nd 76 | 30.1 # 61 Pm 77 | 28.8 # 62 Sm 78 | 27.7 # 63 Eu 79 | 23.5 # 64 Gd 80 | 25.5 # 65 Tb 81 | 24.5 # 66 Dy 82 | 23.6 # 67 Ho 83 | 22.7 # 68 Er 84 | 21.8 # 69 Tm 85 | 21.0 # 70 Yb 86 | 21.9 # 71 Lu 87 | 88 | # 6 cont. 89 | 16.2 # 72 Hf 90 | 13.1 # 73 Ta 91 | 11.1 # 74 W 92 | 9.7 # 75 Re 93 | 8.5 # 76 Os 94 | 7.6 # 77 Ir 95 | 6.5 # 78 Pt 96 | 5.8 # 79 Au 97 | 5.7 # 80 Hg 98 | 7.6 # 81 Tl 99 | 6.8 # 82 Pb 100 | 7.4 # 83 Bi 101 | 6.8 # 84 Po 102 | 6.0 # 85 At 103 | 5.3 # 86 Rn 104 | 105 | # 7 106 | 48.7 # 87 Fr 107 | 38.3 # 88 Ra 108 | 109 | # Actinoid 110 | 32.1 # 89 Ac 111 | 32.1 # 90 Th 112 | 25.4 # 91 Pa 113 | 27.4 # 92 U 114 | 24.8 # 93 Np 115 | 24.5 # 94 Pu 116 | 23.3 # 95 Am 117 | 23.0 # 96 Cm 118 | 22.7 # 97 Bk 119 | 20.5 # 98 Cf 120 | 19.7 # 99 Es 121 | 23.8 # 100 Fm 122 | 18.2 # 101 Md 123 | 17.5 # 102 No 124 | -------------------------------------------------------------------------------- /mordred/data/polarizalibity94.txt: -------------------------------------------------------------------------------- 1 | # Handbook of Chemistry and Physics, 94th Edition, 2013-2014, pg10-188 2 | 3 | # 1 4 | 0.666793 # 1 H 5 | 0.2050522 # 2 He 6 | 7 | # 2 8 | 24.33 # 3 Li 9 | 5.60 # 4 Be 10 | 3.03 # 5 B 11 | 1.67 # 6 C 12 | 1.10 # 7 N 13 | 0.802 # 8 O 14 | 0.557 # 9 F 15 | 0.39432 # 10 Ne 16 | 17 | # 3 18 | 24.11 # 11 Na 19 | 10.6 # 12 Mg 20 | 6.8 # 13 Al 21 | 5.53 # 14 Si 22 | 3.63 # 15 P 23 | 2.90 # 16 S 24 | 2.18 # 17 Cl 25 | 1.6411 # 18 Ar 26 | 27 | # 4 28 | 43.06 # 19 K 29 | 22.8 # 20 Ca 30 | 17.8 # 21 Sc 31 | 14.6 # 22 Ti 32 | 12.4 # 23 V 33 | 11.6 # 24 Cr 34 | 9.4 # 25 Mn 35 | 8.4 # 26 Fe 36 | 7.5 # 27 Co 37 | 6.8 # 28 Ni 38 | 6.2 # 29 Cu 39 | 5.75 # 30 Zn 40 | 8.12 # 31 Ga 41 | 5.84 # 32 Ge 42 | 4.31 # 33 As 43 | 3.77 # 34 Se 44 | 3.05 # 35 Br 45 | 2.4844 # 36 Kr 46 | 47 | # 5 48 | 47.24 # 37 Rb 49 | 23.5 # 38 Sr 50 | 22.7 # 39 Y 51 | 17.9 # 40 Zr 52 | 15.7 # 41 Nb 53 | 12.8 # 42 Mo 54 | 11.4 # 43 Tc 55 | 9.6 # 44 Ru 56 | 8.6 # 45 Rh 57 | 4.8 # 46 Pd 58 | 6.78 # 47 Ag 59 | 7.36 # 48 Cd 60 | 10.2 # 49 In 61 | 7.84 # 50 Sn 62 | 6.6 # 51 Sb 63 | 5.5 # 52 Te 64 | 5.35 # 53 I 65 | 4.044 # 54 Xe 66 | 67 | # 6 68 | 59.42 # 55 Cs 69 | 39.7 # 56 Ba 70 | 71 | # Lanthanoid 72 | 31.1 # 57 La 73 | 29.6 # 58 Ce 74 | 28.2 # 59 Pr 75 | 31.4 # 60 Nd 76 | 30.1 # 61 Pm 77 | 28.8 # 62 Sm 78 | 27.7 # 63 Eu 79 | 23.5 # 64 Gd 80 | 25.5 # 65 Tb 81 | 24.5 # 66 Dy 82 | 23.6 # 67 Ho 83 | 22.7 # 68 Er 84 | 21.8 # 69 Tm 85 | 20.9 # 70 Yb 86 | 21.9 # 71 Lu 87 | 88 | # 6 cont. 89 | 16.2 # 72 Hf 90 | 13.1 # 73 Ta 91 | 11.1 # 74 W 92 | 9.7 # 75 Re 93 | 8.5 # 76 Os 94 | 7.6 # 77 Ir 95 | 6.5 # 78 Pt 96 | 5.8 # 79 Au 97 | 5.02 # 80 Hg 98 | 7.6 # 81 Tl 99 | 7.01 # 82 Pb 100 | 7.4 # 83 Bi 101 | 6.8 # 84 Po 102 | 6.0 # 85 At 103 | 5.3 # 86 Rn 104 | 105 | # 7 106 | 48.6 # 87 Fr 107 | 38.3 # 88 Ra 108 | 109 | # Actinoid 110 | 32.1 # 89 Ac 111 | 32.1 # 90 Th 112 | 25.4 # 91 Pa 113 | 24.9 # 92 U 114 | 24.8 # 93 Np 115 | 24.5 # 94 Pu 116 | 23.3 # 95 Am 117 | 23.0 # 96 Cm 118 | 22.7 # 97 Bk 119 | 20.5 # 98 Cf 120 | 19.7 # 99 Es 121 | 23.8 # 100 Fm 122 | 18.2 # 101 Md 123 | 16.4 # 102 No 124 | - # 103 Lr 125 | 126 | # 7 cont. 127 | - # 104 Rf 128 | - # 105 Db 129 | - # 106 Sg 130 | - # 107 Bh 131 | - # 108 Hs 132 | - # 109 Mt 133 | - # 110 Ds 134 | - # 111 Rg 135 | 4.06 # 112 Cn 136 | - # 113 137 | 4.59 # 114 Fl 138 | - # 115 139 | - # 116 Lv 140 | - # 117 141 | - # 118 142 | 143 | # 8 144 | 24.26 # 119 145 | -------------------------------------------------------------------------------- /mordred/data/sanderson_electron_negativity.txt: -------------------------------------------------------------------------------- 1 | # Sanderson, RT. Electronegativity and Bond Energy. J. Am. Chem. Soc. 1983, 105: 2259-2261. 2 | # Remaining values come from http://www.talete.mi.it/help/dragon_help/weighting_schemes.htm 3 | 4 | # 1 5 | 2.592 # 1 H 6 | - # 2 He 7 | 8 | # 2 9 | 0.670 # 3 Li 10 | 1.810 # 4 Be 11 | 2.275 # 5 B 12 | 2.746 # 6 C 13 | 3.194 # 7 N 14 | 3.654 # 8 O 15 | 4.000 # 9 F 16 | 4.5 # 10 Ne 17 | 18 | # 3 19 | 0.560 # 11 Na 20 | 1.318 # 12 Mg 21 | 1.714 # 13 Al 22 | 2.138 # 14 Si 23 | 2.515 # 15 P 24 | 2.957 # 16 S 25 | 3.475 # 17 Cl 26 | 3.31 # 18 Ar 27 | 28 | # 4 29 | 0.445 # 19 K 30 | 0.946 # 20 Ca 31 | 1.02 # 21 Sc 32 | 1.09 # 22 Ti 33 | 1.39 # 23 V 34 | 1.66 # 24 Cr 35 | 2.2 # 25 Mn 36 | 2.2 # 26 Fe 37 | 2.56 # 27 Co 38 | 1.94 # 28 Ni 39 | 2.033 # 29 Cu 40 | 2.223 # 30 Zn 41 | 2.419 # 31 Ga 42 | 2.618 # 32 Ge 43 | 2.816 # 33 As 44 | 3.014 # 34 Se 45 | 3.219 # 35 Br 46 | 2.91 # 36 Kr 47 | 48 | # 5 49 | 0.312 # 37 Rb 50 | 0.721 # 38 Sr 51 | 0.65 # 39 Y 52 | 0.9 # 40 Zr 53 | 1.42 # 41 Nb 54 | 1.15 # 42 Mo 55 | - # 43 Tc 56 | - # 44 Ru 57 | - # 45 Rh 58 | - # 46 Pd 59 | 1.826 # 47 Ag 60 | 1.978 # 48 Cd 61 | 2.138 # 49 In 62 | 2.298 # 50 Sn 63 | 2.458 # 51 Sb 64 | 2.618 # 52 Te 65 | 2.778 # 53 I 66 | 2.34 # 54 Xe 67 | 68 | # 6 69 | 0.220 # 55 Cs 70 | 0.651 # 56 Ba 71 | 72 | # Lanthanoid 73 | - # 57 La 74 | - # 58 Ce 75 | - # 59 Pr 76 | - # 60 Nd 77 | - # 61 Pm 78 | - # 62 Sm 79 | - # 63 Eu 80 | - # 64 Gd 81 | - # 65 Tb 82 | - # 66 Dy 83 | - # 67 Ho 84 | - # 68 Er 85 | - # 69 Tm 86 | - # 70 Yb 87 | - # 71 Lu 88 | 89 | # 6 cont. 90 | - # 72 Hf 91 | - # 73 Ta 92 | 0.98 # 74 W 93 | - # 75 Re 94 | - # 76 Os 95 | - # 77 Ir 96 | - # 78 Pt 97 | - # 79 Au 98 | 2.195 # 80 Hg 99 | 2.246 # 81 Tl 100 | 2.291 # 82 Pb 101 | 2.342 # 83 Bi 102 | -------------------------------------------------------------------------------- /mordred/data/van_der_waals_radii.txt: -------------------------------------------------------------------------------- 1 | # Handbook of Chemistry and Physics, 94th Edition, 2013-2014, pg9-49 2 | 3 | # 1 4 | 1.10 # 1 H 5 | 1.40 # 2 He 6 | 7 | # 2 8 | 1.82 # 3 Li 9 | 1.53 # 4 Be 10 | 1.92 # 5 B 11 | 1.70 # 6 C 12 | 1.55 # 7 N 13 | 1.52 # 8 O 14 | 1.47 # 9 F 15 | 1.54 # 10 Ne 16 | 17 | # 3 18 | 2.27 # 11 Na 19 | 1.73 # 12 Mg 20 | 1.84 # 13 Al 21 | 2.10 # 14 Si 22 | 1.80 # 15 P 23 | 1.80 # 16 S 24 | 1.75 # 17 Cl 25 | 1.88 # 18 Ar 26 | 27 | # 4 28 | 2.75 # 19 K 29 | 2.31 # 20 Ca 30 | 2.15 # 21 Sc 31 | 2.11 # 22 Ti 32 | 2.07 # 23 V 33 | 2.06 # 24 Cr 34 | 2.05 # 25 Mn 35 | 2.04 # 26 Fe 36 | 2.00 # 27 Co 37 | 1.97 # 28 Ni 38 | 1.96 # 29 Cu 39 | 2.01 # 30 Zn 40 | 1.87 # 31 Ga 41 | 2.11 # 32 Ge 42 | 1.85 # 33 As 43 | 1.90 # 34 Se 44 | 1.85 # 35 Br 45 | 2.02 # 36 Kr 46 | 47 | # 5 48 | 3.03 # 37 Rb 49 | 2.49 # 38 Sr 50 | 2.32 # 39 Y 51 | 2.23 # 40 Zr 52 | 2.18 # 41 Nb 53 | 2.17 # 42 Mo 54 | 2.16 # 43 Tc 55 | 2.13 # 44 Ru 56 | 2.10 # 45 Rh 57 | 2.10 # 46 Pd 58 | 2.11 # 47 Ag 59 | 2.18 # 48 Cd 60 | 1.93 # 49 In 61 | 2.17 # 50 Sn 62 | 2.06 # 51 Sb 63 | 2.06 # 52 Te 64 | 1.98 # 53 I 65 | 2.16 # 54 Xe 66 | 67 | # 6 68 | 3.43 # 55 Cs 69 | 2.68 # 56 Ba 70 | 71 | # Lanthanoid 72 | 2.43 # 57 La 73 | 2.42 # 58 Ce 74 | 2.40 # 59 Pr 75 | 2.39 # 60 Nd 76 | 2.38 # 61 Pm 77 | 2.36 # 62 Sm 78 | 2.35 # 63 Eu 79 | 2.34 # 64 Gd 80 | 2.33 # 65 Tb 81 | 2.31 # 66 Dy 82 | 2.30 # 67 Ho 83 | 2.29 # 68 Er 84 | 2.27 # 69 Tm 85 | 2.26 # 70 Yb 86 | 2.24 # 71 Lu 87 | 88 | # 6 cont. 89 | 2.23 # 72 Hf 90 | 2.22 # 73 Ta 91 | 2.18 # 74 W 92 | 2.16 # 75 Re 93 | 2.16 # 76 Os 94 | 2.13 # 77 Ir 95 | 2.13 # 78 Pt 96 | 2.14 # 79 Au 97 | 2.23 # 80 Hg 98 | 1.96 # 81 Tl 99 | 2.02 # 82 Pb 100 | 2.07 # 83 Bi 101 | 1.97 # 84 Po 102 | 2.02 # 85 At 103 | 2.20 # 86 Rn 104 | 105 | # 7 106 | 3.48 # 87 Fr 107 | 2.83 # 88 Ra 108 | 109 | # Actinoid 110 | 2.47 # 89 Ac 111 | 2.45 # 90 Th 112 | 2.43 # 91 Pa 113 | 2.41 # 92 U 114 | 2.39 # 93 Np 115 | 2.43 # 94 Pu 116 | 2.44 # 95 Am 117 | 2.45 # 96 Cm 118 | 2.44 # 97 Bk 119 | 2.45 # 98 Cf 120 | 2.45 # 99 Es 121 | 2.45 # 100 Fm 122 | 2.46 # 101 Md 123 | 2.46 # 102 No 124 | 2.46 # 103 Lr 125 | -------------------------------------------------------------------------------- /mordred/descriptors/__init__.py: -------------------------------------------------------------------------------- 1 | """All descriptor modules are loaded. 2 | 3 | .. code:: python 4 | 5 | >>> from mordred import Calculator, descriptors 6 | 7 | >>> descriptors.ABCIndex.__name__ # ABCIndex module 8 | 'mordred.ABCIndex' 9 | 10 | >>> len(descriptors.all) # all descriptor modules 11 | 50 12 | 13 | >>> calc = Calculator(descriptors) # all descriptors 14 | """ 15 | 16 | 17 | def _import_all_descriptors(): 18 | import os 19 | from importlib import import_module 20 | from .._base.descriptor import is_descriptor_class 21 | 22 | names = [] 23 | values = [] 24 | base_dir = os.path.dirname(os.path.dirname(__file__)) 25 | 26 | for name in sorted(os.listdir(base_dir)): 27 | name, ext = os.path.splitext(name) 28 | if name[:1] == "_" or ext != ".py": 29 | continue 30 | 31 | mdl = import_module(".." + name, __package__) 32 | 33 | if any(v for v in mdl.__dict__.values() if is_descriptor_class(v)): 34 | names.append(name) 35 | values.append(mdl) 36 | globals()[name] = mdl 37 | 38 | globals()["__all__"] = tuple(names) 39 | globals()["all"] = tuple(values) 40 | 41 | 42 | _import_all_descriptors() 43 | -------------------------------------------------------------------------------- /mordred/error/__init__.py: -------------------------------------------------------------------------------- 1 | """Error objects.""" 2 | 3 | from abc import ABCMeta, abstractproperty 4 | 5 | import six 6 | import numpy as np 7 | 8 | 9 | class MissingValueBase(six.with_metaclass(ABCMeta, object)): 10 | """Base class of missing values. 11 | 12 | Args: 13 | error (Exception): error object 14 | stack (callstack) 15 | 16 | """ 17 | 18 | __slots__ = "error", "stack" 19 | 20 | def __reduce_ex__(self, version): 21 | return self.__class__, (self.error, self.stack) 22 | 23 | def __init__(self, error, stack): 24 | self.error = error 25 | self.stack = stack 26 | 27 | def __float__(self): 28 | return np.nan 29 | 30 | def __add__(self, other): 31 | return np.nan 32 | 33 | def __sub__(self, other): 34 | return np.nan 35 | 36 | def __str__(self): 37 | return "{} ({})".format(self.error, "/".join(str(d) for d in self.stack)) 38 | 39 | @abstractproperty 40 | def header(self): 41 | """Header of warning message. 42 | 43 | Returns: 44 | str 45 | 46 | """ 47 | raise NotImplementedError("require header") 48 | 49 | 50 | class Missing(MissingValueBase): 51 | """known errored value.""" 52 | 53 | __slots__ = () 54 | header = "Missing" 55 | 56 | 57 | class Error(MissingValueBase): 58 | """unknown errored value.""" 59 | 60 | __slots__ = () 61 | header = "ERROR" 62 | 63 | 64 | class MordredException(Exception): 65 | __slots__ = () 66 | 67 | 68 | class MultipleFragments(MordredException): 69 | """multiple fragments detected on require_connected Descriptor.""" 70 | 71 | __slots__ = () 72 | 73 | def __str__(self): 74 | return "multiple fragments" 75 | 76 | 77 | class Missing3DCoordinate(MordredException): 78 | """missing 3D coordinate on require_3D Descriptor.""" 79 | 80 | __slots__ = () 81 | 82 | def __str__(self): 83 | return "missing 3D coordinate" 84 | 85 | 86 | class DuplicatedDescriptorName(MordredException): 87 | """duplicated string replisantation of descriptor.""" 88 | 89 | __slots__ = () 90 | 91 | def __init__(self, a, b): 92 | self.a = a 93 | self.b = b 94 | 95 | def __str__(self): 96 | return "duplicated descriptor name: {!r} and {!r}".format(self.a, self.b) 97 | 98 | 99 | class Timeout(MordredException): 100 | """calculation timed out.""" 101 | 102 | __slots__ = () 103 | 104 | def __str__(self): 105 | return "timed out" 106 | -------------------------------------------------------------------------------- /mordred/surface_area/__init__.py: -------------------------------------------------------------------------------- 1 | r"""surface area subpackage. 2 | 3 | .. code:: console 4 | 5 | $ python -m mordred.surface_area -h 6 | usage: python -m mordred.surface_area [-h] [-s R] [-l L] FILE 7 | 8 | positional arguments: 9 | FILE input sdf/mol file 10 | 11 | optional arguments: 12 | -h, --help show this help message and exit 13 | -s R, --solvent-radius R 14 | solvent radius (default: 1.4) 15 | -l L, --mesh-level L mesh level (default: 5) 16 | """ 17 | 18 | from ._sasa import SurfaceArea 19 | 20 | __all__ = ("SurfaceArea",) 21 | -------------------------------------------------------------------------------- /mordred/surface_area/__main__.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function 2 | 3 | import argparse 4 | 5 | from rdkit import Chem 6 | 7 | from . import SurfaceArea 8 | from .._util import PathType, module_prog 9 | 10 | 11 | def main(): 12 | parser = argparse.ArgumentParser( 13 | prog=module_prog(__package__), formatter_class=argparse.MetavarTypeHelpFormatter 14 | ) 15 | parser.add_argument("sdf", type=PathType, help="input sd file", metavar="SDF") 16 | parser.add_argument( 17 | "-s", 18 | "--solvent-radius", 19 | type=float, 20 | default=1.4, 21 | help="solvent radius (default: %(default)s)", 22 | ) 23 | parser.add_argument( 24 | "-l", 25 | "--mesh-level", 26 | type=int, 27 | default=5, 28 | help="mesh level (default: %(default)s)", 29 | ) 30 | result = parser.parse_args() 31 | main_process( 32 | sdf=result.sdf, 33 | solvent_radius=result.solvent_radius, 34 | mesh_level=result.mesh_level, 35 | ) 36 | 37 | 38 | def main_process(sdf, solvent_radius, mesh_level): 39 | for i, mol in enumerate(Chem.SDMolSupplier(sdf, removeHs=False)): 40 | name = mol.GetProp("_Name") if mol.HasProp("_Name") else str(i) 41 | sa = SurfaceArea.from_mol(mol, solvent_radius=solvent_radius, level=mesh_level) 42 | 43 | print(name) # noqa: T003 44 | 45 | for a, s in zip(mol.GetAtoms(), sa.surface_area()): 46 | print( # noqa: T001 47 | "{:4d} {:2s} {:8.3f}".format(a.GetIdx(), a.GetSymbol(), s) 48 | ) # noqa: T003 49 | 50 | 51 | if __name__ == "__main__": 52 | main() 53 | -------------------------------------------------------------------------------- /mordred/surface_area/_mesh.py: -------------------------------------------------------------------------------- 1 | """Mesh generation. 2 | 3 | References: 4 | * http://prideout.net/blog/?p=44 5 | * http://blog.andreaskahler.com/2009/06/creating-icosphere-mesh-in-code.html 6 | 7 | """ 8 | 9 | import numpy as np 10 | 11 | 12 | class SphereMesh(object): 13 | def __init__(self, level=4): 14 | t = (1.0 + np.sqrt(5.0)) / 2.0 15 | self.vertices = np.array( 16 | [ 17 | (-1, t, 0), 18 | (1, t, 0), 19 | (-1, -t, 0), 20 | (1, -t, 0), 21 | (0, -1, t), 22 | (0, 1, t), 23 | (0, -1, -t), 24 | (0, 1, -t), 25 | (t, 0, -1), 26 | (t, 0, 1), 27 | (-t, 0, -1), 28 | (-t, 0, 1), 29 | ], 30 | dtype="float", 31 | ) 32 | 33 | self.faces = np.array( 34 | [ 35 | (0, 11, 5), 36 | (0, 5, 1), 37 | (0, 1, 7), 38 | (0, 7, 10), 39 | (0, 10, 11), 40 | (1, 5, 9), 41 | (5, 11, 4), 42 | (11, 10, 2), 43 | (10, 7, 6), 44 | (7, 1, 8), 45 | (3, 9, 4), 46 | (3, 4, 2), 47 | (3, 2, 6), 48 | (3, 6, 8), 49 | (3, 8, 9), 50 | (4, 9, 5), 51 | (2, 4, 11), 52 | (6, 2, 10), 53 | (8, 6, 7), 54 | (9, 8, 1), 55 | ], 56 | dtype="int", 57 | ) 58 | 59 | self.normalize(0) 60 | 61 | self.level = 1 62 | self.subdivide(level) 63 | 64 | def normalize(self, begin): 65 | self.vertices[begin:] /= np.sqrt((self.vertices[begin:] ** 2).sum(axis=1))[ 66 | :, np.newaxis 67 | ] 68 | 69 | def _subdivide(self): 70 | self.level += 1 71 | 72 | Nv = len(self.vertices) 73 | Nf = len(self.faces) 74 | 75 | A = self.faces[:, 0] 76 | B = self.faces[:, 1] 77 | C = self.faces[:, 2] 78 | 79 | Av = self.vertices[A] 80 | Bv = self.vertices[B] 81 | Cv = self.vertices[C] 82 | 83 | self.vertices = np.r_[self.vertices, Av + Bv, Bv + Cv, Av + Cv] 84 | self.normalize(Nv) 85 | 86 | AB = np.arange(len(self.faces)) + Nv 87 | BC = AB + Nf 88 | AC = AB + 2 * Nf 89 | 90 | self.faces = ( 91 | np.concatenate([A, B, C, AB, AB, AB, AC, AC, AC, BC, BC, BC]) 92 | .reshape(3, -1) 93 | .T 94 | ) 95 | 96 | def subdivide(self, level): 97 | for _ in range(level - self.level): 98 | self._subdivide() 99 | 100 | def __len__(self): 101 | return len(self.vertices) 102 | -------------------------------------------------------------------------------- /mordred/tests/Dummy.py: -------------------------------------------------------------------------------- 1 | from mordred import Descriptor 2 | 3 | 4 | class Dummy1(Descriptor): 5 | pass 6 | 7 | 8 | class Dummy2(Dummy1): 9 | since = "1.0.0" 10 | 11 | def parameters(self): 12 | return () 13 | 14 | def calculate(self): 15 | return 0.0 16 | 17 | rtype = float 18 | 19 | 20 | class Dummy3(Dummy2): 21 | @classmethod 22 | def preset(cls, version): 23 | yield cls() 24 | 25 | 26 | class Dummy4(Dummy3): 27 | def __init__(self, i=0): 28 | self.i = i 29 | 30 | def __eq__(self, other): 31 | return isinstance(other, Dummy4) and self.i == other.i 32 | 33 | def __str__(self): 34 | return "Dummy4_{}".format(self.i) 35 | 36 | @classmethod 37 | def preset(cls, version): 38 | yield cls(0) 39 | yield cls(1) 40 | -------------------------------------------------------------------------------- /mordred/tests/__init__.py: -------------------------------------------------------------------------------- 1 | """Mordred test package.""" 2 | -------------------------------------------------------------------------------- /mordred/tests/__main__.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | import nose 4 | 5 | 6 | def main(): 7 | base = os.path.dirname(os.path.dirname(__file__)) 8 | hidden = [ 9 | os.path.join(base, n) 10 | for n in os.listdir(base) 11 | if n[:1] == "_" and os.path.splitext(n)[1] == ".py" 12 | ] 13 | 14 | tests = [base, os.path.join(base, "_base")] + hidden 15 | 16 | os.environ["NOSE_WITH_DOCTEST"] = "1" 17 | 18 | nose.main(defaultTest=",".join(tests)) 19 | 20 | 21 | if __name__ == "__main__": 22 | main() 23 | -------------------------------------------------------------------------------- /mordred/tests/references/Aromatic.yaml: -------------------------------------------------------------------------------- 1 | # chemaxon cxcalc 2 | - names: [nAromAtom, nAromBond] 3 | results: 4 | Hexane: [0, 0] 5 | Benzene: [6, 6] 6 | Caffeine: [9, 10] 7 | Cyanidin: [16, 17] 8 | Lycopene: [0, 0] 9 | Epicatechin: [12, 12] 10 | Limonene: [0, 0] 11 | Allicin: [0, 0] 12 | Glutathione: [0, 0] 13 | Digoxin: [0, 0] 14 | Capsaicin: [6, 6] 15 | EllagicAcid: [16, 19] 16 | Astaxanthin: [0, 0] 17 | -------------------------------------------------------------------------------- /mordred/tests/references/Atom/AtomCount.yaml: -------------------------------------------------------------------------------- 1 | - names: [nAtom, nHeavyAtom, nH, nB, nC, nN, nO, nS, nP, nF, nCl, nBr, nI, nX] 2 | results: 3 | Hexane: [20, 6, 14, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0] 4 | Benzene: [12, 6, 6, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0] 5 | Caffeine: [24, 14, 10, 0, 8, 4, 2, 0, 0, 0, 0, 0, 0, 0] 6 | Cyanidin: [32, 21, 11, 0, 15, 0, 6, 0, 0, 0, 0, 0, 0, 0] 7 | Lycopene: [96, 40, 56, 0, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0] 8 | Epicatechin: [35, 21, 14, 0, 15, 0, 6, 0, 0, 0, 0, 0, 0, 0] 9 | Limonene: [26, 10, 16, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0] 10 | Allicin: [19, 9, 10, 0, 6, 0, 1, 2, 0, 0, 0, 0, 0, 0] 11 | Glutathione: [37, 20, 17, 0, 10, 3, 6, 1, 0, 0, 0, 0, 0, 0] 12 | Digoxin: [119, 55, 64, 0, 41, 0, 14, 0, 0, 0, 0, 0, 0, 0] 13 | Capsaicin: [49, 22, 27, 0, 18, 1, 3, 0, 0, 0, 0, 0, 0, 0] 14 | EllagicAcid: [28, 22, 6, 0, 14, 0, 8, 0, 0, 0, 0, 0, 0, 0] 15 | Astaxanthin: [96, 44, 52, 0, 40, 0, 4, 0, 0, 0, 0, 0, 0, 0] 16 | -------------------------------------------------------------------------------- /mordred/tests/references/Atom/CarbonTypes.yaml: -------------------------------------------------------------------------------- 1 | # PaDEL-descriptor 2 | - names: [C1SP1, C2SP1, C1SP2, C2SP2, C3SP2, C1SP3, C2SP3, C3SP3, C4SP3] 3 | results: 4 | Hexane: [0, 0, 0, 0, 0, 2, 4, 0, 0] 5 | Benzene: [0, 0, 0, 6, 0, 0, 0, 0, 0] 6 | Caffeine: [0, 0, 2, 1, 0, 0, 0, 0, 0] 7 | # Cyanidin 8 | Lycopene: [0, 0, 0, 18, 8, 10, 4, 0, 0] 9 | Epicatechin: [0, 0, 0, 10, 2, 0, 3, 0, 0] 10 | Limonene: [0, 0, 1, 1, 2, 2, 3, 1, 0] 11 | Allicin: [0, 0, 2, 2, 0, 2, 0, 0, 0] 12 | Glutathione: [0, 0, 4, 0, 0, 2, 4, 0, 0] 13 | Digoxin: [0, 0, 1, 1, 1, 9, 22, 5, 2] 14 | Capsaicin: [0, 0, 1, 7, 1, 3, 4, 1, 0] 15 | EllagicAcid: [0, 0, 2, 8, 4, 0, 0, 0, 0] 16 | Astaxanthin: [0, 0, 0, 16, 8, 10, 4, 0, 2] 17 | 18 | # PaDEL-descriptor 19 | - names: HybRatio 20 | digit: 7 21 | results: 22 | Hexane: 1 23 | Benzene: 0 24 | Caffeine: 0.375 25 | # Cyanidin 26 | Lycopene: 0.35 27 | Epicatechin: 0.2 28 | Limonene: 0.6 29 | Allicin: 0.333333333 30 | Glutathione: 0.6 31 | Digoxin: 0.926829268 32 | Capsaicin: 0.5 33 | EllagicAcid: 0 34 | Astaxanthin: 0.4 35 | -------------------------------------------------------------------------------- /mordred/tests/references/Bond/BondTypes.yaml: -------------------------------------------------------------------------------- 1 | - names: [nBonds, nBondsO, nBondsS, nBondsD, nBondsT, nBondsA, nBondsM, nBondsKS, nBondsKD] 2 | results: 3 | Hexane: [19, 5, 19, 0, 0, 0, 0, 19, 0] 4 | Benzene: [12, 6, 6, 0, 0, 6, 6, 9, 3] 5 | Caffeine: [25, 15, 13, 2, 0, 10, 12, 21, 4] 6 | Cyanidin: [34, 23, 17, 0, 0, 17, 17, 26, 8] 7 | Lycopene: [95, 39, 82, 13, 0, 0, 13, 82, 13] 8 | Epicatechin: [37, 23, 25, 0, 0, 12, 12, 31, 6] 9 | Limonene: [26, 10, 24, 2, 0, 0, 2, 24, 2] 10 | Allicin: [18, 8, 15, 3, 0, 0, 3, 15, 3] 11 | Glutathione: [36, 19, 32, 4, 0, 0, 4, 32, 4] 12 | Digoxin: [126, 62, 124, 2, 0, 0, 2, 124, 2] 13 | Capsaicin: [49, 22, 41, 2, 0, 6, 8, 44, 5] 14 | EllagicAcid: [31, 25, 10, 2, 0, 19, 21, 23, 8] 15 | Astaxanthin: [97, 45, 84, 13, 0, 0, 13, 84, 13] 16 | DMSO: [9, 3, 8, 1, 0, 0, 1, 8, 1] 17 | DiethylThioketone: [15, 5, 14, 1, 0, 0, 1, 14, 1] 18 | VinylsulfonicAcid: [9, 5, 6, 3, 0, 0, 3, 6, 3] 19 | Thiophene: [9, 5, 4, 0, 0, 5, 5, 7, 2] 20 | Triethoxyphosphine: [24, 9, 24, 0, 0, 0, 0, 24, 0] 21 | MethylphosphonicAcid: [9, 4, 8, 1, 0, 0, 1, 8, 1] 22 | Acetonitrile: [5, 2, 4, 0, 1, 0, 1, 4, 0] 23 | -------------------------------------------------------------------------------- /mordred/tests/references/Bond/HBond.yaml: -------------------------------------------------------------------------------- 1 | # e-dragon 2 | - names: [nHBAcc, nHBDon] 3 | results: 4 | Hexane: [0, 0] 5 | Benzene: [0, 0] 6 | Caffeine: [skip, 0] 7 | Cyanidin: [skip, 5] 8 | Lycopene: [0, 0] 9 | Epicatechin: [6, 5] 10 | Limonene: [0, 0] 11 | Allicin: [skip, 0] 12 | Glutathione: [skip, 6] 13 | Digoxin: [14, 6] 14 | Capsaicin: [skip, 2] 15 | EllagicAcid: [8, 4] 16 | Astaxanthin: [4, 2] 17 | -------------------------------------------------------------------------------- /mordred/tests/references/Bond/Rotatable.yaml: -------------------------------------------------------------------------------- 1 | - names: nRot 2 | results: 3 | Hexane: 3 4 | Benzene: 0 5 | Caffeine: 0 6 | Cyanidin: 1 7 | Lycopene: 16 8 | Epicatechin: 1 9 | Limonene: 1 10 | Allicin: 5 11 | Glutathione: 9 12 | Digoxin: 7 13 | Capsaicin: 9 14 | EllagicAcid: 0 15 | Astaxanthin: 10 16 | 17 | - names: RotRatio 18 | digit: 7 19 | results: 20 | Hexane: 0.6 21 | Benzene: 0 22 | Caffeine: 0 23 | Cyanidin: 0.043478261 24 | Lycopene: 0.41025641 25 | Epicatechin: 0.043478261 26 | Limonene: 0.1 27 | Allicin: 0.625 28 | Glutathione: 0.473684211 29 | Digoxin: 0.112903226 30 | Capsaicin: 0.409090909 31 | EllagicAcid: 0 32 | Astaxanthin: 0.222222222 33 | -------------------------------------------------------------------------------- /mordred/tests/references/CPSA.yaml: -------------------------------------------------------------------------------- 1 | - names: [PNSA1, PNSA2, PNSA3, PNSA4, PNSA5] 2 | digit: 7 3 | results: 4 | Caffeine: [82.94041380284872, -132.79309686674299, -20.700982716698846, -5.533045702780957, -22.13218281112383] 5 | 6 | - names: [PPSA1, PPSA2, PPSA3, PPSA4, PPSA5] 7 | digit: 7 8 | results: 9 | Caffeine: [276.8584081526843, 443.26865187317077, 19.5222150781725, 18.469527161382114, 24.626036215176157] 10 | 11 | - names: [DPSA1, DPSA2, DPSA3, DPSA4, DPSA5] 12 | digit: 7 13 | results: 14 | Caffeine: [193.9179943498356, 576.0617487399138, 40.223197794871346, 24.00257286416307, 46.75821902629998] 15 | 16 | - names: [FNSA1, FNSA2, FNSA3, FNSA4, FNSA5] 17 | digit: 7 18 | results: 19 | Caffeine: [0.2305188587112695, -0.3690759634648128, -0.0575348818658924, -0.015378165144367198, -0.06151266057746879] 20 | 21 | - names: [FPSA1, FPSA2, FPSA3, FPSA4, FPSA5] 22 | digit: 7 23 | results: 24 | Caffeine: [0.7694811412887306, 1.2319902813021262, 0.054258696490632814, 0.05133292838758859, 0.0684439045167848] 25 | 26 | - names: [WNSA1, WNSA2, WNSA3, WNSA4, WNSA5] 27 | digit: 7 28 | results: 29 | Caffeine: [29.8418631787694, -47.778799816481104, -7.4481891947900944, -1.9907833256867127, -7.963133302746851] 30 | 31 | - names: [WPSA1, WPSA2, WPSA3, WPSA4, WPSA5] 32 | digit: 7 33 | results: 34 | Caffeine: [99.61332910181996, 159.48753875378412, 7.0240699870890095, 6.645314114741004, 8.860418819654674] 35 | 36 | - names: [RNCG, RPCG, RNCS, RPCS, TASA, TPSA, RASA, RPSA] 37 | digit: 7 38 | results: 39 | Caffeine: [0.204778202, 0.207176582, 6.4769570309974345, 42.873563992020024, 259.61332603787326, 100.18549591765974, 0.7215513509100885, 0.27844864908991146] 40 | -------------------------------------------------------------------------------- /mordred/tests/references/Constitutional.yaml: -------------------------------------------------------------------------------- 1 | # PaDEL-descriptor 2 | # Si: bug of PaDEL: skip 3 | - names: [Sv, Sse, Spe, Sare, Sp] 4 | digit: 7 5 | results: 6 | Hexane: [9.792794627, 19.21485798, 18.07843137, 18.32, 11.58988144] 7 | Benzene: [7.625483411, 11.66351056, 11.17647059, 11.28, 8.395663473] 8 | Caffeine: [15.17059149, 24.75309541, 24.09411765, 24.512, 15.58798204] 9 | # Cyanidin 10 | Lycopene: [55.17117851, 92.8594319, 88.31372549, 89.28, 62.35952575] 11 | Epicatechin: [23.08158925, 36.19883467, 35.17254902, 35.72, 23.47131856] 12 | Limonene: [14.33462243, 25.10269483, 23.80392157, 24.08, 16.38843593] 13 | Allicin: [11.79804763, 18.92352513, 18, 18.152, 13.94606587] 14 | Glutathione: [22.35527641, 38.59686817, 37.34901961, 38.02, 23.38172515] 15 | Digoxin: [68.34567718, 120.0400583, 115.1019608, 116.92, 73.27709701] 16 | Capsaicin: [28.21703623, 48.64093227, 46.53333333, 47.188, 30.87988683] 17 | EllagicAcid: [21.34387625, 30.30881282, 29.96862745, 30.48, 20.23757964] 18 | Astaxanthin: [56.94671932, 94.40640932, 90.25882353, 91.36, 62.68337485] 19 | 20 | # Mi: bug of PaDEL: skip 21 | - names: [Mv, Mse, Mpe, Mare, Mp] 22 | digit: 7 23 | results: 24 | Hexane: [0.489639731, 0.960742899, 0.903921569, 0.916, 0.579494072] 25 | Benzene: [0.635456951, 0.971959213, 0.931372549, 0.94, 0.699638623] 26 | Caffeine: [0.632107979, 1.031378975, 1.003921569, 1.021333333, 0.649499251] 27 | # Cyanidin 28 | Lycopene: [0.574699776, 0.967285749, 0.919934641, 0.93, 0.649578393] 29 | Epicatechin: [0.659473979, 1.034252419, 1.004929972, 1.020571429, 0.670609102] 30 | Limonene: [0.551331632, 0.965488263, 0.915535445, 0.926153846, 0.630324459] 31 | Allicin: [0.620949875, 0.995975007, 0.947368421, 0.955368421, 0.734003467] 32 | Glutathione: [0.60419666, 1.043158599, 1.009432962, 1.027567568, 0.631938518] 33 | Digoxin: [0.574333422, 1.008739985, 0.967243368, 0.982521008, 0.615773924] 34 | Capsaicin: [0.575857882, 0.992672087, 0.949659864, 0.963020408, 0.630201772] 35 | EllagicAcid: [0.762281295, 1.082457601, 1.070308123, 1.088571429, 0.722770701] 36 | Astaxanthin: [0.593194993, 0.983400097, 0.940196078, 0.951666667, 0.652951821] 37 | -------------------------------------------------------------------------------- /mordred/tests/references/DistanceEdge.yaml: -------------------------------------------------------------------------------- 1 | - names: [MDEC-11, MDEC-12, MDEC-13, MDEC-14, MDEC-22, MDEC-23, MDEC-24, MDEC-33, MDEC-34, MDEC-44] 2 | digit: 7 3 | results: 4 | Hexane: [0.2, 3.614408014, .NAN, .NAN, 3.965406457, .NAN, .NAN, .NAN, .NAN, .NAN] 5 | Benzene: [.NAN, .NAN, .NAN, .NAN, 9.125465128, .NAN, .NAN, .NAN, .NAN, .NAN] 6 | Caffeine: [0.646330407, 0.877205321, 4.326341831, .NAN, .NAN, 1.519671371, .NAN, 3.532775529, .NAN, .NAN] 7 | Cyanidin: [.NAN, .NAN, .NAN, .NAN, 3.941835724, 18.23884539, .NAN, 11.49395718, .NAN, .NAN] 8 | Lycopene: [3.477062287, 23.09685211, 8.941294348, .NAN, skip, 23.72711119, .NAN, 2.691828276, .NAN, .NAN] 9 | Epicatechin: [.NAN, .NAN, .NAN, .NAN, 3.941835724, 18.23884539, .NAN, 11.49395718, .NAN, .NAN] 10 | Limonene: [0.721124785, 3.888322594, 3.867776753, .NAN, 3.301927249, 7.065551058, .NAN, 1.310370697, .NAN, .NAN] 11 | Allicin: [0.142857143, 2.874432896, .NAN, .NAN, 2.40685195, .NAN, .NAN, .NAN, .NAN, .NAN] 12 | Glutathione: [.NAN, .NAN, .NAN, .NAN, 1.550343874, 7.630765803, .NAN, 3.903666633, .NAN, .NAN] 13 | Digoxin: [0.85948907, 7.580389003, 12.82553393, 2.104827693, 12.37415379, 36.20501646, 9.177870076, skip, 8.5608932, 1.310370697] 14 | Capsaicin: [0.391486764, 4.569196073, 2.458790708, .NAN, 11.54816747, 12.03732145, .NAN, 2.10347987, .NAN, .NAN] 15 | EllagicAcid: [.NAN, .NAN, .NAN, .NAN, 0.2, 8.785151666, .NAN, 25.52994922, .NAN, .NAN] 16 | Astaxanthin: [4.205212759, 19.69956747, 14.52247307, 2.786953743, 19.9824405, 26.4431031, 3.926689288, 8.128295751, 3.353777908, 0.047619048] 17 | -------------------------------------------------------------------------------- /mordred/tests/references/EState.yaml: -------------------------------------------------------------------------------- 1 | - names: [NdO, NsOH, NsNH2, NaaN, NaaNH, NaaCH, NaasC, NsssCH, NdssC, NsCH3] 2 | results: 3 | Histidine: [1, 1, 1, 1, 1, 2, 1, 1, 1, 0] 4 | 5 | - names: [SdO, SsOH, SsNH2, SaaN, SaaNH, SaaCH, SaasC, SsssCH, SdssC, SsCH3] 6 | digit: 0 7 | results: 8 | Histidine: [10.263, 8.418, 5.257, 3.840, 2.714, skip, 0.666, -0.863, -1.006, 0] 9 | -------------------------------------------------------------------------------- /mordred/tests/references/FragmentComplexity.yaml: -------------------------------------------------------------------------------- 1 | - names: fragCpx 2 | digit: 7 3 | results: 4 | Hexane: 5 5 | Benzene: 6 6 | Caffeine: 43.06 7 | Cyanidin: 109.06 8 | Lycopene: 39 9 | Epicatechin: 109.06 10 | Limonene: 10 11 | Allicin: 8.03 12 | Glutathione: 19.1 13 | Digoxin: 874.14 14 | Capsaicin: 22.04 15 | EllagicAcid: 163.08 16 | Astaxanthin: 133.04 17 | -------------------------------------------------------------------------------- /mordred/tests/references/Framework.yaml: -------------------------------------------------------------------------------- 1 | - names: fMF 2 | digit: 7 3 | results: 4 | Hexane: 0 5 | Benzene: 0.5 6 | Caffeine: 0.375 7 | # Cyanidin 8 | Lycopene: 0 9 | Epicatechin: 0.457142857 10 | Limonene: 0.230769231 11 | Allicin: 0 12 | Glutathione: 0 13 | Digoxin: 0.361344538 14 | Capsaicin: 0.12244898 15 | EllagicAcid: 0.571428571 16 | Astaxanthin: 0.3125 17 | -------------------------------------------------------------------------------- /mordred/tests/references/GeometricalIndex.yaml: -------------------------------------------------------------------------------- 1 | - names: [GeomRadius, GeomDiameter, GeomShapeIndex] 2 | digit: 7 3 | results: 4 | Hexane: [3.885272976, 6.541237774, 0.68359799] 5 | Benzene: [3.876368801, 4.963197199, 0.280372806] 6 | Caffeine: [4.507777125, 7.570430054, 0.67941534] 7 | Cyanidin: [6.138322316, 11.93146321, 0.943766163] 8 | Lycopene: [16.76797511, 32.72265424, 0.951497067] 9 | Epicatechin: [6.105063047, 11.96066464, 0.959138596] 10 | Limonene: [4.528738159, 8.417264424, 0.858633493] 11 | Allicin: [5.31582256, 8.37387507, 0.575273624] 12 | Glutathione: [6.560912296, 12.69166177, 0.934435517] 13 | Digoxin: [13.77763035, 26.27450334, 0.907040809] 14 | Capsaicin: [8.60734835, 17.08936757, 0.985439287] 15 | EllagicAcid: [5.9148244141309894, 10.346072306435907, 0.7491765743237131] 16 | Astaxanthin: [15.22636152, 29.76130938, 0.954591012] 17 | DMSO: [2.411892794, 4.588461679, 0.902431854] 18 | DiethylThioketone: [3.457850377, 5.938201014, 0.717309995] 19 | VinylsulfonicAcid: [3.274863125, 5.176495685, 0.580675432] 20 | Thiophene: [3.3709151843379273, 4.5391689922275429, 0.3465687340095652] 21 | Triethoxyphosphine: [4.73643179, 9.058690043, 0.91255579] 22 | MethylphosphonicAcid: [2.388423704, 4.450995732, 0.863570406] 23 | MethylCyclopropane: [2.238489022, 4.333239358, 0.93578763] 24 | Acetonitrile: [2.114446947, 3.179868392, 0.503877124] 25 | Histidine: [4.616310545, 8.198230336, 0.775926956] 26 | -------------------------------------------------------------------------------- /mordred/tests/references/GravitationalIndex.yaml: -------------------------------------------------------------------------------- 1 | # ~ 3% error with CDK 2 | - names: [GRAV, GRAVH, GRAVp, GRAVHp] 3 | digit: 7 4 | results: 5 | Hexane: [459.8609416496471, 716.1008419243194, 309.53386842095483, 450.7374246255329] 6 | Benzene: [648.8024172690108, 760.4527702105396, 444.89308612731736, 506.40700360431197] 7 | Caffeine: [2700.2670479661274, 2940.7755761680933, 1357.3005389522987, 1458.7082661002728] 8 | Cyanidin: [4025.001032102463, 4352.2283038078795, 1879.2940741168027, 2025.3260747545296] 9 | Lycopene: [5501.948757823909, 6882.216866999394, 2728.4931016572173, 3295.966198841089] 10 | Epicatechin: [4002.6832759201166, 4435.439100919329, 1834.956299570688, 2011.9626419477952] 11 | Limonene: [1155.7631662190804, 1496.9862626115946, 659.4524958934505, 821.1977177096232] 12 | Allicin: [1584.760720062332, 1815.0747036482703, 989.7945825259167, 1091.695646162504] 13 | Glutathione: [3767.1883898529754, 4300.634151693635, 1683.5757309468365, 1890.478606532735] 14 | Digoxin: [12398.479967260831, 14725.735149796004, 4538.459070198493, 5224.9522003819] 15 | Capsaicin: [3330.011303465074, 4007.757337837489, 1681.0758077260975, 1964.4801329551624] 16 | EllagicAcid: [4898.5540420654379, 5096.481065521868, 2150.0365841845105, 2238.3518492910807] 17 | Astaxanthin: [7325.707161552444, 8775.825908055835, 3242.920568558543, 3782.5696390705803] 18 | DMSO: [537.096826896718, 652.1857976868029, 463.3538705325816, 524.2132300149998] 19 | DiethylThioketone: [644.5621403106255, 839.931092118053, 386.13392043542115, 487.09943391470614] 20 | VinylsulfonicAcid: [1213.7308093918246, 1307.874310969384, 897.6550597928317, 945.3159354278254] 21 | Thiophene: [679.97246039377876, 758.9440286512463, 485.97937158259913, 527.33006131801176] 22 | Triethoxyphosphine: [1734.1952645575086, 2064.890204717642, 1039.9213424475302, 1191.2406436817741] 23 | MethylphosphonicAcid: [926.5690100953241, 1046.8876923437017, 729.06740178429, 793.3866428121491] 24 | MethylCyclopropane: [298.7552738080544, 432.4185423280128, 256.01153306024446, 337.82568879220025] 25 | Acetonitrile: [216.9410347421079, 260.5706430773888, 192.4732556334423, 222.8181798092017] 26 | Histidine: [1687.963783123614, 1924.2041122186106, 939.3150558632149, 1047.482783217108] 27 | -------------------------------------------------------------------------------- /mordred/tests/references/Indices.yaml: -------------------------------------------------------------------------------- 1 | - names: ECIndex 2 | results: 3 | Hexane: 38 4 | Benzene: 36 5 | Caffeine: 137 6 | Cyanidin: 353 7 | Lycopene: 1834 8 | Epicatechin: 353 9 | Limonene: 88 10 | Allicin: 83 11 | Glutathione: 347 12 | Digoxin: 2628 13 | Capsaicin: 515 14 | EllagicAcid: 328 15 | Astaxanthin: 1932 16 | 17 | - names: Zagreb1 18 | results: 19 | Hexane: 18 20 | Benzene: 24 21 | Caffeine: 76 22 | Cyanidin: 114 23 | Lycopene: 170 24 | Epicatechin: 114 25 | Limonene: 46 26 | Allicin: 32 27 | Glutathione: 86 28 | Digoxin: 320 29 | Capsaicin: 98 30 | EllagicAcid: 130 31 | Astaxanthin: 218 32 | 33 | - names: [Zagreb1, Zagreb2] 34 | results: 35 | MethylCyclopropane: [18, 19] 36 | 37 | - names: [mZagreb1, mZagreb2] 38 | digit: 2 39 | results: 40 | MethylCyclopropane: [1.61, 0.92] 41 | 42 | - names: [WPath, WPol] 43 | results: 44 | Hexane: [35, 3] 45 | Benzene: [27, 3] 46 | Caffeine: [258, 25] 47 | Cyanidin: [894, 36] 48 | Lycopene: [8904, 43] 49 | Epicatechin: [894, 36] 50 | Limonene: [120, 11] 51 | Allicin: [108, 7] 52 | Glutathione: [969, 24] 53 | Digoxin: [14940, 113] 54 | Capsaicin: [1411, 26] 55 | EllagicAcid: [851, 48] 56 | Astaxanthin: [10234, 69] 57 | 58 | - names: DetourIndex 59 | results: 60 | Benzene: 63 61 | 62 | 63 | - names: [Radius, Diameter] 64 | results: 65 | Hexane: [3, 5] 66 | Benzene: [3, 3] 67 | Caffeine: [4, 6] 68 | Cyanidin: [5, 10] 69 | Lycopene: [16, 31] 70 | Epicatechin: [5, 10] 71 | Limonene: [3, 6] 72 | Allicin: [4, 7] 73 | Glutathione: [6, 12] 74 | Digoxin: [14, 28] 75 | Capsaicin: [8, 15] 76 | EllagicAcid: [5, 9] 77 | Astaxanthin: [14, 27] 78 | 79 | - names: [TopoShapeIndex, PetitjeanIndex] 80 | digit: 7 81 | results: 82 | Hexane: [0.666666667, 0.4] 83 | Benzene: [0, 0] 84 | Caffeine: [0.5, 0.333333333] 85 | Cyanidin: [1, 0.5] 86 | Lycopene: [0.9375, 0.483870968] 87 | Epicatechin: [1, 0.5] 88 | Limonene: [1, 0.5] 89 | Allicin: [0.75, 0.428571429] 90 | Glutathione: [1, 0.5] 91 | Digoxin: [1, 0.5] 92 | Capsaicin: [0.875, 0.466666667] 93 | EllagicAcid: [0.8, 0.444444444] 94 | Astaxanthin: [0.928571429, 0.481481481] 95 | 96 | - names: [Kier1, Kier2, Kier3] 97 | digit: 7 98 | results: 99 | Hexane: [6, 5, 5.333333333] 100 | Benzene: [4.166666667, 2.222222222, 1.333333333] 101 | Caffeine: [10.51555556, 3.538752363, 1.454545455] 102 | Cyanidin: [15.87901701, 6.24567474, 3.2] 103 | Lycopene: [40, 26.61436673, 28.89561925] 104 | Epicatechin: [15.87901701, 6.24567474, 3.2] 105 | Limonene: [8.1, 3.408284024, 2.285714286] 106 | Allicin: [9, 6.125, 5.87755102] 107 | Glutathione: [20, 10.6875, 9.5625] 108 | Digoxin: [41.72216441, 15.79404415, 7.344499774] 109 | Capsaicin: [20.04545455, 11.52263374, 9.03686088] 110 | EllagicAcid: [15.5232, 5.25, 2.111111111] 111 | Astaxanthin: [40.17580247, 18.51855469, 12.8576] 112 | -------------------------------------------------------------------------------- /mordred/tests/references/Lipinski.yaml: -------------------------------------------------------------------------------- 1 | - names: [Lipinski, GhoseFilter] 2 | results: 3 | Hexane: [true, false] 4 | Benzene: [true, false] 5 | Caffeine: [true, false] 6 | Cyanidin: [true, true] 7 | Lycopene: [false, false] 8 | Epicatechin: [true, true] 9 | Limonene: [true, false] 10 | Allicin: [true, false] 11 | Glutathione: [false, false] 12 | Digoxin: [false, false] 13 | Capsaicin: [true, true] 14 | EllagicAcid: [true, true] 15 | Astaxanthin: [false, false] 16 | -------------------------------------------------------------------------------- /mordred/tests/references/LogS.yaml: -------------------------------------------------------------------------------- 1 | - names: FilterItLogS 2 | digit: 3 3 | results: 4 | Hexane: -2.16745 5 | Benzene: -1.36429 6 | Caffeine: -0.518714 7 | Cyanidin: -2.43664 8 | Lycopene: -6.31848 9 | Epicatechin: -1.38604 10 | Limonene: -2.25696 11 | Allicin: -1.70013 12 | Glutathione: -0.0828825 13 | Digoxin: -1.42603 14 | Capsaicin: -4.41986 15 | EllagicAcid: -3.04572 16 | Astaxanthin: -5.68215 17 | DMSO: -0.548208 18 | DiethylThioketone: -1.54044 19 | VinylsulfonicAcid: 0.389452 20 | Thiophene: -0.950294 21 | Triethoxyphosphine: -1.58009 22 | MethylphosphonicAcid: 0.951111 23 | MethylCyclopropane: -0.678471 24 | Acetonitrile: -0.10501 25 | Histidine: -0.385674 26 | Ammonia: 0.470322 27 | PentachloroLambda5Phosphane: -3.08412 28 | SodiumChloride: -0.391668 29 | TrichloroYtterbium: -2.32665 30 | Acetylene: 0.369134 31 | Carbonate: 0.242861 32 | PotassiumIon: 0.249871 33 | Oxygen: 0.607422 34 | Iodine: -1.78464 35 | -------------------------------------------------------------------------------- /mordred/tests/references/Matrix/BCUT.yaml: -------------------------------------------------------------------------------- 1 | # PaDEL-descriptor 2 | - names: [BCUTm-1l, BCUTm-1h] 3 | digit: 0 4 | results: 5 | Hexane: [11.89, 12.11007471] 6 | Benzene: [11.85, 12.1500544] 7 | Caffeine: [11.99347887, 15.99592273] 8 | Cyanidin: [11.85, 15.99993732] 9 | Lycopene: [11.89, 12.11102666] 10 | Epicatechin: [11.85, 15.99993732] 11 | Limonene: [11.9, 12.10017173] 12 | Allicin: [11.79, 31.97307173] 13 | Glutathione: [11.99846101, 31.97267783] 14 | Digoxin: [11.89, 16.00805947] 15 | Capsaicin: [11.89, 15.99692975] 16 | EllagicAcid: [11.85, 16.00194285] 17 | Astaxanthin: [11.89, 15.99795509] 18 | -------------------------------------------------------------------------------- /mordred/tests/references/Matrix/barysz.yaml: -------------------------------------------------------------------------------- 1 | # PaDEL-descriptor 2 | - names: [SpAbs_DzZ, SpMax_DzZ, SpDiam_DzZ, SpAD_DzZ, SpMAD_DzZ, LogEE_DzZ, SM1_DzZ] 3 | digit: 6 4 | results: 5 | Hexane: [24.21862301, 12.1093115, 19.57341312, 24.21862301, 4.036437168, 12.10932554, -3.55E-15] 6 | Benzene: [12, 6, 8.666666667, 12, 2, 6.009012619, -3.55E-15] 7 | # Caffeine 8 | # Cyanidin 9 | Lycopene: [721.7481658, 360.8740829, 560.1974935, 721.7481658, 18.04370415, 360.8740829, -3.98E-13] 10 | # Epicatechin 11 | # Limonene 12 | Allicin: [25.76121946, 12.8958126, 19.50759563, 26.26121946, 2.917913274, 12.89582879, 1.5] 13 | Glutathione: [173.8091125, 88.18134194, 134.7973904, 176.1073267, 8.805366337, 88.18134194, 2.553571429] 14 | Digoxin: [982.7856765, 493.0353652, 769.8501708, 985.9434577, 17.92624469, 493.0353652, 3.5] 15 | Capsaicin: [229.3980496, 115.1454534, 183.8687075, 230.2097379, 10.464079, 115.1454534, 0.892857143] 16 | # EllagicAcid 17 | # Astaxanthin 18 | 19 | # e-dragon 20 | - names: [VE1_DzZ, VE2_DzZ] 21 | digit: 1 22 | results: 23 | Hexane: [2.412, 0.402] 24 | Benzene: [2.449, 0.408] 25 | Caffeine: [3.698, 0.264] 26 | Cyanidin: [4.513, 0.215] 27 | Lycopene: [6.21, 0.155] 28 | Epicatechin: [4.525, 0.215] 29 | Limonene: [3.122, 0.312] 30 | Allicin: [2.921, 0.325] 31 | Glutathione: [4.403, 0.22] 32 | Digoxin: [7.307, 0.133] 33 | Capsaicin: [4.618, 0.21] 34 | EllagicAcid: [4.636, 0.211] 35 | Astaxanthin: [6.556, 0.149] 36 | -------------------------------------------------------------------------------- /mordred/tests/references/Matrix/detour.yaml: -------------------------------------------------------------------------------- 1 | - names: [SpMax_Dt, SpDiam_Dt, SpAD_Dt, SpMAD_Dt, LogEE_Dt] 2 | digit: 5 3 | results: 4 | Hexane: [12.1093115, 19.57341312, 24.21862301, 4.036437168, 12.10932554] 5 | Benzene: [21, 27, 42, 7, 21] 6 | Caffeine: [95.16634059, 114.4774666, 190.3326812, 13.59519151, 95.16634059] 7 | Cyanidin: [191.5904568, 263.4509827, 383.1809137, 18.24671017, 191.5904568] 8 | Lycopene: [462.8935771, 726.367662, 925.7871542, 23.14467886, 462.8935771] 9 | Epicatechin: [191.5904568, 263.4509827, 383.1809137, 18.24671017, 191.5904568] 10 | Limonene: [41.38554761, 57.2454538, 82.77109522, 8.277109522, 41.38554761] 11 | Allicin: [25.02074591, 38.31124324, 50.04149182, 5.560165758, 25.02074591] 12 | Glutathione: [100.5557233, 150.8622885, 201.1114466, 10.05557233, 100.5557233] 13 | Digoxin: [1035.473415, 1452.167174, 2075.168371, 37.73033401, skip] 14 | Capsaicin: [159.9284809, 241.9071906, 319.8569618, 14.53895281, 159.9284809] 15 | EllagicAcid: [282.1476622, 316.918998, 564.2953244, 25.64978747, 282.1476622] 16 | Astaxanthin: [574.3451302, 888.9116878, 1148.69026, 26.10659683, 574.3451302] 17 | -------------------------------------------------------------------------------- /mordred/tests/references/Matrix/distance.yaml: -------------------------------------------------------------------------------- 1 | # padel 2 | - names: [SpMax_D, SpDiam_D, SpAD_D, SpMAD_D, LogEE_D] 3 | digit: 5 4 | results: 5 | Hexane: [12.1093115, 19.57341312, 24.21862301, 4.036437168, 12.10932554, 2.22E-16] 6 | Benzene: [9, 13, 18, 3, 9.000420062] 7 | Caffeine: [37.86260754, 51.54837376, 75.72521508, 5.408943934, 37.86260754, 0.009793972] 8 | Cyanidin: [87.93048362, 130.6445806, 175.8609672, 8.374331774, 87.93048362, 0.084429319] 9 | Lycopene: [462.8935771, 726.367662, 925.7871542, 23.14467886, 462.8935771, 1.44E-15] 10 | Epicatechin: [87.93048362, 130.6445806, 175.8609672, 8.374331774, 87.93048362, 0.084429319] 11 | Limonene: [24.79457074, 37.39674508, 49.58914148, 4.958914148, 24.79457074, 0.015455772] 12 | Allicin: [25.02074591, 38.31124324, 50.04149182, 5.560165758, 25.02074591, 0.045146306] 13 | Glutathione: [100.5557233, 150.8622885, 201.1114466, 10.05557233, 100.5557233, 0.040163544] 14 | Digoxin: [563.352885, 883.3072847, 1126.70577, 20.48555945, 563.352885, 0.236859885] 15 | Capsaicin: [133.1136235, 208.7766518, 266.227247, 12.1012385, 133.1136235, 0.23247064] 16 | EllagicAcid: [79.57404117, 109.2717721, 159.1480823, 7.234003743, 79.57404117] 17 | Astaxanthin: [476.7410508, 765.8660718, 953.4821015, 21.67004776, 476.7410508] 18 | 19 | - names: [VE1_D, VE2_D, VR1_D] 20 | digit: 3 21 | results: 22 | Hexane: [2.412, 0.402, 13.31649] 23 | Benzene: [2.449, 0.408, skip] 24 | Caffeine: [3.695, 0.264, skip] 25 | Cyanidin: [4.517, 0.215, skip] 26 | Lycopene: [6.22, 0.156, skip] 27 | Epicatechin: [4.517, 0.215, skip] 28 | Limonene: [3.117, 0.312, skip] 29 | Allicin: [2.947, 0.327, skip] 30 | Glutathione: [4.4, 0.22, skip] 31 | Digoxin: [7.301, 0.133, skip] 32 | Capsaicin: [4.618, 0.21, skip] 33 | EllagicAcid: [4.63, 0.21, skip] 34 | Astaxanthin: [6.562, 0.149, skip] 35 | -------------------------------------------------------------------------------- /mordred/tests/references/MoRSE.yaml: -------------------------------------------------------------------------------- 1 | # E-dragon 1.0 2 | - names: [Mor01, Mor02, Mor03, Mor04, Mor05, Mor06, Mor07, Mor08] 3 | digit: 2 4 | results: 5 | Hexane: [190, 24.866, -4.391, 1.246, -2.878, -1.499, 0.357, 1.506] 6 | Cyanidin: [496, 28.358, -2.358, 1.491, -4.704, -2.887, 4.308, -0.797] 7 | EllagicAcid: [378, 21.726, -2.29, 1.323, -4.43, -1.414, 3.075, -1.444] 8 | 9 | - names: [Mor01m, Mor02m] 10 | digit: 7 11 | results: 12 | Benzene: [18.126876765152154, 6.888342909698688] # [18.134, 6.889] 13 | Cyanidin: [273.10980699074844, 20.289529509869435] # [273.179, 20.293] 14 | -------------------------------------------------------------------------------- /mordred/tests/references/MolecularId.yaml: -------------------------------------------------------------------------------- 1 | - names: [MID, AMID] 2 | digit: 6 3 | results: 4 | Hexane: [10.83915043, 1.806525072] 5 | Benzene: [11.8125, 1.96875] 6 | Caffeine: [27.80010233, 1.985721595] 7 | Cyanidin: [42.68983013, 2.032849054] 8 | Lycopene: [77.41561711, 1.935390428] 9 | Epicatechin: [42.68983013, 2.032849054] 10 | Limonene: [19.38570823, 1.938570823] 11 | Allicin: [16.65502353, 1.85055817] 12 | Glutathione: [37.80131214, 1.890065607] 13 | Digoxin: [113.2392334, 2.058895153] 14 | Capsaicin: [43.08947003, 1.958612274] 15 | EllagicAcid: [45.46110533, 2.066413879] 16 | Astaxanthin: [86.16657979, 1.958331359] 17 | DMSO: [6.732050808, 1.683012702] 18 | DiethylThioketone: [10.6758508, 1.779308466] 19 | VinylsulfonicAcid: [10.46599026, 1.74433171] 20 | Thiophene: [9.6875, 1.9375] 21 | Triethoxyphosphine: [18.66994061, 1.866994061] 22 | MethylphosphonicAcid: [8.5, 1.7] 23 | MethylCyclopropane: [7.175868588, 1.793967147] 24 | Acetonitrile: [4.914213562, 1.638071187] 25 | -------------------------------------------------------------------------------- /mordred/tests/references/MomentOfInertia.yaml: -------------------------------------------------------------------------------- 1 | # error ~0.2% with PaDEL 2 | - names: [MOMI-X, MOMI-Y, MOMI-Z] 3 | digit: 7 4 | results: 5 | Hexane: [331.43267186199, 304.2623605241771, 79.76094416702296] 6 | Benzene: [177.45574127229264, 88.73087501640376, 88.72486628498366] 7 | Caffeine: [1174.7909527036747, 711.1971116543713, 473.2617745231172] 8 | Cyanidin: [4082.4611900398895, 3380.6561993547775, 756.8345704441458] 9 | Lycopene: [53668.87878535054, 53232.3229004682, 1854.4919458218283] 10 | Epicatechin: [3927.4291449102006, 3385.248192538719, 748.5154021491107] 11 | Limonene: [751.3335552781424, 710.5101161985185, 165.6064046278417] 12 | Allicin: [834.720110773591, 730.7024822923935, 276.2786193188218] 13 | Glutathione: [4875.140084677559, 4511.146752765506, 840.9336738286929] 14 | Digoxin: [47480.2109528471, 46102.43069327005, 3899.8083343798353] 15 | Capsaicin: [8244.643509725149, 8091.655711687317, 665.4068759921556] 16 | EllagicAcid: [3206.2593764536518, 2125.9644784406478, 1080.2948985324103] 17 | Astaxanthin: [55309.41941481355, 54848.0265476281, 1899.4340610561994] 18 | DMSO: [121.73121419158136, 73.79219268379035, 72.94244731550673] 19 | DiethylThioketone: [346.0207050621905, 211.80139248577336, 183.2079342909363] 20 | VinylsulfonicAcid: [197.23419045448654, 195.12810805801954, 106.01424832680848] 21 | Thiophene: [156.60195031204867, 94.173198539770752, 62.428751794628688] 22 | Triethoxyphosphine: [1014.1509285348968, 663.1930189539381, 414.2793997209286] 23 | MethylphosphonicAcid: [126.09250663621268, 124.1495235884038, 111.08030457378948] 24 | MethylCyclopropane: [89.90657392233443, 78.95379333454737, 32.20631103065584] 25 | Acetonitrile: [55.30411423613292, 55.30400025103894, 3.162638275854749] 26 | Histidine: [1038.4042964061784, 909.5320478764941, 168.49073079109507] 27 | Acetylene: [14.24690764612896, 14.24690764612896, 0.0] 28 | -------------------------------------------------------------------------------- /mordred/tests/references/Polarizability.yaml: -------------------------------------------------------------------------------- 1 | # PaDEL-descriptor 2 | - names: [apol78, bpol78] 3 | digit: 7 4 | results: 5 | Hexane: [19.895102, 15.304898] 6 | Benzene: [14.560758, 6.559242] 7 | Caffeine: [26.75193, 20.10807] 8 | # Cyanidin 9 | Lycopene: [107.740408, 61.219592] 10 | Epicatechin: [40.547102, 17.220898] 11 | Limonene: [28.268688, 17.491312] 12 | Allicin: [23.82993, 15.31007] 13 | Glutathione: [39.947481, 25.356519] 14 | Digoxin: [126.062752, 84.335248] 15 | Capsaicin: [53.189411, 33.050589] 16 | EllagicAcid: [35.056758, 12.307242] 17 | Astaxanthin: [108.281236, 58.762764] 18 | -------------------------------------------------------------------------------- /mordred/tests/references/Property/McGowanVolume.yaml: -------------------------------------------------------------------------------- 1 | - names: VMcGowan 2 | digit: 7 3 | results: 4 | Hexane: 95.4 5 | Benzene: 71.64 6 | Caffeine: 136.32 7 | # Cyanidin 8 | Lycopene: 518.56 9 | Epicatechin: 199.05 10 | Limonene: 132.3 11 | Allicin: 125.37 12 | Glutathione: 216.07 13 | Digoxin: 575.25 14 | Capsaicin: 259.71 15 | EllagicAcid: 177.24 16 | Astaxanthin: 520.32 17 | -------------------------------------------------------------------------------- /mordred/tests/references/Property/Vabc.yaml: -------------------------------------------------------------------------------- 1 | - names: Vabc 2 | digit: 4 3 | results: 4 | Hexane: 112.3323665 5 | Benzene: 81.16653165 6 | Caffeine: 151.43307774 7 | Cyanidin: 231.19477193 8 | Lycopene: 666.1218806 9 | Epicatechin: 246.04946 10 | Limonene: 163.8869289 11 | Allicin: 152.8677239 12 | Glutathione: 275.211135 13 | Digoxin: 736.6304152 14 | Capsaicin: 320.8128701 15 | EllagicAcid: 206.90455266 16 | Astaxanthin: 676.56987 17 | -------------------------------------------------------------------------------- /mordred/tests/references/Property/Weight.yaml: -------------------------------------------------------------------------------- 1 | - names: [MW, AMW] 2 | digit: 7 3 | results: 4 | Hexane: [86.10955045, 4.305477522] 5 | Benzene: [78.04695019, 6.503912516] 6 | Caffeine: [194.0803756, 8.086682315] 7 | # Cyanidin 8 | Lycopene: [536.4382018, 5.587897935] 9 | Epicatechin: [290.0790382, 8.287972519] 10 | Limonene: [136.1252005, 5.235584635] 11 | Allicin: [162.0173069, 8.527226681] 12 | Glutathione: [307.0838063, 8.299562331] 13 | Digoxin: [780.4296067, 6.558231989] 14 | Capsaicin: [305.1990937, 6.228552933] 15 | EllagicAcid: [302.0062672, 10.78593811] 16 | Astaxanthin: [596.3865601, 6.212360002] 17 | -------------------------------------------------------------------------------- /mordred/tests/references/Ring.yaml: -------------------------------------------------------------------------------- 1 | - names: [nRing, n5Ring, n6Ring, nFRing, nG12FRing, nHRing] 2 | results: 3 | Hexane: [0, 0, 0, 0, 0, 0] 4 | Benzene: [1, 0, 1, 0, 0, 0] 5 | Caffeine: [2, 1, 1, 1, 0, 2] 6 | Cyanidin: [3, 0, 3, 1, 0, 1] 7 | Lycopene: [0, 0, 0, 0, 0, 0] 8 | Epicatechin: [3, 0, 3, 1, 0, 1] 9 | Limonene: [1, 0, 1, 0, 0, 0] 10 | Allicin: [0, 0, 0, 0, 0, 0] 11 | Glutathione: [0, 0, 0, 0, 0, 0] 12 | Digoxin: [8, 2, 6, 1, 1, 4] 13 | Capsaicin: [1, 0, 1, 0, 0, 0] 14 | EllagicAcid: [4, 0, 4, 1, 1, 2] 15 | Astaxanthin: [2, 0, 2, 0, 0, 0] 16 | -------------------------------------------------------------------------------- /mordred/tests/references/Smarts.yaml: -------------------------------------------------------------------------------- 1 | # PaDEL-descriptor 2 | - names: nAcid 3 | results: 4 | Hexane: 0 5 | Benzene: 0 6 | Caffeine: 0 7 | Cyanidin: 0 8 | Lycopene: 0 9 | Epicatechin: 0 10 | Limonene: 0 11 | Allicin: 0 12 | Glutathione: 2 13 | Digoxin: 0 14 | Capsaicin: 0 15 | EllagicAcid: 0 16 | Astaxanthin: 0 17 | 18 | - names: nBase 19 | results: 20 | Hexane: 0 21 | Benzene: 0 22 | Caffeine: 0 23 | Cyanidin: skip 24 | Lycopene: 0 25 | Epicatechin: 0 26 | Limonene: 0 27 | Allicin: 0 28 | Glutathione: 1 29 | Digoxin: 0 30 | Capsaicin: 0 31 | EllagicAcid: 0 32 | Astaxanthin: 0 33 | -------------------------------------------------------------------------------- /mordred/tests/references/TopoPSA.yaml: -------------------------------------------------------------------------------- 1 | # e-dragon: TPSA(NO) 2 | - names: TopoPSA(NO) 3 | digit: 7 4 | results: 5 | Hexane: 0 6 | Benzene: 0 7 | Caffeine: 61.82 8 | Cyanidin: 112.45 9 | Lycopene: 0 10 | Epicatechin: 110.38 11 | Limonene: 0 12 | Allicin: 17.07 13 | Glutathione: 158.82 14 | Digoxin: 203.06 15 | Capsaicin: 58.56 16 | EllagicAcid: 141.34 17 | Astaxanthin: 74.6 18 | DMSO: 17.07 19 | DiethylThioketone: 0 20 | VinylsulfonicAcid: 54.37 21 | Thiophene: 0 22 | Triethoxyphosphine: 27.69 23 | MethylphosphonicAcid: 57.53 24 | 25 | - names: TopoPSA 26 | digit: 7 27 | results: 28 | Hexane: 0 29 | Benzene: 0 30 | Caffeine: 61.82 31 | Cyanidin: 112.45 32 | Lycopene: 0 33 | Epicatechin: 110.38 34 | Limonene: 0 35 | Allicin: 61.58 36 | Glutathione: 197.62 37 | Digoxin: 203.06 38 | Capsaicin: 58.56 39 | EllagicAcid: 141.34 40 | Astaxanthin: 74.6 41 | DMSO: 36.28 42 | DiethylThioketone: 32.09 43 | VinylsulfonicAcid: 62.75 44 | Thiophene: 28.24 45 | Triethoxyphosphine: 41.28 46 | MethylphosphonicAcid: 67.34 47 | -------------------------------------------------------------------------------- /mordred/tests/references/TopologicalCharge.yaml: -------------------------------------------------------------------------------- 1 | - names: [GGI1, GGI2, GGI3, GGI4, GGI5, GGI6, GGI7, GGI8, GGI9, GGI10] 2 | digit: 7 3 | results: 4 | Hexane: [0.5, 0.222222222, 0.125, 0.08, 0, 0, 0, 0, 0, 0] 5 | Benzene: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0] 6 | Caffeine: [3, 2.666666667, 1.75, 1.391666667, 0.278055556, 0, 0, 0, 0, 0] 7 | Cyanidin: [5.5, 3.111111111, 1.8125, 1.822222222, 0.756944444, 0.607346939, 0.251736111, 0.197026959, 0.116875, 0.012345679] 8 | Lycopene: [8.5, 3.333333333, 1.875, 0.72, 1.111111111, 0.571428571, 0.40625, 0.222222222, 0.3, 0.214876033] 9 | Epicatechin: [5.5, 3.111111111, 1.8125, 1.822222222, 0.756944444, 0.607346939, 0.251736111, 0.197026959, 0.116875, 0.012345679] 10 | Limonene: [2.5, 1.333333333, 0.5, 0.382222222, 0.236111111, 0, 0, 0, 0, 0] 11 | Allicin: [1.5, 0.666666667, 0.375, 0.16, 0.055555556, 0.040816327, 0, 0, 0, 0] 12 | Glutathione: [5.5, 2.666666667, 1.125, 0.96, 0.555555556, 0.285714286, 0.3125, 0.197530864, 0.06, 0.066115702] 13 | Digoxin: [16.5, 10.44444444, 7.194444444, 5.966111111, 2.691111111, 2.56675737, 1.345521542, 0.887873205, 0.648132716, 0.477404346] 14 | Capsaicin: [4.5, 2, 0.9375, 0.893333333, 0.430555556, 0.284897959, 0.227430556, 0.156210632, 0.085625, 0.053667993] 15 | EllagicAcid: [5, 3.555555556, 2.25, 3.182222222, 1.305555556, 0.764081633, 0.180555556, 0.065507685, 0, 0] 16 | Astaxanthin: [12.5, 7.333333333, 4.625, 2.773333333, 1.513888889, 0.896326531, 0.611111111, 0.386495339, 0.43125, 0.338740945] 17 | 18 | - names: [JGI1, JGI2, JGI3, JGI4, JGI5, JGI6, JGI7, JGI8, JGI9, JGI10] 19 | digit: 7 20 | results: 21 | Hexane: [0.1, 0.055555556, 0.041666667, 0.04, 0, 0, 0, 0, 0, 0] 22 | Benzene: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0] 23 | Caffeine: [0.2, 0.115942029, 0.07, 0.073245614, 0.034756944, 0, 0, 0, 0, 0] 24 | Cyanidin: [0.239130435, 0.091503268, 0.050347222, 0.060740741, 0.030277778, 0.028921283, 0.01398534, 0.016418913, 0.014609375, 0.004115226] 25 | Lycopene: [0.217948718, 0.072463768, 0.043604651, 0.017142857, 0.027100271, 0.01242236, 0.010690789, 0.00617284, 0.008571429, 0.005654632] 26 | Epicatechin: [0.239130435, 0.091503268, 0.050347222, 0.060740741, 0.030277778, 0.028921283, 0.01398534, 0.016418913, 0.014609375, 0.004115226] 27 | Limonene: [0.25, 0.102564103, 0.045454545, 0.063703704, 0.078703704, 0, 0, 0, 0, 0] 28 | Allicin: [0.1875, 0.083333333, 0.053571429, 0.026666667, 0.013888889, 0.020408163, 0, 0, 0, 0] 29 | Glutathione: [0.289473684, 0.111111111, 0.046875, 0.043636364, 0.024154589, 0.015037594, 0.01953125, 0.012345679, 0.005454545, 0.011019284] 30 | Digoxin: [0.266129032, 0.106575964, 0.06366765, 0.056284067, 0.027460317, 0.027305929, 0.015829665, 0.013251839, 0.009971273, 0.007344682] 31 | Capsaicin: [0.204545455, 0.074074074, 0.036057692, 0.040606061, 0.021527778, 0.015827664, 0.013378268, 0.009763165, 0.006116071, 0.004878908] 32 | EllagicAcid: [0.2, 0.088888889, 0.046875, 0.072323232, 0.034356725, 0.034730983, 0.020061728, 0.016376921, 0, 0] 33 | Astaxanthin: [0.277777778, 0.114583333, 0.067028986, 0.044731183, 0.030895692, 0.017237049, 0.013888889, 0.009662383, 0.011057692, 0.007698658] 34 | 35 | # e-dragon 36 | - names: JGT10 37 | digit: 3 38 | results: 39 | Hexane: 0.237 40 | Benzene: 0 41 | Caffeine: 0.494 42 | Cyanidin: 0.55 43 | Lycopene: 0.422 44 | Epicatechin: 0.55 45 | Limonene: 0.54 46 | Allicin: 0.385 47 | Glutathione: 0.579 48 | Digoxin: 0.594 49 | Capsaicin: 0.427 50 | EllagicAcid: 0.514 51 | Astaxanthin: 0.595 52 | -------------------------------------------------------------------------------- /mordred/tests/references/VAdjMat.yaml: -------------------------------------------------------------------------------- 1 | # moe-2014.09 2 | - names: VAdjMat 3 | digit: 6 4 | results: 5 | Hexane: 3.321928 6 | Benzene: 3.5849626 7 | Caffeine: 4.9068904 8 | Cyanidin: 5.523562 9 | Lycopene: 6.2854023 10 | Epicatechin: 5.523562 11 | Limonene: 4.321928 12 | Allicin: 4 13 | Glutathione: 5.2479277 14 | Digoxin: 6.9541965 15 | Capsaicin: 5.4594316 16 | EllagicAcid: 5.643856 17 | Astaxanthin: 6.4918532 18 | DMSO: 2.5849626 19 | DiethylThioketone: 3.321928 20 | VinylsulfonicAcid: 3.321928 21 | Thiophene: 3.321928 22 | Triethoxyphosphine: 4.1699252 23 | MethylphosphonicAcid: 3 24 | MethylCyclopropane: 3 25 | Acetonitrile: 2 26 | Histidine: 4.4594316 27 | -------------------------------------------------------------------------------- /mordred/tests/references/structures.smi: -------------------------------------------------------------------------------- 1 | CCCCCC Hexane 2 | c1ccccc1 Benzene 3 | CN1C=NC2=C1C(=O)N(C(=O)N2C)C Caffeine 4 | C1=CC(=C(C=C1C2=C(C=C3C(=CC(=CC3=[O+]2)O)O)O)O)O Cyanidin 5 | CC(=CCC/C(=C/C=C/C(=C/C=C/C(=C/C=C/C=C(/C=C/C=C(/C=C/C=C(/CCC=C(C)C)\C)\C)\C)/C)/C)/C)C Lycopene 6 | C1[C@H]([C@H](OC2=CC(=CC(=C21)O)O)C3=CC(=C(C=C3)O)O)O Epicatechin 7 | CC1=CCC(CC1)C(=C)C Limonene 8 | C=CCSS(=O)CC=C Allicin 9 | C(CC(=O)N[C@@H](CS)C(=O)NCC(=O)O)[C@@H](C(=O)O)N Glutathione 10 | C[C@@H]1[C@H]([C@H](C[C@@H](O1)O[C@@H]2[C@H](O[C@H](C[C@@H]2O)O[C@@H]3[C@H](O[C@H](C[C@@H]3O)O[C@H]4CC[C@]5([C@@H](C4)CC[C@@H]6[C@@H]5C[C@H]([C@]7([C@@]6(CC[C@@H]7C8=CC(=O)OC8)O)C)O)C)C)C)O)O Digoxin 11 | CC(C)/C=C/CCCCC(=O)NCC1=CC(=C(C=C1)O)OC Capsaicin 12 | C1=C2C3=C(C(=C1O)O)OC(=O)C4=CC(=C(C(=C43)OC2=O)O)O EllagicAcid 13 | CC1=C(C(C[C@@H](C1=O)O)(C)C)/C=C/C(=C/C=C/C(=C/C=C/C=C(/C=C/C=C(/C=C/C2=C(C(=O)[C@H](CC2(C)C)O)C)\C)\C)/C)/C Astaxanthin 14 | CS(=O)C DMSO 15 | CCC(=S)CC DiethylThioketone 16 | C=CS(=O)(=O)O VinylsulfonicAcid 17 | c1cscc1 Thiophene 18 | CCOP(OCC)OCC Triethoxyphosphine 19 | CP(=O)(O)O MethylphosphonicAcid 20 | CC1CC1 MethylCyclopropane 21 | CC#N Acetonitrile 22 | C1=C(NC=N1)CC(C(=O)O)N Histidine 23 | N Ammonia 24 | P(Cl)(Cl)(Cl)(Cl)Cl PentachloroLambda5Phosphane 25 | [Na+].[Cl-] SodiumChloride 26 | Cl[Yb](Cl)Cl TrichloroYtterbium 27 | C#C Acetylene 28 | O=C([O-])[O-] Carbonate 29 | [K+] PotassiumIon 30 | O=O Oxygen 31 | II Iodine 32 | -------------------------------------------------------------------------------- /mordred/tests/test_ABCIndex.py: -------------------------------------------------------------------------------- 1 | from rdkit import Chem 2 | from numpy.testing import assert_almost_equal 3 | 4 | from mordred.ABCIndex import ABCIndex, ABCGGIndex 5 | 6 | # doi:10.2298/JSC150901093F 7 | data = """ 8 | CC(C)CCCCCCC 6.58 6.49 9 | CCC(C)CCCCCC 6.47 6.58 10 | CC(C)(C)CCCCCC 6.84 6.82 11 | CCC(C)(C)CCCCC 6.68 6.95 12 | """[ 13 | 1:-1 14 | ] 15 | 16 | 17 | def test_ABC(): 18 | abc = ABCIndex() 19 | abcgg = ABCGGIndex() 20 | 21 | for line in data.split("\n"): 22 | smi, dABC, dABCGG = line.strip().split() 23 | 24 | mol = Chem.MolFromSmiles(smi) 25 | yield assert_almost_equal, abc(mol), float(dABC), 2 26 | yield assert_almost_equal, abcgg(mol), float(dABCGG), 2 27 | -------------------------------------------------------------------------------- /mordred/tests/test_SASA.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | from rdkit import Chem 4 | 5 | from nose.tools import ok_ 6 | from mordred.CPSA import TotalSurfaceArea 7 | from mordred.surface_area import SurfaceArea 8 | 9 | # calculated by pymol 10 | txt_data = """ 11 | Hexane 296.910 12 | Benzene 243.552 13 | Caffeine 369.973 14 | Cyanidin 483.873 15 | Lycopene 1172.253 16 | Epicatechin 489.498 17 | Limonene 361.278 18 | Allicin 356.872 19 | Glutathione 530.679 20 | Digoxin 1074.428 21 | Capsaicin 641.527 22 | EllagicAcid 440.267 23 | Astaxanthin 1080.941 24 | DMSO 227.926 25 | DiethylThioketone 290.503 26 | VinylsulfonicAcid 246.033 27 | Thiophene 227.046 28 | Triethoxyphosphine 396.482 29 | MethylphosphonicAcid 235.685 30 | MethylCyclopropane 229.071 31 | Acetonitrile 182.197 32 | Histidine 335.672 33 | """[ 34 | 1:-1 35 | ] 36 | 37 | 38 | sdf_file = os.path.join(os.path.dirname(__file__), "references", "structures.sdf") 39 | 40 | 41 | def test_SASA(): 42 | data = {} 43 | for line in txt_data.split("\n"): 44 | n, v = line.strip().split() 45 | data[n] = float(v) 46 | 47 | tsa = TotalSurfaceArea() 48 | 49 | for mol in Chem.SDMolSupplier(sdf_file, removeHs=False): 50 | name = mol.GetProp("_Name") 51 | actual = sum(SurfaceArea.from_mol(mol).surface_area()) 52 | 53 | if name not in data: 54 | continue 55 | 56 | desired = data[name] 57 | 58 | e = abs((actual - desired) / desired) 59 | p = 0.05 60 | 61 | yield ok_, e < p, "large SASA error in {}: {}".format(name, e) 62 | 63 | e = abs((tsa(mol) - desired) / desired) 64 | 65 | yield ok_, e < p, "large SASA error in {}: {}".format(name, e) 66 | -------------------------------------------------------------------------------- /mordred/tests/test_SLogP.py: -------------------------------------------------------------------------------- 1 | from rdkit import Chem 2 | from numpy.testing import assert_almost_equal 3 | 4 | from mordred.SLogP import SMR, SLogP 5 | 6 | 7 | def test_WildmanCrippen1(): 8 | mol = Chem.MolFromSmiles("Oc1ccccc1OC") 9 | yield assert_almost_equal, SLogP()(mol), 1.4, 2 10 | yield assert_almost_equal, SMR()(mol), 34.66, 2 11 | 12 | 13 | def test_WildmanCrippen2(): 14 | mol = Chem.MolFromSmiles("c1ccccc1c2ccccn2") 15 | yield assert_almost_equal, SLogP()(mol), 2.75, 2 16 | -------------------------------------------------------------------------------- /mordred/tests/test_attributes.py: -------------------------------------------------------------------------------- 1 | import inspect 2 | 3 | from mordred import descriptors, get_descriptors_in_module 4 | from nose.tools import ok_ 5 | from mordred._base.descriptor import is_descriptor_class 6 | 7 | 8 | def test_attributes(): 9 | for mdl in descriptors.all: 10 | for desc in get_descriptors_in_module(mdl, submodule=False): 11 | for cls in desc.__mro__: 12 | if cls == object: 13 | continue 14 | 15 | if is_descriptor_class(desc, include_abstract=True): 16 | yield ( 17 | ok_, 18 | "__slots__" in cls.__dict__, 19 | "{}({}) class don't have __slots__".format( 20 | cls.__name__, inspect.getfile(desc) 21 | ), 22 | ) 23 | 24 | yield ( 25 | ok_, 26 | "since" in desc.__dict__, 27 | "{}({}) class don't have since".format( 28 | desc.__name__, inspect.getfile(desc) 29 | ), 30 | ) 31 | -------------------------------------------------------------------------------- /mordred/tests/test_base.py: -------------------------------------------------------------------------------- 1 | from mordred import Calculator, Descriptor 2 | from nose.tools import eq_, ok_, raises 3 | 4 | from . import Dummy 5 | 6 | 7 | def test_Calculator_descriptors(): 8 | calc = Calculator() 9 | 10 | def check(l, msg=None): 11 | yield eq_, len(calc), l, msg 12 | yield ok_, all(isinstance(d, Descriptor) for d in calc.descriptors) 13 | 14 | # register instance 15 | calc.register(Dummy.Dummy2()) 16 | for c in check(1, "instance register failed"): 17 | yield c 18 | 19 | # register class 20 | yield raises(ValueError)(lambda: calc.register(Dummy.Dummy1)) 21 | for c in check(1): 22 | yield c 23 | 24 | calc.register(Dummy.Dummy2) 25 | for c in check(1): 26 | yield c 27 | 28 | calc.register(Dummy.Dummy3) 29 | for c in check(2): 30 | yield c 31 | 32 | calc.register(Dummy.Dummy4) 33 | for c in check(4): 34 | yield c 35 | 36 | # delete 37 | del calc.descriptors 38 | for c in check(0): 39 | yield c 40 | 41 | # register module 42 | calc.register(Dummy) 43 | for c in check(3): 44 | yield c 45 | 46 | eq_(calc["Dummy4_1"], Dummy.Dummy4(1)) 47 | 48 | # set instance 49 | calc.descriptors = Dummy.Dummy2() 50 | for c in check(1): 51 | yield c 52 | -------------------------------------------------------------------------------- /mordred/tests/test_by_references.py: -------------------------------------------------------------------------------- 1 | import os 2 | from glob import glob 3 | 4 | import yaml 5 | import numpy as np 6 | from rdkit import Chem 7 | from numpy.testing import assert_almost_equal 8 | 9 | from mordred import Calculator, Polarizability, descriptors 10 | from nose.tools import eq_ 11 | from mordred.error import MissingValueBase 12 | 13 | try: 14 | from yaml import CLoader as Loader 15 | except ImportError: 16 | from yaml import Loader 17 | 18 | 19 | data_dir = os.path.join(os.path.dirname(__file__), "references") 20 | 21 | 22 | def test_by_references(): 23 | calc = Calculator( 24 | d 25 | for d in descriptors.all 26 | if d.__class__ not in [Polarizability.APol, Polarizability.BPol] 27 | ) 28 | 29 | calc.register([Polarizability.APol(True), Polarizability.BPol(True)]) 30 | 31 | actuals = {} 32 | for mol in Chem.SDMolSupplier( 33 | os.path.join(data_dir, "structures.sdf"), removeHs=False 34 | ): 35 | actuals[mol.GetProp("_Name")] = { 36 | str(d): v for d, v in zip(calc.descriptors, calc(mol)) 37 | } 38 | 39 | for path in glob(os.path.join(data_dir, "*.yaml")) + glob( 40 | os.path.join(data_dir, "**/*.yaml") 41 | ): 42 | for test in yaml.load(open(path), Loader=Loader): 43 | dnames = test["names"] 44 | if not isinstance(dnames, list): 45 | dnames = [dnames] 46 | 47 | desireds = ( 48 | (mname, zip(dnames, values if isinstance(values, list) else [values])) 49 | for mname, values in test["results"].items() 50 | ) 51 | 52 | digit = test.get("digit") 53 | if digit is None: 54 | assert_f = eq_ 55 | else: 56 | 57 | def assert_f(a, d, m): 58 | if np.isnan(d): 59 | assert isinstance(a, MissingValueBase) 60 | return 61 | 62 | assert_almost_equal(a, d, digit, m) 63 | 64 | for mname, descs in desireds: 65 | for dname, desired in descs: 66 | if not desired == "skip": 67 | yield ( 68 | assert_f, 69 | actuals[mname][dname], 70 | desired, 71 | "{} of {}".format(dname, mname), 72 | ) 73 | -------------------------------------------------------------------------------- /mordred/tests/test_compose_descriptor.py: -------------------------------------------------------------------------------- 1 | import math 2 | import operator 3 | 4 | import six 5 | from rdkit import Chem 6 | 7 | from nose.tools import eq_ 8 | 9 | from .. import ABCIndex 10 | 11 | binary = [ 12 | operator.add, 13 | operator.sub, 14 | operator.mul, 15 | operator.truediv, 16 | operator.floordiv, 17 | operator.mod, 18 | operator.pow, 19 | ] 20 | 21 | unary = [operator.neg, operator.pos, operator.abs, math.trunc] 22 | 23 | 24 | if six.PY3: 25 | unary.extend([math.ceil, math.floor]) 26 | 27 | 28 | def test_compose_descriptor(): 29 | L = ABCIndex.ABCIndex() 30 | r = ABCIndex.ABCGGIndex() 31 | m = Chem.MolFromSmiles("c1ccccc1C") 32 | 33 | for op in binary: 34 | yield eq_, op(L, r)(m), op(L(m), r(m)) 35 | 36 | for op in unary: 37 | yield eq_, op(L)(m), op(L(m)) 38 | -------------------------------------------------------------------------------- /mordred/tests/test_exceptions.py: -------------------------------------------------------------------------------- 1 | from rdkit import Chem 2 | 3 | from mordred import Calculator, Descriptor 4 | from nose.tools import eq_ 5 | from mordred.error import Error 6 | 7 | 8 | class RaiseDescriptor(Descriptor): 9 | def parameters(self): 10 | return () 11 | 12 | def __init__(self, e, critical): 13 | self.e = e 14 | self.critical = critical 15 | 16 | def calculate(self): 17 | raise self.e 18 | 19 | 20 | mol = Chem.MolFromSmiles("c1ccccc1") 21 | 22 | 23 | def test_catch_non_critical_error(): 24 | calc = Calculator(RaiseDescriptor(ValueError("test exception"), False)) 25 | 26 | result = calc(mol)[0] 27 | assert isinstance(result, Error) 28 | eq_(result.error.args, ("test exception",)) 29 | -------------------------------------------------------------------------------- /mordred/tests/test_import_all_descriptors.py: -------------------------------------------------------------------------------- 1 | from collections import Iterator 2 | 3 | from mordred import ( 4 | Calculator, 5 | descriptors, 6 | get_descriptors_in_module, 7 | get_descriptors_from_module, 8 | ) 9 | from nose.tools import ok_ 10 | 11 | 12 | def test_descriptor_order(): 13 | calc = Calculator(descriptors) 14 | it = iter(calc.descriptors) 15 | before = next(it).__module__ 16 | for current in it: 17 | current = current.__module__ 18 | assert before <= current, "{!r} > {!r}".format(before, current) 19 | 20 | before = current 21 | 22 | 23 | def test_get_descriptors_in_module(): 24 | old = get_descriptors_from_module(descriptors, True) 25 | new = get_descriptors_in_module(descriptors, True) 26 | 27 | yield isinstance, new, Iterator 28 | yield ok_, len(list(new)) > 100 29 | 30 | for a, b in zip(old, new): 31 | assert a == b 32 | -------------------------------------------------------------------------------- /mordred/tests/test_json.py: -------------------------------------------------------------------------------- 1 | import json 2 | 3 | from mordred import Calculator, descriptors 4 | from nose.tools import eq_ 5 | 6 | 7 | def test_json(): 8 | calc = Calculator(descriptors) 9 | j = json.dumps(calc.to_json()) 10 | calc2 = Calculator.from_json(json.loads(j)) 11 | eq_(calc.descriptors, calc2.descriptors) 12 | -------------------------------------------------------------------------------- /mordred/tests/test_pandas.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | 3 | from nose.tools import eq_, ok_ 4 | from mordred.error import Error, Missing 5 | from mordred._base.pandas_module import MordredDataFrame 6 | 7 | df = MordredDataFrame( 8 | [ 9 | [1, 2], 10 | [1, Error(ValueError("error"), ())], 11 | [Missing(ValueError("missing"), ()), 4], 12 | ] 13 | ) 14 | 15 | 16 | def test_copy(): 17 | ok_(isinstance(df.copy(), MordredDataFrame)) 18 | 19 | 20 | def test_fill_missing(): 21 | f = df.fill_missing() 22 | yield eq_, f.ix[0, 0], 1 23 | yield eq_, f.ix[0, 1], 2 24 | yield eq_, f.ix[1, 0], 1 25 | yield ok_, np.isnan(f.ix[1, 1]) 26 | yield ok_, np.isnan(f.ix[2, 0]) 27 | yield eq_, f.ix[2, 1], 4 28 | -------------------------------------------------------------------------------- /mordred/tests/test_parallel.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | from rdkit.Chem import AllChem as Chem 4 | from numpy.testing import assert_almost_equal 5 | 6 | from mordred import Calculator, descriptors 7 | from nose.tools import eq_ 8 | from mordred.error import MissingValueBase 9 | 10 | data_file = os.path.join(os.path.dirname(__file__), "references", "structures.sdf") 11 | 12 | 13 | def test_parallel(): 14 | calc = Calculator(descriptors) 15 | mols = [m for m in Chem.SDMolSupplier(data_file, removeHs=False)] 16 | 17 | for serial, parallel in zip( 18 | calc.map(mols, nproc=1, quiet=True), calc.map(mols, quiet=True) 19 | ): 20 | for d, s, p in zip(calc.descriptors, serial, parallel): 21 | 22 | if isinstance(s, MissingValueBase): 23 | yield eq_, s.error.__class__, p.error.__class__ 24 | else: 25 | msg = "{} (serial: {}, parallel: {})".format(str(d), s, p) 26 | yield assert_almost_equal, s, p, 7, msg 27 | -------------------------------------------------------------------------------- /mordred/tests/test_pickle.py: -------------------------------------------------------------------------------- 1 | import math 2 | import pickle 3 | 4 | import six 5 | from rdkit import Chem 6 | from numpy.testing import assert_almost_equal 7 | 8 | from mordred import Calculator, descriptors 9 | from nose.tools import eq_ 10 | from mordred.error import MissingValueBase 11 | 12 | 13 | def test_pickle_calculator(): 14 | orig = Calculator(descriptors) 15 | d0 = orig.descriptors[0] 16 | d1 = orig.descriptors[1] 17 | orig.register( 18 | [ 19 | d0 + d1, 20 | d0 - d1, 21 | d0 * d1, 22 | d0 // d1, 23 | d0 % d1, 24 | d0 ** d1, 25 | -d0, 26 | +d1, 27 | abs(d0), 28 | math.trunc(d0), 29 | ] 30 | ) 31 | 32 | if six.PY3: 33 | orig.register([math.ceil(d0), math.floor(d1)]) 34 | 35 | pickled = pickle.loads(pickle.dumps(orig)) 36 | 37 | mol = Chem.MolFromSmiles("c1ccccc1C(O)O") 38 | 39 | for a, b in zip(orig.descriptors, pickled.descriptors): 40 | yield eq_, a, b 41 | 42 | for a, b in zip(orig(mol), pickled(mol)): 43 | if isinstance(a, MissingValueBase): 44 | yield eq_, a.__class__, b.__class__ 45 | else: 46 | yield assert_almost_equal, a, b 47 | -------------------------------------------------------------------------------- /mordred/tests/test_result_type.py: -------------------------------------------------------------------------------- 1 | from collections import Iterable 2 | 3 | import numpy as np 4 | 5 | from mordred import Result, Descriptor, error, is_missing 6 | from nose.tools import eq_, ok_, raises 7 | 8 | 9 | class Dummy1(Descriptor): 10 | def __str__(self): 11 | return "Dummy1" 12 | 13 | def parameters(self): 14 | return () 15 | 16 | def calculate(self): 17 | return 1 18 | 19 | 20 | class Dummy2(Descriptor): 21 | def __str__(self): 22 | return "Dummy2" 23 | 24 | def parameters(self): 25 | return () 26 | 27 | def calculate(self): 28 | raise ValueError("error") 29 | 30 | 31 | result = Result(None, [1, error.Error(ValueError("error"), [])], [Dummy1(), Dummy2()]) 32 | 33 | 34 | def test_length(): 35 | eq_(len(result), 2) 36 | 37 | 38 | def test_fill_missing(): 39 | assert np.isnan(result.fill_missing()[1]) 40 | 41 | 42 | def test_drop_missing(): 43 | eq_(len(result.drop_missing()), 1) 44 | 45 | 46 | def test_items(): 47 | i = result.items() 48 | yield ok_, isinstance(i, Iterable) 49 | li = list(i) 50 | yield eq_, len(li), 2 51 | yield eq_, len(li[0]), 2 52 | 53 | d, v = li[0] 54 | yield ok_, isinstance(d, Descriptor) 55 | yield ok_, isinstance(v, int) 56 | 57 | 58 | def test_keys(): 59 | i = result.keys() 60 | yield ok_, isinstance(i, Iterable) 61 | li = list(i) 62 | yield eq_, len(li), 2 63 | 64 | yield ok_, isinstance(li[0], Descriptor) 65 | 66 | 67 | def test_iter(): 68 | i = iter(result) 69 | yield ok_, isinstance(i, Iterable) 70 | li = list(i) 71 | yield eq_, len(li), 2 72 | 73 | yield ok_, isinstance(li[0], int) 74 | 75 | 76 | def test_reversed(): 77 | i = reversed(result) 78 | yield ok_, isinstance(i, Iterable) 79 | li = list(i) 80 | yield eq_, len(li), 2 81 | 82 | yield ok_, isinstance(li[1], int) 83 | 84 | 85 | def test_asdict_non_rawkey(): 86 | d = result.asdict() 87 | yield eq_, len(d), 2 88 | yield ok_, isinstance(d, dict) 89 | for k in d.keys(): 90 | yield ok_, isinstance(k, str) 91 | 92 | 93 | def test_asdict_rawkey(): 94 | d = result.asdict(True) 95 | yield eq_, len(d), 2 96 | yield ok_, isinstance(d, dict) 97 | for k in d.keys(): 98 | yield ok_, isinstance(k, Descriptor) 99 | 100 | 101 | def test_ix(): 102 | yield eq_, 1, result.ix[0] 103 | yield ok_, is_missing(result.ix[1]) 104 | 105 | 106 | def test_name(): 107 | yield eq_, 1, result.name["Dummy1"] 108 | yield ok_, is_missing(result.name["Dummy2"]) 109 | 110 | 111 | def test_getitem(): 112 | yield eq_, 1, result[0] 113 | yield ok_, is_missing(result[1]) 114 | yield eq_, 1, result["Dummy1"] 115 | yield ok_, is_missing(result["Dummy2"]) 116 | 117 | 118 | @raises(TypeError) 119 | def test_getitem_raise(): 120 | result[1.2] 121 | -------------------------------------------------------------------------------- /setup.cfg: -------------------------------------------------------------------------------- 1 | [flake8] 2 | # D100 Missing docstring in public module 3 | # D101 Missing docstring in public class 4 | # D102 Missing docstring in public method 5 | # D103 Missing docstring in public function 6 | # D105 Missing docstring in magic method 7 | # D107 Missing docstring in __init__ 8 | # D203 1 blank line required before class docstring 9 | # 10 | # I101 Imported names are in the wrong order. 11 | # 12 | # N801 class names should use CapWords convention 13 | # N802 function name should be lowercase 14 | # N803 argument name should be lowercase 15 | # N806 variable in function should be lowercase 16 | # N814 camelcase imported as constant 17 | 18 | # H301 one import per line 19 | # H304 No relative imports. 20 | # W503 line break before binary operator 21 | ignore = D100,D101,D102,D103,D105,D107,D203,I101,N801,N802,N803,N806,N814,H301,H304,P101,P102,P103,W503 22 | max-line-length = 99 23 | inline-quotes = " 24 | 25 | [isort] 26 | line_length=100 27 | indent=' ' 28 | multi_line_output=5 29 | length_sort=1 30 | include_trailing_comma=True 31 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | import io 2 | import os 3 | import sys 4 | 5 | from setuptools import setup, find_packages 6 | 7 | install_requires = ["six==1.*", "numpy==1.*", "networkx==2.*"] 8 | 9 | if sys.version_info < (3, 4, 0): 10 | install_requires.append("enum34") 11 | 12 | 13 | def get_version(): 14 | with open(os.path.join("mordred", "_version.txt")) as f: 15 | return f.read().strip() 16 | 17 | 18 | def get_test_data(): 19 | for p, _, fs in os.walk(os.path.join("mordred", "tests", "references")): 20 | p = p.split(os.sep)[2:] 21 | 22 | for f in fs: 23 | yield os.path.join(*(p + [f])) 24 | 25 | 26 | README_rst = "" 27 | fndoc = os.path.join(os.path.dirname(__file__), "README.rst") 28 | with io.open(fndoc, mode="r", encoding="utf-8") as fd: 29 | README_rst = fd.read() 30 | 31 | setup( 32 | name="mordred", 33 | version=get_version(), 34 | description="molecular descriptor calculator", 35 | long_description=README_rst, 36 | license="BSD-3-Clause", 37 | author="Hirotomo Moriwaki", 38 | author_email="philopon.dependence@gmail.com", 39 | url="https://github.com/mordred-descriptor/mordred", 40 | platforms=["any"], 41 | keywords="QSAR chemoinformatics", 42 | packages=find_packages(), 43 | package_data={ 44 | "mordred": ["data/*.txt", "_version.txt"], 45 | "mordred.tests": list(get_test_data()), 46 | }, 47 | install_requires=install_requires, 48 | tests_require=["nose==1.*", "PyYaml>=4.2b1"], 49 | extras_require={"full": ["pandas", "tqdm"]}, 50 | cmdclass={"test": None}, 51 | ) 52 | --------------------------------------------------------------------------------