From d6988e55dc1ed17871f1415f4a9b2abe05c18499 Mon Sep 17 00:00:00 2001 From: Jackson Burns <33505528+JacksonBurns@users.noreply.github.com> Date: Fri, 3 Feb 2023 18:39:06 -0500 Subject: [PATCH 01/35] move up minor numpy versions --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index c3d43c3e..40978216 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,7 +2,7 @@ scipy==1.5.4 matplotlib==3.3.4 seaborn==0.11.1 tabulate==0.8.9 -numpy==1.21.0 +numpy>=1.22 multiprocess==0.70.12.2 scikit_learn_extra==0.2.0 pandas==1.1.5 From 250a5bab325e113de64207c54e9a62f66316a5be Mon Sep 17 00:00:00 2001 From: Jackson Burns Date: Fri, 3 Feb 2023 18:49:17 -0500 Subject: [PATCH 02/35] remove deprecated np.float --- aimsim/utils/plotting_scripts.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aimsim/utils/plotting_scripts.py b/aimsim/utils/plotting_scripts.py index 51437ee8..23fabcef 100644 --- a/aimsim/utils/plotting_scripts.py +++ b/aimsim/utils/plotting_scripts.py @@ -52,7 +52,7 @@ def plot_density(densities, n_densities=1, legends=None, **kwargs): shade = kwargs.pop("shade", False) if n_densities == 1: - valid_number_types = (np.float, np.int64, int, float) + valid_number_types = (float, np.int64, int, float) for density in densities: is_number = isinstance(density, valid_number_types) if not is_number: From 4c6604c4861f497f849cd746c7f8232d0dfd6573 Mon Sep 17 00:00:00 2001 From: Jackson Burns <33505528+JacksonBurns@users.noreply.github.com> Date: Fri, 3 Feb 2023 18:50:57 -0500 Subject: [PATCH 03/35] remove deprecated np.float --- aimsim/utils/plotting_scripts.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aimsim/utils/plotting_scripts.py b/aimsim/utils/plotting_scripts.py index 51437ee8..23fabcef 100644 --- a/aimsim/utils/plotting_scripts.py +++ b/aimsim/utils/plotting_scripts.py @@ -52,7 +52,7 @@ def plot_density(densities, n_densities=1, legends=None, **kwargs): shade = kwargs.pop("shade", False) if n_densities == 1: - valid_number_types = (np.float, np.int64, int, float) + valid_number_types = (float, np.int64, int, float) for density in densities: is_number = isinstance(density, valid_number_types) if not is_number: From 5c53cc99933af7d95044c71775b8c94285605831 Mon Sep 17 00:00:00 2001 From: Jackson Burns <33505528+JacksonBurns@users.noreply.github.com> Date: Fri, 3 Feb 2023 18:58:34 -0500 Subject: [PATCH 04/35] multiple requirements version updates - remove version specification entirely for common utility packages whose API is unlikely to substantially change - remove patch versions where possible - remove minor versions where possible --- requirements.txt | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/requirements.txt b/requirements.txt index 40978216..76c4cb7c 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,15 +1,15 @@ -scipy==1.5.4 -matplotlib==3.3.4 -seaborn==0.11.1 -tabulate==0.8.9 +scipy +matplotlib +seaborn +tabulate numpy>=1.22 -multiprocess==0.70.12.2 +multiprocess>=0.70 scikit_learn_extra==0.2.0 -pandas==1.1.5 +pandas mordred==1.2.0 -PyYAML==5.4.1 -scikit_learn==0.24.2 -networkx==2.5 +PyYAML==5.* +scikit_learn==0.* +networkx<3.0 rdkit psutil padelpy From 36616e91866fb9b23a62b3330587e92a1f0e9137 Mon Sep 17 00:00:00 2001 From: Jackson Burns <33505528+JacksonBurns@users.noreply.github.com> Date: Fri, 3 Feb 2023 19:09:47 -0500 Subject: [PATCH 05/35] set networkx version in the same manner as mordred --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 76c4cb7c..1079c622 100644 --- a/requirements.txt +++ b/requirements.txt @@ -9,7 +9,7 @@ pandas mordred==1.2.0 PyYAML==5.* scikit_learn==0.* -networkx<3.0 +networkx==2.* rdkit psutil padelpy From cc2d0233e596ef57a22395ad1c88a9633601b801 Mon Sep 17 00:00:00 2001 From: Jackson Burns <33505528+JacksonBurns@users.noreply.github.com> Date: Tue, 7 Feb 2023 16:08:54 -0500 Subject: [PATCH 06/35] allow for upgrade to latest sklearn release --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 1079c622..e7b7010f 100644 --- a/requirements.txt +++ b/requirements.txt @@ -8,7 +8,7 @@ scikit_learn_extra==0.2.0 pandas mordred==1.2.0 PyYAML==5.* -scikit_learn==0.* +scikit_learn networkx==2.* rdkit psutil From 49afdde8fe76fca7af7f0152c2f0322e57f61177 Mon Sep 17 00:00:00 2001 From: Jackson Burns Date: Tue, 7 Feb 2023 18:16:28 -0500 Subject: [PATCH 07/35] add a decorator function to handle mordred imports --- aimsim/utils/extras.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 aimsim/utils/extras.py diff --git a/aimsim/utils/extras.py b/aimsim/utils/extras.py new file mode 100644 index 00000000..221da1f2 --- /dev/null +++ b/aimsim/utils/extras.py @@ -0,0 +1,13 @@ +def requries_mordred(function): + try: + from mordred import Calculator, descriptors + + function() + except ImportError: + raise RuntimeError( + """Attempting to call this function ({:s}) requires mordred to be installed. + Please use 'pip install aimsim[mordred]' in an environment with the appropriate version of Python. + """.format( + function.__name__ + ) + ) From 4bcfd84bf63eff5c4e66f92e7732b9f6e766df02 Mon Sep 17 00:00:00 2001 From: Jackson Burns Date: Tue, 7 Feb 2023 18:17:27 -0500 Subject: [PATCH 08/35] remove mordred from required, update readme and setup --- README.md | 4 +++- requirements.txt | 2 -- setup.py | 12 +++++++++--- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 237e8088..5b68b519 100644 --- a/README.md +++ b/README.md @@ -50,6 +50,8 @@ Many of the substrates appear similar to one another and thereby redundant, but `pip install aimsim` This command also installs the required dependencies. It is recommended to install `AIMSim` in a separate virtual environment. +_Optional:_ AIMSim can also use descriptors provided in the `mordred` package, but because it is an older package it is only compatible with Python 3.8. To install with `mordred` support, use `pip install aimsim[mordred]` + ## Running AIMSim `AIMSim` is compatible with Python 3.7 to 3.9. Start `AIMSim` with a graphical user interface: @@ -66,7 +68,7 @@ Start `AIMSim` with a prepared configuration YAML file (`config.yaml`): 2. RDKit Topological Fingerprint 3. RDKit Daylight Fingerprint 4. All fingerprints available from the [ccbmlib](https://github.com/vogt-m/ccbmlib) package (_specify 'ccbmlib:descriptorname' for command line input_). -5. All descriptors available through the [Mordred](https://github.com/mordred-descriptor/mordred) library (_specify 'mordred:desciptorname' for command line input._). +5. All descriptors available through the [Mordred](https://github.com/mordred-descriptor/mordred) library (_specify 'mordred:desciptorname' for command line input._). To enable this option, you must install with `pip install aimsim['mordred']`. 6. All descriptors and fingerprints available from [PaDELPy](https://github.com/ecrl/padelpy), an interface to PaDEL-Descriptor. (_specify 'padelpy:desciptorname' for command line input._). ### Currently Implemented Similarity Scores diff --git a/requirements.txt b/requirements.txt index e7b7010f..479c5097 100644 --- a/requirements.txt +++ b/requirements.txt @@ -6,10 +6,8 @@ numpy>=1.22 multiprocess>=0.70 scikit_learn_extra==0.2.0 pandas -mordred==1.2.0 PyYAML==5.* scikit_learn -networkx==2.* rdkit psutil padelpy diff --git a/setup.py b/setup.py index 8df4a5b8..55fa53e3 100644 --- a/setup.py +++ b/setup.py @@ -12,13 +12,13 @@ def read(rel_path): here = os.path.abspath(os.path.dirname(__file__)) - with codecs.open(os.path.join(here, rel_path), 'r') as fp: + with codecs.open(os.path.join(here, rel_path), "r") as fp: return fp.read() def get_version(rel_path): for line in read(rel_path).splitlines(): - if line.startswith('__version__'): + if line.startswith("__version__"): delim = '"' if '"' in line else "'" return line.split(delim)[1] else: @@ -27,7 +27,7 @@ def get_version(rel_path): setup( name="aimsim", - python_requires='>=3.7,<3.10', + python_requires=">=3.7,<3.10", version=get_version("aimsim/__init__.py"), description=desc, long_description=README, @@ -37,6 +37,12 @@ def get_version(rel_path): license="MIT", classifiers=["Programming Language :: Python :: 3"], install_requires=read("requirements.txt").split("\n"), + extras_require={ + "mordred": [ + "mordred==1.2.0", + "networkx==2.*", + ], + }, packages=find_packages(), include_package_data=True, entry_points={ From 8a173e646625dadc112e27f8e9f5146f9b82cfb5 Mon Sep 17 00:00:00 2001 From: Jackson Burns Date: Tue, 7 Feb 2023 18:17:41 -0500 Subject: [PATCH 09/35] wrap mordred calls with decorator --- aimsim/ops/descriptor.py | 5615 +++++++++++++------------------------- tests/test_Descriptor.py | 135 +- 2 files changed, 1962 insertions(+), 3788 deletions(-) diff --git a/aimsim/ops/descriptor.py b/aimsim/ops/descriptor.py index ba3b8015..c11f6f02 100644 --- a/aimsim/ops/descriptor.py +++ b/aimsim/ops/descriptor.py @@ -8,9 +8,10 @@ from rdkit.Chem import MACCSkeys from rdkit.Chem.AtomPairs import Pairs, Torsions from rdkit.DataStructs import cDataStructs -from mordred import Calculator, descriptors from aimsim.utils.ccbmlib_fingerprints import generate_fingerprints from padelpy import from_smiles +from aimsim.utils.extras import requries_mordred + from ..exceptions import ( InvalidConfigurationError, @@ -93,8 +94,10 @@ def check_init(self): (bool): True if object is initialized. """ - return getattr(self, "numpy_", None) is not None \ + return ( + getattr(self, "numpy_", None) is not None or getattr(self, "rdkit_", None) is not None + ) def _set_morgan_fingerprint(self, molecule_graph, radius, n_bits, **kwargs): """Set the descriptor to a morgan fingerprint. @@ -149,19 +152,20 @@ def _set_padelpy_descriptor(self, molecule_graph, descriptor, **kwargs): Args: molecule_graph (RDKit object): Graph of the molecule of interest. - descriptor (string): Name of descriptor, as implemented in Mordred. + descriptor (string): Name of descriptor, as implemented in PaDEL. """ try: local_smi = Chem.MolToSmiles(molecule_graph) - all_desc = from_smiles( - local_smi, timeout=kwargs.get("timeout", 60)) + all_desc = from_smiles(local_smi, timeout=kwargs.get("timeout", 60)) self.numpy_ = np.array(all_desc[descriptor]) self.label_ = descriptor except Exception as e: raise RuntimeError( - f"Unable to retrieve PaDELPy Descriptor '{descriptor}'. Is it a valid descriptor?") + f"Unable to retrieve PaDELPy Descriptor '{descriptor}'. Is it a valid descriptor?" + ) + @requries_mordred def _set_mordred_descriptor(self, molecule_graph, descriptor, **kwargs): """Set the value of numpy_ to the descriptor as indicated by descriptor. @@ -275,8 +279,7 @@ def make_fingerprint( if fingerprint_type == "morgan_fingerprint": morgan_params = {"radius": 3, "n_bits": 1024} morgan_params.update(fingerprint_params) - self._set_morgan_fingerprint(molecule_graph=molecule_graph, - **morgan_params) + self._set_morgan_fingerprint(molecule_graph=molecule_graph, **morgan_params) elif fingerprint_type == "topological_fingerprint": topological_params = {"min_path": 1, "max_path": 7} topological_params.update(fingerprint_params) @@ -285,13 +288,13 @@ def make_fingerprint( ) elif fingerprint_type == "daylight_fingerprint": daylight_params = { - 'minPath': 1, - 'maxPath': 7, - 'fpSize': 2048, - 'bitsPerHash': 2, - 'useHs': 0, - 'tgtDensity': 0.3, - 'minSize': 64, + "minPath": 1, + "maxPath": 7, + "fpSize": 2048, + "bitsPerHash": 2, + "useHs": 0, + "tgtDensity": 0.3, + "minSize": 64, } daylight_params.update(fingerprint_params) self._set_daylight_fingerprint( @@ -415,8 +418,7 @@ def shorten_label(label): """ if label not in Descriptor.get_all_supported_descriptors(): - raise InvalidConfigurationError( - f"{label} not a " f"supported descriptor") + raise InvalidConfigurationError(f"{label} not a " f"supported descriptor") if label in Descriptor.get_supported_fprints(): return label.replace("_fingerprint", "") return label @@ -439,8 +441,7 @@ def fold_to_equal_length(fingerprint1, fingerprint2): fprint2_arr = fingerprint2.to_numpy() if len(fprint1_arr) > len(fprint2_arr): return ( - fingerprint1.get_folded_fprint( - fold_to_length=len(fprint2_arr)), + fingerprint1.get_folded_fprint(fold_to_length=len(fprint2_arr)), fprint2_arr, ) else: @@ -486,3705 +487,1879 @@ def get_all_supported_descriptors(): "ccbmlib:rdkit_fingerprint", "ccbmlib:torsions", "ccbmlib:hashed_torsions", - "mordred:ABC", - "mordred:ABCGG", - "mordred:nAcid", - "mordred:nBase", - "mordred:SpAbs_A", - "mordred:SpMax_A", - "mordred:SpDiam_A", - "mordred:SpAD_A", - "mordred:SpMAD_A", - "mordred:LogEE_A", - "mordred:VE1_A", - "mordred:VE2_A", - "mordred:VE3_A", - "mordred:VR1_A", - "mordred:VR2_A", - "mordred:VR3_A", - "mordred:nAromAtom", - "mordred:nAromBond", - "mordred:nAtom", - "mordred:nHeavyAtom", - "mordred:nSpiro", - "mordred:nBridgehead", - "mordred:nHetero", - "mordred:nH", - "mordred:nB", - "mordred:nC", - "mordred:nN", - "mordred:nO", - "mordred:nS", - "mordred:nP", - "mordred:nF", - "mordred:nCl", - "mordred:nBr", - "mordred:nI", - "mordred:nX", - "mordred:ATS0dv", - "mordred:ATS1dv", - "mordred:ATS2dv", - "mordred:ATS3dv", - "mordred:ATS4dv", - "mordred:ATS5dv", - "mordred:ATS6dv", - "mordred:ATS7dv", - "mordred:ATS8dv", - "mordred:ATS0d", - "mordred:ATS1d", - "mordred:ATS2d", - "mordred:ATS3d", - "mordred:ATS4d", - "mordred:ATS5d", - "mordred:ATS6d", - "mordred:ATS7d", - "mordred:ATS8d", - "mordred:ATS0s", - "mordred:ATS1s", - "mordred:ATS2s", - "mordred:ATS3s", - "mordred:ATS4s", - "mordred:ATS5s", - "mordred:ATS6s", - "mordred:ATS7s", - "mordred:ATS8s", - "mordred:ATS0Z", - "mordred:ATS1Z", - "mordred:ATS2Z", - "mordred:ATS3Z", - "mordred:ATS4Z", - "mordred:ATS5Z", - "mordred:ATS6Z", - "mordred:ATS7Z", - "mordred:ATS8Z", - "mordred:ATS0m", - "mordred:ATS1m", - "mordred:ATS2m", - "mordred:ATS3m", - "mordred:ATS4m", - "mordred:ATS5m", - "mordred:ATS6m", - "mordred:ATS7m", - "mordred:ATS8m", - "mordred:ATS0v", - "mordred:ATS1v", - "mordred:ATS2v", - "mordred:ATS3v", - "mordred:ATS4v", - "mordred:ATS5v", - "mordred:ATS6v", - "mordred:ATS7v", - "mordred:ATS8v", - "mordred:ATS0se", - "mordred:ATS1se", - "mordred:ATS2se", - "mordred:ATS3se", - "mordred:ATS4se", - "mordred:ATS5se", - "mordred:ATS6se", - "mordred:ATS7se", - "mordred:ATS8se", - "mordred:ATS0pe", - "mordred:ATS1pe", - "mordred:ATS2pe", - "mordred:ATS3pe", - "mordred:ATS4pe", - "mordred:ATS5pe", - "mordred:ATS6pe", - "mordred:ATS7pe", - "mordred:ATS8pe", - "mordred:ATS0are", - "mordred:ATS1are", - "mordred:ATS2are", - "mordred:ATS3are", - "mordred:ATS4are", - "mordred:ATS5are", - "mordred:ATS6are", - "mordred:ATS7are", - "mordred:ATS8are", - "mordred:ATS0p", - "mordred:ATS1p", - "mordred:ATS2p", - "mordred:ATS3p", - "mordred:ATS4p", - "mordred:ATS5p", - "mordred:ATS6p", - "mordred:ATS7p", - "mordred:ATS8p", - "mordred:ATS0i", - "mordred:ATS1i", - "mordred:ATS2i", - "mordred:ATS3i", - "mordred:ATS4i", - "mordred:ATS5i", - "mordred:ATS6i", - "mordred:ATS7i", - "mordred:ATS8i", - "mordred:AATS0dv", - "mordred:AATS1dv", - "mordred:AATS2dv", - "mordred:AATS3dv", - "mordred:AATS4dv", - "mordred:AATS5dv", - "mordred:AATS6dv", - "mordred:AATS7dv", - "mordred:AATS8dv", - "mordred:AATS0d", - "mordred:AATS1d", - "mordred:AATS2d", - "mordred:AATS3d", - "mordred:AATS4d", - "mordred:AATS5d", - "mordred:AATS6d", - "mordred:AATS7d", - "mordred:AATS8d", - "mordred:AATS0s", - "mordred:AATS1s", - "mordred:AATS2s", - "mordred:AATS3s", - "mordred:AATS4s", - "mordred:AATS5s", - "mordred:AATS6s", - "mordred:AATS7s", - "mordred:AATS8s", - "mordred:AATS0Z", - "mordred:AATS1Z", - "mordred:AATS2Z", - "mordred:AATS3Z", - "mordred:AATS4Z", - "mordred:AATS5Z", - "mordred:AATS6Z", - "mordred:AATS7Z", - "mordred:AATS8Z", - "mordred:AATS0m", - "mordred:AATS1m", - "mordred:AATS2m", - "mordred:AATS3m", - "mordred:AATS4m", - "mordred:AATS5m", - "mordred:AATS6m", - "mordred:AATS7m", - "mordred:AATS8m", - "mordred:AATS0v", - "mordred:AATS1v", - "mordred:AATS2v", - "mordred:AATS3v", - "mordred:AATS4v", - "mordred:AATS5v", - "mordred:AATS6v", - "mordred:AATS7v", - "mordred:AATS8v", - "mordred:AATS0se", - "mordred:AATS1se", - "mordred:AATS2se", - "mordred:AATS3se", - "mordred:AATS4se", - "mordred:AATS5se", - "mordred:AATS6se", - "mordred:AATS7se", - "mordred:AATS8se", - "mordred:AATS0pe", - "mordred:AATS1pe", - "mordred:AATS2pe", - "mordred:AATS3pe", - "mordred:AATS4pe", - "mordred:AATS5pe", - "mordred:AATS6pe", - "mordred:AATS7pe", - "mordred:AATS8pe", - "mordred:AATS0are", - "mordred:AATS1are", - "mordred:AATS2are", - "mordred:AATS3are", - "mordred:AATS4are", - "mordred:AATS5are", - "mordred:AATS6are", - "mordred:AATS7are", - "mordred:AATS8are", - "mordred:AATS0p", - "mordred:AATS1p", - "mordred:AATS2p", - "mordred:AATS3p", - "mordred:AATS4p", - "mordred:AATS5p", - "mordred:AATS6p", - "mordred:AATS7p", - "mordred:AATS8p", - "mordred:AATS0i", - "mordred:AATS1i", - "mordred:AATS2i", - "mordred:AATS3i", - "mordred:AATS4i", - "mordred:AATS5i", - "mordred:AATS6i", - "mordred:AATS7i", - "mordred:AATS8i", - "mordred:ATSC0c", - "mordred:ATSC1c", - "mordred:ATSC2c", - "mordred:ATSC3c", - "mordred:ATSC4c", - "mordred:ATSC5c", - "mordred:ATSC6c", - "mordred:ATSC7c", - "mordred:ATSC8c", - "mordred:ATSC0dv", - "mordred:ATSC1dv", - "mordred:ATSC2dv", - "mordred:ATSC3dv", - "mordred:ATSC4dv", - "mordred:ATSC5dv", - "mordred:ATSC6dv", - "mordred:ATSC7dv", - "mordred:ATSC8dv", - "mordred:ATSC0d", - "mordred:ATSC1d", - "mordred:ATSC2d", - "mordred:ATSC3d", - "mordred:ATSC4d", - "mordred:ATSC5d", - "mordred:ATSC6d", - "mordred:ATSC7d", - "mordred:ATSC8d", - "mordred:ATSC0s", - "mordred:ATSC1s", - "mordred:ATSC2s", - "mordred:ATSC3s", - "mordred:ATSC4s", - "mordred:ATSC5s", - "mordred:ATSC6s", - "mordred:ATSC7s", - "mordred:ATSC8s", - "mordred:ATSC0Z", - "mordred:ATSC1Z", - "mordred:ATSC2Z", - "mordred:ATSC3Z", - "mordred:ATSC4Z", - "mordred:ATSC5Z", - "mordred:ATSC6Z", - "mordred:ATSC7Z", - "mordred:ATSC8Z", - "mordred:ATSC0m", - "mordred:ATSC1m", - "mordred:ATSC2m", - "mordred:ATSC3m", - "mordred:ATSC4m", - "mordred:ATSC5m", - "mordred:ATSC6m", - "mordred:ATSC7m", - "mordred:ATSC8m", - "mordred:ATSC0v", - "mordred:ATSC1v", - "mordred:ATSC2v", - "mordred:ATSC3v", - "mordred:ATSC4v", - "mordred:ATSC5v", - "mordred:ATSC6v", - "mordred:ATSC7v", - "mordred:ATSC8v", - "mordred:ATSC0se", - "mordred:ATSC1se", - "mordred:ATSC2se", - "mordred:ATSC3se", - "mordred:ATSC4se", - "mordred:ATSC5se", - "mordred:ATSC6se", - "mordred:ATSC7se", - "mordred:ATSC8se", - "mordred:ATSC0pe", - "mordred:ATSC1pe", - "mordred:ATSC2pe", - "mordred:ATSC3pe", - "mordred:ATSC4pe", - "mordred:ATSC5pe", - "mordred:ATSC6pe", - "mordred:ATSC7pe", - "mordred:ATSC8pe", - "mordred:ATSC0are", - "mordred:ATSC1are", - "mordred:ATSC2are", - "mordred:ATSC3are", - "mordred:ATSC4are", - "mordred:ATSC5are", - "mordred:ATSC6are", - "mordred:ATSC7are", - "mordred:ATSC8are", - "mordred:ATSC0p", - "mordred:ATSC1p", - "mordred:ATSC2p", - "mordred:ATSC3p", - "mordred:ATSC4p", - "mordred:ATSC5p", - "mordred:ATSC6p", - "mordred:ATSC7p", - "mordred:ATSC8p", - "mordred:ATSC0i", - "mordred:ATSC1i", - "mordred:ATSC2i", - "mordred:ATSC3i", - "mordred:ATSC4i", - "mordred:ATSC5i", - "mordred:ATSC6i", - "mordred:ATSC7i", - "mordred:ATSC8i", - "mordred:AATSC0c", - "mordred:AATSC1c", - "mordred:AATSC2c", - "mordred:AATSC3c", - "mordred:AATSC4c", - "mordred:AATSC5c", - "mordred:AATSC6c", - "mordred:AATSC7c", - "mordred:AATSC8c", - "mordred:AATSC0dv", - "mordred:AATSC1dv", - "mordred:AATSC2dv", - "mordred:AATSC3dv", - "mordred:AATSC4dv", - "mordred:AATSC5dv", - "mordred:AATSC6dv", - "mordred:AATSC7dv", - "mordred:AATSC8dv", - "mordred:AATSC0d", - "mordred:AATSC1d", - "mordred:AATSC2d", - "mordred:AATSC3d", - "mordred:AATSC4d", - "mordred:AATSC5d", - "mordred:AATSC6d", - "mordred:AATSC7d", - "mordred:AATSC8d", - "mordred:AATSC0s", - "mordred:AATSC1s", - "mordred:AATSC2s", - "mordred:AATSC3s", - "mordred:AATSC4s", - "mordred:AATSC5s", - "mordred:AATSC6s", - "mordred:AATSC7s", - "mordred:AATSC8s", - "mordred:AATSC0Z", - "mordred:AATSC1Z", - "mordred:AATSC2Z", - "mordred:AATSC3Z", - "mordred:AATSC4Z", - "mordred:AATSC5Z", - "mordred:AATSC6Z", - "mordred:AATSC7Z", - "mordred:AATSC8Z", - "mordred:AATSC0m", - "mordred:AATSC1m", - "mordred:AATSC2m", - "mordred:AATSC3m", - "mordred:AATSC4m", - "mordred:AATSC5m", - "mordred:AATSC6m", - "mordred:AATSC7m", - "mordred:AATSC8m", - "mordred:AATSC0v", - "mordred:AATSC1v", - "mordred:AATSC2v", - "mordred:AATSC3v", - "mordred:AATSC4v", - "mordred:AATSC5v", - "mordred:AATSC6v", - "mordred:AATSC7v", - "mordred:AATSC8v", - "mordred:AATSC0se", - "mordred:AATSC1se", - "mordred:AATSC2se", - "mordred:AATSC3se", - "mordred:AATSC4se", - "mordred:AATSC5se", - "mordred:AATSC6se", - "mordred:AATSC7se", - "mordred:AATSC8se", - "mordred:AATSC0pe", - "mordred:AATSC1pe", - "mordred:AATSC2pe", - "mordred:AATSC3pe", - "mordred:AATSC4pe", - "mordred:AATSC5pe", - "mordred:AATSC6pe", - "mordred:AATSC7pe", - "mordred:AATSC8pe", - "mordred:AATSC0are", - "mordred:AATSC1are", - "mordred:AATSC2are", - "mordred:AATSC3are", - "mordred:AATSC4are", - "mordred:AATSC5are", - "mordred:AATSC6are", - "mordred:AATSC7are", - "mordred:AATSC8are", - "mordred:AATSC0p", - "mordred:AATSC1p", - "mordred:AATSC2p", - "mordred:AATSC3p", - "mordred:AATSC4p", - "mordred:AATSC5p", - "mordred:AATSC6p", - "mordred:AATSC7p", - "mordred:AATSC8p", - "mordred:AATSC0i", - "mordred:AATSC1i", - "mordred:AATSC2i", - "mordred:AATSC3i", - "mordred:AATSC4i", - "mordred:AATSC5i", - "mordred:AATSC6i", - "mordred:AATSC7i", - "mordred:AATSC8i", - "mordred:MATS1c", - "mordred:MATS2c", - "mordred:MATS3c", - "mordred:MATS4c", - "mordred:MATS5c", - "mordred:MATS6c", - "mordred:MATS7c", - "mordred:MATS8c", - "mordred:MATS1dv", - "mordred:MATS2dv", - "mordred:MATS3dv", - "mordred:MATS4dv", - "mordred:MATS5dv", - "mordred:MATS6dv", - "mordred:MATS7dv", - "mordred:MATS8dv", - "mordred:MATS1d", - "mordred:MATS2d", - "mordred:MATS3d", - "mordred:MATS4d", - "mordred:MATS5d", - "mordred:MATS6d", - "mordred:MATS7d", - "mordred:MATS8d", - "mordred:MATS1s", - "mordred:MATS2s", - "mordred:MATS3s", - "mordred:MATS4s", - "mordred:MATS5s", - "mordred:MATS6s", - "mordred:MATS7s", - "mordred:MATS8s", - "mordred:MATS1Z", - "mordred:MATS2Z", - "mordred:MATS3Z", - "mordred:MATS4Z", - "mordred:MATS5Z", - "mordred:MATS6Z", - "mordred:MATS7Z", - "mordred:MATS8Z", - "mordred:MATS1m", - "mordred:MATS2m", - "mordred:MATS3m", - "mordred:MATS4m", - "mordred:MATS5m", - "mordred:MATS6m", - "mordred:MATS7m", - "mordred:MATS8m", - "mordred:MATS1v", - "mordred:MATS2v", - "mordred:MATS3v", - "mordred:MATS4v", - "mordred:MATS5v", - "mordred:MATS6v", - "mordred:MATS7v", - "mordred:MATS8v", - "mordred:MATS1se", - "mordred:MATS2se", - "mordred:MATS3se", - "mordred:MATS4se", - "mordred:MATS5se", - "mordred:MATS6se", - "mordred:MATS7se", - "mordred:MATS8se", - "mordred:MATS1pe", - "mordred:MATS2pe", - "mordred:MATS3pe", - "mordred:MATS4pe", - "mordred:MATS5pe", - "mordred:MATS6pe", - "mordred:MATS7pe", - "mordred:MATS8pe", - "mordred:MATS1are", - "mordred:MATS2are", - "mordred:MATS3are", - "mordred:MATS4are", - "mordred:MATS5are", - "mordred:MATS6are", - "mordred:MATS7are", - "mordred:MATS8are", - "mordred:MATS1p", - "mordred:MATS2p", - "mordred:MATS3p", - "mordred:MATS4p", - "mordred:MATS5p", - "mordred:MATS6p", - "mordred:MATS7p", - "mordred:MATS8p", - "mordred:MATS1i", - "mordred:MATS2i", - "mordred:MATS3i", - "mordred:MATS4i", - "mordred:MATS5i", - "mordred:MATS6i", - "mordred:MATS7i", - "mordred:MATS8i", - "mordred:GATS1c", - "mordred:GATS2c", - "mordred:GATS3c", - "mordred:GATS4c", - "mordred:GATS5c", - "mordred:GATS6c", - "mordred:GATS7c", - "mordred:GATS8c", - "mordred:GATS1dv", - "mordred:GATS2dv", - "mordred:GATS3dv", - "mordred:GATS4dv", - "mordred:GATS5dv", - "mordred:GATS6dv", - "mordred:GATS7dv", - "mordred:GATS8dv", - "mordred:GATS1d", - "mordred:GATS2d", - "mordred:GATS3d", - "mordred:GATS4d", - "mordred:GATS5d", - "mordred:GATS6d", - "mordred:GATS7d", - "mordred:GATS8d", - "mordred:GATS1s", - "mordred:GATS2s", - "mordred:GATS3s", - "mordred:GATS4s", - "mordred:GATS5s", - "mordred:GATS6s", - "mordred:GATS7s", - "mordred:GATS8s", - "mordred:GATS1Z", - "mordred:GATS2Z", - "mordred:GATS3Z", - "mordred:GATS4Z", - "mordred:GATS5Z", - "mordred:GATS6Z", - "mordred:GATS7Z", - "mordred:GATS8Z", - "mordred:GATS1m", - "mordred:GATS2m", - "mordred:GATS3m", - "mordred:GATS4m", - "mordred:GATS5m", - "mordred:GATS6m", - "mordred:GATS7m", - "mordred:GATS8m", - "mordred:GATS1v", - "mordred:GATS2v", - "mordred:GATS3v", - "mordred:GATS4v", - "mordred:GATS5v", - "mordred:GATS6v", - "mordred:GATS7v", - "mordred:GATS8v", - "mordred:GATS1se", - "mordred:GATS2se", - "mordred:GATS3se", - "mordred:GATS4se", - "mordred:GATS5se", - "mordred:GATS6se", - "mordred:GATS7se", - "mordred:GATS8se", - "mordred:GATS1pe", - "mordred:GATS2pe", - "mordred:GATS3pe", - "mordred:GATS4pe", - "mordred:GATS5pe", - "mordred:GATS6pe", - "mordred:GATS7pe", - "mordred:GATS8pe", - "mordred:GATS1are", - "mordred:GATS2are", - "mordred:GATS3are", - "mordred:GATS4are", - "mordred:GATS5are", - "mordred:GATS6are", - "mordred:GATS7are", - "mordred:GATS8are", - "mordred:GATS1p", - "mordred:GATS2p", - "mordred:GATS3p", - "mordred:GATS4p", - "mordred:GATS5p", - "mordred:GATS6p", - "mordred:GATS7p", - "mordred:GATS8p", - "mordred:GATS1i", - "mordred:GATS2i", - "mordred:GATS3i", - "mordred:GATS4i", - "mordred:GATS5i", - "mordred:GATS6i", - "mordred:GATS7i", - "mordred:GATS8i", - "mordred:BCUTc-1h", - "mordred:BCUTc-1l", - "mordred:BCUTdv-1h", - "mordred:BCUTdv-1l", - "mordred:BCUTd-1h", - "mordred:BCUTd-1l", - "mordred:BCUTs-1h", - "mordred:BCUTs-1l", - "mordred:BCUTZ-1h", - "mordred:BCUTZ-1l", - "mordred:BCUTm-1h", - "mordred:BCUTm-1l", - "mordred:BCUTv-1h", - "mordred:BCUTv-1l", - "mordred:BCUTse-1h", - "mordred:BCUTse-1l", - "mordred:BCUTpe-1h", - "mordred:BCUTpe-1l", - "mordred:BCUTare-1h", - "mordred:BCUTare-1l", - "mordred:BCUTp-1h", - "mordred:BCUTp-1l", - "mordred:BCUTi-1h", - "mordred:BCUTi-1l", - "mordred:BalabanJ", - "mordred:SpAbs_DzZ", - "mordred:SpMax_DzZ", - "mordred:SpDiam_DzZ", - "mordred:SpAD_DzZ", - "mordred:SpMAD_DzZ", - "mordred:LogEE_DzZ", - "mordred:SM1_DzZ", - "mordred:VE1_DzZ", - "mordred:VE2_DzZ", - "mordred:VE3_DzZ", - "mordred:VR1_DzZ", - "mordred:VR2_DzZ", - "mordred:VR3_DzZ", - "mordred:SpAbs_Dzm", - "mordred:SpMax_Dzm", - "mordred:SpDiam_Dzm", - "mordred:SpAD_Dzm", - "mordred:SpMAD_Dzm", - "mordred:LogEE_Dzm", - "mordred:SM1_Dzm", - "mordred:VE1_Dzm", - "mordred:VE2_Dzm", - "mordred:VE3_Dzm", - "mordred:VR1_Dzm", - "mordred:VR2_Dzm", - "mordred:VR3_Dzm", - "mordred:SpAbs_Dzv", - "mordred:SpMax_Dzv", - "mordred:SpDiam_Dzv", - "mordred:SpAD_Dzv", - "mordred:SpMAD_Dzv", - "mordred:LogEE_Dzv", - "mordred:SM1_Dzv", - "mordred:VE1_Dzv", - "mordred:VE2_Dzv", - "mordred:VE3_Dzv", - "mordred:VR1_Dzv", - "mordred:VR2_Dzv", - "mordred:VR3_Dzv", - "mordred:SpAbs_Dzse", - "mordred:SpMax_Dzse", - "mordred:SpDiam_Dzse", - "mordred:SpAD_Dzse", - "mordred:SpMAD_Dzse", - "mordred:LogEE_Dzse", - "mordred:SM1_Dzse", - "mordred:VE1_Dzse", - "mordred:VE2_Dzse", - "mordred:VE3_Dzse", - "mordred:VR1_Dzse", - "mordred:VR2_Dzse", - "mordred:VR3_Dzse", - "mordred:SpAbs_Dzpe", - "mordred:SpMax_Dzpe", - "mordred:SpDiam_Dzpe", - "mordred:SpAD_Dzpe", - "mordred:SpMAD_Dzpe", - "mordred:LogEE_Dzpe", - "mordred:SM1_Dzpe", - "mordred:VE1_Dzpe", - "mordred:VE2_Dzpe", - "mordred:VE3_Dzpe", - "mordred:VR1_Dzpe", - "mordred:VR2_Dzpe", - "mordred:VR3_Dzpe", - "mordred:SpAbs_Dzare", - "mordred:SpMax_Dzare", - "mordred:SpDiam_Dzare", - "mordred:SpAD_Dzare", - "mordred:SpMAD_Dzare", - "mordred:LogEE_Dzare", - "mordred:SM1_Dzare", - "mordred:VE1_Dzare", - "mordred:VE2_Dzare", - "mordred:VE3_Dzare", - "mordred:VR1_Dzare", - "mordred:VR2_Dzare", - "mordred:VR3_Dzare", - "mordred:SpAbs_Dzp", - "mordred:SpMax_Dzp", - "mordred:SpDiam_Dzp", - "mordred:SpAD_Dzp", - "mordred:SpMAD_Dzp", - "mordred:LogEE_Dzp", - "mordred:SM1_Dzp", - "mordred:VE1_Dzp", - "mordred:VE2_Dzp", - "mordred:VE3_Dzp", - "mordred:VR1_Dzp", - "mordred:VR2_Dzp", - "mordred:VR3_Dzp", - "mordred:SpAbs_Dzi", - "mordred:SpMax_Dzi", - "mordred:SpDiam_Dzi", - "mordred:SpAD_Dzi", - "mordred:SpMAD_Dzi", - "mordred:LogEE_Dzi", - "mordred:SM1_Dzi", - "mordred:VE1_Dzi", - "mordred:VE2_Dzi", - "mordred:VE3_Dzi", - "mordred:VR1_Dzi", - "mordred:VR2_Dzi", - "mordred:VR3_Dzi", - "mordred:BertzCT", - "mordred:nBonds", - "mordred:nBondsO", - "mordred:nBondsS", - "mordred:nBondsD", - "mordred:nBondsT", - "mordred:nBondsA", - "mordred:nBondsM", - "mordred:nBondsKS", - "mordred:nBondsKD", - "mordred:PNSA1", - "mordred:PNSA2", - "mordred:PNSA3", - "mordred:PNSA4", - "mordred:PNSA5", - "mordred:PPSA1", - "mordred:PPSA2", - "mordred:PPSA3", - "mordred:PPSA4", - "mordred:PPSA5", - "mordred:DPSA1", - "mordred:DPSA2", - "mordred:DPSA3", - "mordred:DPSA4", - "mordred:DPSA5", - "mordred:FNSA1", - "mordred:FNSA2", - "mordred:FNSA3", - "mordred:FNSA4", - "mordred:FNSA5", - "mordred:FPSA1", - "mordred:FPSA2", - "mordred:FPSA3", - "mordred:FPSA4", - "mordred:FPSA5", - "mordred:WNSA1", - "mordred:WNSA2", - "mordred:WNSA3", - "mordred:WNSA4", - "mordred:WNSA5", - "mordred:WPSA1", - "mordred:WPSA2", - "mordred:WPSA3", - "mordred:WPSA4", - "mordred:WPSA5", - "mordred:RNCG", - "mordred:RPCG", - "mordred:RNCS", - "mordred:RPCS", - "mordred:TASA", - "mordred:TPSA", - "mordred:RASA", - "mordred:RPSA", - "mordred:C1SP1", - "mordred:C2SP1", - "mordred:C1SP2", - "mordred:C2SP2", - "mordred:C3SP2", - "mordred:C1SP3", - "mordred:C2SP3", - "mordred:C3SP3", - "mordred:C4SP3", - "mordred:HybRatio", - "mordred:FCSP3", - "mordred:Xch-3d", - "mordred:Xch-4d", - "mordred:Xch-5d", - "mordred:Xch-6d", - "mordred:Xch-7d", - "mordred:Xch-3dv", - "mordred:Xch-4dv", - "mordred:Xch-5dv", - "mordred:Xch-6dv", - "mordred:Xch-7dv", - "mordred:Xc-3d", - "mordred:Xc-4d", - "mordred:Xc-5d", - "mordred:Xc-6d", - "mordred:Xc-3dv", - "mordred:Xc-4dv", - "mordred:Xc-5dv", - "mordred:Xc-6dv", - "mordred:Xpc-4d", - "mordred:Xpc-5d", - "mordred:Xpc-6d", - "mordred:Xpc-4dv", - "mordred:Xpc-5dv", - "mordred:Xpc-6dv", - "mordred:Xp-0d", - "mordred:Xp-1d", - "mordred:Xp-2d", - "mordred:Xp-3d", - "mordred:Xp-4d", - "mordred:Xp-5d", - "mordred:Xp-6d", - "mordred:Xp-7d", - "mordred:AXp-0d", - "mordred:AXp-1d", - "mordred:AXp-2d", - "mordred:AXp-3d", - "mordred:AXp-4d", - "mordred:AXp-5d", - "mordred:AXp-6d", - "mordred:AXp-7d", - "mordred:Xp-0dv", - "mordred:Xp-1dv", - "mordred:Xp-2dv", - "mordred:Xp-3dv", - "mordred:Xp-4dv", - "mordred:Xp-5dv", - "mordred:Xp-6dv", - "mordred:Xp-7dv", - "mordred:AXp-0dv", - "mordred:AXp-1dv", - "mordred:AXp-2dv", - "mordred:AXp-3dv", - "mordred:AXp-4dv", - "mordred:AXp-5dv", - "mordred:AXp-6dv", - "mordred:AXp-7dv", - "mordred:SZ", - "mordred:Sm", - "mordred:Sv", - "mordred:Sse", - "mordred:Spe", - "mordred:Sare", - "mordred:Sp", - "mordred:Si", - "mordred:MZ", - "mordred:Mm", - "mordred:Mv", - "mordred:Mse", - "mordred:Mpe", - "mordred:Mare", - "mordred:Mp", - "mordred:Mi", - "mordred:SpAbs_Dt", - "mordred:SpMax_Dt", - "mordred:SpDiam_Dt", - "mordred:SpAD_Dt", - "mordred:SpMAD_Dt", - "mordred:LogEE_Dt", - "mordred:SM1_Dt", - "mordred:VE1_Dt", - "mordred:VE2_Dt", - "mordred:VE3_Dt", - "mordred:VR1_Dt", - "mordred:VR2_Dt", - "mordred:VR3_Dt", - "mordred:DetourIndex", - "mordred:SpAbs_D", - "mordred:SpMax_D", - "mordred:SpDiam_D", - "mordred:SpAD_D", - "mordred:SpMAD_D", - "mordred:LogEE_D", - "mordred:VE1_D", - "mordred:VE2_D", - "mordred:VE3_D", - "mordred:VR1_D", - "mordred:VR2_D", - "mordred:VR3_D", - "mordred:NsLi", - "mordred:NssBe", - "mordred:NssssBe", - "mordred:NssBH", - "mordred:NsssB", - "mordred:NssssB", - "mordred:NsCH3", - "mordred:NdCH2", - "mordred:NssCH2", - "mordred:NtCH", - "mordred:NdsCH", - "mordred:NaaCH", - "mordred:NsssCH", - "mordred:NddC", - "mordred:NtsC", - "mordred:NdssC", - "mordred:NaasC", - "mordred:NaaaC", - "mordred:NssssC", - "mordred:NsNH3", - "mordred:NsNH2", - "mordred:NssNH2", - "mordred:NdNH", - "mordred:NssNH", - "mordred:NaaNH", - "mordred:NtN", - "mordred:NsssNH", - "mordred:NdsN", - "mordred:NaaN", - "mordred:NsssN", - "mordred:NddsN", - "mordred:NaasN", - "mordred:NssssN", - "mordred:NsOH", - "mordred:NdO", - "mordred:NssO", - "mordred:NaaO", - "mordred:NsF", - "mordred:NsSiH3", - "mordred:NssSiH2", - "mordred:NsssSiH", - "mordred:NssssSi", - "mordred:NsPH2", - "mordred:NssPH", - "mordred:NsssP", - "mordred:NdsssP", - "mordred:NsssssP", - "mordred:NsSH", - "mordred:NdS", - "mordred:NssS", - "mordred:NaaS", - "mordred:NdssS", - "mordred:NddssS", - "mordred:NsCl", - "mordred:NsGeH3", - "mordred:NssGeH2", - "mordred:NsssGeH", - "mordred:NssssGe", - "mordred:NsAsH2", - "mordred:NssAsH", - "mordred:NsssAs", - "mordred:NsssdAs", - "mordred:NsssssAs", - "mordred:NsSeH", - "mordred:NdSe", - "mordred:NssSe", - "mordred:NaaSe", - "mordred:NdssSe", - "mordred:NddssSe", - "mordred:NsBr", - "mordred:NsSnH3", - "mordred:NssSnH2", - "mordred:NsssSnH", - "mordred:NssssSn", - "mordred:NsI", - "mordred:NsPbH3", - "mordred:NssPbH2", - "mordred:NsssPbH", - "mordred:NssssPb", - "mordred:SsLi", - "mordred:SssBe", - "mordred:SssssBe", - "mordred:SssBH", - "mordred:SsssB", - "mordred:SssssB", - "mordred:SsCH3", - "mordred:SdCH2", - "mordred:SssCH2", - "mordred:StCH", - "mordred:SdsCH", - "mordred:SaaCH", - "mordred:SsssCH", - "mordred:SddC", - "mordred:StsC", - "mordred:SdssC", - "mordred:SaasC", - "mordred:SaaaC", - "mordred:SssssC", - "mordred:SsNH3", - "mordred:SsNH2", - "mordred:SssNH2", - "mordred:SdNH", - "mordred:SssNH", - "mordred:SaaNH", - "mordred:StN", - "mordred:SsssNH", - "mordred:SdsN", - "mordred:SaaN", - "mordred:SsssN", - "mordred:SddsN", - "mordred:SaasN", - "mordred:SssssN", - "mordred:SsOH", - "mordred:SdO", - "mordred:SssO", - "mordred:SaaO", - "mordred:SsF", - "mordred:SsSiH3", - "mordred:SssSiH2", - "mordred:SsssSiH", - "mordred:SssssSi", - "mordred:SsPH2", - "mordred:SssPH", - "mordred:SsssP", - "mordred:SdsssP", - "mordred:SsssssP", - "mordred:SsSH", - "mordred:SdS", - "mordred:SssS", - "mordred:SaaS", - "mordred:SdssS", - "mordred:SddssS", - "mordred:SsCl", - "mordred:SsGeH3", - "mordred:SssGeH2", - "mordred:SsssGeH", - "mordred:SssssGe", - "mordred:SsAsH2", - "mordred:SssAsH", - "mordred:SsssAs", - "mordred:SsssdAs", - "mordred:SsssssAs", - "mordred:SsSeH", - "mordred:SdSe", - "mordred:SssSe", - "mordred:SaaSe", - "mordred:SdssSe", - "mordred:SddssSe", - "mordred:SsBr", - "mordred:SsSnH3", - "mordred:SssSnH2", - "mordred:SsssSnH", - "mordred:SssssSn", - "mordred:SsI", - "mordred:SsPbH3", - "mordred:SssPbH2", - "mordred:SsssPbH", - "mordred:SssssPb", - "mordred:MAXsLi", - "mordred:MAXssBe", - "mordred:MAXssssBe", - "mordred:MAXssBH", - "mordred:MAXsssB", - "mordred:MAXssssB", - "mordred:MAXsCH3", - "mordred:MAXdCH2", - "mordred:MAXssCH2", - "mordred:MAXtCH", - "mordred:MAXdsCH", - "mordred:MAXaaCH", - "mordred:MAXsssCH", - "mordred:MAXddC", - "mordred:MAXtsC", - "mordred:MAXdssC", - "mordred:MAXaasC", - "mordred:MAXaaaC", - "mordred:MAXssssC", - "mordred:MAXsNH3", - "mordred:MAXsNH2", - "mordred:MAXssNH2", - "mordred:MAXdNH", - "mordred:MAXssNH", - "mordred:MAXaaNH", - "mordred:MAXtN", - "mordred:MAXsssNH", - "mordred:MAXdsN", - "mordred:MAXaaN", - "mordred:MAXsssN", - "mordred:MAXddsN", - "mordred:MAXaasN", - "mordred:MAXssssN", - "mordred:MAXsOH", - "mordred:MAXdO", - "mordred:MAXssO", - "mordred:MAXaaO", - "mordred:MAXsF", - "mordred:MAXsSiH3", - "mordred:MAXssSiH2", - "mordred:MAXsssSiH", - "mordred:MAXssssSi", - "mordred:MAXsPH2", - "mordred:MAXssPH", - "mordred:MAXsssP", - "mordred:MAXdsssP", - "mordred:MAXsssssP", - "mordred:MAXsSH", - "mordred:MAXdS", - "mordred:MAXssS", - "mordred:MAXaaS", - "mordred:MAXdssS", - "mordred:MAXddssS", - "mordred:MAXsCl", - "mordred:MAXsGeH3", - "mordred:MAXssGeH2", - "mordred:MAXsssGeH", - "mordred:MAXssssGe", - "mordred:MAXsAsH2", - "mordred:MAXssAsH", - "mordred:MAXsssAs", - "mordred:MAXsssdAs", - "mordred:MAXsssssAs", - "mordred:MAXsSeH", - "mordred:MAXdSe", - "mordred:MAXssSe", - "mordred:MAXaaSe", - "mordred:MAXdssSe", - "mordred:MAXddssSe", - "mordred:MAXsBr", - "mordred:MAXsSnH3", - "mordred:MAXssSnH2", - "mordred:MAXsssSnH", - "mordred:MAXssssSn", - "mordred:MAXsI", - "mordred:MAXsPbH3", - "mordred:MAXssPbH2", - "mordred:MAXsssPbH", - "mordred:MAXssssPb", - "mordred:MINsLi", - "mordred:MINssBe", - "mordred:MINssssBe", - "mordred:MINssBH", - "mordred:MINsssB", - "mordred:MINssssB", - "mordred:MINsCH3", - "mordred:MINdCH2", - "mordred:MINssCH2", - "mordred:MINtCH", - "mordred:MINdsCH", - "mordred:MINaaCH", - "mordred:MINsssCH", - "mordred:MINddC", - "mordred:MINtsC", - "mordred:MINdssC", - "mordred:MINaasC", - "mordred:MINaaaC", - "mordred:MINssssC", - "mordred:MINsNH3", - "mordred:MINsNH2", - "mordred:MINssNH2", - "mordred:MINdNH", - "mordred:MINssNH", - "mordred:MINaaNH", - "mordred:MINtN", - "mordred:MINsssNH", - "mordred:MINdsN", - "mordred:MINaaN", - "mordred:MINsssN", - "mordred:MINddsN", - "mordred:MINaasN", - "mordred:MINssssN", - "mordred:MINsOH", - "mordred:MINdO", - "mordred:MINssO", - "mordred:MINaaO", - "mordred:MINsF", - "mordred:MINsSiH3", - "mordred:MINssSiH2", - "mordred:MINsssSiH", - "mordred:MINssssSi", - "mordred:MINsPH2", - "mordred:MINssPH", - "mordred:MINsssP", - "mordred:MINdsssP", - "mordred:MINsssssP", - "mordred:MINsSH", - "mordred:MINdS", - "mordred:MINssS", - "mordred:MINaaS", - "mordred:MINdssS", - "mordred:MINddssS", - "mordred:MINsCl", - "mordred:MINsGeH3", - "mordred:MINssGeH2", - "mordred:MINsssGeH", - "mordred:MINssssGe", - "mordred:MINsAsH2", - "mordred:MINssAsH", - "mordred:MINsssAs", - "mordred:MINsssdAs", - "mordred:MINsssssAs", - "mordred:MINsSeH", - "mordred:MINdSe", - "mordred:MINssSe", - "mordred:MINaaSe", - "mordred:MINdssSe", - "mordred:MINddssSe", - "mordred:MINsBr", - "mordred:MINsSnH3", - "mordred:MINssSnH2", - "mordred:MINsssSnH", - "mordred:MINssssSn", - "mordred:MINsI", - "mordred:MINsPbH3", - "mordred:MINssPbH2", - "mordred:MINsssPbH", - "mordred:MINssssPb", - "mordred:ECIndex", - "mordred:ETA_alpha", - "mordred:AETA_alpha", - "mordred:ETA_shape_p", - "mordred:ETA_shape_y", - "mordred:ETA_shape_x", - "mordred:ETA_beta", - "mordred:AETA_beta", - "mordred:ETA_beta_s", - "mordred:AETA_beta_s", - "mordred:ETA_beta_ns", - "mordred:AETA_beta_ns", - "mordred:ETA_beta_ns_d", - "mordred:AETA_beta_ns_d", - "mordred:ETA_eta", - "mordred:AETA_eta", - "mordred:ETA_eta_L", - "mordred:AETA_eta_L", - "mordred:ETA_eta_R", - "mordred:AETA_eta_R", - "mordred:ETA_eta_RL", - "mordred:AETA_eta_RL", - "mordred:ETA_eta_F", - "mordred:AETA_eta_F", - "mordred:ETA_eta_FL", - "mordred:AETA_eta_FL", - "mordred:ETA_eta_B", - "mordred:AETA_eta_B", - "mordred:ETA_eta_BR", - "mordred:AETA_eta_BR", - "mordred:ETA_dAlpha_A", - "mordred:ETA_dAlpha_B", - "mordred:ETA_epsilon_1", - "mordred:ETA_epsilon_2", - "mordred:ETA_epsilon_3", - "mordred:ETA_epsilon_4", - "mordred:ETA_epsilon_5", - "mordred:ETA_dEpsilon_A", - "mordred:ETA_dEpsilon_B", - "mordred:ETA_dEpsilon_C", - "mordred:ETA_dEpsilon_D", - "mordred:ETA_dBeta", - "mordred:AETA_dBeta", - "mordred:ETA_psi_1", - "mordred:ETA_dPsi_A", - "mordred:ETA_dPsi_B", - "mordred:fragCpx", - "mordred:fMF", - "mordred:GeomDiameter", - "mordred:GeomRadius", - "mordred:GeomShapeIndex", - "mordred:GeomPetitjeanIndex", - "mordred:GRAV", - "mordred:GRAVH", - "mordred:GRAVp", - "mordred:GRAVHp", - "mordred:nHBAcc", - "mordred:nHBDon", - "mordred:IC0", - "mordred:IC1", - "mordred:IC2", - "mordred:IC3", - "mordred:IC4", - "mordred:IC5", - "mordred:TIC0", - "mordred:TIC1", - "mordred:TIC2", - "mordred:TIC3", - "mordred:TIC4", - "mordred:TIC5", - "mordred:SIC0", - "mordred:SIC1", - "mordred:SIC2", - "mordred:SIC3", - "mordred:SIC4", - "mordred:SIC5", - "mordred:BIC0", - "mordred:BIC1", - "mordred:BIC2", - "mordred:BIC3", - "mordred:BIC4", - "mordred:BIC5", - "mordred:CIC0", - "mordred:CIC1", - "mordred:CIC2", - "mordred:CIC3", - "mordred:CIC4", - "mordred:CIC5", - "mordred:MIC0", - "mordred:MIC1", - "mordred:MIC2", - "mordred:MIC3", - "mordred:MIC4", - "mordred:MIC5", - "mordred:ZMIC0", - "mordred:ZMIC1", - "mordred:ZMIC2", - "mordred:ZMIC3", - "mordred:ZMIC4", - "mordred:ZMIC5", - "mordred:Kier1", - "mordred:Kier2", - "mordred:Kier3", - "mordred:Lipinski", - "mordred:GhoseFilter", - "mordred:FilterItLogS", - "mordred:VMcGowan", - "mordred:Mor01", - "mordred:Mor02", - "mordred:Mor03", - "mordred:Mor04", - "mordred:Mor05", - "mordred:Mor06", - "mordred:Mor07", - "mordred:Mor08", - "mordred:Mor09", - "mordred:Mor10", - "mordred:Mor11", - "mordred:Mor12", - "mordred:Mor13", - "mordred:Mor14", - "mordred:Mor15", - "mordred:Mor16", - "mordred:Mor17", - "mordred:Mor18", - "mordred:Mor19", - "mordred:Mor20", - "mordred:Mor21", - "mordred:Mor22", - "mordred:Mor23", - "mordred:Mor24", - "mordred:Mor25", - "mordred:Mor26", - "mordred:Mor27", - "mordred:Mor28", - "mordred:Mor29", - "mordred:Mor30", - "mordred:Mor31", - "mordred:Mor32", - "mordred:Mor01m", - "mordred:Mor02m", - "mordred:Mor03m", - "mordred:Mor04m", - "mordred:Mor05m", - "mordred:Mor06m", - "mordred:Mor07m", - "mordred:Mor08m", - "mordred:Mor09m", - "mordred:Mor10m", - "mordred:Mor11m", - "mordred:Mor12m", - "mordred:Mor13m", - "mordred:Mor14m", - "mordred:Mor15m", - "mordred:Mor16m", - "mordred:Mor17m", - "mordred:Mor18m", - "mordred:Mor19m", - "mordred:Mor20m", - "mordred:Mor21m", - "mordred:Mor22m", - "mordred:Mor23m", - "mordred:Mor24m", - "mordred:Mor25m", - "mordred:Mor26m", - "mordred:Mor27m", - "mordred:Mor28m", - "mordred:Mor29m", - "mordred:Mor30m", - "mordred:Mor31m", - "mordred:Mor32m", - "mordred:Mor01v", - "mordred:Mor02v", - "mordred:Mor03v", - "mordred:Mor04v", - "mordred:Mor05v", - "mordred:Mor06v", - "mordred:Mor07v", - "mordred:Mor08v", - "mordred:Mor09v", - "mordred:Mor10v", - "mordred:Mor11v", - "mordred:Mor12v", - "mordred:Mor13v", - "mordred:Mor14v", - "mordred:Mor15v", - "mordred:Mor16v", - "mordred:Mor17v", - "mordred:Mor18v", - "mordred:Mor19v", - "mordred:Mor20v", - "mordred:Mor21v", - "mordred:Mor22v", - "mordred:Mor23v", - "mordred:Mor24v", - "mordred:Mor25v", - "mordred:Mor26v", - "mordred:Mor27v", - "mordred:Mor28v", - "mordred:Mor29v", - "mordred:Mor30v", - "mordred:Mor31v", - "mordred:Mor32v", - "mordred:Mor01se", - "mordred:Mor02se", - "mordred:Mor03se", - "mordred:Mor04se", - "mordred:Mor05se", - "mordred:Mor06se", - "mordred:Mor07se", - "mordred:Mor08se", - "mordred:Mor09se", - "mordred:Mor10se", - "mordred:Mor11se", - "mordred:Mor12se", - "mordred:Mor13se", - "mordred:Mor14se", - "mordred:Mor15se", - "mordred:Mor16se", - "mordred:Mor17se", - "mordred:Mor18se", - "mordred:Mor19se", - "mordred:Mor20se", - "mordred:Mor21se", - "mordred:Mor22se", - "mordred:Mor23se", - "mordred:Mor24se", - "mordred:Mor25se", - "mordred:Mor26se", - "mordred:Mor27se", - "mordred:Mor28se", - "mordred:Mor29se", - "mordred:Mor30se", - "mordred:Mor31se", - "mordred:Mor32se", - "mordred:Mor01p", - "mordred:Mor02p", - "mordred:Mor03p", - "mordred:Mor04p", - "mordred:Mor05p", - "mordred:Mor06p", - "mordred:Mor07p", - "mordred:Mor08p", - "mordred:Mor09p", - "mordred:Mor10p", - "mordred:Mor11p", - "mordred:Mor12p", - "mordred:Mor13p", - "mordred:Mor14p", - "mordred:Mor15p", - "mordred:Mor16p", - "mordred:Mor17p", - "mordred:Mor18p", - "mordred:Mor19p", - "mordred:Mor20p", - "mordred:Mor21p", - "mordred:Mor22p", - "mordred:Mor23p", - "mordred:Mor24p", - "mordred:Mor25p", - "mordred:Mor26p", - "mordred:Mor27p", - "mordred:Mor28p", - "mordred:Mor29p", - "mordred:Mor30p", - "mordred:Mor31p", - "mordred:Mor32p", - "mordred:LabuteASA", - "mordred:PEOE_VSA1", - "mordred:PEOE_VSA2", - "mordred:PEOE_VSA3", - "mordred:PEOE_VSA4", - "mordred:PEOE_VSA5", - "mordred:PEOE_VSA6", - "mordred:PEOE_VSA7", - "mordred:PEOE_VSA8", - "mordred:PEOE_VSA9", - "mordred:PEOE_VSA10", - "mordred:PEOE_VSA11", - "mordred:PEOE_VSA12", - "mordred:PEOE_VSA13", - "mordred:SMR_VSA1", - "mordred:SMR_VSA2", - "mordred:SMR_VSA3", - "mordred:SMR_VSA4", - "mordred:SMR_VSA5", - "mordred:SMR_VSA6", - "mordred:SMR_VSA7", - "mordred:SMR_VSA8", - "mordred:SMR_VSA9", - "mordred:SlogP_VSA1", - "mordred:SlogP_VSA2", - "mordred:SlogP_VSA3", - "mordred:SlogP_VSA4", - "mordred:SlogP_VSA5", - "mordred:SlogP_VSA6", - "mordred:SlogP_VSA7", - "mordred:SlogP_VSA8", - "mordred:SlogP_VSA9", - "mordred:SlogP_VSA10", - "mordred:SlogP_VSA11", - "mordred:EState_VSA1", - "mordred:EState_VSA2", - "mordred:EState_VSA3", - "mordred:EState_VSA4", - "mordred:EState_VSA5", - "mordred:EState_VSA6", - "mordred:EState_VSA7", - "mordred:EState_VSA8", - "mordred:EState_VSA9", - "mordred:EState_VSA10", - "mordred:VSA_EState1", - "mordred:VSA_EState2", - "mordred:VSA_EState3", - "mordred:VSA_EState4", - "mordred:VSA_EState5", - "mordred:VSA_EState6", - "mordred:VSA_EState7", - "mordred:VSA_EState8", - "mordred:VSA_EState9", - "mordred:MDEC-11", - "mordred:MDEC-12", - "mordred:MDEC-13", - "mordred:MDEC-14", - "mordred:MDEC-22", - "mordred:MDEC-23", - "mordred:MDEC-24", - "mordred:MDEC-33", - "mordred:MDEC-34", - "mordred:MDEC-44", - "mordred:MDEO-11", - "mordred:MDEO-12", - "mordred:MDEO-22", - "mordred:MDEN-11", - "mordred:MDEN-12", - "mordred:MDEN-13", - "mordred:MDEN-22", - "mordred:MDEN-23", - "mordred:MDEN-33", - "mordred:MID", - "mordred:AMID", - "mordred:MID_h", - "mordred:AMID_h", - "mordred:MID_C", - "mordred:AMID_C", - "mordred:MID_N", - "mordred:AMID_N", - "mordred:MID_O", - "mordred:AMID_O", - "mordred:MID_X", - "mordred:AMID_X", - "mordred:MOMI-X", - "mordred:MOMI-Y", - "mordred:MOMI-Z", - "mordred:PBF", - "mordred:MPC2", - "mordred:MPC3", - "mordred:MPC4", - "mordred:MPC5", - "mordred:MPC6", - "mordred:MPC7", - "mordred:MPC8", - "mordred:MPC9", - "mordred:MPC10", - "mordred:TMPC10", - "mordred:piPC1", - "mordred:piPC2", - "mordred:piPC3", - "mordred:piPC4", - "mordred:piPC5", - "mordred:piPC6", - "mordred:piPC7", - "mordred:piPC8", - "mordred:piPC9", - "mordred:piPC10", - "mordred:TpiPC10", - "mordred:apol", - "mordred:bpol", - "mordred:nRing", - "mordred:n3Ring", - "mordred:n4Ring", - "mordred:n5Ring", - "mordred:n6Ring", - "mordred:n7Ring", - "mordred:n8Ring", - "mordred:n9Ring", - "mordred:n10Ring", - "mordred:n11Ring", - "mordred:n12Ring", - "mordred:nG12Ring", - "mordred:nHRing", - "mordred:n3HRing", - "mordred:n4HRing", - "mordred:n5HRing", - "mordred:n6HRing", - "mordred:n7HRing", - "mordred:n8HRing", - "mordred:n9HRing", - "mordred:n10HRing", - "mordred:n11HRing", - "mordred:n12HRing", - "mordred:nG12HRing", - "mordred:naRing", - "mordred:n3aRing", - "mordred:n4aRing", - "mordred:n5aRing", - "mordred:n6aRing", - "mordred:n7aRing", - "mordred:n8aRing", - "mordred:n9aRing", - "mordred:n10aRing", - "mordred:n11aRing", - "mordred:n12aRing", - "mordred:nG12aRing", - "mordred:naHRing", - "mordred:n3aHRing", - "mordred:n4aHRing", - "mordred:n5aHRing", - "mordred:n6aHRing", - "mordred:n7aHRing", - "mordred:n8aHRing", - "mordred:n9aHRing", - "mordred:n10aHRing", - "mordred:n11aHRing", - "mordred:n12aHRing", - "mordred:nG12aHRing", - "mordred:nARing", - "mordred:n3ARing", - "mordred:n4ARing", - "mordred:n5ARing", - "mordred:n6ARing", - "mordred:n7ARing", - "mordred:n8ARing", - "mordred:n9ARing", - "mordred:n10ARing", - "mordred:n11ARing", - "mordred:n12ARing", - "mordred:nG12ARing", - "mordred:nAHRing", - "mordred:n3AHRing", - "mordred:n4AHRing", - "mordred:n5AHRing", - "mordred:n6AHRing", - "mordred:n7AHRing", - "mordred:n8AHRing", - "mordred:n9AHRing", - "mordred:n10AHRing", - "mordred:n11AHRing", - "mordred:n12AHRing", - "mordred:nG12AHRing", - "mordred:nFRing", - "mordred:n4FRing", - "mordred:n5FRing", - "mordred:n6FRing", - "mordred:n7FRing", - "mordred:n8FRing", - "mordred:n9FRing", - "mordred:n10FRing", - "mordred:n11FRing", - "mordred:n12FRing", - "mordred:nG12FRing", - "mordred:nFHRing", - "mordred:n4FHRing", - "mordred:n5FHRing", - "mordred:n6FHRing", - "mordred:n7FHRing", - "mordred:n8FHRing", - "mordred:n9FHRing", - "mordred:n10FHRing", - "mordred:n11FHRing", - "mordred:n12FHRing", - "mordred:nG12FHRing", - "mordred:nFaRing", - "mordred:n4FaRing", - "mordred:n5FaRing", - "mordred:n6FaRing", - "mordred:n7FaRing", - "mordred:n8FaRing", - "mordred:n9FaRing", - "mordred:n10FaRing", - "mordred:n11FaRing", - "mordred:n12FaRing", - "mordred:nG12FaRing", - "mordred:nFaHRing", - "mordred:n4FaHRing", - "mordred:n5FaHRing", - "mordred:n6FaHRing", - "mordred:n7FaHRing", - "mordred:n8FaHRing", - "mordred:n9FaHRing", - "mordred:n10FaHRing", - "mordred:n11FaHRing", - "mordred:n12FaHRing", - "mordred:nG12FaHRing", - "mordred:nFARing", - "mordred:n4FARing", - "mordred:n5FARing", - "mordred:n6FARing", - "mordred:n7FARing", - "mordred:n8FARing", - "mordred:n9FARing", - "mordred:n10FARing", - "mordred:n11FARing", - "mordred:n12FARing", - "mordred:nG12FARing", - "mordred:nFAHRing", - "mordred:n4FAHRing", - "mordred:n5FAHRing", - "mordred:n6FAHRing", - "mordred:n7FAHRing", - "mordred:n8FAHRing", - "mordred:n9FAHRing", - "mordred:n10FAHRing", - "mordred:n11FAHRing", - "mordred:n12FAHRing", - "mordred:nG12FAHRing", - "mordred:nRot", - "mordred:RotRatio", - "mordred:SLogP", - "mordred:SMR", - "mordred:TopoPSA(NO)", - "mordred:TopoPSA", - "mordred:GGI1", - "mordred:GGI2", - "mordred:GGI3", - "mordred:GGI4", - "mordred:GGI5", - "mordred:GGI6", - "mordred:GGI7", - "mordred:GGI8", - "mordred:GGI9", - "mordred:GGI10", - "mordred:JGI1", - "mordred:JGI2", - "mordred:JGI3", - "mordred:JGI4", - "mordred:JGI5", - "mordred:JGI6", - "mordred:JGI7", - "mordred:JGI8", - "mordred:JGI9", - "mordred:JGI10", - "mordred:JGT10", - "mordred:Diameter", - "mordred:Radius", - "mordred:TopoShapeIndex", - "mordred:PetitjeanIndex", - "mordred:Vabc", - "mordred:VAdjMat", - "mordred:MWC01", - "mordred:MWC02", - "mordred:MWC03", - "mordred:MWC04", - "mordred:MWC05", - "mordred:MWC06", - "mordred:MWC07", - "mordred:MWC08", - "mordred:MWC09", - "mordred:MWC10", - "mordred:TMWC10", - "mordred:SRW02", - "mordred:SRW03", - "mordred:SRW04", - "mordred:SRW05", - "mordred:SRW06", - "mordred:SRW07", - "mordred:SRW08", - "mordred:SRW09", - "mordred:SRW10", - "mordred:TSRW10", - "mordred:MW", - "mordred:AMW", - "mordred:WPath", - "mordred:WPol", - "mordred:Zagreb1", - "mordred:Zagreb2", - "mordred:mZagreb1", - "mordred:mZagreb2", - 'padelpy:nAcid', - 'padelpy:ALogP', - 'padelpy:ALogp2', - 'padelpy:AMR', - 'padelpy:apol', - 'padelpy:naAromAtom', - 'padelpy:nAromBond', - 'padelpy:nAtom', - 'padelpy:nHeavyAtom', - 'padelpy:nH', - 'padelpy:nB', - 'padelpy:nC', - 'padelpy:nN', - 'padelpy:nO', - 'padelpy:nS', - 'padelpy:nP', - 'padelpy:nF', - 'padelpy:nCl', - 'padelpy:nBr', - 'padelpy:nI', - 'padelpy:nX', - 'padelpy:ATS0m', - 'padelpy:ATS1m', - 'padelpy:ATS2m', - 'padelpy:ATS3m', - 'padelpy:ATS4m', - 'padelpy:ATS5m', - 'padelpy:ATS6m', - 'padelpy:ATS7m', - 'padelpy:ATS8m', - 'padelpy:ATS0v', - 'padelpy:ATS1v', - 'padelpy:ATS2v', - 'padelpy:ATS3v', - 'padelpy:ATS4v', - 'padelpy:ATS5v', - 'padelpy:ATS6v', - 'padelpy:ATS7v', - 'padelpy:ATS8v', - 'padelpy:ATS0e', - 'padelpy:ATS1e', - 'padelpy:ATS2e', - 'padelpy:ATS3e', - 'padelpy:ATS4e', - 'padelpy:ATS5e', - 'padelpy:ATS6e', - 'padelpy:ATS7e', - 'padelpy:ATS8e', - 'padelpy:ATS0p', - 'padelpy:ATS1p', - 'padelpy:ATS2p', - 'padelpy:ATS3p', - 'padelpy:ATS4p', - 'padelpy:ATS5p', - 'padelpy:ATS6p', - 'padelpy:ATS7p', - 'padelpy:ATS8p', - 'padelpy:ATS0i', - 'padelpy:ATS1i', - 'padelpy:ATS2i', - 'padelpy:ATS3i', - 'padelpy:ATS4i', - 'padelpy:ATS5i', - 'padelpy:ATS6i', - 'padelpy:ATS7i', - 'padelpy:ATS8i', - 'padelpy:ATS0s', - 'padelpy:ATS1s', - 'padelpy:ATS2s', - 'padelpy:ATS3s', - 'padelpy:ATS4s', - 'padelpy:ATS5s', - 'padelpy:ATS6s', - 'padelpy:ATS7s', - 'padelpy:ATS8s', - 'padelpy:AATS0m', - 'padelpy:AATS1m', - 'padelpy:AATS2m', - 'padelpy:AATS3m', - 'padelpy:AATS4m', - 'padelpy:AATS5m', - 'padelpy:AATS6m', - 'padelpy:AATS7m', - 'padelpy:AATS8m', - 'padelpy:AATS0v', - 'padelpy:AATS1v', - 'padelpy:AATS2v', - 'padelpy:AATS3v', - 'padelpy:AATS4v', - 'padelpy:AATS5v', - 'padelpy:AATS6v', - 'padelpy:AATS7v', - 'padelpy:AATS8v', - 'padelpy:AATS0e', - 'padelpy:AATS1e', - 'padelpy:AATS2e', - 'padelpy:AATS3e', - 'padelpy:AATS4e', - 'padelpy:AATS5e', - 'padelpy:AATS6e', - 'padelpy:AATS7e', - 'padelpy:AATS8e', - 'padelpy:AATS0p', - 'padelpy:AATS1p', - 'padelpy:AATS2p', - 'padelpy:AATS3p', - 'padelpy:AATS4p', - 'padelpy:AATS5p', - 'padelpy:AATS6p', - 'padelpy:AATS7p', - 'padelpy:AATS8p', - 'padelpy:AATS0i', - 'padelpy:AATS1i', - 'padelpy:AATS2i', - 'padelpy:AATS3i', - 'padelpy:AATS4i', - 'padelpy:AATS5i', - 'padelpy:AATS6i', - 'padelpy:AATS7i', - 'padelpy:AATS8i', - 'padelpy:AATS0s', - 'padelpy:AATS1s', - 'padelpy:AATS2s', - 'padelpy:AATS3s', - 'padelpy:AATS4s', - 'padelpy:AATS5s', - 'padelpy:AATS6s', - 'padelpy:AATS7s', - 'padelpy:AATS8s', - 'padelpy:ATSC0c', - 'padelpy:ATSC1c', - 'padelpy:ATSC2c', - 'padelpy:ATSC3c', - 'padelpy:ATSC4c', - 'padelpy:ATSC5c', - 'padelpy:ATSC6c', - 'padelpy:ATSC7c', - 'padelpy:ATSC8c', - 'padelpy:ATSC0m', - 'padelpy:ATSC1m', - 'padelpy:ATSC2m', - 'padelpy:ATSC3m', - 'padelpy:ATSC4m', - 'padelpy:ATSC5m', - 'padelpy:ATSC6m', - 'padelpy:ATSC7m', - 'padelpy:ATSC8m', - 'padelpy:ATSC0v', - 'padelpy:ATSC1v', - 'padelpy:ATSC2v', - 'padelpy:ATSC3v', - 'padelpy:ATSC4v', - 'padelpy:ATSC5v', - 'padelpy:ATSC6v', - 'padelpy:ATSC7v', - 'padelpy:ATSC8v', - 'padelpy:ATSC0e', - 'padelpy:ATSC1e', - 'padelpy:ATSC2e', - 'padelpy:ATSC3e', - 'padelpy:ATSC4e', - 'padelpy:ATSC5e', - 'padelpy:ATSC6e', - 'padelpy:ATSC7e', - 'padelpy:ATSC8e', - 'padelpy:ATSC0p', - 'padelpy:ATSC1p', - 'padelpy:ATSC2p', - 'padelpy:ATSC3p', - 'padelpy:ATSC4p', - 'padelpy:ATSC5p', - 'padelpy:ATSC6p', - 'padelpy:ATSC7p', - 'padelpy:ATSC8p', - 'padelpy:ATSC0i', - 'padelpy:ATSC1i', - 'padelpy:ATSC2i', - 'padelpy:ATSC3i', - 'padelpy:ATSC4i', - 'padelpy:ATSC5i', - 'padelpy:ATSC6i', - 'padelpy:ATSC7i', - 'padelpy:ATSC8i', - 'padelpy:ATSC0s', - 'padelpy:ATSC1s', - 'padelpy:ATSC2s', - 'padelpy:ATSC3s', - 'padelpy:ATSC4s', - 'padelpy:ATSC5s', - 'padelpy:ATSC6s', - 'padelpy:ATSC7s', - 'padelpy:ATSC8s', - 'padelpy:AATSC0c', - 'padelpy:AATSC1c', - 'padelpy:AATSC2c', - 'padelpy:AATSC3c', - 'padelpy:AATSC4c', - 'padelpy:AATSC5c', - 'padelpy:AATSC6c', - 'padelpy:AATSC7c', - 'padelpy:AATSC8c', - 'padelpy:AATSC0m', - 'padelpy:AATSC1m', - 'padelpy:AATSC2m', - 'padelpy:AATSC3m', - 'padelpy:AATSC4m', - 'padelpy:AATSC5m', - 'padelpy:AATSC6m', - 'padelpy:AATSC7m', - 'padelpy:AATSC8m', - 'padelpy:AATSC0v', - 'padelpy:AATSC1v', - 'padelpy:AATSC2v', - 'padelpy:AATSC3v', - 'padelpy:AATSC4v', - 'padelpy:AATSC5v', - 'padelpy:AATSC6v', - 'padelpy:AATSC7v', - 'padelpy:AATSC8v', - 'padelpy:AATSC0e', - 'padelpy:AATSC1e', - 'padelpy:AATSC2e', - 'padelpy:AATSC3e', - 'padelpy:AATSC4e', - 'padelpy:AATSC5e', - 'padelpy:AATSC6e', - 'padelpy:AATSC7e', - 'padelpy:AATSC8e', - 'padelpy:AATSC0p', - 'padelpy:AATSC1p', - 'padelpy:AATSC2p', - 'padelpy:AATSC3p', - 'padelpy:AATSC4p', - 'padelpy:AATSC5p', - 'padelpy:AATSC6p', - 'padelpy:AATSC7p', - 'padelpy:AATSC8p', - 'padelpy:AATSC0i', - 'padelpy:AATSC1i', - 'padelpy:AATSC2i', - 'padelpy:AATSC3i', - 'padelpy:AATSC4i', - 'padelpy:AATSC5i', - 'padelpy:AATSC6i', - 'padelpy:AATSC7i', - 'padelpy:AATSC8i', - 'padelpy:AATSC0s', - 'padelpy:AATSC1s', - 'padelpy:AATSC2s', - 'padelpy:AATSC3s', - 'padelpy:AATSC4s', - 'padelpy:AATSC5s', - 'padelpy:AATSC6s', - 'padelpy:AATSC7s', - 'padelpy:AATSC8s', - 'padelpy:MATS1c', - 'padelpy:MATS2c', - 'padelpy:MATS3c', - 'padelpy:MATS4c', - 'padelpy:MATS5c', - 'padelpy:MATS6c', - 'padelpy:MATS7c', - 'padelpy:MATS8c', - 'padelpy:MATS1m', - 'padelpy:MATS2m', - 'padelpy:MATS3m', - 'padelpy:MATS4m', - 'padelpy:MATS5m', - 'padelpy:MATS6m', - 'padelpy:MATS7m', - 'padelpy:MATS8m', - 'padelpy:MATS1v', - 'padelpy:MATS2v', - 'padelpy:MATS3v', - 'padelpy:MATS4v', - 'padelpy:MATS5v', - 'padelpy:MATS6v', - 'padelpy:MATS7v', - 'padelpy:MATS8v', - 'padelpy:MATS1e', - 'padelpy:MATS2e', - 'padelpy:MATS3e', - 'padelpy:MATS4e', - 'padelpy:MATS5e', - 'padelpy:MATS6e', - 'padelpy:MATS7e', - 'padelpy:MATS8e', - 'padelpy:MATS1p', - 'padelpy:MATS2p', - 'padelpy:MATS3p', - 'padelpy:MATS4p', - 'padelpy:MATS5p', - 'padelpy:MATS6p', - 'padelpy:MATS7p', - 'padelpy:MATS8p', - 'padelpy:MATS1i', - 'padelpy:MATS2i', - 'padelpy:MATS3i', - 'padelpy:MATS4i', - 'padelpy:MATS5i', - 'padelpy:MATS6i', - 'padelpy:MATS7i', - 'padelpy:MATS8i', - 'padelpy:MATS1s', - 'padelpy:MATS2s', - 'padelpy:MATS3s', - 'padelpy:MATS4s', - 'padelpy:MATS5s', - 'padelpy:MATS6s', - 'padelpy:MATS7s', - 'padelpy:MATS8s', - 'padelpy:GATS1c', - 'padelpy:GATS2c', - 'padelpy:GATS3c', - 'padelpy:GATS4c', - 'padelpy:GATS5c', - 'padelpy:GATS6c', - 'padelpy:GATS7c', - 'padelpy:GATS8c', - 'padelpy:GATS1m', - 'padelpy:GATS2m', - 'padelpy:GATS3m', - 'padelpy:GATS4m', - 'padelpy:GATS5m', - 'padelpy:GATS6m', - 'padelpy:GATS7m', - 'padelpy:GATS8m', - 'padelpy:GATS1v', - 'padelpy:GATS2v', - 'padelpy:GATS3v', - 'padelpy:GATS4v', - 'padelpy:GATS5v', - 'padelpy:GATS6v', - 'padelpy:GATS7v', - 'padelpy:GATS8v', - 'padelpy:GATS1e', - 'padelpy:GATS2e', - 'padelpy:GATS3e', - 'padelpy:GATS4e', - 'padelpy:GATS5e', - 'padelpy:GATS6e', - 'padelpy:GATS7e', - 'padelpy:GATS8e', - 'padelpy:GATS1p', - 'padelpy:GATS2p', - 'padelpy:GATS3p', - 'padelpy:GATS4p', - 'padelpy:GATS5p', - 'padelpy:GATS6p', - 'padelpy:GATS7p', - 'padelpy:GATS8p', - 'padelpy:GATS1i', - 'padelpy:GATS2i', - 'padelpy:GATS3i', - 'padelpy:GATS4i', - 'padelpy:GATS5i', - 'padelpy:GATS6i', - 'padelpy:GATS7i', - 'padelpy:GATS8i', - 'padelpy:GATS1s', - 'padelpy:GATS2s', - 'padelpy:GATS3s', - 'padelpy:GATS4s', - 'padelpy:GATS5s', - 'padelpy:GATS6s', - 'padelpy:GATS7s', - 'padelpy:GATS8s', - 'padelpy:SpAbs_DzZ', - 'padelpy:SpMax_DzZ', - 'padelpy:SpDiam_DzZ', - 'padelpy:SpAD_DzZ', - 'padelpy:SpMAD_DzZ', - 'padelpy:EE_DzZ', - 'padelpy:SM1_DzZ', - 'padelpy:VE1_DzZ', - 'padelpy:VE2_DzZ', - 'padelpy:VE3_DzZ', - 'padelpy:VR1_DzZ', - 'padelpy:VR2_DzZ', - 'padelpy:VR3_DzZ', - 'padelpy:SpAbs_Dzm', - 'padelpy:SpMax_Dzm', - 'padelpy:SpDiam_Dzm', - 'padelpy:SpAD_Dzm', - 'padelpy:SpMAD_Dzm', - 'padelpy:EE_Dzm', - 'padelpy:SM1_Dzm', - 'padelpy:VE1_Dzm', - 'padelpy:VE2_Dzm', - 'padelpy:VE3_Dzm', - 'padelpy:VR1_Dzm', - 'padelpy:VR2_Dzm', - 'padelpy:VR3_Dzm', - 'padelpy:SpAbs_Dzv', - 'padelpy:SpMax_Dzv', - 'padelpy:SpDiam_Dzv', - 'padelpy:SpAD_Dzv', - 'padelpy:SpMAD_Dzv', - 'padelpy:EE_Dzv', - 'padelpy:SM1_Dzv', - 'padelpy:VE1_Dzv', - 'padelpy:VE2_Dzv', - 'padelpy:VE3_Dzv', - 'padelpy:VR1_Dzv', - 'padelpy:VR2_Dzv', - 'padelpy:VR3_Dzv', - 'padelpy:SpAbs_Dze', - 'padelpy:SpMax_Dze', - 'padelpy:SpDiam_Dze', - 'padelpy:SpAD_Dze', - 'padelpy:SpMAD_Dze', - 'padelpy:EE_Dze', - 'padelpy:SM1_Dze', - 'padelpy:VE1_Dze', - 'padelpy:VE2_Dze', - 'padelpy:VE3_Dze', - 'padelpy:VR1_Dze', - 'padelpy:VR2_Dze', - 'padelpy:VR3_Dze', - 'padelpy:SpAbs_Dzp', - 'padelpy:SpMax_Dzp', - 'padelpy:SpDiam_Dzp', - 'padelpy:SpAD_Dzp', - 'padelpy:SpMAD_Dzp', - 'padelpy:EE_Dzp', - 'padelpy:SM1_Dzp', - 'padelpy:VE1_Dzp', - 'padelpy:VE2_Dzp', - 'padelpy:VE3_Dzp', - 'padelpy:VR1_Dzp', - 'padelpy:VR2_Dzp', - 'padelpy:VR3_Dzp', - 'padelpy:SpAbs_Dzi', - 'padelpy:SpMax_Dzi', - 'padelpy:SpDiam_Dzi', - 'padelpy:SpAD_Dzi', - 'padelpy:SpMAD_Dzi', - 'padelpy:EE_Dzi', - 'padelpy:SM1_Dzi', - 'padelpy:VE1_Dzi', - 'padelpy:VE2_Dzi', - 'padelpy:VE3_Dzi', - 'padelpy:VR1_Dzi', - 'padelpy:VR2_Dzi', - 'padelpy:VR3_Dzi', - 'padelpy:SpAbs_Dzs', - 'padelpy:SpMax_Dzs', - 'padelpy:SpDiam_Dzs', - 'padelpy:SpAD_Dzs', - 'padelpy:SpMAD_Dzs', - 'padelpy:EE_Dzs', - 'padelpy:SM1_Dzs', - 'padelpy:VE1_Dzs', - 'padelpy:VE2_Dzs', - 'padelpy:VE3_Dzs', - 'padelpy:VR1_Dzs', - 'padelpy:VR2_Dzs', - 'padelpy:VR3_Dzs', - 'padelpy:nBase', - 'padelpy:BCUTw-1l', - 'padelpy:BCUTw-1h', - 'padelpy:BCUTc-1l', - 'padelpy:BCUTc-1h', - 'padelpy:BCUTp-1l', - 'padelpy:BCUTp-1h', - 'padelpy:nBonds', - 'padelpy:nBonds2', - 'padelpy:nBondsS', - 'padelpy:nBondsS2', - 'padelpy:nBondsS3', - 'padelpy:nBondsD', - 'padelpy:nBondsD2', - 'padelpy:nBondsT', - 'padelpy:nBondsQ', - 'padelpy:nBondsM', - 'padelpy:bpol', - 'padelpy:SpMax1_Bhm', - 'padelpy:SpMax2_Bhm', - 'padelpy:SpMax3_Bhm', - 'padelpy:SpMax4_Bhm', - 'padelpy:SpMax5_Bhm', - 'padelpy:SpMax6_Bhm', - 'padelpy:SpMax7_Bhm', - 'padelpy:SpMax8_Bhm', - 'padelpy:SpMin1_Bhm', - 'padelpy:SpMin2_Bhm', - 'padelpy:SpMin3_Bhm', - 'padelpy:SpMin4_Bhm', - 'padelpy:SpMin5_Bhm', - 'padelpy:SpMin6_Bhm', - 'padelpy:SpMin7_Bhm', - 'padelpy:SpMin8_Bhm', - 'padelpy:SpMax1_Bhv', - 'padelpy:SpMax2_Bhv', - 'padelpy:SpMax3_Bhv', - 'padelpy:SpMax4_Bhv', - 'padelpy:SpMax5_Bhv', - 'padelpy:SpMax6_Bhv', - 'padelpy:SpMax7_Bhv', - 'padelpy:SpMax8_Bhv', - 'padelpy:SpMin1_Bhv', - 'padelpy:SpMin2_Bhv', - 'padelpy:SpMin3_Bhv', - 'padelpy:SpMin4_Bhv', - 'padelpy:SpMin5_Bhv', - 'padelpy:SpMin6_Bhv', - 'padelpy:SpMin7_Bhv', - 'padelpy:SpMin8_Bhv', - 'padelpy:SpMax1_Bhe', - 'padelpy:SpMax2_Bhe', - 'padelpy:SpMax3_Bhe', - 'padelpy:SpMax4_Bhe', - 'padelpy:SpMax5_Bhe', - 'padelpy:SpMax6_Bhe', - 'padelpy:SpMax7_Bhe', - 'padelpy:SpMax8_Bhe', - 'padelpy:SpMin1_Bhe', - 'padelpy:SpMin2_Bhe', - 'padelpy:SpMin3_Bhe', - 'padelpy:SpMin4_Bhe', - 'padelpy:SpMin5_Bhe', - 'padelpy:SpMin6_Bhe', - 'padelpy:SpMin7_Bhe', - 'padelpy:SpMin8_Bhe', - 'padelpy:SpMax1_Bhp', - 'padelpy:SpMax2_Bhp', - 'padelpy:SpMax3_Bhp', - 'padelpy:SpMax4_Bhp', - 'padelpy:SpMax5_Bhp', - 'padelpy:SpMax6_Bhp', - 'padelpy:SpMax7_Bhp', - 'padelpy:SpMax8_Bhp', - 'padelpy:SpMin1_Bhp', - 'padelpy:SpMin2_Bhp', - 'padelpy:SpMin3_Bhp', - 'padelpy:SpMin4_Bhp', - 'padelpy:SpMin5_Bhp', - 'padelpy:SpMin6_Bhp', - 'padelpy:SpMin7_Bhp', - 'padelpy:SpMin8_Bhp', - 'padelpy:SpMax1_Bhi', - 'padelpy:SpMax2_Bhi', - 'padelpy:SpMax3_Bhi', - 'padelpy:SpMax4_Bhi', - 'padelpy:SpMax5_Bhi', - 'padelpy:SpMax6_Bhi', - 'padelpy:SpMax7_Bhi', - 'padelpy:SpMax8_Bhi', - 'padelpy:SpMin1_Bhi', - 'padelpy:SpMin2_Bhi', - 'padelpy:SpMin3_Bhi', - 'padelpy:SpMin4_Bhi', - 'padelpy:SpMin5_Bhi', - 'padelpy:SpMin6_Bhi', - 'padelpy:SpMin7_Bhi', - 'padelpy:SpMin8_Bhi', - 'padelpy:SpMax1_Bhs', - 'padelpy:SpMax2_Bhs', - 'padelpy:SpMax3_Bhs', - 'padelpy:SpMax4_Bhs', - 'padelpy:SpMax5_Bhs', - 'padelpy:SpMax6_Bhs', - 'padelpy:SpMax7_Bhs', - 'padelpy:SpMax8_Bhs', - 'padelpy:SpMin1_Bhs', - 'padelpy:SpMin2_Bhs', - 'padelpy:SpMin3_Bhs', - 'padelpy:SpMin4_Bhs', - 'padelpy:SpMin5_Bhs', - 'padelpy:SpMin6_Bhs', - 'padelpy:SpMin7_Bhs', - 'padelpy:SpMin8_Bhs', - 'padelpy:C1SP1', - 'padelpy:C2SP1', - 'padelpy:C1SP2', - 'padelpy:C2SP2', - 'padelpy:C3SP2', - 'padelpy:C1SP3', - 'padelpy:C2SP3', - 'padelpy:C3SP3', - 'padelpy:C4SP3', - 'padelpy:SCH-3', - 'padelpy:SCH-4', - 'padelpy:SCH-5', - 'padelpy:SCH-6', - 'padelpy:SCH-7', - 'padelpy:VCH-3', - 'padelpy:VCH-4', - 'padelpy:VCH-5', - 'padelpy:VCH-6', - 'padelpy:VCH-7', - 'padelpy:SC-3', - 'padelpy:SC-4', - 'padelpy:SC-5', - 'padelpy:SC-6', - 'padelpy:VC-3', - 'padelpy:VC-4', - 'padelpy:VC-5', - 'padelpy:VC-6', - 'padelpy:SPC-4', - 'padelpy:SPC-5', - 'padelpy:SPC-6', - 'padelpy:VPC-4', - 'padelpy:VPC-5', - 'padelpy:VPC-6', - 'padelpy:SP-0', - 'padelpy:SP-1', - 'padelpy:SP-2', - 'padelpy:SP-3', - 'padelpy:SP-4', - 'padelpy:SP-5', - 'padelpy:SP-6', - 'padelpy:SP-7', - 'padelpy:ASP-0', - 'padelpy:ASP-1', - 'padelpy:ASP-2', - 'padelpy:ASP-3', - 'padelpy:ASP-4', - 'padelpy:ASP-5', - 'padelpy:ASP-6', - 'padelpy:ASP-7', - 'padelpy:VP-0', - 'padelpy:VP-1', - 'padelpy:VP-2', - 'padelpy:VP-3', - 'padelpy:VP-4', - 'padelpy:VP-5', - 'padelpy:VP-6', - 'padelpy:VP-7', - 'padelpy:AVP-0', - 'padelpy:AVP-1', - 'padelpy:AVP-2', - 'padelpy:AVP-3', - 'padelpy:AVP-4', - 'padelpy:AVP-5', - 'padelpy:AVP-6', - 'padelpy:AVP-7', - 'padelpy:Sv', - 'padelpy:Sse', - 'padelpy:Spe', - 'padelpy:Sare', - 'padelpy:Sp', - 'padelpy:Si', - 'padelpy:Mv', - 'padelpy:Mse', - 'padelpy:Mpe', - 'padelpy:Mare', - 'padelpy:Mp', - 'padelpy:Mi', - 'padelpy:CrippenLogP', - 'padelpy:CrippenMR', - 'padelpy:SpMax_Dt', - 'padelpy:SpDiam_Dt', - 'padelpy:SpAD_Dt', - 'padelpy:SpMAD_Dt', - 'padelpy:EE_Dt', - 'padelpy:VE1_Dt', - 'padelpy:VE2_Dt', - 'padelpy:VE3_Dt', - 'padelpy:VR1_Dt', - 'padelpy:VR2_Dt', - 'padelpy:VR3_Dt', - 'padelpy:ECCEN', - 'padelpy:nHBd', - 'padelpy:nwHBd', - 'padelpy:nHBa', - 'padelpy:nwHBa', - 'padelpy:nHBint2', - 'padelpy:nHBint3', - 'padelpy:nHBint4', - 'padelpy:nHBint5', - 'padelpy:nHBint6', - 'padelpy:nHBint7', - 'padelpy:nHBint8', - 'padelpy:nHBint9', - 'padelpy:nHBint10', - 'padelpy:nHsOH', - 'padelpy:nHdNH', - 'padelpy:nHsSH', - 'padelpy:nHsNH2', - 'padelpy:nHssNH', - 'padelpy:nHaaNH', - 'padelpy:nHsNH3p', - 'padelpy:nHssNH2p', - 'padelpy:nHsssNHp', - 'padelpy:nHtCH', - 'padelpy:nHdCH2', - 'padelpy:nHdsCH', - 'padelpy:nHaaCH', - 'padelpy:nHCHnX', - 'padelpy:nHCsats', - 'padelpy:nHCsatu', - 'padelpy:nHAvin', - 'padelpy:nHother', - 'padelpy:nHmisc', - 'padelpy:nsLi', - 'padelpy:nssBe', - 'padelpy:nssssBem', - 'padelpy:nsBH2', - 'padelpy:nssBH', - 'padelpy:nsssB', - 'padelpy:nssssBm', - 'padelpy:nsCH3', - 'padelpy:ndCH2', - 'padelpy:nssCH2', - 'padelpy:ntCH', - 'padelpy:ndsCH', - 'padelpy:naaCH', - 'padelpy:nsssCH', - 'padelpy:nddC', - 'padelpy:ntsC', - 'padelpy:ndssC', - 'padelpy:naasC', - 'padelpy:naaaC', - 'padelpy:nssssC', - 'padelpy:nsNH3p', - 'padelpy:nsNH2', - 'padelpy:nssNH2p', - 'padelpy:ndNH', - 'padelpy:nssNH', - 'padelpy:naaNH', - 'padelpy:ntN', - 'padelpy:nsssNHp', - 'padelpy:ndsN', - 'padelpy:naaN', - 'padelpy:nsssN', - 'padelpy:nddsN', - 'padelpy:naasN', - 'padelpy:nssssNp', - 'padelpy:nsOH', - 'padelpy:ndO', - 'padelpy:nssO', - 'padelpy:naaO', - 'padelpy:naOm', - 'padelpy:nsOm', - 'padelpy:nsF', - 'padelpy:nsSiH3', - 'padelpy:nssSiH2', - 'padelpy:nsssSiH', - 'padelpy:nssssSi', - 'padelpy:nsPH2', - 'padelpy:nssPH', - 'padelpy:nsssP', - 'padelpy:ndsssP', - 'padelpy:nddsP', - 'padelpy:nsssssP', - 'padelpy:nsSH', - 'padelpy:ndS', - 'padelpy:nssS', - 'padelpy:naaS', - 'padelpy:ndssS', - 'padelpy:nddssS', - 'padelpy:nssssssS', - 'padelpy:nSm', - 'padelpy:nsCl', - 'padelpy:nsGeH3', - 'padelpy:nssGeH2', - 'padelpy:nsssGeH', - 'padelpy:nssssGe', - 'padelpy:nsAsH2', - 'padelpy:nssAsH', - 'padelpy:nsssAs', - 'padelpy:ndsssAs', - 'padelpy:nddsAs', - 'padelpy:nsssssAs', - 'padelpy:nsSeH', - 'padelpy:ndSe', - 'padelpy:nssSe', - 'padelpy:naaSe', - 'padelpy:ndssSe', - 'padelpy:nssssssSe', - 'padelpy:nddssSe', - 'padelpy:nsBr', - 'padelpy:nsSnH3', - 'padelpy:nssSnH2', - 'padelpy:nsssSnH', - 'padelpy:nssssSn', - 'padelpy:nsI', - 'padelpy:nsPbH3', - 'padelpy:nssPbH2', - 'padelpy:nsssPbH', - 'padelpy:nssssPb', - 'padelpy:SHBd', - 'padelpy:SwHBd', - 'padelpy:SHBa', - 'padelpy:SwHBa', - 'padelpy:SHBint2', - 'padelpy:SHBint3', - 'padelpy:SHBint4', - 'padelpy:SHBint5', - 'padelpy:SHBint6', - 'padelpy:SHBint7', - 'padelpy:SHBint8', - 'padelpy:SHBint9', - 'padelpy:SHBint10', - 'padelpy:SHsOH', - 'padelpy:SHdNH', - 'padelpy:SHsSH', - 'padelpy:SHsNH2', - 'padelpy:SHssNH', - 'padelpy:SHaaNH', - 'padelpy:SHsNH3p', - 'padelpy:SHssNH2p', - 'padelpy:SHsssNHp', - 'padelpy:SHtCH', - 'padelpy:SHdCH2', - 'padelpy:SHdsCH', - 'padelpy:SHaaCH', - 'padelpy:SHCHnX', - 'padelpy:SHCsats', - 'padelpy:SHCsatu', - 'padelpy:SHAvin', - 'padelpy:SHother', - 'padelpy:SHmisc', - 'padelpy:SsLi', - 'padelpy:SssBe', - 'padelpy:SssssBem', - 'padelpy:SsBH2', - 'padelpy:SssBH', - 'padelpy:SsssB', - 'padelpy:SssssBm', - 'padelpy:SsCH3', - 'padelpy:SdCH2', - 'padelpy:SssCH2', - 'padelpy:StCH', - 'padelpy:SdsCH', - 'padelpy:SaaCH', - 'padelpy:SsssCH', - 'padelpy:SddC', - 'padelpy:StsC', - 'padelpy:SdssC', - 'padelpy:SaasC', - 'padelpy:SaaaC', - 'padelpy:SssssC', - 'padelpy:SsNH3p', - 'padelpy:SsNH2', - 'padelpy:SssNH2p', - 'padelpy:SdNH', - 'padelpy:SssNH', - 'padelpy:SaaNH', - 'padelpy:StN', - 'padelpy:SsssNHp', - 'padelpy:SdsN', - 'padelpy:SaaN', - 'padelpy:SsssN', - 'padelpy:SddsN', - 'padelpy:SaasN', - 'padelpy:SssssNp', - 'padelpy:SsOH', - 'padelpy:SdO', - 'padelpy:SssO', - 'padelpy:SaaO', - 'padelpy:SaOm', - 'padelpy:SsOm', - 'padelpy:SsF', - 'padelpy:SsSiH3', - 'padelpy:SssSiH2', - 'padelpy:SsssSiH', - 'padelpy:SssssSi', - 'padelpy:SsPH2', - 'padelpy:SssPH', - 'padelpy:SsssP', - 'padelpy:SdsssP', - 'padelpy:SddsP', - 'padelpy:SsssssP', - 'padelpy:SsSH', - 'padelpy:SdS', - 'padelpy:SssS', - 'padelpy:SaaS', - 'padelpy:SdssS', - 'padelpy:SddssS', - 'padelpy:SssssssS', - 'padelpy:SSm', - 'padelpy:SsCl', - 'padelpy:SsGeH3', - 'padelpy:SssGeH2', - 'padelpy:SsssGeH', - 'padelpy:SssssGe', - 'padelpy:SsAsH2', - 'padelpy:SssAsH', - 'padelpy:SsssAs', - 'padelpy:SdsssAs', - 'padelpy:SddsAs', - 'padelpy:SsssssAs', - 'padelpy:SsSeH', - 'padelpy:SdSe', - 'padelpy:SssSe', - 'padelpy:SaaSe', - 'padelpy:SdssSe', - 'padelpy:SssssssSe', - 'padelpy:SddssSe', - 'padelpy:SsBr', - 'padelpy:SsSnH3', - 'padelpy:SssSnH2', - 'padelpy:SsssSnH', - 'padelpy:SssssSn', - 'padelpy:SsI', - 'padelpy:SsPbH3', - 'padelpy:SssPbH2', - 'padelpy:SsssPbH', - 'padelpy:SssssPb', - 'padelpy:minHBd', - 'padelpy:minwHBd', - 'padelpy:minHBa', - 'padelpy:minwHBa', - 'padelpy:minHBint2', - 'padelpy:minHBint3', - 'padelpy:minHBint4', - 'padelpy:minHBint5', - 'padelpy:minHBint6', - 'padelpy:minHBint7', - 'padelpy:minHBint8', - 'padelpy:minHBint9', - 'padelpy:minHBint10', - 'padelpy:minHsOH', - 'padelpy:minHdNH', - 'padelpy:minHsSH', - 'padelpy:minHsNH2', - 'padelpy:minHssNH', - 'padelpy:minHaaNH', - 'padelpy:minHsNH3p', - 'padelpy:minHssNH2p', - 'padelpy:minHsssNHp', - 'padelpy:minHtCH', - 'padelpy:minHdCH2', - 'padelpy:minHdsCH', - 'padelpy:minHaaCH', - 'padelpy:minHCHnX', - 'padelpy:minHCsats', - 'padelpy:minHCsatu', - 'padelpy:minHAvin', - 'padelpy:minHother', - 'padelpy:minHmisc', - 'padelpy:minsLi', - 'padelpy:minssBe', - 'padelpy:minssssBem', - 'padelpy:minsBH2', - 'padelpy:minssBH', - 'padelpy:minsssB', - 'padelpy:minssssBm', - 'padelpy:minsCH3', - 'padelpy:mindCH2', - 'padelpy:minssCH2', - 'padelpy:mintCH', - 'padelpy:mindsCH', - 'padelpy:minaaCH', - 'padelpy:minsssCH', - 'padelpy:minddC', - 'padelpy:mintsC', - 'padelpy:mindssC', - 'padelpy:minaasC', - 'padelpy:minaaaC', - 'padelpy:minssssC', - 'padelpy:minsNH3p', - 'padelpy:minsNH2', - 'padelpy:minssNH2p', - 'padelpy:mindNH', - 'padelpy:minssNH', - 'padelpy:minaaNH', - 'padelpy:mintN', - 'padelpy:minsssNHp', - 'padelpy:mindsN', - 'padelpy:minaaN', - 'padelpy:minsssN', - 'padelpy:minddsN', - 'padelpy:minaasN', - 'padelpy:minssssNp', - 'padelpy:minsOH', - 'padelpy:mindO', - 'padelpy:minssO', - 'padelpy:minaaO', - 'padelpy:minaOm', - 'padelpy:minsOm', - 'padelpy:minsF', - 'padelpy:minsSiH3', - 'padelpy:minssSiH2', - 'padelpy:minsssSiH', - 'padelpy:minssssSi', - 'padelpy:minsPH2', - 'padelpy:minssPH', - 'padelpy:minsssP', - 'padelpy:mindsssP', - 'padelpy:minddsP', - 'padelpy:minsssssP', - 'padelpy:minsSH', - 'padelpy:mindS', - 'padelpy:minssS', - 'padelpy:minaaS', - 'padelpy:mindssS', - 'padelpy:minddssS', - 'padelpy:minssssssS', - 'padelpy:minSm', - 'padelpy:minsCl', - 'padelpy:minsGeH3', - 'padelpy:minssGeH2', - 'padelpy:minsssGeH', - 'padelpy:minssssGe', - 'padelpy:minsAsH2', - 'padelpy:minssAsH', - 'padelpy:minsssAs', - 'padelpy:mindsssAs', - 'padelpy:minddsAs', - 'padelpy:minsssssAs', - 'padelpy:minsSeH', - 'padelpy:mindSe', - 'padelpy:minssSe', - 'padelpy:minaaSe', - 'padelpy:mindssSe', - 'padelpy:minssssssSe', - 'padelpy:minddssSe', - 'padelpy:minsBr', - 'padelpy:minsSnH3', - 'padelpy:minssSnH2', - 'padelpy:minsssSnH', - 'padelpy:minssssSn', - 'padelpy:minsI', - 'padelpy:minsPbH3', - 'padelpy:minssPbH2', - 'padelpy:minsssPbH', - 'padelpy:minssssPb', - 'padelpy:maxHBd', - 'padelpy:maxwHBd', - 'padelpy:maxHBa', - 'padelpy:maxwHBa', - 'padelpy:maxHBint2', - 'padelpy:maxHBint3', - 'padelpy:maxHBint4', - 'padelpy:maxHBint5', - 'padelpy:maxHBint6', - 'padelpy:maxHBint7', - 'padelpy:maxHBint8', - 'padelpy:maxHBint9', - 'padelpy:maxHBint10', - 'padelpy:maxHsOH', - 'padelpy:maxHdNH', - 'padelpy:maxHsSH', - 'padelpy:maxHsNH2', - 'padelpy:maxHssNH', - 'padelpy:maxHaaNH', - 'padelpy:maxHsNH3p', - 'padelpy:maxHssNH2p', - 'padelpy:maxHsssNHp', - 'padelpy:maxHtCH', - 'padelpy:maxHdCH2', - 'padelpy:maxHdsCH', - 'padelpy:maxHaaCH', - 'padelpy:maxHCHnX', - 'padelpy:maxHCsats', - 'padelpy:maxHCsatu', - 'padelpy:maxHAvin', - 'padelpy:maxHother', - 'padelpy:maxHmisc', - 'padelpy:maxsLi', - 'padelpy:maxssBe', - 'padelpy:maxssssBem', - 'padelpy:maxsBH2', - 'padelpy:maxssBH', - 'padelpy:maxsssB', - 'padelpy:maxssssBm', - 'padelpy:maxsCH3', - 'padelpy:maxdCH2', - 'padelpy:maxssCH2', - 'padelpy:maxtCH', - 'padelpy:maxdsCH', - 'padelpy:maxaaCH', - 'padelpy:maxsssCH', - 'padelpy:maxddC', - 'padelpy:maxtsC', - 'padelpy:maxdssC', - 'padelpy:maxaasC', - 'padelpy:maxaaaC', - 'padelpy:maxssssC', - 'padelpy:maxsNH3p', - 'padelpy:maxsNH2', - 'padelpy:maxssNH2p', - 'padelpy:maxdNH', - 'padelpy:maxssNH', - 'padelpy:maxaaNH', - 'padelpy:maxtN', - 'padelpy:maxsssNHp', - 'padelpy:maxdsN', - 'padelpy:maxaaN', - 'padelpy:maxsssN', - 'padelpy:maxddsN', - 'padelpy:maxaasN', - 'padelpy:maxssssNp', - 'padelpy:maxsOH', - 'padelpy:maxdO', - 'padelpy:maxssO', - 'padelpy:maxaaO', - 'padelpy:maxaOm', - 'padelpy:maxsOm', - 'padelpy:maxsF', - 'padelpy:maxsSiH3', - 'padelpy:maxssSiH2', - 'padelpy:maxsssSiH', - 'padelpy:maxssssSi', - 'padelpy:maxsPH2', - 'padelpy:maxssPH', - 'padelpy:maxsssP', - 'padelpy:maxdsssP', - 'padelpy:maxddsP', - 'padelpy:maxsssssP', - 'padelpy:maxsSH', - 'padelpy:maxdS', - 'padelpy:maxssS', - 'padelpy:maxaaS', - 'padelpy:maxdssS', - 'padelpy:maxddssS', - 'padelpy:maxssssssS', - 'padelpy:maxSm', - 'padelpy:maxsCl', - 'padelpy:maxsGeH3', - 'padelpy:maxssGeH2', - 'padelpy:maxsssGeH', - 'padelpy:maxssssGe', - 'padelpy:maxsAsH2', - 'padelpy:maxssAsH', - 'padelpy:maxsssAs', - 'padelpy:maxdsssAs', - 'padelpy:maxddsAs', - 'padelpy:maxsssssAs', - 'padelpy:maxsSeH', - 'padelpy:maxdSe', - 'padelpy:maxssSe', - 'padelpy:maxaaSe', - 'padelpy:maxdssSe', - 'padelpy:maxssssssSe', - 'padelpy:maxddssSe', - 'padelpy:maxsBr', - 'padelpy:maxsSnH3', - 'padelpy:maxssSnH2', - 'padelpy:maxsssSnH', - 'padelpy:maxssssSn', - 'padelpy:maxsI', - 'padelpy:maxsPbH3', - 'padelpy:maxssPbH2', - 'padelpy:maxsssPbH', - 'padelpy:maxssssPb', - 'padelpy:sumI', - 'padelpy:meanI', - 'padelpy:hmax', - 'padelpy:gmax', - 'padelpy:hmin', - 'padelpy:gmin', - 'padelpy:LipoaffinityIndex', - 'padelpy:MAXDN', - 'padelpy:MAXDP', - 'padelpy:DELS', - 'padelpy:MAXDN2', - 'padelpy:MAXDP2', - 'padelpy:DELS2', - 'padelpy:ETA_Alpha', - 'padelpy:ETA_AlphaP', - 'padelpy:ETA_dAlpha_A', - 'padelpy:ETA_dAlpha_B', - 'padelpy:ETA_Epsilon_1', - 'padelpy:ETA_Epsilon_2', - 'padelpy:ETA_Epsilon_3', - 'padelpy:ETA_Epsilon_4', - 'padelpy:ETA_Epsilon_5', - 'padelpy:ETA_dEpsilon_A', - 'padelpy:ETA_dEpsilon_B', - 'padelpy:ETA_dEpsilon_C', - 'padelpy:ETA_dEpsilon_D', - 'padelpy:ETA_Psi_1', - 'padelpy:ETA_dPsi_A', - 'padelpy:ETA_dPsi_B', - 'padelpy:ETA_Shape_P', - 'padelpy:ETA_Shape_Y', - 'padelpy:ETA_Shape_X', - 'padelpy:ETA_Beta', - 'padelpy:ETA_BetaP', - 'padelpy:ETA_Beta_s', - 'padelpy:ETA_BetaP_s', - 'padelpy:ETA_Beta_ns', - 'padelpy:ETA_BetaP_ns', - 'padelpy:ETA_dBeta', - 'padelpy:ETA_dBetaP', - 'padelpy:ETA_Beta_ns_d', - 'padelpy:ETA_BetaP_ns_d', - 'padelpy:ETA_Eta', - 'padelpy:ETA_EtaP', - 'padelpy:ETA_Eta_R', - 'padelpy:ETA_Eta_F', - 'padelpy:ETA_EtaP_F', - 'padelpy:ETA_Eta_L', - 'padelpy:ETA_EtaP_L', - 'padelpy:ETA_Eta_R_L', - 'padelpy:ETA_Eta_F_L', - 'padelpy:ETA_EtaP_F_L', - 'padelpy:ETA_Eta_B', - 'padelpy:ETA_EtaP_B', - 'padelpy:ETA_Eta_B_RC', - 'padelpy:ETA_EtaP_B_RC', - 'padelpy:FMF', - 'padelpy:fragC', - 'padelpy:nHBAcc', - 'padelpy:nHBAcc2', - 'padelpy:nHBAcc3', - 'padelpy:nHBAcc_Lipinski', - 'padelpy:nHBDon', - 'padelpy:nHBDon_Lipinski', - 'padelpy:HybRatio', - 'padelpy:IC0', - 'padelpy:IC1', - 'padelpy:IC2', - 'padelpy:IC3', - 'padelpy:IC4', - 'padelpy:IC5', - 'padelpy:TIC0', - 'padelpy:TIC1', - 'padelpy:TIC2', - 'padelpy:TIC3', - 'padelpy:TIC4', - 'padelpy:TIC5', - 'padelpy:SIC0', - 'padelpy:SIC1', - 'padelpy:SIC2', - 'padelpy:SIC3', - 'padelpy:SIC4', - 'padelpy:SIC5', - 'padelpy:CIC0', - 'padelpy:CIC1', - 'padelpy:CIC2', - 'padelpy:CIC3', - 'padelpy:CIC4', - 'padelpy:CIC5', - 'padelpy:BIC0', - 'padelpy:BIC1', - 'padelpy:BIC2', - 'padelpy:BIC3', - 'padelpy:BIC4', - 'padelpy:BIC5', - 'padelpy:MIC0', - 'padelpy:MIC1', - 'padelpy:MIC2', - 'padelpy:MIC3', - 'padelpy:MIC4', - 'padelpy:MIC5', - 'padelpy:ZMIC0', - 'padelpy:ZMIC1', - 'padelpy:ZMIC2', - 'padelpy:ZMIC3', - 'padelpy:ZMIC4', - 'padelpy:ZMIC5', - 'padelpy:Kier1', - 'padelpy:Kier2', - 'padelpy:Kier3', - 'padelpy:nAtomLC', - 'padelpy:nAtomP', - 'padelpy:nAtomLAC', - 'padelpy:MLogP', - 'padelpy:McGowan_Volume', - 'padelpy:MDEC-11', - 'padelpy:MDEC-12', - 'padelpy:MDEC-13', - 'padelpy:MDEC-14', - 'padelpy:MDEC-22', - 'padelpy:MDEC-23', - 'padelpy:MDEC-24', - 'padelpy:MDEC-33', - 'padelpy:MDEC-34', - 'padelpy:MDEC-44', - 'padelpy:MDEO-11', - 'padelpy:MDEO-12', - 'padelpy:MDEO-22', - 'padelpy:MDEN-11', - 'padelpy:MDEN-12', - 'padelpy:MDEN-13', - 'padelpy:MDEN-22', - 'padelpy:MDEN-23', - 'padelpy:MDEN-33', - 'padelpy:MLFER_A', - 'padelpy:MLFER_BH', - 'padelpy:MLFER_BO', - 'padelpy:MLFER_S', - 'padelpy:MLFER_E', - 'padelpy:MLFER_L', - 'padelpy:MPC2', - 'padelpy:MPC3', - 'padelpy:MPC4', - 'padelpy:MPC5', - 'padelpy:MPC6', - 'padelpy:MPC7', - 'padelpy:MPC8', - 'padelpy:MPC9', - 'padelpy:MPC10', - 'padelpy:TPC', - 'padelpy:piPC1', - 'padelpy:piPC2', - 'padelpy:piPC3', - 'padelpy:piPC4', - 'padelpy:piPC5', - 'padelpy:piPC6', - 'padelpy:piPC7', - 'padelpy:piPC8', - 'padelpy:piPC9', - 'padelpy:piPC10', - 'padelpy:TpiPC', - 'padelpy:R_TpiPCTPC', - 'padelpy:PetitjeanNumber', - 'padelpy:nRing', - 'padelpy:n3Ring', - 'padelpy:n4Ring', - 'padelpy:n5Ring', - 'padelpy:n6Ring', - 'padelpy:n7Ring', - 'padelpy:n8Ring', - 'padelpy:n9Ring', - 'padelpy:n10Ring', - 'padelpy:n11Ring', - 'padelpy:n12Ring', - 'padelpy:nG12Ring', - 'padelpy:nFRing', - 'padelpy:nF4Ring', - 'padelpy:nF5Ring', - 'padelpy:nF6Ring', - 'padelpy:nF7Ring', - 'padelpy:nF8Ring', - 'padelpy:nF9Ring', - 'padelpy:nF10Ring', - 'padelpy:nF11Ring', - 'padelpy:nF12Ring', - 'padelpy:nFG12Ring', - 'padelpy:nTRing', - 'padelpy:nT4Ring', - 'padelpy:nT5Ring', - 'padelpy:nT6Ring', - 'padelpy:nT7Ring', - 'padelpy:nT8Ring', - 'padelpy:nT9Ring', - 'padelpy:nT10Ring', - 'padelpy:nT11Ring', - 'padelpy:nT12Ring', - 'padelpy:nTG12Ring', - 'padelpy:nHeteroRing', - 'padelpy:n3HeteroRing', - 'padelpy:n4HeteroRing', - 'padelpy:n5HeteroRing', - 'padelpy:n6HeteroRing', - 'padelpy:n7HeteroRing', - 'padelpy:n8HeteroRing', - 'padelpy:n9HeteroRing', - 'padelpy:n10HeteroRing', - 'padelpy:n11HeteroRing', - 'padelpy:n12HeteroRing', - 'padelpy:nG12HeteroRing', - 'padelpy:nFHeteroRing', - 'padelpy:nF4HeteroRing', - 'padelpy:nF5HeteroRing', - 'padelpy:nF6HeteroRing', - 'padelpy:nF7HeteroRing', - 'padelpy:nF8HeteroRing', - 'padelpy:nF9HeteroRing', - 'padelpy:nF10HeteroRing', - 'padelpy:nF11HeteroRing', - 'padelpy:nF12HeteroRing', - 'padelpy:nFG12HeteroRing', - 'padelpy:nTHeteroRing', - 'padelpy:nT4HeteroRing', - 'padelpy:nT5HeteroRing', - 'padelpy:nT6HeteroRing', - 'padelpy:nT7HeteroRing', - 'padelpy:nT8HeteroRing', - 'padelpy:nT9HeteroRing', - 'padelpy:nT10HeteroRing', - 'padelpy:nT11HeteroRing', - 'padelpy:nT12HeteroRing', - 'padelpy:nTG12HeteroRing', - 'padelpy:nRotB', - 'padelpy:RotBFrac', - 'padelpy:nRotBt', - 'padelpy:RotBtFrac', - 'padelpy:LipinskiFailures', - 'padelpy:topoRadius', - 'padelpy:topoDiameter', - 'padelpy:topoShape', - 'padelpy:GGI1', - 'padelpy:GGI2', - 'padelpy:GGI3', - 'padelpy:GGI4', - 'padelpy:GGI5', - 'padelpy:GGI6', - 'padelpy:GGI7', - 'padelpy:GGI8', - 'padelpy:GGI9', - 'padelpy:GGI10', - 'padelpy:JGI1', - 'padelpy:JGI2', - 'padelpy:JGI3', - 'padelpy:JGI4', - 'padelpy:JGI5', - 'padelpy:JGI6', - 'padelpy:JGI7', - 'padelpy:JGI8', - 'padelpy:JGI9', - 'padelpy:JGI10', - 'padelpy:JGT', - 'padelpy:SpMax_D', - 'padelpy:SpDiam_D', - 'padelpy:SpAD_D', - 'padelpy:SpMAD_D', - 'padelpy:EE_D', - 'padelpy:VE1_D', - 'padelpy:VE2_D', - 'padelpy:VE3_D', - 'padelpy:VR1_D', - 'padelpy:VR2_D', - 'padelpy:VR3_D', - 'padelpy:TopoPSA', - 'padelpy:VABC', - 'padelpy:VAdjMat', - 'padelpy:MWC2', - 'padelpy:MWC3', - 'padelpy:MWC4', - 'padelpy:MWC5', - 'padelpy:MWC6', - 'padelpy:MWC7', - 'padelpy:MWC8', - 'padelpy:MWC9', - 'padelpy:MWC10', - 'padelpy:TWC', - 'padelpy:SRW2', - 'padelpy:SRW3', - 'padelpy:SRW4', - 'padelpy:SRW5', - 'padelpy:SRW6', - 'padelpy:SRW7', - 'padelpy:SRW8', - 'padelpy:SRW9', - 'padelpy:SRW10', - 'padelpy:TSRW', - 'padelpy:MW', - 'padelpy:AMW', - 'padelpy:WTPT-1', - 'padelpy:WTPT-2', - 'padelpy:WTPT-3', - 'padelpy:WTPT-4', - 'padelpy:WTPT-5', - 'padelpy:WPATH', - 'padelpy:WPOL', - 'padelpy:XLogP', - 'padelpy:Zagreb', - 'padelpy:TDB1u', - 'padelpy:TDB2u', - 'padelpy:TDB3u', - 'padelpy:TDB4u', - 'padelpy:TDB5u', - 'padelpy:TDB6u', - 'padelpy:TDB7u', - 'padelpy:TDB8u', - 'padelpy:TDB9u', - 'padelpy:TDB10u', - 'padelpy:TDB1m', - 'padelpy:TDB2m', - 'padelpy:TDB3m', - 'padelpy:TDB4m', - 'padelpy:TDB5m', - 'padelpy:TDB6m', - 'padelpy:TDB7m', - 'padelpy:TDB8m', - 'padelpy:TDB9m', - 'padelpy:TDB10m', - 'padelpy:TDB1v', - 'padelpy:TDB2v', - 'padelpy:TDB3v', - 'padelpy:TDB4v', - 'padelpy:TDB5v', - 'padelpy:TDB6v', - 'padelpy:TDB7v', - 'padelpy:TDB8v', - 'padelpy:TDB9v', - 'padelpy:TDB10v', - 'padelpy:TDB1e', - 'padelpy:TDB2e', - 'padelpy:TDB3e', - 'padelpy:TDB4e', - 'padelpy:TDB5e', - 'padelpy:TDB6e', - 'padelpy:TDB7e', - 'padelpy:TDB8e', - 'padelpy:TDB9e', - 'padelpy:TDB10e', - 'padelpy:TDB1p', - 'padelpy:TDB2p', - 'padelpy:TDB3p', - 'padelpy:TDB4p', - 'padelpy:TDB5p', - 'padelpy:TDB6p', - 'padelpy:TDB7p', - 'padelpy:TDB8p', - 'padelpy:TDB9p', - 'padelpy:TDB10p', - 'padelpy:TDB1i', - 'padelpy:TDB2i', - 'padelpy:TDB3i', - 'padelpy:TDB4i', - 'padelpy:TDB5i', - 'padelpy:TDB6i', - 'padelpy:TDB7i', - 'padelpy:TDB8i', - 'padelpy:TDB9i', - 'padelpy:TDB10i', - 'padelpy:TDB1s', - 'padelpy:TDB2s', - 'padelpy:TDB3s', - 'padelpy:TDB4s', - 'padelpy:TDB5s', - 'padelpy:TDB6s', - 'padelpy:TDB7s', - 'padelpy:TDB8s', - 'padelpy:TDB9s', - 'padelpy:TDB10s', - 'padelpy:TDB1r', - 'padelpy:TDB2r', - 'padelpy:TDB3r', - 'padelpy:TDB4r', - 'padelpy:TDB5r', - 'padelpy:TDB6r', - 'padelpy:TDB7r', - 'padelpy:TDB8r', - 'padelpy:TDB9r', - 'padelpy:TDB10r', - 'padelpy:PPSA-1', - 'padelpy:PPSA-2', - 'padelpy:PPSA-3', - 'padelpy:PNSA-1', - 'padelpy:PNSA-2', - 'padelpy:PNSA-3', - 'padelpy:DPSA-1', - 'padelpy:DPSA-2', - 'padelpy:DPSA-3', - 'padelpy:FPSA-1', - 'padelpy:FPSA-2', - 'padelpy:FPSA-3', - 'padelpy:FNSA-1', - 'padelpy:FNSA-2', - 'padelpy:FNSA-3', - 'padelpy:WPSA-1', - 'padelpy:WPSA-2', - 'padelpy:WPSA-3', - 'padelpy:WNSA-1', - 'padelpy:WNSA-2', - 'padelpy:WNSA-3', - 'padelpy:RPCG', - 'padelpy:RNCG', - 'padelpy:RPCS', - 'padelpy:RNCS', - 'padelpy:THSA', - 'padelpy:TPSA', - 'padelpy:RHSA', - 'padelpy:RPSA', - 'padelpy:GRAV-1', - 'padelpy:GRAV-2', - 'padelpy:GRAV-3', - 'padelpy:GRAVH-1', - 'padelpy:GRAVH-2', - 'padelpy:GRAVH-3', - 'padelpy:GRAV-4', - 'padelpy:GRAV-5', - 'padelpy:GRAV-6', - 'padelpy:LOBMAX', - 'padelpy:LOBMIN', - 'padelpy:MOMI-X', - 'padelpy:MOMI-Y', - 'padelpy:MOMI-Z', - 'padelpy:MOMI-XY', - 'padelpy:MOMI-XZ', - 'padelpy:MOMI-YZ', - 'padelpy:MOMI-R', - 'padelpy:geomRadius', - 'padelpy:geomDiameter', - 'padelpy:geomShape', - 'padelpy:RDF10u', - 'padelpy:RDF15u', - 'padelpy:RDF20u', - 'padelpy:RDF25u', - 'padelpy:RDF30u', - 'padelpy:RDF35u', - 'padelpy:RDF40u', - 'padelpy:RDF45u', - 'padelpy:RDF50u', - 'padelpy:RDF55u', - 'padelpy:RDF60u', - 'padelpy:RDF65u', - 'padelpy:RDF70u', - 'padelpy:RDF75u', - 'padelpy:RDF80u', - 'padelpy:RDF85u', - 'padelpy:RDF90u', - 'padelpy:RDF95u', - 'padelpy:RDF100u', - 'padelpy:RDF105u', - 'padelpy:RDF110u', - 'padelpy:RDF115u', - 'padelpy:RDF120u', - 'padelpy:RDF125u', - 'padelpy:RDF130u', - 'padelpy:RDF135u', - 'padelpy:RDF140u', - 'padelpy:RDF145u', - 'padelpy:RDF150u', - 'padelpy:RDF155u', - 'padelpy:RDF10m', - 'padelpy:RDF15m', - 'padelpy:RDF20m', - 'padelpy:RDF25m', - 'padelpy:RDF30m', - 'padelpy:RDF35m', - 'padelpy:RDF40m', - 'padelpy:RDF45m', - 'padelpy:RDF50m', - 'padelpy:RDF55m', - 'padelpy:RDF60m', - 'padelpy:RDF65m', - 'padelpy:RDF70m', - 'padelpy:RDF75m', - 'padelpy:RDF80m', - 'padelpy:RDF85m', - 'padelpy:RDF90m', - 'padelpy:RDF95m', - 'padelpy:RDF100m', - 'padelpy:RDF105m', - 'padelpy:RDF110m', - 'padelpy:RDF115m', - 'padelpy:RDF120m', - 'padelpy:RDF125m', - 'padelpy:RDF130m', - 'padelpy:RDF135m', - 'padelpy:RDF140m', - 'padelpy:RDF145m', - 'padelpy:RDF150m', - 'padelpy:RDF155m', - 'padelpy:RDF10v', - 'padelpy:RDF15v', - 'padelpy:RDF20v', - 'padelpy:RDF25v', - 'padelpy:RDF30v', - 'padelpy:RDF35v', - 'padelpy:RDF40v', - 'padelpy:RDF45v', - 'padelpy:RDF50v', - 'padelpy:RDF55v', - 'padelpy:RDF60v', - 'padelpy:RDF65v', - 'padelpy:RDF70v', - 'padelpy:RDF75v', - 'padelpy:RDF80v', - 'padelpy:RDF85v', - 'padelpy:RDF90v', - 'padelpy:RDF95v', - 'padelpy:RDF100v', - 'padelpy:RDF105v', - 'padelpy:RDF110v', - 'padelpy:RDF115v', - 'padelpy:RDF120v', - 'padelpy:RDF125v', - 'padelpy:RDF130v', - 'padelpy:RDF135v', - 'padelpy:RDF140v', - 'padelpy:RDF145v', - 'padelpy:RDF150v', - 'padelpy:RDF155v', - 'padelpy:RDF10e', - 'padelpy:RDF15e', - 'padelpy:RDF20e', - 'padelpy:RDF25e', - 'padelpy:RDF30e', - 'padelpy:RDF35e', - 'padelpy:RDF40e', - 'padelpy:RDF45e', - 'padelpy:RDF50e', - 'padelpy:RDF55e', - 'padelpy:RDF60e', - 'padelpy:RDF65e', - 'padelpy:RDF70e', - 'padelpy:RDF75e', - 'padelpy:RDF80e', - 'padelpy:RDF85e', - 'padelpy:RDF90e', - 'padelpy:RDF95e', - 'padelpy:RDF100e', - 'padelpy:RDF105e', - 'padelpy:RDF110e', - 'padelpy:RDF115e', - 'padelpy:RDF120e', - 'padelpy:RDF125e', - 'padelpy:RDF130e', - 'padelpy:RDF135e', - 'padelpy:RDF140e', - 'padelpy:RDF145e', - 'padelpy:RDF150e', - 'padelpy:RDF155e', - 'padelpy:RDF10p', - 'padelpy:RDF15p', - 'padelpy:RDF20p', - 'padelpy:RDF25p', - 'padelpy:RDF30p', - 'padelpy:RDF35p', - 'padelpy:RDF40p', - 'padelpy:RDF45p', - 'padelpy:RDF50p', - 'padelpy:RDF55p', - 'padelpy:RDF60p', - 'padelpy:RDF65p', - 'padelpy:RDF70p', - 'padelpy:RDF75p', - 'padelpy:RDF80p', - 'padelpy:RDF85p', - 'padelpy:RDF90p', - 'padelpy:RDF95p', - 'padelpy:RDF100p', - 'padelpy:RDF105p', - 'padelpy:RDF110p', - 'padelpy:RDF115p', - 'padelpy:RDF120p', - 'padelpy:RDF125p', - 'padelpy:RDF130p', - 'padelpy:RDF135p', - 'padelpy:RDF140p', - 'padelpy:RDF145p', - 'padelpy:RDF150p', - 'padelpy:RDF155p', - 'padelpy:RDF10i', - 'padelpy:RDF15i', - 'padelpy:RDF20i', - 'padelpy:RDF25i', - 'padelpy:RDF30i', - 'padelpy:RDF35i', - 'padelpy:RDF40i', - 'padelpy:RDF45i', - 'padelpy:RDF50i', - 'padelpy:RDF55i', - 'padelpy:RDF60i', - 'padelpy:RDF65i', - 'padelpy:RDF70i', - 'padelpy:RDF75i', - 'padelpy:RDF80i', - 'padelpy:RDF85i', - 'padelpy:RDF90i', - 'padelpy:RDF95i', - 'padelpy:RDF100i', - 'padelpy:RDF105i', - 'padelpy:RDF110i', - 'padelpy:RDF115i', - 'padelpy:RDF120i', - 'padelpy:RDF125i', - 'padelpy:RDF130i', - 'padelpy:RDF135i', - 'padelpy:RDF140i', - 'padelpy:RDF145i', - 'padelpy:RDF150i', - 'padelpy:RDF155i', - 'padelpy:RDF10s', - 'padelpy:RDF15s', - 'padelpy:RDF20s', - 'padelpy:RDF25s', - 'padelpy:RDF30s', - 'padelpy:RDF35s', - 'padelpy:RDF40s', - 'padelpy:RDF45s', - 'padelpy:RDF50s', - 'padelpy:RDF55s', - 'padelpy:RDF60s', - 'padelpy:RDF65s', - 'padelpy:RDF70s', - 'padelpy:RDF75s', - 'padelpy:RDF80s', - 'padelpy:RDF85s', - 'padelpy:RDF90s', - 'padelpy:RDF95s', - 'padelpy:RDF100s', - 'padelpy:RDF105s', - 'padelpy:RDF110s', - 'padelpy:RDF115s', - 'padelpy:RDF120s', - 'padelpy:RDF125s', - 'padelpy:RDF130s', - 'padelpy:RDF135s', - 'padelpy:RDF140s', - 'padelpy:RDF145s', - 'padelpy:RDF150s', - 'padelpy:RDF155s', - 'padelpy:L1u', - 'padelpy:L2u', - 'padelpy:L3u', - 'padelpy:P1u', - 'padelpy:P2u', - 'padelpy:E1u', - 'padelpy:E2u', - 'padelpy:E3u', - 'padelpy:Tu', - 'padelpy:Au', - 'padelpy:Vu', - 'padelpy:Ku', - 'padelpy:Du', - 'padelpy:L1m', - 'padelpy:L2m', - 'padelpy:L3m', - 'padelpy:P1m', - 'padelpy:P2m', - 'padelpy:E1m', - 'padelpy:E2m', - 'padelpy:E3m', - 'padelpy:Tm', - 'padelpy:Am', - 'padelpy:Vm', - 'padelpy:Km', - 'padelpy:Dm', - 'padelpy:L1v', - 'padelpy:L2v', - 'padelpy:L3v', - 'padelpy:P1v', - 'padelpy:P2v', - 'padelpy:E1v', - 'padelpy:E2v', - 'padelpy:E3v', - 'padelpy:Tv', - 'padelpy:Av', - 'padelpy:Vv', - 'padelpy:Kv', - 'padelpy:Dv', - 'padelpy:L1e', - 'padelpy:L2e', - 'padelpy:L3e', - 'padelpy:P1e', - 'padelpy:P2e', - 'padelpy:E1e', - 'padelpy:E2e', - 'padelpy:E3e', - 'padelpy:Te', - 'padelpy:Ae', - 'padelpy:Ve', - 'padelpy:Ke', - 'padelpy:De', - 'padelpy:L1p', - 'padelpy:L2p', - 'padelpy:L3p', - 'padelpy:P1p', - 'padelpy:P2p', - 'padelpy:E1p', - 'padelpy:E2p', - 'padelpy:E3p', - 'padelpy:Tp', - 'padelpy:Ap', - 'padelpy:Vp', - 'padelpy:Kp', - 'padelpy:Dp', - 'padelpy:L1i', - 'padelpy:L2i', - 'padelpy:L3i', - 'padelpy:P1i', - 'padelpy:P2i', - 'padelpy:E1i', - 'padelpy:E2i', - 'padelpy:E3i', - 'padelpy:Ti', - 'padelpy:Ai', - 'padelpy:Vi', - 'padelpy:Ki', - 'padelpy:Di', - 'padelpy:L1s', - 'padelpy:L2s', - 'padelpy:L3s', - 'padelpy:P1s', - 'padelpy:P2s', - 'padelpy:E1s', - 'padelpy:E2s', - 'padelpy:E3s', - 'padelpy:Ts', - 'padelpy:As', - 'padelpy:Vs', - 'padelpy:Ks', - 'padelpy:Ds', + "padelpy:nAcid", + "padelpy:ALogP", + "padelpy:ALogp2", + "padelpy:AMR", + "padelpy:apol", + "padelpy:naAromAtom", + "padelpy:nAromBond", + "padelpy:nAtom", + "padelpy:nHeavyAtom", + "padelpy:nH", + "padelpy:nB", + "padelpy:nC", + "padelpy:nN", + "padelpy:nO", + "padelpy:nS", + "padelpy:nP", + "padelpy:nF", + "padelpy:nCl", + "padelpy:nBr", + "padelpy:nI", + "padelpy:nX", + "padelpy:ATS0m", + "padelpy:ATS1m", + "padelpy:ATS2m", + "padelpy:ATS3m", + "padelpy:ATS4m", + "padelpy:ATS5m", + "padelpy:ATS6m", + "padelpy:ATS7m", + "padelpy:ATS8m", + "padelpy:ATS0v", + "padelpy:ATS1v", + "padelpy:ATS2v", + "padelpy:ATS3v", + "padelpy:ATS4v", + "padelpy:ATS5v", + "padelpy:ATS6v", + "padelpy:ATS7v", + "padelpy:ATS8v", + "padelpy:ATS0e", + "padelpy:ATS1e", + "padelpy:ATS2e", + "padelpy:ATS3e", + "padelpy:ATS4e", + "padelpy:ATS5e", + "padelpy:ATS6e", + "padelpy:ATS7e", + "padelpy:ATS8e", + "padelpy:ATS0p", + "padelpy:ATS1p", + "padelpy:ATS2p", + "padelpy:ATS3p", + "padelpy:ATS4p", + "padelpy:ATS5p", + "padelpy:ATS6p", + "padelpy:ATS7p", + "padelpy:ATS8p", + "padelpy:ATS0i", + "padelpy:ATS1i", + "padelpy:ATS2i", + "padelpy:ATS3i", + "padelpy:ATS4i", + "padelpy:ATS5i", + "padelpy:ATS6i", + "padelpy:ATS7i", + "padelpy:ATS8i", + "padelpy:ATS0s", + "padelpy:ATS1s", + "padelpy:ATS2s", + "padelpy:ATS3s", + "padelpy:ATS4s", + "padelpy:ATS5s", + "padelpy:ATS6s", + "padelpy:ATS7s", + "padelpy:ATS8s", + "padelpy:AATS0m", + "padelpy:AATS1m", + "padelpy:AATS2m", + "padelpy:AATS3m", + "padelpy:AATS4m", + "padelpy:AATS5m", + "padelpy:AATS6m", + "padelpy:AATS7m", + "padelpy:AATS8m", + "padelpy:AATS0v", + "padelpy:AATS1v", + "padelpy:AATS2v", + "padelpy:AATS3v", + "padelpy:AATS4v", + "padelpy:AATS5v", + "padelpy:AATS6v", + "padelpy:AATS7v", + "padelpy:AATS8v", + "padelpy:AATS0e", + "padelpy:AATS1e", + "padelpy:AATS2e", + "padelpy:AATS3e", + "padelpy:AATS4e", + "padelpy:AATS5e", + "padelpy:AATS6e", + "padelpy:AATS7e", + "padelpy:AATS8e", + "padelpy:AATS0p", + "padelpy:AATS1p", + "padelpy:AATS2p", + "padelpy:AATS3p", + "padelpy:AATS4p", + "padelpy:AATS5p", + "padelpy:AATS6p", + "padelpy:AATS7p", + "padelpy:AATS8p", + "padelpy:AATS0i", + "padelpy:AATS1i", + "padelpy:AATS2i", + "padelpy:AATS3i", + "padelpy:AATS4i", + "padelpy:AATS5i", + "padelpy:AATS6i", + "padelpy:AATS7i", + "padelpy:AATS8i", + "padelpy:AATS0s", + "padelpy:AATS1s", + "padelpy:AATS2s", + "padelpy:AATS3s", + "padelpy:AATS4s", + "padelpy:AATS5s", + "padelpy:AATS6s", + "padelpy:AATS7s", + "padelpy:AATS8s", + "padelpy:ATSC0c", + "padelpy:ATSC1c", + "padelpy:ATSC2c", + "padelpy:ATSC3c", + "padelpy:ATSC4c", + "padelpy:ATSC5c", + "padelpy:ATSC6c", + "padelpy:ATSC7c", + "padelpy:ATSC8c", + "padelpy:ATSC0m", + "padelpy:ATSC1m", + "padelpy:ATSC2m", + "padelpy:ATSC3m", + "padelpy:ATSC4m", + "padelpy:ATSC5m", + "padelpy:ATSC6m", + "padelpy:ATSC7m", + "padelpy:ATSC8m", + "padelpy:ATSC0v", + "padelpy:ATSC1v", + "padelpy:ATSC2v", + "padelpy:ATSC3v", + "padelpy:ATSC4v", + "padelpy:ATSC5v", + "padelpy:ATSC6v", + "padelpy:ATSC7v", + "padelpy:ATSC8v", + "padelpy:ATSC0e", + "padelpy:ATSC1e", + "padelpy:ATSC2e", + "padelpy:ATSC3e", + "padelpy:ATSC4e", + "padelpy:ATSC5e", + "padelpy:ATSC6e", + "padelpy:ATSC7e", + "padelpy:ATSC8e", + "padelpy:ATSC0p", + "padelpy:ATSC1p", + "padelpy:ATSC2p", + "padelpy:ATSC3p", + "padelpy:ATSC4p", + "padelpy:ATSC5p", + "padelpy:ATSC6p", + "padelpy:ATSC7p", + "padelpy:ATSC8p", + "padelpy:ATSC0i", + "padelpy:ATSC1i", + "padelpy:ATSC2i", + "padelpy:ATSC3i", + "padelpy:ATSC4i", + "padelpy:ATSC5i", + "padelpy:ATSC6i", + "padelpy:ATSC7i", + "padelpy:ATSC8i", + "padelpy:ATSC0s", + "padelpy:ATSC1s", + "padelpy:ATSC2s", + "padelpy:ATSC3s", + "padelpy:ATSC4s", + "padelpy:ATSC5s", + "padelpy:ATSC6s", + "padelpy:ATSC7s", + "padelpy:ATSC8s", + "padelpy:AATSC0c", + "padelpy:AATSC1c", + "padelpy:AATSC2c", + "padelpy:AATSC3c", + "padelpy:AATSC4c", + "padelpy:AATSC5c", + "padelpy:AATSC6c", + "padelpy:AATSC7c", + "padelpy:AATSC8c", + "padelpy:AATSC0m", + "padelpy:AATSC1m", + "padelpy:AATSC2m", + "padelpy:AATSC3m", + "padelpy:AATSC4m", + "padelpy:AATSC5m", + "padelpy:AATSC6m", + "padelpy:AATSC7m", + "padelpy:AATSC8m", + "padelpy:AATSC0v", + "padelpy:AATSC1v", + "padelpy:AATSC2v", + "padelpy:AATSC3v", + "padelpy:AATSC4v", + "padelpy:AATSC5v", + "padelpy:AATSC6v", + "padelpy:AATSC7v", + "padelpy:AATSC8v", + "padelpy:AATSC0e", + "padelpy:AATSC1e", + "padelpy:AATSC2e", + "padelpy:AATSC3e", + "padelpy:AATSC4e", + "padelpy:AATSC5e", + "padelpy:AATSC6e", + "padelpy:AATSC7e", + "padelpy:AATSC8e", + "padelpy:AATSC0p", + "padelpy:AATSC1p", + "padelpy:AATSC2p", + "padelpy:AATSC3p", + "padelpy:AATSC4p", + "padelpy:AATSC5p", + "padelpy:AATSC6p", + "padelpy:AATSC7p", + "padelpy:AATSC8p", + "padelpy:AATSC0i", + "padelpy:AATSC1i", + "padelpy:AATSC2i", + "padelpy:AATSC3i", + "padelpy:AATSC4i", + "padelpy:AATSC5i", + "padelpy:AATSC6i", + "padelpy:AATSC7i", + "padelpy:AATSC8i", + "padelpy:AATSC0s", + "padelpy:AATSC1s", + "padelpy:AATSC2s", + "padelpy:AATSC3s", + "padelpy:AATSC4s", + "padelpy:AATSC5s", + "padelpy:AATSC6s", + "padelpy:AATSC7s", + "padelpy:AATSC8s", + "padelpy:MATS1c", + "padelpy:MATS2c", + "padelpy:MATS3c", + "padelpy:MATS4c", + "padelpy:MATS5c", + "padelpy:MATS6c", + "padelpy:MATS7c", + "padelpy:MATS8c", + "padelpy:MATS1m", + "padelpy:MATS2m", + "padelpy:MATS3m", + "padelpy:MATS4m", + "padelpy:MATS5m", + "padelpy:MATS6m", + "padelpy:MATS7m", + "padelpy:MATS8m", + "padelpy:MATS1v", + "padelpy:MATS2v", + "padelpy:MATS3v", + "padelpy:MATS4v", + "padelpy:MATS5v", + "padelpy:MATS6v", + "padelpy:MATS7v", + "padelpy:MATS8v", + "padelpy:MATS1e", + "padelpy:MATS2e", + "padelpy:MATS3e", + "padelpy:MATS4e", + "padelpy:MATS5e", + "padelpy:MATS6e", + "padelpy:MATS7e", + "padelpy:MATS8e", + "padelpy:MATS1p", + "padelpy:MATS2p", + "padelpy:MATS3p", + "padelpy:MATS4p", + "padelpy:MATS5p", + "padelpy:MATS6p", + "padelpy:MATS7p", + "padelpy:MATS8p", + "padelpy:MATS1i", + "padelpy:MATS2i", + "padelpy:MATS3i", + "padelpy:MATS4i", + "padelpy:MATS5i", + "padelpy:MATS6i", + "padelpy:MATS7i", + "padelpy:MATS8i", + "padelpy:MATS1s", + "padelpy:MATS2s", + "padelpy:MATS3s", + "padelpy:MATS4s", + "padelpy:MATS5s", + "padelpy:MATS6s", + "padelpy:MATS7s", + "padelpy:MATS8s", + "padelpy:GATS1c", + "padelpy:GATS2c", + "padelpy:GATS3c", + "padelpy:GATS4c", + "padelpy:GATS5c", + "padelpy:GATS6c", + "padelpy:GATS7c", + "padelpy:GATS8c", + "padelpy:GATS1m", + "padelpy:GATS2m", + "padelpy:GATS3m", + "padelpy:GATS4m", + "padelpy:GATS5m", + "padelpy:GATS6m", + "padelpy:GATS7m", + "padelpy:GATS8m", + "padelpy:GATS1v", + "padelpy:GATS2v", + "padelpy:GATS3v", + "padelpy:GATS4v", + "padelpy:GATS5v", + "padelpy:GATS6v", + "padelpy:GATS7v", + "padelpy:GATS8v", + "padelpy:GATS1e", + "padelpy:GATS2e", + "padelpy:GATS3e", + "padelpy:GATS4e", + "padelpy:GATS5e", + "padelpy:GATS6e", + "padelpy:GATS7e", + "padelpy:GATS8e", + "padelpy:GATS1p", + "padelpy:GATS2p", + "padelpy:GATS3p", + "padelpy:GATS4p", + "padelpy:GATS5p", + "padelpy:GATS6p", + "padelpy:GATS7p", + "padelpy:GATS8p", + "padelpy:GATS1i", + "padelpy:GATS2i", + "padelpy:GATS3i", + "padelpy:GATS4i", + "padelpy:GATS5i", + "padelpy:GATS6i", + "padelpy:GATS7i", + "padelpy:GATS8i", + "padelpy:GATS1s", + "padelpy:GATS2s", + "padelpy:GATS3s", + "padelpy:GATS4s", + "padelpy:GATS5s", + "padelpy:GATS6s", + "padelpy:GATS7s", + "padelpy:GATS8s", + "padelpy:SpAbs_DzZ", + "padelpy:SpMax_DzZ", + "padelpy:SpDiam_DzZ", + "padelpy:SpAD_DzZ", + "padelpy:SpMAD_DzZ", + "padelpy:EE_DzZ", + "padelpy:SM1_DzZ", + "padelpy:VE1_DzZ", + "padelpy:VE2_DzZ", + "padelpy:VE3_DzZ", + "padelpy:VR1_DzZ", + "padelpy:VR2_DzZ", + "padelpy:VR3_DzZ", + "padelpy:SpAbs_Dzm", + "padelpy:SpMax_Dzm", + "padelpy:SpDiam_Dzm", + "padelpy:SpAD_Dzm", + "padelpy:SpMAD_Dzm", + "padelpy:EE_Dzm", + "padelpy:SM1_Dzm", + "padelpy:VE1_Dzm", + "padelpy:VE2_Dzm", + "padelpy:VE3_Dzm", + "padelpy:VR1_Dzm", + "padelpy:VR2_Dzm", + "padelpy:VR3_Dzm", + "padelpy:SpAbs_Dzv", + "padelpy:SpMax_Dzv", + "padelpy:SpDiam_Dzv", + "padelpy:SpAD_Dzv", + "padelpy:SpMAD_Dzv", + "padelpy:EE_Dzv", + "padelpy:SM1_Dzv", + "padelpy:VE1_Dzv", + "padelpy:VE2_Dzv", + "padelpy:VE3_Dzv", + "padelpy:VR1_Dzv", + "padelpy:VR2_Dzv", + "padelpy:VR3_Dzv", + "padelpy:SpAbs_Dze", + "padelpy:SpMax_Dze", + "padelpy:SpDiam_Dze", + "padelpy:SpAD_Dze", + "padelpy:SpMAD_Dze", + "padelpy:EE_Dze", + "padelpy:SM1_Dze", + "padelpy:VE1_Dze", + "padelpy:VE2_Dze", + "padelpy:VE3_Dze", + "padelpy:VR1_Dze", + "padelpy:VR2_Dze", + "padelpy:VR3_Dze", + "padelpy:SpAbs_Dzp", + "padelpy:SpMax_Dzp", + "padelpy:SpDiam_Dzp", + "padelpy:SpAD_Dzp", + "padelpy:SpMAD_Dzp", + "padelpy:EE_Dzp", + "padelpy:SM1_Dzp", + "padelpy:VE1_Dzp", + "padelpy:VE2_Dzp", + "padelpy:VE3_Dzp", + "padelpy:VR1_Dzp", + "padelpy:VR2_Dzp", + "padelpy:VR3_Dzp", + "padelpy:SpAbs_Dzi", + "padelpy:SpMax_Dzi", + "padelpy:SpDiam_Dzi", + "padelpy:SpAD_Dzi", + "padelpy:SpMAD_Dzi", + "padelpy:EE_Dzi", + "padelpy:SM1_Dzi", + "padelpy:VE1_Dzi", + "padelpy:VE2_Dzi", + "padelpy:VE3_Dzi", + "padelpy:VR1_Dzi", + "padelpy:VR2_Dzi", + "padelpy:VR3_Dzi", + "padelpy:SpAbs_Dzs", + "padelpy:SpMax_Dzs", + "padelpy:SpDiam_Dzs", + "padelpy:SpAD_Dzs", + "padelpy:SpMAD_Dzs", + "padelpy:EE_Dzs", + "padelpy:SM1_Dzs", + "padelpy:VE1_Dzs", + "padelpy:VE2_Dzs", + "padelpy:VE3_Dzs", + "padelpy:VR1_Dzs", + "padelpy:VR2_Dzs", + "padelpy:VR3_Dzs", + "padelpy:nBase", + "padelpy:BCUTw-1l", + "padelpy:BCUTw-1h", + "padelpy:BCUTc-1l", + "padelpy:BCUTc-1h", + "padelpy:BCUTp-1l", + "padelpy:BCUTp-1h", + "padelpy:nBonds", + "padelpy:nBonds2", + "padelpy:nBondsS", + "padelpy:nBondsS2", + "padelpy:nBondsS3", + "padelpy:nBondsD", + "padelpy:nBondsD2", + "padelpy:nBondsT", + "padelpy:nBondsQ", + "padelpy:nBondsM", + "padelpy:bpol", + "padelpy:SpMax1_Bhm", + "padelpy:SpMax2_Bhm", + "padelpy:SpMax3_Bhm", + "padelpy:SpMax4_Bhm", + "padelpy:SpMax5_Bhm", + "padelpy:SpMax6_Bhm", + "padelpy:SpMax7_Bhm", + "padelpy:SpMax8_Bhm", + "padelpy:SpMin1_Bhm", + "padelpy:SpMin2_Bhm", + "padelpy:SpMin3_Bhm", + "padelpy:SpMin4_Bhm", + "padelpy:SpMin5_Bhm", + "padelpy:SpMin6_Bhm", + "padelpy:SpMin7_Bhm", + "padelpy:SpMin8_Bhm", + "padelpy:SpMax1_Bhv", + "padelpy:SpMax2_Bhv", + "padelpy:SpMax3_Bhv", + "padelpy:SpMax4_Bhv", + "padelpy:SpMax5_Bhv", + "padelpy:SpMax6_Bhv", + "padelpy:SpMax7_Bhv", + "padelpy:SpMax8_Bhv", + "padelpy:SpMin1_Bhv", + "padelpy:SpMin2_Bhv", + "padelpy:SpMin3_Bhv", + "padelpy:SpMin4_Bhv", + "padelpy:SpMin5_Bhv", + "padelpy:SpMin6_Bhv", + "padelpy:SpMin7_Bhv", + "padelpy:SpMin8_Bhv", + "padelpy:SpMax1_Bhe", + "padelpy:SpMax2_Bhe", + "padelpy:SpMax3_Bhe", + "padelpy:SpMax4_Bhe", + "padelpy:SpMax5_Bhe", + "padelpy:SpMax6_Bhe", + "padelpy:SpMax7_Bhe", + "padelpy:SpMax8_Bhe", + "padelpy:SpMin1_Bhe", + "padelpy:SpMin2_Bhe", + "padelpy:SpMin3_Bhe", + "padelpy:SpMin4_Bhe", + "padelpy:SpMin5_Bhe", + "padelpy:SpMin6_Bhe", + "padelpy:SpMin7_Bhe", + "padelpy:SpMin8_Bhe", + "padelpy:SpMax1_Bhp", + "padelpy:SpMax2_Bhp", + "padelpy:SpMax3_Bhp", + "padelpy:SpMax4_Bhp", + "padelpy:SpMax5_Bhp", + "padelpy:SpMax6_Bhp", + "padelpy:SpMax7_Bhp", + "padelpy:SpMax8_Bhp", + "padelpy:SpMin1_Bhp", + "padelpy:SpMin2_Bhp", + "padelpy:SpMin3_Bhp", + "padelpy:SpMin4_Bhp", + "padelpy:SpMin5_Bhp", + "padelpy:SpMin6_Bhp", + "padelpy:SpMin7_Bhp", + "padelpy:SpMin8_Bhp", + "padelpy:SpMax1_Bhi", + "padelpy:SpMax2_Bhi", + "padelpy:SpMax3_Bhi", + "padelpy:SpMax4_Bhi", + "padelpy:SpMax5_Bhi", + "padelpy:SpMax6_Bhi", + "padelpy:SpMax7_Bhi", + "padelpy:SpMax8_Bhi", + "padelpy:SpMin1_Bhi", + "padelpy:SpMin2_Bhi", + "padelpy:SpMin3_Bhi", + "padelpy:SpMin4_Bhi", + "padelpy:SpMin5_Bhi", + "padelpy:SpMin6_Bhi", + "padelpy:SpMin7_Bhi", + "padelpy:SpMin8_Bhi", + "padelpy:SpMax1_Bhs", + "padelpy:SpMax2_Bhs", + "padelpy:SpMax3_Bhs", + "padelpy:SpMax4_Bhs", + "padelpy:SpMax5_Bhs", + "padelpy:SpMax6_Bhs", + "padelpy:SpMax7_Bhs", + "padelpy:SpMax8_Bhs", + "padelpy:SpMin1_Bhs", + "padelpy:SpMin2_Bhs", + "padelpy:SpMin3_Bhs", + "padelpy:SpMin4_Bhs", + "padelpy:SpMin5_Bhs", + "padelpy:SpMin6_Bhs", + "padelpy:SpMin7_Bhs", + "padelpy:SpMin8_Bhs", + "padelpy:C1SP1", + "padelpy:C2SP1", + "padelpy:C1SP2", + "padelpy:C2SP2", + "padelpy:C3SP2", + "padelpy:C1SP3", + "padelpy:C2SP3", + "padelpy:C3SP3", + "padelpy:C4SP3", + "padelpy:SCH-3", + "padelpy:SCH-4", + "padelpy:SCH-5", + "padelpy:SCH-6", + "padelpy:SCH-7", + "padelpy:VCH-3", + "padelpy:VCH-4", + "padelpy:VCH-5", + "padelpy:VCH-6", + "padelpy:VCH-7", + "padelpy:SC-3", + "padelpy:SC-4", + "padelpy:SC-5", + "padelpy:SC-6", + "padelpy:VC-3", + "padelpy:VC-4", + "padelpy:VC-5", + "padelpy:VC-6", + "padelpy:SPC-4", + "padelpy:SPC-5", + "padelpy:SPC-6", + "padelpy:VPC-4", + "padelpy:VPC-5", + "padelpy:VPC-6", + "padelpy:SP-0", + "padelpy:SP-1", + "padelpy:SP-2", + "padelpy:SP-3", + "padelpy:SP-4", + "padelpy:SP-5", + "padelpy:SP-6", + "padelpy:SP-7", + "padelpy:ASP-0", + "padelpy:ASP-1", + "padelpy:ASP-2", + "padelpy:ASP-3", + "padelpy:ASP-4", + "padelpy:ASP-5", + "padelpy:ASP-6", + "padelpy:ASP-7", + "padelpy:VP-0", + "padelpy:VP-1", + "padelpy:VP-2", + "padelpy:VP-3", + "padelpy:VP-4", + "padelpy:VP-5", + "padelpy:VP-6", + "padelpy:VP-7", + "padelpy:AVP-0", + "padelpy:AVP-1", + "padelpy:AVP-2", + "padelpy:AVP-3", + "padelpy:AVP-4", + "padelpy:AVP-5", + "padelpy:AVP-6", + "padelpy:AVP-7", + "padelpy:Sv", + "padelpy:Sse", + "padelpy:Spe", + "padelpy:Sare", + "padelpy:Sp", + "padelpy:Si", + "padelpy:Mv", + "padelpy:Mse", + "padelpy:Mpe", + "padelpy:Mare", + "padelpy:Mp", + "padelpy:Mi", + "padelpy:CrippenLogP", + "padelpy:CrippenMR", + "padelpy:SpMax_Dt", + "padelpy:SpDiam_Dt", + "padelpy:SpAD_Dt", + "padelpy:SpMAD_Dt", + "padelpy:EE_Dt", + "padelpy:VE1_Dt", + "padelpy:VE2_Dt", + "padelpy:VE3_Dt", + "padelpy:VR1_Dt", + "padelpy:VR2_Dt", + "padelpy:VR3_Dt", + "padelpy:ECCEN", + "padelpy:nHBd", + "padelpy:nwHBd", + "padelpy:nHBa", + "padelpy:nwHBa", + "padelpy:nHBint2", + "padelpy:nHBint3", + "padelpy:nHBint4", + "padelpy:nHBint5", + "padelpy:nHBint6", + "padelpy:nHBint7", + "padelpy:nHBint8", + "padelpy:nHBint9", + "padelpy:nHBint10", + "padelpy:nHsOH", + "padelpy:nHdNH", + "padelpy:nHsSH", + "padelpy:nHsNH2", + "padelpy:nHssNH", + "padelpy:nHaaNH", + "padelpy:nHsNH3p", + "padelpy:nHssNH2p", + "padelpy:nHsssNHp", + "padelpy:nHtCH", + "padelpy:nHdCH2", + "padelpy:nHdsCH", + "padelpy:nHaaCH", + "padelpy:nHCHnX", + "padelpy:nHCsats", + "padelpy:nHCsatu", + "padelpy:nHAvin", + "padelpy:nHother", + "padelpy:nHmisc", + "padelpy:nsLi", + "padelpy:nssBe", + "padelpy:nssssBem", + "padelpy:nsBH2", + "padelpy:nssBH", + "padelpy:nsssB", + "padelpy:nssssBm", + "padelpy:nsCH3", + "padelpy:ndCH2", + "padelpy:nssCH2", + "padelpy:ntCH", + "padelpy:ndsCH", + "padelpy:naaCH", + "padelpy:nsssCH", + "padelpy:nddC", + "padelpy:ntsC", + "padelpy:ndssC", + "padelpy:naasC", + "padelpy:naaaC", + "padelpy:nssssC", + "padelpy:nsNH3p", + "padelpy:nsNH2", + "padelpy:nssNH2p", + "padelpy:ndNH", + "padelpy:nssNH", + "padelpy:naaNH", + "padelpy:ntN", + "padelpy:nsssNHp", + "padelpy:ndsN", + "padelpy:naaN", + "padelpy:nsssN", + "padelpy:nddsN", + "padelpy:naasN", + "padelpy:nssssNp", + "padelpy:nsOH", + "padelpy:ndO", + "padelpy:nssO", + "padelpy:naaO", + "padelpy:naOm", + "padelpy:nsOm", + "padelpy:nsF", + "padelpy:nsSiH3", + "padelpy:nssSiH2", + "padelpy:nsssSiH", + "padelpy:nssssSi", + "padelpy:nsPH2", + "padelpy:nssPH", + "padelpy:nsssP", + "padelpy:ndsssP", + "padelpy:nddsP", + "padelpy:nsssssP", + "padelpy:nsSH", + "padelpy:ndS", + "padelpy:nssS", + "padelpy:naaS", + "padelpy:ndssS", + "padelpy:nddssS", + "padelpy:nssssssS", + "padelpy:nSm", + "padelpy:nsCl", + "padelpy:nsGeH3", + "padelpy:nssGeH2", + "padelpy:nsssGeH", + "padelpy:nssssGe", + "padelpy:nsAsH2", + "padelpy:nssAsH", + "padelpy:nsssAs", + "padelpy:ndsssAs", + "padelpy:nddsAs", + "padelpy:nsssssAs", + "padelpy:nsSeH", + "padelpy:ndSe", + "padelpy:nssSe", + "padelpy:naaSe", + "padelpy:ndssSe", + "padelpy:nssssssSe", + "padelpy:nddssSe", + "padelpy:nsBr", + "padelpy:nsSnH3", + "padelpy:nssSnH2", + "padelpy:nsssSnH", + "padelpy:nssssSn", + "padelpy:nsI", + "padelpy:nsPbH3", + "padelpy:nssPbH2", + "padelpy:nsssPbH", + "padelpy:nssssPb", + "padelpy:SHBd", + "padelpy:SwHBd", + "padelpy:SHBa", + "padelpy:SwHBa", + "padelpy:SHBint2", + "padelpy:SHBint3", + "padelpy:SHBint4", + "padelpy:SHBint5", + "padelpy:SHBint6", + "padelpy:SHBint7", + "padelpy:SHBint8", + "padelpy:SHBint9", + "padelpy:SHBint10", + "padelpy:SHsOH", + "padelpy:SHdNH", + "padelpy:SHsSH", + "padelpy:SHsNH2", + "padelpy:SHssNH", + "padelpy:SHaaNH", + "padelpy:SHsNH3p", + "padelpy:SHssNH2p", + "padelpy:SHsssNHp", + "padelpy:SHtCH", + "padelpy:SHdCH2", + "padelpy:SHdsCH", + "padelpy:SHaaCH", + "padelpy:SHCHnX", + "padelpy:SHCsats", + "padelpy:SHCsatu", + "padelpy:SHAvin", + "padelpy:SHother", + "padelpy:SHmisc", + "padelpy:SsLi", + "padelpy:SssBe", + "padelpy:SssssBem", + "padelpy:SsBH2", + "padelpy:SssBH", + "padelpy:SsssB", + "padelpy:SssssBm", + "padelpy:SsCH3", + "padelpy:SdCH2", + "padelpy:SssCH2", + "padelpy:StCH", + "padelpy:SdsCH", + "padelpy:SaaCH", + "padelpy:SsssCH", + "padelpy:SddC", + "padelpy:StsC", + "padelpy:SdssC", + "padelpy:SaasC", + "padelpy:SaaaC", + "padelpy:SssssC", + "padelpy:SsNH3p", + "padelpy:SsNH2", + "padelpy:SssNH2p", + "padelpy:SdNH", + "padelpy:SssNH", + "padelpy:SaaNH", + "padelpy:StN", + "padelpy:SsssNHp", + "padelpy:SdsN", + "padelpy:SaaN", + "padelpy:SsssN", + "padelpy:SddsN", + "padelpy:SaasN", + "padelpy:SssssNp", + "padelpy:SsOH", + "padelpy:SdO", + "padelpy:SssO", + "padelpy:SaaO", + "padelpy:SaOm", + "padelpy:SsOm", + "padelpy:SsF", + "padelpy:SsSiH3", + "padelpy:SssSiH2", + "padelpy:SsssSiH", + "padelpy:SssssSi", + "padelpy:SsPH2", + "padelpy:SssPH", + "padelpy:SsssP", + "padelpy:SdsssP", + "padelpy:SddsP", + "padelpy:SsssssP", + "padelpy:SsSH", + "padelpy:SdS", + "padelpy:SssS", + "padelpy:SaaS", + "padelpy:SdssS", + "padelpy:SddssS", + "padelpy:SssssssS", + "padelpy:SSm", + "padelpy:SsCl", + "padelpy:SsGeH3", + "padelpy:SssGeH2", + "padelpy:SsssGeH", + "padelpy:SssssGe", + "padelpy:SsAsH2", + "padelpy:SssAsH", + "padelpy:SsssAs", + "padelpy:SdsssAs", + "padelpy:SddsAs", + "padelpy:SsssssAs", + "padelpy:SsSeH", + "padelpy:SdSe", + "padelpy:SssSe", + "padelpy:SaaSe", + "padelpy:SdssSe", + "padelpy:SssssssSe", + "padelpy:SddssSe", + "padelpy:SsBr", + "padelpy:SsSnH3", + "padelpy:SssSnH2", + "padelpy:SsssSnH", + "padelpy:SssssSn", + "padelpy:SsI", + "padelpy:SsPbH3", + "padelpy:SssPbH2", + "padelpy:SsssPbH", + "padelpy:SssssPb", + "padelpy:minHBd", + "padelpy:minwHBd", + "padelpy:minHBa", + "padelpy:minwHBa", + "padelpy:minHBint2", + "padelpy:minHBint3", + "padelpy:minHBint4", + "padelpy:minHBint5", + "padelpy:minHBint6", + "padelpy:minHBint7", + "padelpy:minHBint8", + "padelpy:minHBint9", + "padelpy:minHBint10", + "padelpy:minHsOH", + "padelpy:minHdNH", + "padelpy:minHsSH", + "padelpy:minHsNH2", + "padelpy:minHssNH", + "padelpy:minHaaNH", + "padelpy:minHsNH3p", + "padelpy:minHssNH2p", + "padelpy:minHsssNHp", + "padelpy:minHtCH", + "padelpy:minHdCH2", + "padelpy:minHdsCH", + "padelpy:minHaaCH", + "padelpy:minHCHnX", + "padelpy:minHCsats", + "padelpy:minHCsatu", + "padelpy:minHAvin", + "padelpy:minHother", + "padelpy:minHmisc", + "padelpy:minsLi", + "padelpy:minssBe", + "padelpy:minssssBem", + "padelpy:minsBH2", + "padelpy:minssBH", + "padelpy:minsssB", + "padelpy:minssssBm", + "padelpy:minsCH3", + "padelpy:mindCH2", + "padelpy:minssCH2", + "padelpy:mintCH", + "padelpy:mindsCH", + "padelpy:minaaCH", + "padelpy:minsssCH", + "padelpy:minddC", + "padelpy:mintsC", + "padelpy:mindssC", + "padelpy:minaasC", + "padelpy:minaaaC", + "padelpy:minssssC", + "padelpy:minsNH3p", + "padelpy:minsNH2", + "padelpy:minssNH2p", + "padelpy:mindNH", + "padelpy:minssNH", + "padelpy:minaaNH", + "padelpy:mintN", + "padelpy:minsssNHp", + "padelpy:mindsN", + "padelpy:minaaN", + "padelpy:minsssN", + "padelpy:minddsN", + "padelpy:minaasN", + "padelpy:minssssNp", + "padelpy:minsOH", + "padelpy:mindO", + "padelpy:minssO", + "padelpy:minaaO", + "padelpy:minaOm", + "padelpy:minsOm", + "padelpy:minsF", + "padelpy:minsSiH3", + "padelpy:minssSiH2", + "padelpy:minsssSiH", + "padelpy:minssssSi", + "padelpy:minsPH2", + "padelpy:minssPH", + "padelpy:minsssP", + "padelpy:mindsssP", + "padelpy:minddsP", + "padelpy:minsssssP", + "padelpy:minsSH", + "padelpy:mindS", + "padelpy:minssS", + "padelpy:minaaS", + "padelpy:mindssS", + "padelpy:minddssS", + "padelpy:minssssssS", + "padelpy:minSm", + "padelpy:minsCl", + "padelpy:minsGeH3", + "padelpy:minssGeH2", + "padelpy:minsssGeH", + "padelpy:minssssGe", + "padelpy:minsAsH2", + "padelpy:minssAsH", + "padelpy:minsssAs", + "padelpy:mindsssAs", + "padelpy:minddsAs", + "padelpy:minsssssAs", + "padelpy:minsSeH", + "padelpy:mindSe", + "padelpy:minssSe", + "padelpy:minaaSe", + "padelpy:mindssSe", + "padelpy:minssssssSe", + "padelpy:minddssSe", + "padelpy:minsBr", + "padelpy:minsSnH3", + "padelpy:minssSnH2", + "padelpy:minsssSnH", + "padelpy:minssssSn", + "padelpy:minsI", + "padelpy:minsPbH3", + "padelpy:minssPbH2", + "padelpy:minsssPbH", + "padelpy:minssssPb", + "padelpy:maxHBd", + "padelpy:maxwHBd", + "padelpy:maxHBa", + "padelpy:maxwHBa", + "padelpy:maxHBint2", + "padelpy:maxHBint3", + "padelpy:maxHBint4", + "padelpy:maxHBint5", + "padelpy:maxHBint6", + "padelpy:maxHBint7", + "padelpy:maxHBint8", + "padelpy:maxHBint9", + "padelpy:maxHBint10", + "padelpy:maxHsOH", + "padelpy:maxHdNH", + "padelpy:maxHsSH", + "padelpy:maxHsNH2", + "padelpy:maxHssNH", + "padelpy:maxHaaNH", + "padelpy:maxHsNH3p", + "padelpy:maxHssNH2p", + "padelpy:maxHsssNHp", + "padelpy:maxHtCH", + "padelpy:maxHdCH2", + "padelpy:maxHdsCH", + "padelpy:maxHaaCH", + "padelpy:maxHCHnX", + "padelpy:maxHCsats", + "padelpy:maxHCsatu", + "padelpy:maxHAvin", + "padelpy:maxHother", + "padelpy:maxHmisc", + "padelpy:maxsLi", + "padelpy:maxssBe", + "padelpy:maxssssBem", + "padelpy:maxsBH2", + "padelpy:maxssBH", + "padelpy:maxsssB", + "padelpy:maxssssBm", + "padelpy:maxsCH3", + "padelpy:maxdCH2", + "padelpy:maxssCH2", + "padelpy:maxtCH", + "padelpy:maxdsCH", + "padelpy:maxaaCH", + "padelpy:maxsssCH", + "padelpy:maxddC", + "padelpy:maxtsC", + "padelpy:maxdssC", + "padelpy:maxaasC", + "padelpy:maxaaaC", + "padelpy:maxssssC", + "padelpy:maxsNH3p", + "padelpy:maxsNH2", + "padelpy:maxssNH2p", + "padelpy:maxdNH", + "padelpy:maxssNH", + "padelpy:maxaaNH", + "padelpy:maxtN", + "padelpy:maxsssNHp", + "padelpy:maxdsN", + "padelpy:maxaaN", + "padelpy:maxsssN", + "padelpy:maxddsN", + "padelpy:maxaasN", + "padelpy:maxssssNp", + "padelpy:maxsOH", + "padelpy:maxdO", + "padelpy:maxssO", + "padelpy:maxaaO", + "padelpy:maxaOm", + "padelpy:maxsOm", + "padelpy:maxsF", + "padelpy:maxsSiH3", + "padelpy:maxssSiH2", + "padelpy:maxsssSiH", + "padelpy:maxssssSi", + "padelpy:maxsPH2", + "padelpy:maxssPH", + "padelpy:maxsssP", + "padelpy:maxdsssP", + "padelpy:maxddsP", + "padelpy:maxsssssP", + "padelpy:maxsSH", + "padelpy:maxdS", + "padelpy:maxssS", + "padelpy:maxaaS", + "padelpy:maxdssS", + "padelpy:maxddssS", + "padelpy:maxssssssS", + "padelpy:maxSm", + "padelpy:maxsCl", + "padelpy:maxsGeH3", + "padelpy:maxssGeH2", + "padelpy:maxsssGeH", + "padelpy:maxssssGe", + "padelpy:maxsAsH2", + "padelpy:maxssAsH", + "padelpy:maxsssAs", + "padelpy:maxdsssAs", + "padelpy:maxddsAs", + "padelpy:maxsssssAs", + "padelpy:maxsSeH", + "padelpy:maxdSe", + "padelpy:maxssSe", + "padelpy:maxaaSe", + "padelpy:maxdssSe", + "padelpy:maxssssssSe", + "padelpy:maxddssSe", + "padelpy:maxsBr", + "padelpy:maxsSnH3", + "padelpy:maxssSnH2", + "padelpy:maxsssSnH", + "padelpy:maxssssSn", + "padelpy:maxsI", + "padelpy:maxsPbH3", + "padelpy:maxssPbH2", + "padelpy:maxsssPbH", + "padelpy:maxssssPb", + "padelpy:sumI", + "padelpy:meanI", + "padelpy:hmax", + "padelpy:gmax", + "padelpy:hmin", + "padelpy:gmin", + "padelpy:LipoaffinityIndex", + "padelpy:MAXDN", + "padelpy:MAXDP", + "padelpy:DELS", + "padelpy:MAXDN2", + "padelpy:MAXDP2", + "padelpy:DELS2", + "padelpy:ETA_Alpha", + "padelpy:ETA_AlphaP", + "padelpy:ETA_dAlpha_A", + "padelpy:ETA_dAlpha_B", + "padelpy:ETA_Epsilon_1", + "padelpy:ETA_Epsilon_2", + "padelpy:ETA_Epsilon_3", + "padelpy:ETA_Epsilon_4", + "padelpy:ETA_Epsilon_5", + "padelpy:ETA_dEpsilon_A", + "padelpy:ETA_dEpsilon_B", + "padelpy:ETA_dEpsilon_C", + "padelpy:ETA_dEpsilon_D", + "padelpy:ETA_Psi_1", + "padelpy:ETA_dPsi_A", + "padelpy:ETA_dPsi_B", + "padelpy:ETA_Shape_P", + "padelpy:ETA_Shape_Y", + "padelpy:ETA_Shape_X", + "padelpy:ETA_Beta", + "padelpy:ETA_BetaP", + "padelpy:ETA_Beta_s", + "padelpy:ETA_BetaP_s", + "padelpy:ETA_Beta_ns", + "padelpy:ETA_BetaP_ns", + "padelpy:ETA_dBeta", + "padelpy:ETA_dBetaP", + "padelpy:ETA_Beta_ns_d", + "padelpy:ETA_BetaP_ns_d", + "padelpy:ETA_Eta", + "padelpy:ETA_EtaP", + "padelpy:ETA_Eta_R", + "padelpy:ETA_Eta_F", + "padelpy:ETA_EtaP_F", + "padelpy:ETA_Eta_L", + "padelpy:ETA_EtaP_L", + "padelpy:ETA_Eta_R_L", + "padelpy:ETA_Eta_F_L", + "padelpy:ETA_EtaP_F_L", + "padelpy:ETA_Eta_B", + "padelpy:ETA_EtaP_B", + "padelpy:ETA_Eta_B_RC", + "padelpy:ETA_EtaP_B_RC", + "padelpy:FMF", + "padelpy:fragC", + "padelpy:nHBAcc", + "padelpy:nHBAcc2", + "padelpy:nHBAcc3", + "padelpy:nHBAcc_Lipinski", + "padelpy:nHBDon", + "padelpy:nHBDon_Lipinski", + "padelpy:HybRatio", + "padelpy:IC0", + "padelpy:IC1", + "padelpy:IC2", + "padelpy:IC3", + "padelpy:IC4", + "padelpy:IC5", + "padelpy:TIC0", + "padelpy:TIC1", + "padelpy:TIC2", + "padelpy:TIC3", + "padelpy:TIC4", + "padelpy:TIC5", + "padelpy:SIC0", + "padelpy:SIC1", + "padelpy:SIC2", + "padelpy:SIC3", + "padelpy:SIC4", + "padelpy:SIC5", + "padelpy:CIC0", + "padelpy:CIC1", + "padelpy:CIC2", + "padelpy:CIC3", + "padelpy:CIC4", + "padelpy:CIC5", + "padelpy:BIC0", + "padelpy:BIC1", + "padelpy:BIC2", + "padelpy:BIC3", + "padelpy:BIC4", + "padelpy:BIC5", + "padelpy:MIC0", + "padelpy:MIC1", + "padelpy:MIC2", + "padelpy:MIC3", + "padelpy:MIC4", + "padelpy:MIC5", + "padelpy:ZMIC0", + "padelpy:ZMIC1", + "padelpy:ZMIC2", + "padelpy:ZMIC3", + "padelpy:ZMIC4", + "padelpy:ZMIC5", + "padelpy:Kier1", + "padelpy:Kier2", + "padelpy:Kier3", + "padelpy:nAtomLC", + "padelpy:nAtomP", + "padelpy:nAtomLAC", + "padelpy:MLogP", + "padelpy:McGowan_Volume", + "padelpy:MDEC-11", + "padelpy:MDEC-12", + "padelpy:MDEC-13", + "padelpy:MDEC-14", + "padelpy:MDEC-22", + "padelpy:MDEC-23", + "padelpy:MDEC-24", + "padelpy:MDEC-33", + "padelpy:MDEC-34", + "padelpy:MDEC-44", + "padelpy:MDEO-11", + "padelpy:MDEO-12", + "padelpy:MDEO-22", + "padelpy:MDEN-11", + "padelpy:MDEN-12", + "padelpy:MDEN-13", + "padelpy:MDEN-22", + "padelpy:MDEN-23", + "padelpy:MDEN-33", + "padelpy:MLFER_A", + "padelpy:MLFER_BH", + "padelpy:MLFER_BO", + "padelpy:MLFER_S", + "padelpy:MLFER_E", + "padelpy:MLFER_L", + "padelpy:MPC2", + "padelpy:MPC3", + "padelpy:MPC4", + "padelpy:MPC5", + "padelpy:MPC6", + "padelpy:MPC7", + "padelpy:MPC8", + "padelpy:MPC9", + "padelpy:MPC10", + "padelpy:TPC", + "padelpy:piPC1", + "padelpy:piPC2", + "padelpy:piPC3", + "padelpy:piPC4", + "padelpy:piPC5", + "padelpy:piPC6", + "padelpy:piPC7", + "padelpy:piPC8", + "padelpy:piPC9", + "padelpy:piPC10", + "padelpy:TpiPC", + "padelpy:R_TpiPCTPC", + "padelpy:PetitjeanNumber", + "padelpy:nRing", + "padelpy:n3Ring", + "padelpy:n4Ring", + "padelpy:n5Ring", + "padelpy:n6Ring", + "padelpy:n7Ring", + "padelpy:n8Ring", + "padelpy:n9Ring", + "padelpy:n10Ring", + "padelpy:n11Ring", + "padelpy:n12Ring", + "padelpy:nG12Ring", + "padelpy:nFRing", + "padelpy:nF4Ring", + "padelpy:nF5Ring", + "padelpy:nF6Ring", + "padelpy:nF7Ring", + "padelpy:nF8Ring", + "padelpy:nF9Ring", + "padelpy:nF10Ring", + "padelpy:nF11Ring", + "padelpy:nF12Ring", + "padelpy:nFG12Ring", + "padelpy:nTRing", + "padelpy:nT4Ring", + "padelpy:nT5Ring", + "padelpy:nT6Ring", + "padelpy:nT7Ring", + "padelpy:nT8Ring", + "padelpy:nT9Ring", + "padelpy:nT10Ring", + "padelpy:nT11Ring", + "padelpy:nT12Ring", + "padelpy:nTG12Ring", + "padelpy:nHeteroRing", + "padelpy:n3HeteroRing", + "padelpy:n4HeteroRing", + "padelpy:n5HeteroRing", + "padelpy:n6HeteroRing", + "padelpy:n7HeteroRing", + "padelpy:n8HeteroRing", + "padelpy:n9HeteroRing", + "padelpy:n10HeteroRing", + "padelpy:n11HeteroRing", + "padelpy:n12HeteroRing", + "padelpy:nG12HeteroRing", + "padelpy:nFHeteroRing", + "padelpy:nF4HeteroRing", + "padelpy:nF5HeteroRing", + "padelpy:nF6HeteroRing", + "padelpy:nF7HeteroRing", + "padelpy:nF8HeteroRing", + "padelpy:nF9HeteroRing", + "padelpy:nF10HeteroRing", + "padelpy:nF11HeteroRing", + "padelpy:nF12HeteroRing", + "padelpy:nFG12HeteroRing", + "padelpy:nTHeteroRing", + "padelpy:nT4HeteroRing", + "padelpy:nT5HeteroRing", + "padelpy:nT6HeteroRing", + "padelpy:nT7HeteroRing", + "padelpy:nT8HeteroRing", + "padelpy:nT9HeteroRing", + "padelpy:nT10HeteroRing", + "padelpy:nT11HeteroRing", + "padelpy:nT12HeteroRing", + "padelpy:nTG12HeteroRing", + "padelpy:nRotB", + "padelpy:RotBFrac", + "padelpy:nRotBt", + "padelpy:RotBtFrac", + "padelpy:LipinskiFailures", + "padelpy:topoRadius", + "padelpy:topoDiameter", + "padelpy:topoShape", + "padelpy:GGI1", + "padelpy:GGI2", + "padelpy:GGI3", + "padelpy:GGI4", + "padelpy:GGI5", + "padelpy:GGI6", + "padelpy:GGI7", + "padelpy:GGI8", + "padelpy:GGI9", + "padelpy:GGI10", + "padelpy:JGI1", + "padelpy:JGI2", + "padelpy:JGI3", + "padelpy:JGI4", + "padelpy:JGI5", + "padelpy:JGI6", + "padelpy:JGI7", + "padelpy:JGI8", + "padelpy:JGI9", + "padelpy:JGI10", + "padelpy:JGT", + "padelpy:SpMax_D", + "padelpy:SpDiam_D", + "padelpy:SpAD_D", + "padelpy:SpMAD_D", + "padelpy:EE_D", + "padelpy:VE1_D", + "padelpy:VE2_D", + "padelpy:VE3_D", + "padelpy:VR1_D", + "padelpy:VR2_D", + "padelpy:VR3_D", + "padelpy:TopoPSA", + "padelpy:VABC", + "padelpy:VAdjMat", + "padelpy:MWC2", + "padelpy:MWC3", + "padelpy:MWC4", + "padelpy:MWC5", + "padelpy:MWC6", + "padelpy:MWC7", + "padelpy:MWC8", + "padelpy:MWC9", + "padelpy:MWC10", + "padelpy:TWC", + "padelpy:SRW2", + "padelpy:SRW3", + "padelpy:SRW4", + "padelpy:SRW5", + "padelpy:SRW6", + "padelpy:SRW7", + "padelpy:SRW8", + "padelpy:SRW9", + "padelpy:SRW10", + "padelpy:TSRW", + "padelpy:MW", + "padelpy:AMW", + "padelpy:WTPT-1", + "padelpy:WTPT-2", + "padelpy:WTPT-3", + "padelpy:WTPT-4", + "padelpy:WTPT-5", + "padelpy:WPATH", + "padelpy:WPOL", + "padelpy:XLogP", + "padelpy:Zagreb", + "padelpy:TDB1u", + "padelpy:TDB2u", + "padelpy:TDB3u", + "padelpy:TDB4u", + "padelpy:TDB5u", + "padelpy:TDB6u", + "padelpy:TDB7u", + "padelpy:TDB8u", + "padelpy:TDB9u", + "padelpy:TDB10u", + "padelpy:TDB1m", + "padelpy:TDB2m", + "padelpy:TDB3m", + "padelpy:TDB4m", + "padelpy:TDB5m", + "padelpy:TDB6m", + "padelpy:TDB7m", + "padelpy:TDB8m", + "padelpy:TDB9m", + "padelpy:TDB10m", + "padelpy:TDB1v", + "padelpy:TDB2v", + "padelpy:TDB3v", + "padelpy:TDB4v", + "padelpy:TDB5v", + "padelpy:TDB6v", + "padelpy:TDB7v", + "padelpy:TDB8v", + "padelpy:TDB9v", + "padelpy:TDB10v", + "padelpy:TDB1e", + "padelpy:TDB2e", + "padelpy:TDB3e", + "padelpy:TDB4e", + "padelpy:TDB5e", + "padelpy:TDB6e", + "padelpy:TDB7e", + "padelpy:TDB8e", + "padelpy:TDB9e", + "padelpy:TDB10e", + "padelpy:TDB1p", + "padelpy:TDB2p", + "padelpy:TDB3p", + "padelpy:TDB4p", + "padelpy:TDB5p", + "padelpy:TDB6p", + "padelpy:TDB7p", + "padelpy:TDB8p", + "padelpy:TDB9p", + "padelpy:TDB10p", + "padelpy:TDB1i", + "padelpy:TDB2i", + "padelpy:TDB3i", + "padelpy:TDB4i", + "padelpy:TDB5i", + "padelpy:TDB6i", + "padelpy:TDB7i", + "padelpy:TDB8i", + "padelpy:TDB9i", + "padelpy:TDB10i", + "padelpy:TDB1s", + "padelpy:TDB2s", + "padelpy:TDB3s", + "padelpy:TDB4s", + "padelpy:TDB5s", + "padelpy:TDB6s", + "padelpy:TDB7s", + "padelpy:TDB8s", + "padelpy:TDB9s", + "padelpy:TDB10s", + "padelpy:TDB1r", + "padelpy:TDB2r", + "padelpy:TDB3r", + "padelpy:TDB4r", + "padelpy:TDB5r", + "padelpy:TDB6r", + "padelpy:TDB7r", + "padelpy:TDB8r", + "padelpy:TDB9r", + "padelpy:TDB10r", + "padelpy:PPSA-1", + "padelpy:PPSA-2", + "padelpy:PPSA-3", + "padelpy:PNSA-1", + "padelpy:PNSA-2", + "padelpy:PNSA-3", + "padelpy:DPSA-1", + "padelpy:DPSA-2", + "padelpy:DPSA-3", + "padelpy:FPSA-1", + "padelpy:FPSA-2", + "padelpy:FPSA-3", + "padelpy:FNSA-1", + "padelpy:FNSA-2", + "padelpy:FNSA-3", + "padelpy:WPSA-1", + "padelpy:WPSA-2", + "padelpy:WPSA-3", + "padelpy:WNSA-1", + "padelpy:WNSA-2", + "padelpy:WNSA-3", + "padelpy:RPCG", + "padelpy:RNCG", + "padelpy:RPCS", + "padelpy:RNCS", + "padelpy:THSA", + "padelpy:TPSA", + "padelpy:RHSA", + "padelpy:RPSA", + "padelpy:GRAV-1", + "padelpy:GRAV-2", + "padelpy:GRAV-3", + "padelpy:GRAVH-1", + "padelpy:GRAVH-2", + "padelpy:GRAVH-3", + "padelpy:GRAV-4", + "padelpy:GRAV-5", + "padelpy:GRAV-6", + "padelpy:LOBMAX", + "padelpy:LOBMIN", + "padelpy:MOMI-X", + "padelpy:MOMI-Y", + "padelpy:MOMI-Z", + "padelpy:MOMI-XY", + "padelpy:MOMI-XZ", + "padelpy:MOMI-YZ", + "padelpy:MOMI-R", + "padelpy:geomRadius", + "padelpy:geomDiameter", + "padelpy:geomShape", + "padelpy:RDF10u", + "padelpy:RDF15u", + "padelpy:RDF20u", + "padelpy:RDF25u", + "padelpy:RDF30u", + "padelpy:RDF35u", + "padelpy:RDF40u", + "padelpy:RDF45u", + "padelpy:RDF50u", + "padelpy:RDF55u", + "padelpy:RDF60u", + "padelpy:RDF65u", + "padelpy:RDF70u", + "padelpy:RDF75u", + "padelpy:RDF80u", + "padelpy:RDF85u", + "padelpy:RDF90u", + "padelpy:RDF95u", + "padelpy:RDF100u", + "padelpy:RDF105u", + "padelpy:RDF110u", + "padelpy:RDF115u", + "padelpy:RDF120u", + "padelpy:RDF125u", + "padelpy:RDF130u", + "padelpy:RDF135u", + "padelpy:RDF140u", + "padelpy:RDF145u", + "padelpy:RDF150u", + "padelpy:RDF155u", + "padelpy:RDF10m", + "padelpy:RDF15m", + "padelpy:RDF20m", + "padelpy:RDF25m", + "padelpy:RDF30m", + "padelpy:RDF35m", + "padelpy:RDF40m", + "padelpy:RDF45m", + "padelpy:RDF50m", + "padelpy:RDF55m", + "padelpy:RDF60m", + "padelpy:RDF65m", + "padelpy:RDF70m", + "padelpy:RDF75m", + "padelpy:RDF80m", + "padelpy:RDF85m", + "padelpy:RDF90m", + "padelpy:RDF95m", + "padelpy:RDF100m", + "padelpy:RDF105m", + "padelpy:RDF110m", + "padelpy:RDF115m", + "padelpy:RDF120m", + "padelpy:RDF125m", + "padelpy:RDF130m", + "padelpy:RDF135m", + "padelpy:RDF140m", + "padelpy:RDF145m", + "padelpy:RDF150m", + "padelpy:RDF155m", + "padelpy:RDF10v", + "padelpy:RDF15v", + "padelpy:RDF20v", + "padelpy:RDF25v", + "padelpy:RDF30v", + "padelpy:RDF35v", + "padelpy:RDF40v", + "padelpy:RDF45v", + "padelpy:RDF50v", + "padelpy:RDF55v", + "padelpy:RDF60v", + "padelpy:RDF65v", + "padelpy:RDF70v", + "padelpy:RDF75v", + "padelpy:RDF80v", + "padelpy:RDF85v", + "padelpy:RDF90v", + "padelpy:RDF95v", + "padelpy:RDF100v", + "padelpy:RDF105v", + "padelpy:RDF110v", + "padelpy:RDF115v", + "padelpy:RDF120v", + "padelpy:RDF125v", + "padelpy:RDF130v", + "padelpy:RDF135v", + "padelpy:RDF140v", + "padelpy:RDF145v", + "padelpy:RDF150v", + "padelpy:RDF155v", + "padelpy:RDF10e", + "padelpy:RDF15e", + "padelpy:RDF20e", + "padelpy:RDF25e", + "padelpy:RDF30e", + "padelpy:RDF35e", + "padelpy:RDF40e", + "padelpy:RDF45e", + "padelpy:RDF50e", + "padelpy:RDF55e", + "padelpy:RDF60e", + "padelpy:RDF65e", + "padelpy:RDF70e", + "padelpy:RDF75e", + "padelpy:RDF80e", + "padelpy:RDF85e", + "padelpy:RDF90e", + "padelpy:RDF95e", + "padelpy:RDF100e", + "padelpy:RDF105e", + "padelpy:RDF110e", + "padelpy:RDF115e", + "padelpy:RDF120e", + "padelpy:RDF125e", + "padelpy:RDF130e", + "padelpy:RDF135e", + "padelpy:RDF140e", + "padelpy:RDF145e", + "padelpy:RDF150e", + "padelpy:RDF155e", + "padelpy:RDF10p", + "padelpy:RDF15p", + "padelpy:RDF20p", + "padelpy:RDF25p", + "padelpy:RDF30p", + "padelpy:RDF35p", + "padelpy:RDF40p", + "padelpy:RDF45p", + "padelpy:RDF50p", + "padelpy:RDF55p", + "padelpy:RDF60p", + "padelpy:RDF65p", + "padelpy:RDF70p", + "padelpy:RDF75p", + "padelpy:RDF80p", + "padelpy:RDF85p", + "padelpy:RDF90p", + "padelpy:RDF95p", + "padelpy:RDF100p", + "padelpy:RDF105p", + "padelpy:RDF110p", + "padelpy:RDF115p", + "padelpy:RDF120p", + "padelpy:RDF125p", + "padelpy:RDF130p", + "padelpy:RDF135p", + "padelpy:RDF140p", + "padelpy:RDF145p", + "padelpy:RDF150p", + "padelpy:RDF155p", + "padelpy:RDF10i", + "padelpy:RDF15i", + "padelpy:RDF20i", + "padelpy:RDF25i", + "padelpy:RDF30i", + "padelpy:RDF35i", + "padelpy:RDF40i", + "padelpy:RDF45i", + "padelpy:RDF50i", + "padelpy:RDF55i", + "padelpy:RDF60i", + "padelpy:RDF65i", + "padelpy:RDF70i", + "padelpy:RDF75i", + "padelpy:RDF80i", + "padelpy:RDF85i", + "padelpy:RDF90i", + "padelpy:RDF95i", + "padelpy:RDF100i", + "padelpy:RDF105i", + "padelpy:RDF110i", + "padelpy:RDF115i", + "padelpy:RDF120i", + "padelpy:RDF125i", + "padelpy:RDF130i", + "padelpy:RDF135i", + "padelpy:RDF140i", + "padelpy:RDF145i", + "padelpy:RDF150i", + "padelpy:RDF155i", + "padelpy:RDF10s", + "padelpy:RDF15s", + "padelpy:RDF20s", + "padelpy:RDF25s", + "padelpy:RDF30s", + "padelpy:RDF35s", + "padelpy:RDF40s", + "padelpy:RDF45s", + "padelpy:RDF50s", + "padelpy:RDF55s", + "padelpy:RDF60s", + "padelpy:RDF65s", + "padelpy:RDF70s", + "padelpy:RDF75s", + "padelpy:RDF80s", + "padelpy:RDF85s", + "padelpy:RDF90s", + "padelpy:RDF95s", + "padelpy:RDF100s", + "padelpy:RDF105s", + "padelpy:RDF110s", + "padelpy:RDF115s", + "padelpy:RDF120s", + "padelpy:RDF125s", + "padelpy:RDF130s", + "padelpy:RDF135s", + "padelpy:RDF140s", + "padelpy:RDF145s", + "padelpy:RDF150s", + "padelpy:RDF155s", + "padelpy:L1u", + "padelpy:L2u", + "padelpy:L3u", + "padelpy:P1u", + "padelpy:P2u", + "padelpy:E1u", + "padelpy:E2u", + "padelpy:E3u", + "padelpy:Tu", + "padelpy:Au", + "padelpy:Vu", + "padelpy:Ku", + "padelpy:Du", + "padelpy:L1m", + "padelpy:L2m", + "padelpy:L3m", + "padelpy:P1m", + "padelpy:P2m", + "padelpy:E1m", + "padelpy:E2m", + "padelpy:E3m", + "padelpy:Tm", + "padelpy:Am", + "padelpy:Vm", + "padelpy:Km", + "padelpy:Dm", + "padelpy:L1v", + "padelpy:L2v", + "padelpy:L3v", + "padelpy:P1v", + "padelpy:P2v", + "padelpy:E1v", + "padelpy:E2v", + "padelpy:E3v", + "padelpy:Tv", + "padelpy:Av", + "padelpy:Vv", + "padelpy:Kv", + "padelpy:Dv", + "padelpy:L1e", + "padelpy:L2e", + "padelpy:L3e", + "padelpy:P1e", + "padelpy:P2e", + "padelpy:E1e", + "padelpy:E2e", + "padelpy:E3e", + "padelpy:Te", + "padelpy:Ae", + "padelpy:Ve", + "padelpy:Ke", + "padelpy:De", + "padelpy:L1p", + "padelpy:L2p", + "padelpy:L3p", + "padelpy:P1p", + "padelpy:P2p", + "padelpy:E1p", + "padelpy:E2p", + "padelpy:E3p", + "padelpy:Tp", + "padelpy:Ap", + "padelpy:Vp", + "padelpy:Kp", + "padelpy:Dp", + "padelpy:L1i", + "padelpy:L2i", + "padelpy:L3i", + "padelpy:P1i", + "padelpy:P2i", + "padelpy:E1i", + "padelpy:E2i", + "padelpy:E3i", + "padelpy:Ti", + "padelpy:Ai", + "padelpy:Vi", + "padelpy:Ki", + "padelpy:Di", + "padelpy:L1s", + "padelpy:L2s", + "padelpy:L3s", + "padelpy:P1s", + "padelpy:P2s", + "padelpy:E1s", + "padelpy:E2s", + "padelpy:E3s", + "padelpy:Ts", + "padelpy:As", + "padelpy:Vs", + "padelpy:Ks", + "padelpy:Ds", ] diff --git a/tests/test_Descriptor.py b/tests/test_Descriptor.py index b700480b..a503aedf 100644 --- a/tests/test_Descriptor.py +++ b/tests/test_Descriptor.py @@ -5,6 +5,7 @@ from rdkit.Chem import MolFromSmiles from aimsim.ops import Descriptor from aimsim.exceptions import MordredCalculatorError, InvalidConfigurationError +from aimsim.utils.extras import requries_mordred SUPPORTED_FPRINTS = Descriptor.get_supported_fprints() @@ -77,8 +78,7 @@ def test_descriptor_arbitrary_numpy_init(self): 'arbitrary vector to be "arbitrary"', ) self.assertIsInstance( - descriptor.to_numpy(), np.ndarray, - "Expected numpy.ndarray from to_numpy()" + descriptor.to_numpy(), np.ndarray, "Expected numpy.ndarray from to_numpy()" ) self.assertTrue( (descriptor.to_numpy() == descriptor_value).all(), @@ -88,47 +88,44 @@ def test_descriptor_arbitrary_numpy_init(self): descriptor.to_rdkit() def test_topological_fprint_min_path_lesser_than_atoms(self): - atomic_mols = [MolFromSmiles(smiles) - for smiles in ['C', 'O', 'N', 'P']] - diatomic_mols = [MolFromSmiles(smiles) for smiles in ['CC', - 'CO', - 'CN', - 'CP']] - triatomic_mols = [MolFromSmiles(smiles) for smiles in ['CCC', - 'COO', - 'CCN', - 'CCP']] + atomic_mols = [MolFromSmiles(smiles) for smiles in ["C", "O", "N", "P"]] + diatomic_mols = [MolFromSmiles(smiles) for smiles in ["CC", "CO", "CN", "CP"]] + triatomic_mols = [ + MolFromSmiles(smiles) for smiles in ["CCC", "COO", "CCN", "CCP"] + ] min_path = 1 for mol in atomic_mols: with self.assertRaises(InvalidConfigurationError): descriptor = Descriptor() descriptor.make_fingerprint( molecule_graph=mol, - fingerprint_type='topological_fingerprint', - fingerprint_params={'min_path': min_path} + fingerprint_type="topological_fingerprint", + fingerprint_params={"min_path": min_path}, ) for diatomic_mol in diatomic_mols: descriptor = Descriptor() try: descriptor.make_fingerprint( molecule_graph=diatomic_mol, - fingerprint_type='topological_fingerprint', - fingerprint_params={'min_path': min_path} + fingerprint_type="topological_fingerprint", + fingerprint_params={"min_path": min_path}, ) except InvalidConfigurationError: - self.fail("Did not expect Descriptor to raise " - "InvalidConfigurationError") + self.fail( + "Did not expect Descriptor to raise " "InvalidConfigurationError" + ) for triatomic_mol in triatomic_mols: descriptor = Descriptor() try: descriptor.make_fingerprint( molecule_graph=triatomic_mol, - fingerprint_type='topological_fingerprint', - fingerprint_params={'min_path': min_path} + fingerprint_type="topological_fingerprint", + fingerprint_params={"min_path": min_path}, ) except InvalidConfigurationError: - self.fail("Did not expect Descriptor to raise " - "InvalidConfigurationError") + self.fail( + "Did not expect Descriptor to raise " "InvalidConfigurationError" + ) min_path = 2 for mol in atomic_mols: @@ -136,28 +133,29 @@ def test_topological_fprint_min_path_lesser_than_atoms(self): descriptor = Descriptor() descriptor.make_fingerprint( molecule_graph=mol, - fingerprint_type='topological_fingerprint', - fingerprint_params={'min_path': min_path} + fingerprint_type="topological_fingerprint", + fingerprint_params={"min_path": min_path}, ) for diatomic_mol in diatomic_mols: with self.assertRaises(InvalidConfigurationError): descriptor = Descriptor() descriptor.make_fingerprint( molecule_graph=diatomic_mol, - fingerprint_type='topological_fingerprint', - fingerprint_params={'min_path': min_path} + fingerprint_type="topological_fingerprint", + fingerprint_params={"min_path": min_path}, ) for triatomic_mol in triatomic_mols: descriptor = Descriptor() try: descriptor.make_fingerprint( molecule_graph=triatomic_mol, - fingerprint_type='topological_fingerprint', - fingerprint_params={'min_path': min_path} + fingerprint_type="topological_fingerprint", + fingerprint_params={"min_path": min_path}, ) except InvalidConfigurationError: - self.fail("Did not expect Descriptor to raise " - "InvalidConfigurationError") + self.fail( + "Did not expect Descriptor to raise " "InvalidConfigurationError" + ) min_path = 3 for mol in atomic_mols: @@ -165,24 +163,24 @@ def test_topological_fprint_min_path_lesser_than_atoms(self): descriptor = Descriptor() descriptor.make_fingerprint( molecule_graph=mol, - fingerprint_type='topological_fingerprint', - fingerprint_params={'min_path': min_path} + fingerprint_type="topological_fingerprint", + fingerprint_params={"min_path": min_path}, ) for diatomic_mol in diatomic_mols: with self.assertRaises(InvalidConfigurationError): descriptor = Descriptor() descriptor.make_fingerprint( molecule_graph=diatomic_mol, - fingerprint_type='topological_fingerprint', - fingerprint_params={'min_path': min_path} + fingerprint_type="topological_fingerprint", + fingerprint_params={"min_path": min_path}, ) for triatomic_mol in triatomic_mols: with self.assertRaises(InvalidConfigurationError): descriptor = Descriptor() descriptor.make_fingerprint( molecule_graph=triatomic_mol, - fingerprint_type='topological_fingerprint', - fingerprint_params={'min_path': min_path} + fingerprint_type="topological_fingerprint", + fingerprint_params={"min_path": min_path}, ) def test_descriptor_make_fingerprint(self): @@ -220,6 +218,7 @@ def test_descriptor_make_fingerprint(self): f"of {fprint} fingerprint", ) + @requires_mordred def test_mordred_descriptors(self): """Test ability to passthrough descriptors to Mordred.""" mol_graph = MolFromSmiles( @@ -250,9 +249,7 @@ def test_mordred_descriptors(self): def test_padelpy_descriptors(self): """Test ability to passthrough descriptors to PadelPy.""" - mol_graph = MolFromSmiles( - "CCOCC" - ) + mol_graph = MolFromSmiles("CCOCC") for desc in ["MATS7e", "Ti", "ATSC6p"]: descriptor = Descriptor() descriptor.make_fingerprint( @@ -278,9 +275,7 @@ def test_padelpy_descriptors(self): def test_ccbmlib_descriptors(self): """Test ability to passthrough descriptors to ccbmlib.""" - mol_graph = MolFromSmiles( - "CCOCC" - ) + mol_graph = MolFromSmiles("CCOCC") fprint_list = [ "atom_pairs", "hashed_atom_pairs", @@ -310,9 +305,7 @@ def test_ccbmlib_descriptors(self): def test_exptl_descriptors(self): """Test ability to use experimental descriptors.""" - mol_graph = MolFromSmiles( - "CCOCC" - ) + mol_graph = MolFromSmiles("CCOCC") fprint_list = [ "maccs_keys", "atom-pair_fingerprint", @@ -320,9 +313,7 @@ def test_exptl_descriptors(self): ] for desc in fprint_list: descriptor = Descriptor() - descriptor.make_fingerprint( - molecule_graph=mol_graph, fingerprint_type=desc - ) + descriptor.make_fingerprint(molecule_graph=mol_graph, fingerprint_type=desc) self.assertTrue( descriptor.check_init(), "Expected Descriptor object to be initialized", @@ -334,6 +325,7 @@ def test_exptl_descriptors(self): "{} to match the fingerprint".format(desc), ) + @requries_mordred def test_nonexistent_mordred_descriptors(self): """Test ability to pass through descriptors to Mordred.""" mol_graph = MolFromSmiles("C") @@ -354,14 +346,14 @@ def test_bad_descriptors_padelpy_descriptors(self): descriptor.make_fingerprint( molecule_graph=mol_graph, fingerprint_type="padelpy:" + desc, - fingerprint_params={'timeout': 2}, + fingerprint_params={"timeout": 2}, ) def test_fingerprint_folding(self): """Create arbitrary fingerprint vector to check fold method""" # Case 1 arbit_vector = np.array([1, 1, 1, 1, 1, 1, 1, 1, 1, 1]) - arbit_label = 'arbitrary' + arbit_label = "arbitrary" desc = Descriptor() desc.label_ = arbit_label desc.numpy_ = arbit_vector @@ -371,7 +363,7 @@ def test_fingerprint_folding(self): # Case 2 arbit_vector = np.array([1, 0, 1, 0, 1, 0]) folded_vector = np.array([1, 1, 1]) - arbit_label = 'arbitrary_fingerprint' + arbit_label = "arbitrary_fingerprint" desc = Descriptor() desc.label_ = arbit_label desc.numpy_ = arbit_vector @@ -379,14 +371,15 @@ def test_fingerprint_folding(self): desc.get_folded_fprint(fold_to_length=4) with self.assertRaises(InvalidConfigurationError): desc.get_folded_fprint(fold_to_length=10) - self.assertTrue(((desc.get_folded_fprint(fold_to_length=3) - == folded_vector).all())) + self.assertTrue( + ((desc.get_folded_fprint(fold_to_length=3) == folded_vector).all()) + ) # Case 3 arbit_vector = np.array([1, 0, 1, 0, 0, 0, 0, 0]) folded_once_vector = np.array([1, 0, 1, 0]) folded_twice_vector = np.array([1, 0]) - arbit_label = 'arbitrary_fingerprint' + arbit_label = "arbitrary_fingerprint" desc = Descriptor() desc.label_ = arbit_label desc.numpy_ = arbit_vector @@ -394,16 +387,18 @@ def test_fingerprint_folding(self): desc.get_folded_fprint(fold_to_length=3) with self.assertRaises(InvalidConfigurationError): desc.get_folded_fprint(fold_to_length=10) - self.assertTrue(((desc.get_folded_fprint(fold_to_length=4) - == folded_once_vector).all())) - self.assertTrue(((desc.get_folded_fprint(fold_to_length=2) - == folded_twice_vector).all())) + self.assertTrue( + ((desc.get_folded_fprint(fold_to_length=4) == folded_once_vector).all()) + ) + self.assertTrue( + ((desc.get_folded_fprint(fold_to_length=2) == folded_twice_vector).all()) + ) # Case 3 arbit_vector = np.array([0, 0, 0, 0, 0, 0, 0, 0]) folded_once_vector = np.array([0, 0, 0, 0]) folded_twice_vector = np.array([0, 0]) - arbit_label = 'arbitrary_fingerprint' + arbit_label = "arbitrary_fingerprint" desc = Descriptor() desc.label_ = arbit_label desc.numpy_ = arbit_vector @@ -411,16 +406,18 @@ def test_fingerprint_folding(self): desc.get_folded_fprint(fold_to_length=3) with self.assertRaises(InvalidConfigurationError): desc.get_folded_fprint(fold_to_length=10) - self.assertTrue(((desc.get_folded_fprint(fold_to_length=4) - == folded_once_vector).all())) - self.assertTrue(((desc.get_folded_fprint(fold_to_length=2) - == folded_twice_vector).all())) + self.assertTrue( + ((desc.get_folded_fprint(fold_to_length=4) == folded_once_vector).all()) + ) + self.assertTrue( + ((desc.get_folded_fprint(fold_to_length=2) == folded_twice_vector).all()) + ) # Case 4 arbit_vector = np.array([1, 1, 1, 1, 1, 1, 1, 1]) folded_once_vector = np.array([1, 1, 1, 1]) folded_twice_vector = np.array([1, 1]) - arbit_label = 'arbitrary_fingerprint' + arbit_label = "arbitrary_fingerprint" desc = Descriptor() desc.label_ = arbit_label desc.numpy_ = arbit_vector @@ -428,10 +425,12 @@ def test_fingerprint_folding(self): desc.get_folded_fprint(fold_to_length=3) with self.assertRaises(InvalidConfigurationError): desc.get_folded_fprint(fold_to_length=10) - self.assertTrue(((desc.get_folded_fprint(fold_to_length=4) - == folded_once_vector).all())) - self.assertTrue(((desc.get_folded_fprint(fold_to_length=2) - == folded_twice_vector).all())) + self.assertTrue( + ((desc.get_folded_fprint(fold_to_length=4) == folded_once_vector).all()) + ) + self.assertTrue( + ((desc.get_folded_fprint(fold_to_length=2) == folded_twice_vector).all()) + ) if __name__ == "__main__": From 8f8a0421cbf5afa89fc2dc151b47da87cc41264d Mon Sep 17 00:00:00 2001 From: Jackson Burns Date: Tue, 7 Feb 2023 18:22:40 -0500 Subject: [PATCH 10/35] remove sklearn_extra version requirement --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 479c5097..548095a3 100644 --- a/requirements.txt +++ b/requirements.txt @@ -4,7 +4,7 @@ seaborn tabulate numpy>=1.22 multiprocess>=0.70 -scikit_learn_extra==0.2.0 +scikit_learn_extra pandas PyYAML==5.* scikit_learn From 97edce58792204be4cdeb52e740ca9abd6dfc288 Mon Sep 17 00:00:00 2001 From: Jackson Burns Date: Tue, 7 Feb 2023 18:34:23 -0500 Subject: [PATCH 11/35] switch decorator to a warning, not an error --- aimsim/exceptions.py | 8 ++++++++ aimsim/utils/extras.py | 9 +++++++-- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/aimsim/exceptions.py b/aimsim/exceptions.py index 56f92bd9..6c7a7880 100644 --- a/aimsim/exceptions.py +++ b/aimsim/exceptions.py @@ -14,6 +14,14 @@ def __init__(self, message=None): super().__init__(message) +class MordredNotInstalledWarning(RuntimeWarning): + """Used in descriptor.py when the Mordred property calculator is not present.""" + + def __init__(self, message=None): + self.message = message + super().__init__(message) + + class InvalidConfigurationError(IOError): """Used when a configuration parameter is invalid.""" diff --git a/aimsim/utils/extras.py b/aimsim/utils/extras.py index 221da1f2..5cdeb9a2 100644 --- a/aimsim/utils/extras.py +++ b/aimsim/utils/extras.py @@ -1,10 +1,15 @@ +from warnings import warn + +from aimsim.exceptions import MordredNotInstalledWarning + + def requries_mordred(function): try: from mordred import Calculator, descriptors - function() + return function() except ImportError: - raise RuntimeError( + return MordredNotInstalledWarning( """Attempting to call this function ({:s}) requires mordred to be installed. Please use 'pip install aimsim[mordred]' in an environment with the appropriate version of Python. """.format( From daeed8770d66768b129d305012066cc723b91f19 Mon Sep 17 00:00:00 2001 From: Jackson Burns Date: Tue, 7 Feb 2023 18:38:26 -0500 Subject: [PATCH 12/35] typo in decorator function name --- aimsim/ops/descriptor.py | 4 ++-- aimsim/utils/extras.py | 2 +- tests/test_Descriptor.py | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/aimsim/ops/descriptor.py b/aimsim/ops/descriptor.py index c11f6f02..f369ff29 100644 --- a/aimsim/ops/descriptor.py +++ b/aimsim/ops/descriptor.py @@ -10,7 +10,7 @@ from rdkit.DataStructs import cDataStructs from aimsim.utils.ccbmlib_fingerprints import generate_fingerprints from padelpy import from_smiles -from aimsim.utils.extras import requries_mordred +from aimsim.utils.extras import requires_mordred from ..exceptions import ( @@ -165,7 +165,7 @@ def _set_padelpy_descriptor(self, molecule_graph, descriptor, **kwargs): f"Unable to retrieve PaDELPy Descriptor '{descriptor}'. Is it a valid descriptor?" ) - @requries_mordred + @requires_mordred def _set_mordred_descriptor(self, molecule_graph, descriptor, **kwargs): """Set the value of numpy_ to the descriptor as indicated by descriptor. diff --git a/aimsim/utils/extras.py b/aimsim/utils/extras.py index 5cdeb9a2..49dd7f3a 100644 --- a/aimsim/utils/extras.py +++ b/aimsim/utils/extras.py @@ -3,7 +3,7 @@ from aimsim.exceptions import MordredNotInstalledWarning -def requries_mordred(function): +def requires_mordred(function): try: from mordred import Calculator, descriptors diff --git a/tests/test_Descriptor.py b/tests/test_Descriptor.py index a503aedf..ebdf11d2 100644 --- a/tests/test_Descriptor.py +++ b/tests/test_Descriptor.py @@ -5,7 +5,7 @@ from rdkit.Chem import MolFromSmiles from aimsim.ops import Descriptor from aimsim.exceptions import MordredCalculatorError, InvalidConfigurationError -from aimsim.utils.extras import requries_mordred +from aimsim.utils.extras import requires_mordred SUPPORTED_FPRINTS = Descriptor.get_supported_fprints() @@ -325,7 +325,7 @@ def test_exptl_descriptors(self): "{} to match the fingerprint".format(desc), ) - @requries_mordred + @requires_mordred def test_nonexistent_mordred_descriptors(self): """Test ability to pass through descriptors to Mordred.""" mol_graph = MolFromSmiles("C") From 57cb00315c932a56f3ac891ae906697b8ea473fe Mon Sep 17 00:00:00 2001 From: Jackson Burns Date: Tue, 7 Feb 2023 18:45:06 -0500 Subject: [PATCH 13/35] add more testing CI --- .github/workflows/run_tests.yml | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/.github/workflows/run_tests.yml b/.github/workflows/run_tests.yml index 8f249ff1..b9f33b8b 100644 --- a/.github/workflows/run_tests.yml +++ b/.github/workflows/run_tests.yml @@ -1,5 +1,7 @@ name: Run Tests on: + schedule: + - cron: '0 8 * * 1-5' push: branches: [ master ] pull_request: @@ -9,25 +11,29 @@ on: jobs: build: - runs-on: ubuntu-latest strategy: fail-fast: false matrix: - python-version: ['3.7', '3.8', '3.9'] - name: Python ${{ matrix.python-version }} sample + python-version: ['3.6', '3.7', '3.8', '3.9', '3.10', '3.11'] + exclude: + - os: macos-latest + python-version: "3.6" + - os: ubuntu-latest + python-version: "3.6" + os: [ubuntu-latest, windows-latest, macos-latest] + + runs-on: ${{ matrix.os }} + name: ${{ matrix.os }} Python ${{ matrix.python-version }} Subtest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Setup python - uses: actions/setup-python@v1 + uses: actions/setup-python@v4 with: python-version: ${{ matrix.python-version }} architecture: x64 - name: Install Dependencies run: | sudo apt-get install -y idle3 python3-tk - python -m pip install rdkit-pypi - python -m pip install networkx==2.1 - python -m pip install openpyxl python -m pip install -r requirements.txt python -m pip install -e . python -m pip install coverage From 41f85d449d8f79e13c2d1c1ad98dead0d83ca6d8 Mon Sep 17 00:00:00 2001 From: Jackson Burns Date: Tue, 7 Feb 2023 18:45:45 -0500 Subject: [PATCH 14/35] remove numpy subversion According to https://nvd.nist.gov/vuln/detail/cve-2021-34141 the risk of pre-1.22 versions is non-existent. --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 548095a3..3f6bf26b 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,7 +2,7 @@ scipy matplotlib seaborn tabulate -numpy>=1.22 +numpy>=1 multiprocess>=0.70 scikit_learn_extra pandas From 5cd4343b4b22a4733629ecd6ffde11e86c616698 Mon Sep 17 00:00:00 2001 From: Jackson Burns Date: Tue, 7 Feb 2023 18:48:53 -0500 Subject: [PATCH 15/35] apt-get only for ubuntu --- .github/workflows/run_tests.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/run_tests.yml b/.github/workflows/run_tests.yml index b9f33b8b..aabb5b5f 100644 --- a/.github/workflows/run_tests.yml +++ b/.github/workflows/run_tests.yml @@ -31,9 +31,12 @@ jobs: with: python-version: ${{ matrix.python-version }} architecture: x64 - - name: Install Dependencies + - name: Install Ubuntu Packages + if: runner.os == 'ubuntu' run: | sudo apt-get install -y idle3 python3-tk + - name: Install Dependencies + run: | python -m pip install -r requirements.txt python -m pip install -e . python -m pip install coverage From 1859d8a529d7fe52f6e1721468863d018981fc56 Mon Sep 17 00:00:00 2001 From: Jackson Burns Date: Tue, 7 Feb 2023 18:50:18 -0500 Subject: [PATCH 16/35] missing openpyxl --- .github/workflows/run_tests.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/run_tests.yml b/.github/workflows/run_tests.yml index aabb5b5f..32fa8e99 100644 --- a/.github/workflows/run_tests.yml +++ b/.github/workflows/run_tests.yml @@ -37,6 +37,7 @@ jobs: sudo apt-get install -y idle3 python3-tk - name: Install Dependencies run: | + python -m pip install openpyxl python -m pip install -r requirements.txt python -m pip install -e . python -m pip install coverage From 2188ab58c5848f54962e2fce05003300c3aa154f Mon Sep 17 00:00:00 2001 From: Jackson Burns Date: Tue, 7 Feb 2023 18:52:52 -0500 Subject: [PATCH 17/35] add a temporary fix for the perplexity call in sklearn --- tests/test_MoleculeSet.py | 152 ++++++++++++++++---------------------- 1 file changed, 63 insertions(+), 89 deletions(-) diff --git a/tests/test_MoleculeSet.py b/tests/test_MoleculeSet.py index 7c131d53..24de28f1 100644 --- a/tests/test_MoleculeSet.py +++ b/tests/test_MoleculeSet.py @@ -44,9 +44,12 @@ def get_feature_set(self, dimensionality=10): test_feature_set = [] feature_value_upper_limit = 1000 for i in range(n_test_mols): - test_feature_set.append([np.random.random() - * feature_value_upper_limit - for _ in range(dimensionality)]) + test_feature_set.append( + [ + np.random.random() * feature_value_upper_limit + for _ in range(dimensionality) + ] + ) return np.array(test_feature_set) def smiles_seq_to_textfile(self, property_seq=None): @@ -193,8 +196,7 @@ def smiles_seq_to_xl_or_csv( if feature_arr is not None: feature_arr = np.array(feature_arr) for feature_num in range(feature_arr.shape[1]): - data.update({f"descriptor_{feature_num}": - feature_arr[:, feature_num]}) + data.update({f"descriptor_{feature_num}": feature_arr[:, feature_num]}) data_df = pd.DataFrame(data) fpath = "temp_mol_file" if ftype == "excel": @@ -223,8 +225,7 @@ def test_set_molecule_database_from_textfile(self): similarity_measure="tanimoto", is_verbose=True, ) - self.assertTrue(molecule_set.is_verbose, - "Expected is_verbose to be True") + self.assertTrue(molecule_set.is_verbose, "Expected is_verbose to be True") self.assertIsNotNone( molecule_set.molecule_database, "Expected molecule_database to be set from text", @@ -268,8 +269,7 @@ def test_set_molecule_database_from_smi_file(self): similarity_measure="tanimoto", is_verbose=True, ) - self.assertTrue(molecule_set.is_verbose, - "Expected is_verbose to be True") + self.assertTrue(molecule_set.is_verbose, "Expected is_verbose to be True") self.assertIsNotNone( molecule_set.molecule_database, "Expected molecule_database to be set from text", @@ -313,8 +313,7 @@ def test_set_molecule_database_from_smiles_file(self): similarity_measure="tanimoto", is_verbose=True, ) - self.assertTrue(molecule_set.is_verbose, - "Expected is_verbose to be True") + self.assertTrue(molecule_set.is_verbose, "Expected is_verbose to be True") self.assertIsNotNone( molecule_set.molecule_database, "Expected molecule_database to be set from text", @@ -358,8 +357,7 @@ def test_set_molecule_database_from_smarts_file(self): similarity_measure="tanimoto", is_verbose=True, ) - self.assertTrue(molecule_set.is_verbose, - "Expected is_verbose to be True") + self.assertTrue(molecule_set.is_verbose, "Expected is_verbose to be True") self.assertIsNotNone( molecule_set.molecule_database, "Expected molecule_database to be set from text", @@ -438,8 +436,7 @@ def test_set_molecule_database_w_property_from_textfile(self): similarity_measure="tanimoto", is_verbose=True, ) - self.assertTrue(molecule_set.is_verbose, - "Expected is_verbose to be True") + self.assertTrue(molecule_set.is_verbose, "Expected is_verbose to be True") self.assertIsNotNone( molecule_set.molecule_database, "Expected molecule_database to be set from text", @@ -486,8 +483,7 @@ def test_set_molecule_database_from_pdb_dir(self): similarity_measure="tanimoto", is_verbose=True, ) - self.assertTrue(molecule_set.is_verbose, - "Expected is_verbose to be True") + self.assertTrue(molecule_set.is_verbose, "Expected is_verbose to be True") self.assertIsNotNone( molecule_set.molecule_database, "Expected molecule_database to be set from dir", @@ -565,8 +561,7 @@ def test_set_molecule_database_from_excel(self): similarity_measure="tanimoto", is_verbose=True, ) - self.assertTrue(molecule_set.is_verbose, - "Expected is_verbose to be True") + self.assertTrue(molecule_set.is_verbose, "Expected is_verbose to be True") self.assertIsNotNone( molecule_set.molecule_database, "Expected molecule_database to be set from excel file", @@ -597,11 +592,11 @@ def test_set_molecule_database_from_excel(self): remove(xl_fpath) def test_set_molecule_database_from_excel_without_smiles_name(self): - xl_fpath = 'test_files.xlsx' + xl_fpath = "test_files.xlsx" features = self.get_feature_set() # n_samples x dimensionality data = dict() for feature_id in range(features.shape[-1]): - data[f'descriptor_{feature_id}'] = features[:, feature_id].flatten() + data[f"descriptor_{feature_id}"] = features[:, feature_id].flatten() df = pd.DataFrame(data) print(f"Creating text file {xl_fpath}") df.to_excel(xl_fpath) @@ -611,8 +606,7 @@ def test_set_molecule_database_from_excel_without_smiles_name(self): similarity_measure="l2_similarity", is_verbose=True, ) - self.assertTrue(molecule_set.is_verbose, - "Expected is_verbose to be True") + self.assertTrue(molecule_set.is_verbose, "Expected is_verbose to be True") self.assertIsNotNone( molecule_set.molecule_database, "Expected molecule_database to be set from excel file", @@ -622,16 +616,16 @@ def test_set_molecule_database_from_excel_without_smiles_name(self): len(self.test_smiles), "Expected the size of database to be equal to number of smiles", ) - self.assertTrue(np.allclose(features, - molecule_set.get_mol_features(), - rtol=1e-4), - 'Expected molecule feature vectors to ' - 'be the same as features in input file') + self.assertTrue( + np.allclose(features, molecule_set.get_mol_features(), rtol=1e-4), + "Expected molecule feature vectors to " + "be the same as features in input file", + ) with self.assertRaises(ValueError): molecule_set = MoleculeSet( molecule_database_src=xl_fpath, molecule_database_src_type="excel", - fingerprint_type='morgan_fingerprint', + fingerprint_type="morgan_fingerprint", similarity_measure="l2_similarity", is_verbose=True, ) @@ -687,8 +681,7 @@ def test_set_molecule_database_w_property_from_excel(self): """ properties = np.random.normal(size=len(self.test_smiles)) - xl_fpath = self.smiles_seq_to_xl_or_csv(ftype="excel", - property_seq=properties) + xl_fpath = self.smiles_seq_to_xl_or_csv(ftype="excel", property_seq=properties) molecule_set = MoleculeSet( molecule_database_src=xl_fpath, molecule_database_src_type="excel", @@ -696,8 +689,7 @@ def test_set_molecule_database_w_property_from_excel(self): similarity_measure="tanimoto", is_verbose=True, ) - self.assertTrue(molecule_set.is_verbose, - "Expected is_verbose to be True") + self.assertTrue(molecule_set.is_verbose, "Expected is_verbose to be True") self.assertIsNotNone( molecule_set.molecule_database, "Expected molecule_database to be set from excel file", @@ -749,8 +741,7 @@ def test_set_molecule_database_w_descriptor_property_from_excel(self): similarity_measure="l0_similarity", is_verbose=True, ) - self.assertTrue(molecule_set.is_verbose, - "Expected is_verbose to be True") + self.assertTrue(molecule_set.is_verbose, "Expected is_verbose to be True") self.assertIsNotNone( molecule_set.molecule_database, "Expected molecule_database to be set from " "excel file", @@ -803,8 +794,7 @@ def test_set_molecule_database_from_csv(self): similarity_measure="tanimoto", is_verbose=True, ) - self.assertTrue(molecule_set.is_verbose, - "Expected is_verbose to be True") + self.assertTrue(molecule_set.is_verbose, "Expected is_verbose to be True") self.assertIsNotNone( molecule_set.molecule_database, "Expected molecule_database to be set from " "csv file", @@ -876,8 +866,7 @@ def test_set_molecule_database_w_property_from_csv(self): """ properties = np.random.normal(size=len(self.test_smiles)) - csv_fpath = self.smiles_seq_to_xl_or_csv(ftype="csv", - property_seq=properties) + csv_fpath = self.smiles_seq_to_xl_or_csv(ftype="csv", property_seq=properties) molecule_set = MoleculeSet( molecule_database_src=csv_fpath, molecule_database_src_type="csv", @@ -885,8 +874,7 @@ def test_set_molecule_database_w_property_from_csv(self): similarity_measure="tanimoto", is_verbose=True, ) - self.assertTrue(molecule_set.is_verbose, - "Expected is_verbose to be True") + self.assertTrue(molecule_set.is_verbose, "Expected is_verbose to be True") self.assertIsNotNone( molecule_set.molecule_database, "Expected molecule_database to be set from csv file", @@ -929,8 +917,7 @@ def test_set_molecule_database_w_descriptor_property_from_csv(self): similarity_measure="l0_similarity", is_verbose=True, ) - self.assertTrue(molecule_set.is_verbose, - "Expected is_verbose to be True") + self.assertTrue(molecule_set.is_verbose, "Expected is_verbose to be True") self.assertIsNotNone( molecule_set.molecule_database, "Expected molecule_database to be set from " "excel file", @@ -976,8 +963,7 @@ def test_set_molecule_database_w_similarity_from_csv(self): """ properties = np.random.normal(size=len(self.test_smiles)) - csv_fpath = self.smiles_seq_to_xl_or_csv(ftype="csv", - property_seq=properties) + csv_fpath = self.smiles_seq_to_xl_or_csv(ftype="csv", property_seq=properties) for similarity_measure in SUPPORTED_SIMILARITIES: with self.assertRaises(NotInitializedError): MoleculeSet( @@ -997,8 +983,7 @@ def test_set_molecule_database_fingerprint_from_csv(self): """ properties = np.random.normal(size=len(self.test_smiles)) - csv_fpath = self.smiles_seq_to_xl_or_csv(ftype="csv", - property_seq=properties) + csv_fpath = self.smiles_seq_to_xl_or_csv(ftype="csv", property_seq=properties) for descriptor in SUPPORTED_FPRINTS: with self.assertRaises(TypeError): MoleculeSet( @@ -1018,8 +1003,7 @@ def test_set_molecule_database_w_fingerprint_similarity_from_csv(self): """ properties = np.random.normal(size=len(self.test_smiles)) - csv_fpath = self.smiles_seq_to_xl_or_csv(ftype="csv", - property_seq=properties) + csv_fpath = self.smiles_seq_to_xl_or_csv(ftype="csv", property_seq=properties) for descriptor in SUPPORTED_FPRINTS: for similarity_measure in SUPPORTED_SIMILARITIES: molecule_set = MoleculeSet( @@ -1120,8 +1104,7 @@ def test_pca_transform(self): """ n_features = 20 features = np.random.normal(size=(len(self.test_smiles), n_features)) - csv_fpath = self.smiles_seq_to_xl_or_csv( - ftype="csv", feature_arr=features) + csv_fpath = self.smiles_seq_to_xl_or_csv(ftype="csv", feature_arr=features) molecule_set = MoleculeSet( molecule_database_src=csv_fpath, molecule_database_src_type="csv", @@ -1148,19 +1131,18 @@ def test_mds_transform(self): """ n_features = 20 features = np.random.normal(size=(len(self.test_smiles), n_features)) - csv_fpath = self.smiles_seq_to_xl_or_csv( - ftype="csv", feature_arr=features) + csv_fpath = self.smiles_seq_to_xl_or_csv(ftype="csv", feature_arr=features) molecule_set = MoleculeSet( molecule_database_src=csv_fpath, molecule_database_src_type="csv", similarity_measure="l0_similarity", is_verbose=True, - ) features = StandardScaler().fit_transform(features) features = MDS().fit_transform(features) - error_matrix = features - \ - molecule_set.get_transformed_descriptors(method_="mds") + error_matrix = features - molecule_set.get_transformed_descriptors( + method_="mds" + ) error_threshold = 1e-6 self.assertLessEqual( error_matrix.min(), @@ -1178,19 +1160,18 @@ def test_tsne_transform(self): """ n_features = 20 features = np.random.normal(size=(len(self.test_smiles), n_features)) - csv_fpath = self.smiles_seq_to_xl_or_csv( - ftype="csv", feature_arr=features) + csv_fpath = self.smiles_seq_to_xl_or_csv(ftype="csv", feature_arr=features) molecule_set = MoleculeSet( molecule_database_src=csv_fpath, molecule_database_src_type="csv", similarity_measure="l0_similarity", is_verbose=True, - ) features = StandardScaler().fit_transform(features) - features = TSNE().fit_transform(features) - error_matrix = features - \ - molecule_set.get_transformed_descriptors(method_="tsne") + features = TSNE(perplexity=n_features / 2).fit_transform(features) + error_matrix = features - molecule_set.get_transformed_descriptors( + method_="tsne" + ) error_threshold = 1e-6 self.assertLessEqual( error_matrix.min(), @@ -1208,19 +1189,18 @@ def test_isomap_transform(self): """ n_features = 20 features = np.random.normal(size=(len(self.test_smiles), n_features)) - csv_fpath = self.smiles_seq_to_xl_or_csv( - ftype="csv", feature_arr=features) + csv_fpath = self.smiles_seq_to_xl_or_csv(ftype="csv", feature_arr=features) molecule_set = MoleculeSet( molecule_database_src=csv_fpath, molecule_database_src_type="csv", similarity_measure="l0_similarity", is_verbose=True, - ) features = StandardScaler().fit_transform(features) features = Isomap().fit_transform(features) - error_matrix = features - \ - molecule_set.get_transformed_descriptors(method_="isomap") + error_matrix = features - molecule_set.get_transformed_descriptors( + method_="isomap" + ) error_threshold = 1e-6 self.assertLessEqual( error_matrix.min(), @@ -1238,19 +1218,18 @@ def test_spectral_embedding_transform(self): """ n_features = 20 features = np.random.normal(size=(len(self.test_smiles), n_features)) - csv_fpath = self.smiles_seq_to_xl_or_csv( - ftype="csv", feature_arr=features) + csv_fpath = self.smiles_seq_to_xl_or_csv(ftype="csv", feature_arr=features) molecule_set = MoleculeSet( molecule_database_src=csv_fpath, molecule_database_src_type="csv", similarity_measure="l0_similarity", is_verbose=True, - ) features = StandardScaler().fit_transform(features) features = SpectralEmbedding().fit_transform(features) - error_matrix = features - \ - molecule_set.get_transformed_descriptors(method_="spectral_embedding") + error_matrix = features - molecule_set.get_transformed_descriptors( + method_="spectral_embedding" + ) error_threshold = 1e-6 self.assertLessEqual( error_matrix.min(), @@ -1266,21 +1245,19 @@ def test_invalid_transform_error(self): """ n_features = 20 features = np.random.normal(size=(len(self.test_smiles), n_features)) - csv_fpath = self.smiles_seq_to_xl_or_csv( - ftype="csv", feature_arr=features) + csv_fpath = self.smiles_seq_to_xl_or_csv(ftype="csv", feature_arr=features) molecule_set = MoleculeSet( molecule_database_src=csv_fpath, molecule_database_src_type="csv", similarity_measure="l0_similarity", is_verbose=True, - ) features = StandardScaler().fit_transform(features) features = TSNE().fit_transform(features) with self.assertRaises(InvalidConfigurationError): - error_matrix = features - \ - molecule_set.get_transformed_descriptors( - method_="not a real method") + error_matrix = features - molecule_set.get_transformed_descriptors( + method_="not a real method" + ) remove(csv_fpath) def test_clustering_fingerprints(self): @@ -1329,11 +1306,9 @@ def test_clustering_fingerprints(self): remove(csv_fpath) def test_molecule_set_getters(self): - """Retrieve names and properties of mols using MoleculeSet. - """ + """Retrieve names and properties of mols using MoleculeSet.""" properties = np.random.normal(size=len(self.test_smiles)) - csv_fpath = self.smiles_seq_to_xl_or_csv(ftype="csv", - property_seq=properties) + csv_fpath = self.smiles_seq_to_xl_or_csv(ftype="csv", property_seq=properties) molecule_set = MoleculeSet( molecule_database_src=csv_fpath, molecule_database_src_type="csv", @@ -1342,19 +1317,18 @@ def test_molecule_set_getters(self): is_verbose=True, ) - self.assertListEqual( - self.test_smiles, molecule_set.get_mol_names().tolist()) + self.assertListEqual(self.test_smiles, molecule_set.get_mol_names().tolist()) - for a, b in zip(properties.tolist(), molecule_set.get_mol_properties().tolist()): + for a, b in zip( + properties.tolist(), molecule_set.get_mol_properties().tolist() + ): self.assertAlmostEqual(a, b) remove(csv_fpath) def test_molecule_set_sim_getters(self): - """Get the properties for most and least similar molecule pairs. - """ + """Get the properties for most and least similar molecule pairs.""" properties = np.array([i for i in range(len(self.test_smiles))]) - csv_fpath = self.smiles_seq_to_xl_or_csv(ftype="csv", - property_seq=properties) + csv_fpath = self.smiles_seq_to_xl_or_csv(ftype="csv", property_seq=properties) molecule_set = MoleculeSet( molecule_database_src=csv_fpath, molecule_database_src_type="csv", From 5c088e6d7b5e8c0c600a884662258235face4391 Mon Sep 17 00:00:00 2001 From: Jackson Burns Date: Tue, 7 Feb 2023 18:55:51 -0500 Subject: [PATCH 18/35] change supported python range to check unit tests --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 55fa53e3..607afb08 100644 --- a/setup.py +++ b/setup.py @@ -27,7 +27,7 @@ def get_version(rel_path): setup( name="aimsim", - python_requires=">=3.7,<3.10", + python_requires=">=3.6", version=get_version("aimsim/__init__.py"), description=desc, long_description=README, From 481b86be4373edfd5c408d7453d1649447779e25 Mon Sep 17 00:00:00 2001 From: Jackson Burns Date: Tue, 7 Feb 2023 19:01:32 -0500 Subject: [PATCH 19/35] set perplexity to half of n_features in TSNE tests --- tests/test_MoleculeSet.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_MoleculeSet.py b/tests/test_MoleculeSet.py index 24de28f1..61470d11 100644 --- a/tests/test_MoleculeSet.py +++ b/tests/test_MoleculeSet.py @@ -1253,7 +1253,7 @@ def test_invalid_transform_error(self): is_verbose=True, ) features = StandardScaler().fit_transform(features) - features = TSNE().fit_transform(features) + features = TSNE(perplexity=n_features / 2).fit_transform(features) with self.assertRaises(InvalidConfigurationError): error_matrix = features - molecule_set.get_transformed_descriptors( method_="not a real method" From b5ee0c0eb059382d0698644be9599cfe12a62343 Mon Sep 17 00:00:00 2001 From: Jackson Burns Date: Tue, 7 Feb 2023 19:02:31 -0500 Subject: [PATCH 20/35] extra ubuntu installs no longer required --- .github/workflows/run_tests.yml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/.github/workflows/run_tests.yml b/.github/workflows/run_tests.yml index 32fa8e99..64f90ed2 100644 --- a/.github/workflows/run_tests.yml +++ b/.github/workflows/run_tests.yml @@ -31,10 +31,6 @@ jobs: with: python-version: ${{ matrix.python-version }} architecture: x64 - - name: Install Ubuntu Packages - if: runner.os == 'ubuntu' - run: | - sudo apt-get install -y idle3 python3-tk - name: Install Dependencies run: | python -m pip install openpyxl From 98f9c31e94c9f6b1526e7bf3940a6fc0c518ed46 Mon Sep 17 00:00:00 2001 From: Jackson Burns Date: Tue, 7 Feb 2023 19:12:10 -0500 Subject: [PATCH 21/35] perplexity is based on samples, not features --- requirements.txt | 2 +- tests/test_MoleculeSet.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/requirements.txt b/requirements.txt index 3f6bf26b..11b92b7c 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,7 +2,7 @@ scipy matplotlib seaborn tabulate -numpy>=1 +numpy multiprocess>=0.70 scikit_learn_extra pandas diff --git a/tests/test_MoleculeSet.py b/tests/test_MoleculeSet.py index 61470d11..00f4a9d4 100644 --- a/tests/test_MoleculeSet.py +++ b/tests/test_MoleculeSet.py @@ -1168,7 +1168,7 @@ def test_tsne_transform(self): is_verbose=True, ) features = StandardScaler().fit_transform(features) - features = TSNE(perplexity=n_features / 2).fit_transform(features) + features = TSNE(perplexity=len(self.test_smiles) / 2).fit_transform(features) error_matrix = features - molecule_set.get_transformed_descriptors( method_="tsne" ) @@ -1253,7 +1253,7 @@ def test_invalid_transform_error(self): is_verbose=True, ) features = StandardScaler().fit_transform(features) - features = TSNE(perplexity=n_features / 2).fit_transform(features) + features = TSNE(perplexity=len(self.test_smiles) / 2).fit_transform(features) with self.assertRaises(InvalidConfigurationError): error_matrix = features - molecule_set.get_transformed_descriptors( method_="not a real method" From 55a657c80350955ccedbef894343e2c663415055 Mon Sep 17 00:00:00 2001 From: Jackson Burns Date: Tue, 7 Feb 2023 19:16:53 -0500 Subject: [PATCH 22/35] another missing perplexity config in tsne test --- tests/test_MoleculeSet.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/test_MoleculeSet.py b/tests/test_MoleculeSet.py index 00f4a9d4..5d2c2889 100644 --- a/tests/test_MoleculeSet.py +++ b/tests/test_MoleculeSet.py @@ -1170,7 +1170,8 @@ def test_tsne_transform(self): features = StandardScaler().fit_transform(features) features = TSNE(perplexity=len(self.test_smiles) / 2).fit_transform(features) error_matrix = features - molecule_set.get_transformed_descriptors( - method_="tsne" + method_="tsne", + kwargs={"perplexity": len(self.test_smiles) / 2}, ) error_threshold = 1e-6 self.assertLessEqual( From 2c0c8b4b1f5cac11e0625ea82904c19af4ae9e44 Mon Sep 17 00:00:00 2001 From: Jackson Burns Date: Tue, 7 Feb 2023 19:23:36 -0500 Subject: [PATCH 23/35] passthrough kwargs correctly --- tests/test_MoleculeSet.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/test_MoleculeSet.py b/tests/test_MoleculeSet.py index 5d2c2889..3b5bec2b 100644 --- a/tests/test_MoleculeSet.py +++ b/tests/test_MoleculeSet.py @@ -1170,8 +1170,8 @@ def test_tsne_transform(self): features = StandardScaler().fit_transform(features) features = TSNE(perplexity=len(self.test_smiles) / 2).fit_transform(features) error_matrix = features - molecule_set.get_transformed_descriptors( - method_="tsne", - kwargs={"perplexity": len(self.test_smiles) / 2}, + "tsne", + {"perplexity": len(self.test_smiles) / 2}, ) error_threshold = 1e-6 self.assertLessEqual( From 5a4c1f44da30191b29fe1c853507d1f989274748 Mon Sep 17 00:00:00 2001 From: Jackson Burns Date: Tue, 7 Feb 2023 19:27:01 -0500 Subject: [PATCH 24/35] set perplexity low --- tests/test_MoleculeSet.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/test_MoleculeSet.py b/tests/test_MoleculeSet.py index 3b5bec2b..b2876718 100644 --- a/tests/test_MoleculeSet.py +++ b/tests/test_MoleculeSet.py @@ -1170,8 +1170,8 @@ def test_tsne_transform(self): features = StandardScaler().fit_transform(features) features = TSNE(perplexity=len(self.test_smiles) / 2).fit_transform(features) error_matrix = features - molecule_set.get_transformed_descriptors( - "tsne", - {"perplexity": len(self.test_smiles) / 2}, + method_="tsne", + kwargs={"perplexity": 1}, ) error_threshold = 1e-6 self.assertLessEqual( From b38e7dbc081367c19f252969162c016ac3bbebb2 Mon Sep 17 00:00:00 2001 From: Jackson Burns Date: Wed, 8 Feb 2023 11:13:40 -0500 Subject: [PATCH 25/35] switch to conda for env management in CI --- .github/workflows/run_tests.yml | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/.github/workflows/run_tests.yml b/.github/workflows/run_tests.yml index 64f90ed2..e2acf2e7 100644 --- a/.github/workflows/run_tests.yml +++ b/.github/workflows/run_tests.yml @@ -23,14 +23,16 @@ jobs: os: [ubuntu-latest, windows-latest, macos-latest] runs-on: ${{ matrix.os }} + defaults: + run: + shell: bash -el {0} name: ${{ matrix.os }} Python ${{ matrix.python-version }} Subtest steps: - - uses: actions/checkout@v3 - - name: Setup python - uses: actions/setup-python@v4 + - uses: actions/checkout@v3 + - uses: conda-incubator/setup-miniconda@v2 with: + auto-update-conda: true python-version: ${{ matrix.python-version }} - architecture: x64 - name: Install Dependencies run: | python -m pip install openpyxl From e4708285a3f2bb02b745f27d15cef8035f6bb34a Mon Sep 17 00:00:00 2001 From: Jackson Burns Date: Wed, 8 Feb 2023 11:19:06 -0500 Subject: [PATCH 26/35] drop Python 3.6 since rdkit does not support it --- .github/workflows/run_tests.yml | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/.github/workflows/run_tests.yml b/.github/workflows/run_tests.yml index e2acf2e7..ece01a18 100644 --- a/.github/workflows/run_tests.yml +++ b/.github/workflows/run_tests.yml @@ -14,12 +14,7 @@ jobs: strategy: fail-fast: false matrix: - python-version: ['3.6', '3.7', '3.8', '3.9', '3.10', '3.11'] - exclude: - - os: macos-latest - python-version: "3.6" - - os: ubuntu-latest - python-version: "3.6" + python-version: ['3.7', '3.8', '3.9', '3.10', '3.11'] os: [ubuntu-latest, windows-latest, macos-latest] runs-on: ${{ matrix.os }} From 0ef3a23220d10efdce83c78b056dcf98387673cc Mon Sep 17 00:00:00 2001 From: Jackson Burns Date: Wed, 8 Feb 2023 11:32:47 -0500 Subject: [PATCH 27/35] use kwargs correctly in moleculeset test --- tests/test_MoleculeSet.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_MoleculeSet.py b/tests/test_MoleculeSet.py index b2876718..a8aa762a 100644 --- a/tests/test_MoleculeSet.py +++ b/tests/test_MoleculeSet.py @@ -1171,7 +1171,7 @@ def test_tsne_transform(self): features = TSNE(perplexity=len(self.test_smiles) / 2).fit_transform(features) error_matrix = features - molecule_set.get_transformed_descriptors( method_="tsne", - kwargs={"perplexity": 1}, + perplexity=1, ) error_threshold = 1e-6 self.assertLessEqual( From ba6113d081907a295bb872e4d2804e1b5803de3a Mon Sep 17 00:00:00 2001 From: Jackson Burns Date: Wed, 8 Feb 2023 14:18:38 -0500 Subject: [PATCH 28/35] cast pearson-heron intermediate to int64 for windows overflow warning --- aimsim/ops/similarity_measures.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/aimsim/ops/similarity_measures.py b/aimsim/ops/similarity_measures.py index 12f88d88..a085159c 100644 --- a/aimsim/ops/similarity_measures.py +++ b/aimsim/ops/similarity_measures.py @@ -1458,7 +1458,9 @@ def _get_pearson_heron(self, mol1_descriptor, mol2_descriptor): return 1.0 if b == p or c == p: return 0.0 - denominator_ = np.sqrt((a + b) * (a + c) * (b + d) * (c + d)) + denominator_ = np.sqrt( + np.int64(a + b) * np.int64(a + c) * np.int64(b + d) * np.int64(c + d) + ) if denominator_ < SMALL_NUMBER: return 0.0 similarity_ = (a * d - b * c) / denominator_ From 269d10fc30acef28289be077f8b1cbe0c1a97647 Mon Sep 17 00:00:00 2001 From: Jackson Burns Date: Wed, 8 Feb 2023 14:31:03 -0500 Subject: [PATCH 29/35] replace unicode minus with hypen, formatting --- .../chemical_datastructures/molecule_set.py | 369 ++++++++--------- aimsim/ops/similarity_measures.py | 381 ++++++++---------- docs/_sources/implemented_metrics.rst.txt | 20 +- implemented_metrics.md | 10 +- 4 files changed, 362 insertions(+), 418 deletions(-) diff --git a/aimsim/chemical_datastructures/molecule_set.py b/aimsim/chemical_datastructures/molecule_set.py index b24fe73c..8cf8a971 100644 --- a/aimsim/chemical_datastructures/molecule_set.py +++ b/aimsim/chemical_datastructures/molecule_set.py @@ -20,68 +20,68 @@ class MoleculeSet: """An abstraction of a collection of molecules constituting a chemical - dataset. - - Attributes: - is_verbose (bool): Controls how much information is displayed during - plotting. - molecule_database (list): Collection of Molecule objects. - descriptor (Descriptor): Descriptor or fingerprint used to featurize - molecules in the molecule set. - similarity_measure (SimilarityMeasure): Similarity measure used. - similarity_matrix (numpy ndarray): n_mols X n_mols matrix of - pairwise similarity scores. - sampling_ratio (float): Fraction of dataset to keep for analysis. - Default is 1. - n_threads (int or str): Number of threads used for analysis. Can be - an integer denoting the number of threads or 'auto' to - heuristically determine if multiprocessing is worthwhile - based on a curve fitted to the speedup data in the manuscript SI - Default is 1. - - Methods: - is_present(target_molecule): Searches the name of a target - molecule in the molecule set to determine if the target - molecule is present in the molecule set. - compare_against_molecule(query_molecule): Compare the a query - molecule to all molecules of the set. - get_most_similar_pairs(): Get pairs of samples which are - most similar. - get_most_dissimilar_pairs(): Get pairs of samples which are - least similar. - get_property_of_most_similar(): Get property of pairs of molecules - which are most similar to each other. - get_property_of_most_dissimilar(): Get property of pairs of - molecule which are most dissimilar to each other. - get_similarity_matrix(): Get the similarity matrix for the data set. - get_distance_matrix(): Get the distance matrix for the data set. - This is can only be done for similarity measures which yields - valid distances. - get_pairwise_similarities(): Get an array of pairwise similarities - of molecules in the set. - get_mol_names(): Get names of the molecules in the set. - get_mol_properties(): Get properties of all the molecules - in the dataset. - cluster(n_clusters=8, clustering_method=None, **kwargs): Cluster - the molecules of the MoleculeSet. Implemented methods. - 'kmedoids': for the K-Medoids algorithm. - 'complete_linkage', 'complete': - Complete linkage agglomerative hierarchical - clustering. - 'average_linkage', 'average': - average linkage agglomerative hierarchical clustering. - 'single_linkage', 'single': - single linkage agglomerative hierarchical clustering. - 'ward': - for Ward's algorithm. - get_cluster_labels(): Get cluster membership of Molecules. - get_transformed_descriptors(method_="pca", **kwargs): Use an - embedding method to transform molecular descriptor to a - low dimensional representation. Implemented methods are - Principal Component Analysis ('pca'), - Multidimensional scaling ('mds'), - t-SNE ('tsne'), Isomap ('isomap'), - Spectral Embedding ('spectral_embedding') + dataset. + + Attributes: + is_verbose (bool): Controls how much information is displayed during + plotting. + molecule_database (list): Collection of Molecule objects. + descriptor (Descriptor): Descriptor or fingerprint used to featurize + molecules in the molecule set. + similarity_measure (SimilarityMeasure): Similarity measure used. + similarity_matrix (numpy ndarray): n_mols X n_mols matrix of + pairwise similarity scores. + sampling_ratio (float): Fraction of dataset to keep for analysis. + Default is 1. + n_threads (int or str): Number of threads used for analysis. Can be + an integer denoting the number of threads or 'auto' to + heuristically determine if multiprocessing is worthwhile + based on a curve fitted to the speedup data in the manuscript SI + Default is 1. + + Methods: + is_present(target_molecule): Searches the name of a target + molecule in the molecule set to determine if the target + molecule is present in the molecule set. + compare_against_molecule(query_molecule): Compare the a query + molecule to all molecules of the set. + get_most_similar_pairs(): Get pairs of samples which are + most similar. + get_most_dissimilar_pairs(): Get pairs of samples which are + least similar. + get_property_of_most_similar(): Get property of pairs of molecules + which are most similar to each other. + get_property_of_most_dissimilar(): Get property of pairs of + molecule which are most dissimilar to each other. + get_similarity_matrix(): Get the similarity matrix for the data set. + get_distance_matrix(): Get the distance matrix for the data set. + This is can only be done for similarity measures which yields + valid distances. + get_pairwise_similarities(): Get an array of pairwise similarities + of molecules in the set. + get_mol_names(): Get names of the molecules in the set. + get_mol_properties(): Get properties of all the molecules + in the dataset. + cluster(n_clusters=8, clustering_method=None, **kwargs): Cluster + the molecules of the MoleculeSet. Implemented methods. + 'kmedoids': for the K-Medoids algorithm. + 'complete_linkage', 'complete': + Complete linkage agglomerative hierarchical + clustering. + 'average_linkage', 'average': + average linkage agglomerative hierarchical clustering. + 'single_linkage', 'single': + single linkage agglomerative hierarchical clustering. + 'ward': + for Ward's algorithm. + get_cluster_labels(): Get cluster membership of Molecules. + get_transformed_descriptors(method_="pca", **kwargs): Use an + embedding method to transform molecular descriptor to a + low dimensional representation. Implemented methods are + Principal Component Analysis ('pca'), + Multidimensional scaling ('mds'), + t-SNE ('tsne'), Isomap ('isomap'), + Spectral Embedding ('spectral_embedding') """ @@ -117,27 +117,29 @@ def __init__( if self.is_verbose: print(f"Using {int(sampling_ratio * 100)}% of the database...") self._subsample_database( - sampling_ratio=sampling_ratio, - random_state=sampling_random_state + sampling_ratio=sampling_ratio, random_state=sampling_random_state ) if fingerprint_type is not None: if descriptors is not None and is_verbose: - print('Descriptor and fingerprint specified.' - 'Descriptors imported from database source will ' - 'be overwritten by fingerprint.') + print( + "Descriptor and fingerprint specified." + "Descriptors imported from database source will " + "be overwritten by fingerprint." + ) self._set_descriptor( - fingerprint_type=fingerprint_type, - fingerprint_params=fingerprint_params + fingerprint_type=fingerprint_type, fingerprint_params=fingerprint_params ) self.similarity_measure = SimilarityMeasure(similarity_measure) - if n_threads == 'auto': + if n_threads == "auto": + def speedup_eqn(n_mols, n_procs): - return 1.8505e-4 * n_mols + 2.235e-1*n_procs + 7.082e-2 + return 1.8505e-4 * n_mols + 2.235e-1 * n_procs + 7.082e-2 + n_cores = psutil.cpu_count(logical=False) n_mols = len(self.molecule_database) if speedup_eqn(n_mols, n_cores) > 1.0: self.n_threads = n_cores - elif speedup_eqn(n_mols, n_cores//2) > 1.0: + elif speedup_eqn(n_mols, n_cores // 2) > 1.0: self.n_threads = n_cores // 2 else: self.n_threads = n_cores @@ -146,9 +148,7 @@ def speedup_eqn(n_mols, n_procs): self.similarity_matrix = None self._set_similarity_matrix() - def _get_molecule_database(self, - molecule_database_src, - molecule_database_src_type): + def _get_molecule_database(self, molecule_database_src, molecule_database_src_type): """Load molecular database and return it. Optionally return features if found in excel / csv file. @@ -170,7 +170,7 @@ def _get_molecule_database(self, """ if not self.is_verbose: - RDLogger.DisableLog('rdApp.*') + RDLogger.DisableLog("rdApp.*") molecule_database = [] descriptors = None @@ -199,8 +199,9 @@ def _get_molecule_database(self, if len(line_fields) > 1: mol_property_val = float(line_fields[1]) if self.is_verbose: - print(f"Processing {smile} " f"({count + 1}/" - f"{len(smiles_data)})") + print( + f"Processing {smile} " f"({count + 1}/" f"{len(smiles_data)})" + ) mol_text = smile try: molecule_database.append( @@ -232,10 +233,10 @@ def _get_molecule_database(self, database_descriptor_df = database_df[descriptor_cols] mol_names, mol_smiles, responses = None, None, None if "descriptor_name" in descriptor_cols: - mol_names = database_descriptor_df["descriptor_name"].values.flatten( - ) + mol_names = database_descriptor_df["descriptor_name"].values.flatten() database_descriptor_df = database_descriptor_df.drop( - ["descriptor_name"], axis=1) + ["descriptor_name"], axis=1 + ) if "descriptor_smiles" in descriptor_cols: mol_smiles = database_df["descriptor_smiles"].values.flatten() database_descriptor_df = database_descriptor_df.drop( @@ -257,12 +258,9 @@ def _get_molecule_database(self, f"({mol_id + 1}/" f"{len(database_descriptor_df.index)})" ) - mol_smile = mol_smiles[mol_id] if mol_smiles is not None \ - else None - mol_text = mol_names[mol_id] if mol_names is not None \ - else mol_smile - mol_property_val = responses[mol_id] if responses is not None \ - else None + mol_smile = mol_smiles[mol_id] if mol_smiles is not None else None + mol_text = mol_names[mol_id] if mol_names is not None else mol_smile + mol_property_val = responses[mol_id] if responses is not None else None try: molecule_database.append( @@ -274,8 +272,10 @@ def _get_molecule_database(self, ) except LoadingError as e: if self.is_verbose: - print(f"Molecule index {mol_id} could not be imported. " - f"Skipping") + print( + f"Molecule index {mol_id} could not be imported. " + f"Skipping" + ) if len(database_descriptor_df.columns) > 0: descriptors = database_descriptor_df.values @@ -357,7 +357,9 @@ def _set_similarity_matrix(self): # worker thread - def worker(thread_idx, n_mols, start_idx, end_idx, queue): # pragma: no cover + def worker( + thread_idx, n_mols, start_idx, end_idx, queue + ): # pragma: no cover # make a local copy of the overall similarity matrix local_similarity_matrix = np.zeros(shape=(n_mols, n_mols)) if self.is_verbose: @@ -402,7 +404,7 @@ def worker(thread_idx, n_mols, start_idx, end_idx, queue): # pragma: no cover raise e except ValueError as e: raise RuntimeError( - f'Unable to proccess molecule {molecule.mol_text}' + f"Unable to proccess molecule {molecule.mol_text}" ) from e queue.put(local_similarity_matrix) return None @@ -465,7 +467,7 @@ def worker(thread_idx, n_mols, start_idx, end_idx, queue): # pragma: no cover ) except ValueError as e: raise RuntimeError( - f'Unable to proccess molecule {molecule.mol_text}' + f"Unable to proccess molecule {molecule.mol_text}" ) from e self.similarity_matrix = similarity_matrix @@ -509,16 +511,19 @@ def _do_pca(self, get_component_info=False, **kwargs): [1] Bishop, C. M., Pattern recognition and machine learning. 2006. """ - params = {'n_components': kwargs.get('n_components', 2), - 'copy': kwargs.get('copy', True), - 'whiten': kwargs.get('whiten', False), - 'svd_solver': kwargs.get('svd_solver', 'auto'), - 'tol': kwargs.get('tol', 0.0), - 'iterated_power': kwargs.get('iterated_power', 'auto'), - 'random_state': kwargs.get('random_state', None)} + params = { + "n_components": kwargs.get("n_components", 2), + "copy": kwargs.get("copy", True), + "whiten": kwargs.get("whiten", False), + "svd_solver": kwargs.get("svd_solver", "auto"), + "tol": kwargs.get("tol", 0.0), + "iterated_power": kwargs.get("iterated_power", "auto"), + "random_state": kwargs.get("random_state", None), + } pca = PCA(**params) - X = np.array([molecule.get_descriptor_val() - for molecule in self.molecule_database]) + X = np.array( + [molecule.get_descriptor_val() for molecule in self.molecule_database] + ) scaler = StandardScaler() X = scaler.fit_transform(X) X = pca.fit_transform(X) @@ -565,23 +570,24 @@ def _do_mds(self, get_component_info=False, **kwargs): 29: p. 1-27. """ - params = {'n_components': kwargs.get('n_components', 2), - 'metric': kwargs.get('metric', True), - 'n_init': kwargs.get('n_init', 4), - 'max_iter': kwargs.get('max_iter', 3000), - 'verbose': kwargs.get('verbose', 0), - 'eps': kwargs.get('eps', 1e-3), - 'random_state': kwargs.get('random_state', 42), - } - embedding = MDS(dissimilarity='precomputed', **params) + params = { + "n_components": kwargs.get("n_components", 2), + "metric": kwargs.get("metric", True), + "n_init": kwargs.get("n_init", 4), + "max_iter": kwargs.get("max_iter", 3000), + "verbose": kwargs.get("verbose", 0), + "eps": kwargs.get("eps", 1e-3), + "random_state": kwargs.get("random_state", 42), + } + embedding = MDS(dissimilarity="precomputed", **params) dissimilarity_matrix = self.get_distance_matrix() X = embedding.fit_transform(dissimilarity_matrix) if not get_component_info: return X else: component_info = { - 'stress_': embedding.stress_, - 'n_iter_': embedding.n_iter_ + "stress_": embedding.stress_, + "n_iter_": embedding.n_iter_, } return X, component_info @@ -611,29 +617,29 @@ def _do_tsne(self, get_component_info=False, **kwargs): Journal of Machine Learning Research, 2008. 9: p. 2579-2605. """ - params = {'n_components': kwargs.get('n_components', 2), - 'perplexity': kwargs.get('perplexity', 30), - 'early_exaggeration': kwargs.get('early_exaggeration', 12), - 'learning_rate': kwargs.get('learning_rate', 200), - 'n_iter': kwargs.get('n_iter', 1000), - 'n_iter_without_progress': kwargs.get( - 'n_iter_without_progress', 300), - 'min_grad_norm': kwargs.get('min_grad_norm', 1e-7), - 'init': kwargs.get('init', 'random'), - 'verbose': kwargs.get('verbose', 0), - 'method': kwargs.get('method', 'barnes_hut'), - 'angle': kwargs.get('angle', 0.5), - 'n_jobs': kwargs.get('n_jobs', None), - } - embedding = TSNE(metric='precomputed', **params) + params = { + "n_components": kwargs.get("n_components", 2), + "perplexity": kwargs.get("perplexity", 30), + "early_exaggeration": kwargs.get("early_exaggeration", 12), + "learning_rate": kwargs.get("learning_rate", 200), + "n_iter": kwargs.get("n_iter", 1000), + "n_iter_without_progress": kwargs.get("n_iter_without_progress", 300), + "min_grad_norm": kwargs.get("min_grad_norm", 1e-7), + "init": kwargs.get("init", "random"), + "verbose": kwargs.get("verbose", 0), + "method": kwargs.get("method", "barnes_hut"), + "angle": kwargs.get("angle", 0.5), + "n_jobs": kwargs.get("n_jobs", None), + } + embedding = TSNE(metric="precomputed", **params) dissimilarity_matrix = self.get_distance_matrix() X = embedding.fit_transform(dissimilarity_matrix) if not get_component_info: return X else: component_info = { - 'kl_divergence': embedding.kl_divergence_, - 'n_iter_': embedding.n_iter_ + "kl_divergence": embedding.kl_divergence_, + "n_iter_": embedding.n_iter_, } return X, component_info @@ -664,26 +670,26 @@ def _do_isomap(self, get_component_info=False, **kwargs): Reduction. Science, 2000. 290(5500): p. 2319-2323. """ - params = {'n_neighbors': kwargs.get('n_neighbors', 5), - 'n_components': kwargs.get('n_components', 2), - 'eigen_solver': kwargs.get('eigen_solver', 'auto'), - 'tol': kwargs.get('tol', 0), - 'max_iter': kwargs.get('max_iter', None), - 'path_method': kwargs.get('path_method', 'auto'), - 'neighbors_algorithm': kwargs.get('neighbors_algorithm', - 'auto'), - 'n_jobs': kwargs.get('n_jobs', None), - 'p': kwargs.get('p', 2), - } - embedding = Isomap(metric='precomputed', **params) + params = { + "n_neighbors": kwargs.get("n_neighbors", 5), + "n_components": kwargs.get("n_components", 2), + "eigen_solver": kwargs.get("eigen_solver", "auto"), + "tol": kwargs.get("tol", 0), + "max_iter": kwargs.get("max_iter", None), + "path_method": kwargs.get("path_method", "auto"), + "neighbors_algorithm": kwargs.get("neighbors_algorithm", "auto"), + "n_jobs": kwargs.get("n_jobs", None), + "p": kwargs.get("p", 2), + } + embedding = Isomap(metric="precomputed", **params) dissimilarity_matrix = self.get_distance_matrix() X = embedding.fit_transform(dissimilarity_matrix) if not get_component_info: return X else: component_info = { - 'kernel_pca_': embedding.kernel_pca_, - 'nbrs_': embedding.nbrs_ + "kernel_pca_": embedding.kernel_pca_, + "nbrs_": embedding.nbrs_, } return X, component_info @@ -713,21 +719,21 @@ def _do_spectral_embedding(self, get_component_info=False, **kwargs): Analysis and an algorithm. 2001. MIT Press. """ - params = {'n_components': kwargs.get('n_components', 2), - 'gamma': kwargs.get('gamma', None), - 'random_state': kwargs.get('random_state', None), - 'eigen_solver': kwargs.get('eigen_solver', None), - 'n_neighbors': kwargs.get('n_neighbors', None), - 'n_jobs': kwargs.get('n_jobs', None)} - embedding = SpectralEmbedding(affinity='precomputed', **params) + params = { + "n_components": kwargs.get("n_components", 2), + "gamma": kwargs.get("gamma", None), + "random_state": kwargs.get("random_state", None), + "eigen_solver": kwargs.get("eigen_solver", None), + "n_neighbors": kwargs.get("n_neighbors", None), + "n_jobs": kwargs.get("n_jobs", None), + } + embedding = SpectralEmbedding(affinity="precomputed", **params) similarity_matrix = self.get_similarity_matrix() X = embedding.fit_transform(similarity_matrix) if not get_component_info: return X else: - component_info = { - 'n_neighbors_': embedding.n_neighbors_ - } + component_info = {"n_neighbors_": embedding.n_neighbors_} return X, component_info def is_present(self, target_molecule): @@ -794,12 +800,11 @@ def get_most_similar_pairs(self): n_samples = self.similarity_matrix.shape[0] for index, row in enumerate(self.similarity_matrix): post_diag_closest_index = ( - np.argmax(row[(index + 1):]) + index + 1 + np.argmax(row[(index + 1) :]) + index + 1 if index < n_samples - 1 else -1 ) - pre_diag_closest_index = np.argmax( - row[:index]) if index > 0 else -1 + pre_diag_closest_index = np.argmax(row[:index]) if index > 0 else -1 # if either (pre_) post_diag_closest_index not set, the # closest_index is set to the (post_) pre_diag_closest_index if pre_diag_closest_index == -1: @@ -816,8 +821,7 @@ def get_most_similar_pairs(self): else pre_diag_closest_index ) out_list.append( - (self.molecule_database[index], - self.molecule_database[closest_index]) + (self.molecule_database[index], self.molecule_database[closest_index]) ) return out_list @@ -843,8 +847,7 @@ def get_most_dissimilar_pairs(self): for index, row in enumerate(self.similarity_matrix): furthest_index = np.argmin(row) out_list.append( - (self.molecule_database[index], - self.molecule_database[furthest_index]) + (self.molecule_database[index], self.molecule_database[furthest_index]) ) return out_list @@ -915,10 +918,12 @@ def get_distance_matrix(self): Shape (n_samples, n_samples). """ - if not hasattr(self.similarity_measure, 'to_distance'): - raise InvalidConfigurationError(f'{self.similarity_measure.metric} ' - f'does not have an equivalent ' - f'distance') + if not hasattr(self.similarity_measure, "to_distance"): + raise InvalidConfigurationError( + f"{self.similarity_measure.metric} " + f"does not have an equivalent " + f"distance" + ) return self.similarity_measure.to_distance(self.similarity_matrix) def get_pairwise_similarities(self): @@ -958,9 +963,9 @@ def get_mol_names(self): def get_mol_properties(self): """Get properties of all the molecules in the dataset. - If all molecules don't have properties, None is returned. - Returns: - np.ndarray or None: Array with molecules properties or None. + If all molecules don't have properties, None is returned. + Returns: + np.ndarray or None: Array with molecules properties or None. """ mol_properties = [] @@ -978,8 +983,7 @@ def get_mol_features(self): np.ndarray: (n_molecules, feature_dimensionality) array. """ - mol_features = [mol.get_descriptor_val() - for mol in self.molecule_database] + mol_features = [mol.get_descriptor_val() for mol in self.molecule_database] return np.array(mol_features) def cluster(self, n_clusters=8, clustering_method=None, **kwargs): @@ -1029,9 +1033,9 @@ def cluster(self, n_clusters=8, clustering_method=None, **kwargs): "Clustering will not yield " "meaningful results." ) - if ((clustering_method == "kmedoids" - or clustering_method == 'ward') - and self.similarity_measure.type_ == "discrete"): + if ( + clustering_method == "kmedoids" or clustering_method == "ward" + ) and self.similarity_measure.type_ == "discrete": print( f"{clustering_method} cannot be used with " f"{self.similarity_measure.type_} " @@ -1043,9 +1047,9 @@ def cluster(self, n_clusters=8, clustering_method=None, **kwargs): clustering_method = "kmedoids" else: clustering_method = "complete_linkage" - self.clusters_ = Cluster(n_clusters=n_clusters, - clustering_method=clustering_method, - **kwargs).fit(self.get_distance_matrix()) + self.clusters_ = Cluster( + n_clusters=n_clusters, clustering_method=clustering_method, **kwargs + ).fit(self.get_distance_matrix()) def get_cluster_labels(self): """ @@ -1105,16 +1109,17 @@ def get_transformed_descriptors(self, method_="pca", **kwargs): Analysis and an algorithm. 2001. MIT Press. """ - if method_.lower() == 'pca': + if method_.lower() == "pca": return self._do_pca(**kwargs) - elif method_.lower() == 'mds': + elif method_.lower() == "mds": return self._do_mds(**kwargs) - elif method_.lower() == 'tsne': + elif method_.lower() == "tsne": return self._do_tsne(**kwargs) - elif method_.lower() == 'isomap': + elif method_.lower() == "isomap": return self._do_isomap(**kwargs) - elif method_.lower() == 'spectral_embedding': + elif method_.lower() == "spectral_embedding": return self._do_spectral_embedding(**kwargs) else: - raise InvalidConfigurationError(f'Embedding method {method_} ' - f'not implemented') + raise InvalidConfigurationError( + f"Embedding method {method_} " f"not implemented" + ) diff --git a/aimsim/ops/similarity_measures.py b/aimsim/ops/similarity_measures.py index a085159c..4ee91ec2 100644 --- a/aimsim/ops/similarity_measures.py +++ b/aimsim/ops/similarity_measures.py @@ -17,11 +17,13 @@ def __init__(self, metric): self.type_ = "continuous" self.to_distance = lambda x: 1 - x - elif metric.lower() in ["l1_similarity", - "manhattan_similarity", - "taxicab_similarity", - "city_block_similarity", - "snake_similarity"]: + elif metric.lower() in [ + "l1_similarity", + "manhattan_similarity", + "taxicab_similarity", + "city_block_similarity", + "snake_similarity", + ]: self.metric = "l1_similarity" self.type_ = "continuous" self.to_distance = lambda x: 1 - x @@ -155,24 +157,24 @@ def __init__(self, metric): self.metric = "harris_lahey" self.type_ = "discrete" - elif metric.lower() in ["consonni−todeschini-1", "consonni−todeschini_1"]: + elif metric.lower() in ["consonni-todeschini-1", "consonni-todeschini_1"]: self.metric = "consonni_todeschini_1" self.type_ = "discrete" self.to_distance = lambda x: 1 - x - elif metric.lower() in ["consonni−todeschini-2", "consonni−todeschini_2"]: + elif metric.lower() in ["consonni-todeschini-2", "consonni-todeschini_2"]: self.metric = "consonni_todeschini_2" self.type_ = "discrete" - elif metric.lower() in ["consonni−todeschini-3", "consonni−todeschini_3"]: + elif metric.lower() in ["consonni-todeschini-3", "consonni-todeschini_3"]: self.metric = "consonni_todeschini_3" self.type_ = "discrete" - elif metric.lower() in ["consonni−todeschini-4", "consonni−todeschini_4"]: + elif metric.lower() in ["consonni-todeschini-4", "consonni-todeschini_4"]: self.metric = "consonni_todeschini_4" self.type_ = "discrete" - elif metric.lower() in ["consonni−todeschini-5", "consonni−todeschini_5"]: + elif metric.lower() in ["consonni-todeschini-5", "consonni-todeschini_5"]: self.metric = "consonni_todeschini_5" self.type_ = "discrete" self.to_distance = lambda x: 1 - x @@ -213,11 +215,11 @@ def __init__(self, metric): self.metric = "dispersion" self.type_ = "discrete" - elif metric.lower() in ["goodman−kruskal", "goodman_kruskal"]: + elif metric.lower() in ["goodman-kruskal", "goodman_kruskal"]: self.metric = "goodman_kruskal" self.type_ = "discrete" - elif metric.lower() in ["pearson−heron", "pearson_heron"]: + elif metric.lower() in ["pearson-heron", "pearson_heron"]: self.metric = "pearson_heron" self.type_ = "discrete" self.to_distance = lambda x: 1 - x @@ -253,39 +255,40 @@ def __call__(self, mol1_descriptor, mol2_descriptor): Returns: similarity_ (float): Similarity value """ - if not self._validate_fprint(mol1_descriptor) or not self._validate_fprint(mol2_descriptor): + if not self._validate_fprint(mol1_descriptor) or not self._validate_fprint( + mol2_descriptor + ): raise ValueError( - f'Molecule descriptor ({mol1_descriptor.label_}) has no active bits.' + f"Molecule descriptor ({mol1_descriptor.label_}) has no active bits." ) similarity_ = None if self.metric == "l0_similarity": try: - similarity_ = self._get_vector_norm_similarity(mol1_descriptor, - mol2_descriptor, - ord=0) + similarity_ = self._get_vector_norm_similarity( + mol1_descriptor, mol2_descriptor, ord=0 + ) except ValueError as e: raise e elif self.metric == "l1_similarity": try: - similarity_ = self._get_vector_norm_similarity(mol1_descriptor, - mol2_descriptor, - ord=1) + similarity_ = self._get_vector_norm_similarity( + mol1_descriptor, mol2_descriptor, ord=1 + ) except ValueError as e: raise e elif self.metric == "l2_similarity": try: - similarity_ = self._get_vector_norm_similarity(mol1_descriptor, - mol2_descriptor, - ord=2) + similarity_ = self._get_vector_norm_similarity( + mol1_descriptor, mol2_descriptor, ord=2 + ) except ValueError as e: raise e elif self.metric == "austin_colwell": try: - similarity_ = self._get_austin_colwell( - mol1_descriptor, mol2_descriptor) + similarity_ = self._get_austin_colwell(mol1_descriptor, mol2_descriptor) except ValueError as e: raise e @@ -299,8 +302,7 @@ def __call__(self, mol1_descriptor, mol2_descriptor): elif self.metric == "braun_blanquet": try: - similarity_ = self._get_braun_blanquet( - mol1_descriptor, mol2_descriptor) + similarity_ = self._get_braun_blanquet(mol1_descriptor, mol2_descriptor) except ValueError as e: raise e @@ -312,15 +314,13 @@ def __call__(self, mol1_descriptor, mol2_descriptor): elif self.metric == "cole_1": try: - similarity_ = self._get_cole_1( - mol1_descriptor, mol2_descriptor) + similarity_ = self._get_cole_1(mol1_descriptor, mol2_descriptor) except ValueError as e: raise e elif self.metric == "cole_2": try: - similarity_ = self._get_cole_2( - mol1_descriptor, mol2_descriptor) + similarity_ = self._get_cole_2(mol1_descriptor, mol2_descriptor) except ValueError as e: raise e @@ -364,17 +364,17 @@ def __call__(self, mol1_descriptor, mol2_descriptor): except ValueError as e: raise e - elif self.metric == 'cosine': + elif self.metric == "cosine": try: - similarity_ = self._get_cosine_similarity(mol1_descriptor, - mol2_descriptor) + similarity_ = self._get_cosine_similarity( + mol1_descriptor, mol2_descriptor + ) except ValueError as e: raise e elif self.metric == "dennis": try: - similarity_ = self._get_dennis( - mol1_descriptor, mol2_descriptor) + similarity_ = self._get_dennis(mol1_descriptor, mol2_descriptor) except ValueError as e: raise e @@ -386,22 +386,19 @@ def __call__(self, mol1_descriptor, mol2_descriptor): elif self.metric == "dice_2": try: - similarity_ = self._get_dice_2( - mol1_descriptor, mol2_descriptor) + similarity_ = self._get_dice_2(mol1_descriptor, mol2_descriptor) except ValueError as e: raise e elif self.metric == "dice_3": try: - similarity_ = self._get_dice_3( - mol1_descriptor, mol2_descriptor) + similarity_ = self._get_dice_3(mol1_descriptor, mol2_descriptor) except ValueError as e: raise e elif self.metric == "dispersion": try: - similarity_ = self._get_dispersion(mol1_descriptor, - mol2_descriptor) + similarity_ = self._get_dispersion(mol1_descriptor, mol2_descriptor) except ValueError as e: raise e @@ -413,15 +410,13 @@ def __call__(self, mol1_descriptor, mol2_descriptor): elif self.metric == "forbes": try: - similarity_ = self._get_forbes( - mol1_descriptor, mol2_descriptor) + similarity_ = self._get_forbes(mol1_descriptor, mol2_descriptor) except ValueError as e: raise e elif self.metric == "fossum": try: - similarity_ = self._get_fossum( - mol1_descriptor, mol2_descriptor) + similarity_ = self._get_fossum(mol1_descriptor, mol2_descriptor) except ValueError as e: raise e @@ -435,29 +430,25 @@ def __call__(self, mol1_descriptor, mol2_descriptor): elif self.metric == "harris_lahey": try: - similarity_ = self._get_harris_lahey( - mol1_descriptor, mol2_descriptor) + similarity_ = self._get_harris_lahey(mol1_descriptor, mol2_descriptor) except ValueError as e: raise e elif self.metric == "hawkins_dotson": try: - similarity_ = self._get_hawkins_dotson(mol1_descriptor, - mol2_descriptor) + similarity_ = self._get_hawkins_dotson(mol1_descriptor, mol2_descriptor) except ValueError as e: raise e elif self.metric == "jaccard": try: - similarity_ = self._get_jaccard( - mol1_descriptor, mol2_descriptor) + similarity_ = self._get_jaccard(mol1_descriptor, mol2_descriptor) except ValueError as e: raise e elif self.metric == "kulczynski": try: - similarity_ = self._get_kulczynski(mol1_descriptor, - mol2_descriptor) + similarity_ = self._get_kulczynski(mol1_descriptor, mol2_descriptor) except ValueError as e: raise e elif self.metric == "maxwell_pilliner": @@ -470,36 +461,31 @@ def __call__(self, mol1_descriptor, mol2_descriptor): elif self.metric == "michael": try: - similarity_ = self._get_michael(mol1_descriptor, - mol2_descriptor) + similarity_ = self._get_michael(mol1_descriptor, mol2_descriptor) except ValueError as e: raise e elif self.metric == "mountford": try: - similarity_ = self._get_mountford(mol1_descriptor, - mol2_descriptor) + similarity_ = self._get_mountford(mol1_descriptor, mol2_descriptor) except ValueError as e: raise e elif self.metric == "pearson_heron": try: - similarity_ = self._get_pearson_heron(mol1_descriptor, - mol2_descriptor) + similarity_ = self._get_pearson_heron(mol1_descriptor, mol2_descriptor) except ValueError as e: raise e elif self.metric == "peirce_1": try: - similarity_ = self._get_peirce_1(mol1_descriptor, - mol2_descriptor) + similarity_ = self._get_peirce_1(mol1_descriptor, mol2_descriptor) except ValueError as e: raise e elif self.metric == "peirce_2": try: - similarity_ = self._get_peirce_2(mol1_descriptor, - mol2_descriptor) + similarity_ = self._get_peirce_2(mol1_descriptor, mol2_descriptor) except ValueError as e: raise e @@ -513,15 +499,13 @@ def __call__(self, mol1_descriptor, mol2_descriptor): elif self.metric == "rogot_goldberg": try: - similarity_ = self._get_rogot_goldberg(mol1_descriptor, - mol2_descriptor) + similarity_ = self._get_rogot_goldberg(mol1_descriptor, mol2_descriptor) except ValueError as e: raise e elif self.metric == "russel_rao": try: - similarity_ = self._get_russel_rao(mol1_descriptor, - mol2_descriptor) + similarity_ = self._get_russel_rao(mol1_descriptor, mol2_descriptor) except ValueError as e: raise e @@ -535,15 +519,13 @@ def __call__(self, mol1_descriptor, mol2_descriptor): elif self.metric == "simpson": try: - similarity_ = self._get_simpson(mol1_descriptor, - mol2_descriptor) + similarity_ = self._get_simpson(mol1_descriptor, mol2_descriptor) except ValueError as e: raise e elif self.metric == "sokal_sneath": try: - similarity_ = self._get_sokal_sneath(mol1_descriptor, - mol2_descriptor) + similarity_ = self._get_sokal_sneath(mol1_descriptor, mol2_descriptor) except ValueError as e: raise e @@ -557,22 +539,19 @@ def __call__(self, mol1_descriptor, mol2_descriptor): elif self.metric == "sokal_sneath_3": try: - similarity_ = self._get_sokal_sneath_3(mol1_descriptor, - mol2_descriptor) + similarity_ = self._get_sokal_sneath_3(mol1_descriptor, mol2_descriptor) except ValueError as e: raise e elif self.metric == "sokal_sneath_4": try: - similarity_ = self._get_sokal_sneath_4(mol1_descriptor, - mol2_descriptor) + similarity_ = self._get_sokal_sneath_4(mol1_descriptor, mol2_descriptor) except ValueError as e: raise e elif self.metric == "sorgenfrei": try: - similarity_ = self._get_sorgenfrei(mol1_descriptor, - mol2_descriptor) + similarity_ = self._get_sorgenfrei(mol1_descriptor, mol2_descriptor) except ValueError as e: raise e @@ -589,15 +568,13 @@ def __call__(self, mol1_descriptor, mol2_descriptor): ) elif self.metric == "yule_1": try: - similarity_ = self._get_yule_1( - mol1_descriptor, mol2_descriptor) + similarity_ = self._get_yule_1(mol1_descriptor, mol2_descriptor) except ValueError as e: raise e elif self.metric == "yule_2": try: - similarity_ = self._get_yule_2( - mol1_descriptor, mol2_descriptor) + similarity_ = self._get_yule_2(mol1_descriptor, mol2_descriptor) except ValueError as e: raise e @@ -606,10 +583,7 @@ def __call__(self, mol1_descriptor, mol2_descriptor): return similarity_ - def _get_vector_norm_similarity(self, - mol1_descriptor, - mol2_descriptor, - ord): + def _get_vector_norm_similarity(self, mol1_descriptor, mol2_descriptor, ord): """Calculate the norm based similarity between two molecules. This is defined as: Norm similarity (order n) = 1 / (1 + n-norm(A - B) @@ -628,11 +602,13 @@ def _get_vector_norm_similarity(self, arr2 = mol2_descriptor.to_numpy() if len(arr1) != len(arr2): try: - arr1, arr2 = Descriptor.fold_to_equal_length(mol1_descriptor, - mol2_descriptor) + arr1, arr2 = Descriptor.fold_to_equal_length( + mol1_descriptor, mol2_descriptor + ) except ValueError as e: raise ValueError( - 'Fingerprints are of unequal length and cannot be folded.') from e + "Fingerprints are of unequal length and cannot be folded." + ) from e norm_ = np.linalg.norm(arr1 - arr2, ord=ord) similarity_ = 1 / (1 + norm_) @@ -652,8 +628,7 @@ def _get_austin_colwell(self, mol1_descriptor, mol2_descriptor): Returns: (float): Austin-Colwell similarity value """ - if not (mol1_descriptor.is_fingerprint() - and mol2_descriptor.is_fingerprint()): + if not (mol1_descriptor.is_fingerprint() and mol2_descriptor.is_fingerprint()): raise ValueError( "Austin-Colwell similarity is only useful for " "bit strings generated from fingerprints. Consider using " @@ -679,8 +654,7 @@ def _get_baroni_urbani_buser(self, mol1_descriptor, mol2_descriptor): Returns: (float): Baroni-Urbani-Buser similarity value """ - if not (mol1_descriptor.is_fingerprint() - and mol2_descriptor.is_fingerprint()): + if not (mol1_descriptor.is_fingerprint() and mol2_descriptor.is_fingerprint()): raise ValueError( "Baroni-Urbani-Buser similarity is only useful for " "bit strings generated from fingerprints. Consider using " @@ -707,8 +681,7 @@ def _get_braun_blanquet(self, mol1_descriptor, mol2_descriptor): Returns: (float): Braun-Blanquet similarity value """ - if not (mol1_descriptor.is_fingerprint() - and mol2_descriptor.is_fingerprint()): + if not (mol1_descriptor.is_fingerprint() and mol2_descriptor.is_fingerprint()): raise ValueError( "Braun-Blanquet similarity is only useful for bit strings " "generated from fingerprints. Consider using " @@ -734,8 +707,7 @@ def _get_cohen(self, mol1_descriptor, mol2_descriptor): Returns: (float): Cohen similarity value """ - if not (mol1_descriptor.is_fingerprint() - and mol2_descriptor.is_fingerprint()): + if not (mol1_descriptor.is_fingerprint() and mol2_descriptor.is_fingerprint()): raise ValueError( "Cohen similarity is only useful for bit strings " "generated from fingerprints. Consider using " @@ -766,8 +738,7 @@ def _get_cole_1(self, mol1_descriptor, mol2_descriptor): Returns: (float): Cole(1) similarity value """ - if not (mol1_descriptor.is_fingerprint() - and mol2_descriptor.is_fingerprint()): + if not (mol1_descriptor.is_fingerprint() and mol2_descriptor.is_fingerprint()): raise ValueError( "Cole(1) similarity is only useful for bit strings " "generated from fingerprints. Consider using " @@ -797,8 +768,7 @@ def _get_cole_2(self, mol1_descriptor, mol2_descriptor): Returns: (float): Cole(2) similarity value """ - if not (mol1_descriptor.is_fingerprint() - and mol2_descriptor.is_fingerprint()): + if not (mol1_descriptor.is_fingerprint() and mol2_descriptor.is_fingerprint()): raise ValueError( "Cole(2) similarity is only useful for bit strings " "generated from fingerprints. Consider using " @@ -828,8 +798,7 @@ def _get_consonni_todeschini_1(self, mol1_descriptor, mol2_descriptor): Returns: (float): Consonni-Todeschini(1) similarity value """ - if not (mol1_descriptor.is_fingerprint() - and mol2_descriptor.is_fingerprint()): + if not (mol1_descriptor.is_fingerprint() and mol2_descriptor.is_fingerprint()): raise ValueError( "Consonni-Todeschini(1) similarity is only useful for " "bit strings generated from fingerprints. Consider using " @@ -855,8 +824,7 @@ def _get_consonni_todeschini_2(self, mol1_descriptor, mol2_descriptor): Returns: (float): Consonni-Todeschini(2) similarity value """ - if not (mol1_descriptor.is_fingerprint() - and mol2_descriptor.is_fingerprint()): + if not (mol1_descriptor.is_fingerprint() and mol2_descriptor.is_fingerprint()): raise ValueError( "Consonni-Todeschini(2) similarity is only useful for " "bit strings generated from fingerprints. Consider using " @@ -881,8 +849,7 @@ def _get_consonni_todeschini_3(self, mol1_descriptor, mol2_descriptor): Returns: (float): Consonni-Todeschini(3) similarity value """ - if not (mol1_descriptor.is_fingerprint() - and mol2_descriptor.is_fingerprint()): + if not (mol1_descriptor.is_fingerprint() and mol2_descriptor.is_fingerprint()): raise ValueError( "Consonni-Todeschini(3) similarity is only useful for " "bit strings generated from fingerprints. Consider using " @@ -907,8 +874,7 @@ def _get_consonni_todeschini_4(self, mol1_descriptor, mol2_descriptor): Returns: (float): Consonni-Todeschini(4) similarity value """ - if not (mol1_descriptor.is_fingerprint() - and mol2_descriptor.is_fingerprint()): + if not (mol1_descriptor.is_fingerprint() and mol2_descriptor.is_fingerprint()): raise ValueError( "Consonni-Todeschini(4) similarity is only useful for " "bit strings generated from fingerprints. Consider using " @@ -916,7 +882,7 @@ def _get_consonni_todeschini_4(self, mol1_descriptor, mol2_descriptor): ) a, b, c, _ = self._get_abcd(mol1_descriptor, mol2_descriptor) if np.log(1 + a + b + c) == 0: - raise InvalidConfigurationError('Empty string supplied') + raise InvalidConfigurationError("Empty string supplied") similarity_ = np.log(1 + a) / np.log(1 + a + b + c) self.normalize_fn["shift_"] = 0.0 self.normalize_fn["scale_"] = 1.0 @@ -935,8 +901,7 @@ def _get_consonni_todeschini_5(self, mol1_descriptor, mol2_descriptor): Returns: (float): Consonni-Todeschini(5) similarity value """ - if not (mol1_descriptor.is_fingerprint() - and mol2_descriptor.is_fingerprint()): + if not (mol1_descriptor.is_fingerprint() and mol2_descriptor.is_fingerprint()): raise ValueError( "Consonni-Todeschini(5) similarity is only useful for " "bit strings generated from fingerprints. Consider using " @@ -944,20 +909,19 @@ def _get_consonni_todeschini_5(self, mol1_descriptor, mol2_descriptor): ) a, b, c, d = self._get_abcd(mol1_descriptor, mol2_descriptor) p = a + b + c + d - similarity_ = (np.log(1 + a * d) - np.log(1 + b * c)) / np.log( - 1 + (p ** 2)/4) + similarity_ = (np.log(1 + a * d) - np.log(1 + b * c)) / np.log(1 + (p**2) / 4) self.normalize_fn["shift_"] = 1.0 self.normalize_fn["scale_"] = 2.0 return self._normalize(similarity_) def _get_cosine_similarity(self, mol1_descriptor, mol2_descriptor): a, b, c, _ = self._get_abcd(mol1_descriptor, mol2_descriptor) - denominator = np.sqrt((a+b)*(a+c)) + denominator = np.sqrt((a + b) * (a + c)) if denominator < SMALL_NUMBER: - return 0. + return 0.0 similarity_ = a / denominator - self.normalize_fn["shift_"] = 0. - self.normalize_fn["scale_"] = 1. + self.normalize_fn["shift_"] = 0.0 + self.normalize_fn["scale_"] = 1.0 return self._normalize(similarity_) def _get_dennis(self, mol1_descriptor, mol2_descriptor): @@ -972,8 +936,7 @@ def _get_dennis(self, mol1_descriptor, mol2_descriptor): Returns: (float): Dennis similarity value """ - if not (mol1_descriptor.is_fingerprint() - and mol2_descriptor.is_fingerprint()): + if not (mol1_descriptor.is_fingerprint() and mol2_descriptor.is_fingerprint()): raise ValueError( "Dennis similarity is only useful for bit strings " "generated from fingerprints. Consider using " @@ -1003,8 +966,7 @@ def _get_dice(self, mol1_descriptor, mol2_descriptor): Returns: (float): Dice similarity value """ - if not (mol1_descriptor.is_fingerprint() - and mol2_descriptor.is_fingerprint()): + if not (mol1_descriptor.is_fingerprint() and mol2_descriptor.is_fingerprint()): raise ValueError( "Dice similarity is only useful for bit strings " "generated from fingerprints, not {} and {}. Consider using " @@ -1015,7 +977,7 @@ def _get_dice(self, mol1_descriptor, mol2_descriptor): a, b, c, _ = self._get_abcd(mol1_descriptor, mol2_descriptor) if a < SMALL_NUMBER: return 0.0 - similarity_ = 2*a / (2*a + b + c) + similarity_ = 2 * a / (2 * a + b + c) self.normalize_fn["shift_"] = 0.0 self.normalize_fn["scale_"] = 1.0 return self._normalize(similarity_) @@ -1032,8 +994,7 @@ def _get_dice_2(self, mol1_descriptor, mol2_descriptor): Returns: (float): Dice(2) similarity value """ - if not (mol1_descriptor.is_fingerprint() - and mol2_descriptor.is_fingerprint()): + if not (mol1_descriptor.is_fingerprint() and mol2_descriptor.is_fingerprint()): raise ValueError( "Dice(2) similarity is only useful for bit strings " "generated from fingerprints, not {} and {}. Consider using " @@ -1061,8 +1022,7 @@ def _get_dice_3(self, mol1_descriptor, mol2_descriptor): Returns: (float): Dice(3) similarity value """ - if not (mol1_descriptor.is_fingerprint() - and mol2_descriptor.is_fingerprint()): + if not (mol1_descriptor.is_fingerprint() and mol2_descriptor.is_fingerprint()): raise ValueError( "Dice(3) similarity is only useful for bit strings " "generated from fingerprints. Consider using " @@ -1089,8 +1049,7 @@ def _get_dispersion(self, mol1_descriptor, mol2_descriptor): Returns: (float): dispersion similarity value """ - if not (mol1_descriptor.is_fingerprint() - and mol2_descriptor.is_fingerprint()): + if not (mol1_descriptor.is_fingerprint() and mol2_descriptor.is_fingerprint()): raise ValueError( "Dispersion similarity is only useful for bit strings " "generated from fingerprints. Consider using " @@ -1100,7 +1059,7 @@ def _get_dispersion(self, mol1_descriptor, mol2_descriptor): p = a + b + c + d if a == p or d == p: return 1.0 - similarity_ = (a * d - b * c) / p ** 2 + similarity_ = (a * d - b * c) / p**2 self.normalize_fn["shift_"] = 1 / 4 self.normalize_fn["scale_"] = 1 / 2 return self._normalize(similarity_) @@ -1117,8 +1076,7 @@ def _get_faith(self, mol1_descriptor, mol2_descriptor): Returns: (float): Faith similarity value """ - if not (mol1_descriptor.is_fingerprint() - and mol2_descriptor.is_fingerprint()): + if not (mol1_descriptor.is_fingerprint() and mol2_descriptor.is_fingerprint()): raise ValueError( "Faith similarity is only useful for bit strings " "generated from fingerprints. Consider using " @@ -1146,8 +1104,7 @@ def _get_forbes(self, mol1_descriptor, mol2_descriptor): Note: The Forbes similarity is normalized to [0, 1] """ - if not (mol1_descriptor.is_fingerprint() - and mol2_descriptor.is_fingerprint()): + if not (mol1_descriptor.is_fingerprint() and mol2_descriptor.is_fingerprint()): raise ValueError( "Forbes similarity is only useful for bit strings " "generated from fingerprints. Consider using " @@ -1177,8 +1134,7 @@ def _get_fossum(self, mol1_descriptor, mol2_descriptor): Note: The similarity is normalized to [0, 1]. """ - if not (mol1_descriptor.is_fingerprint() - and mol2_descriptor.is_fingerprint()): + if not (mol1_descriptor.is_fingerprint() and mol2_descriptor.is_fingerprint()): raise ValueError( "Fossum similarity is only useful for bit strings " "generated from fingerprints. Consider using " @@ -1206,8 +1162,7 @@ def _get_goodman_kruskal(self, mol1_descriptor, mol2_descriptor): Returns: (float): Goodman-Kruskal similarity value """ - if not (mol1_descriptor.is_fingerprint() - and mol2_descriptor.is_fingerprint()): + if not (mol1_descriptor.is_fingerprint() and mol2_descriptor.is_fingerprint()): raise ValueError( "Goodman-Kruskal similarity is only useful for bit strings " "generated from fingerprints. Consider using " @@ -1236,8 +1191,7 @@ def _get_harris_lahey(self, mol1_descriptor, mol2_descriptor): Returns: (float): Harris-Lahey similarity value """ - if not (mol1_descriptor.is_fingerprint() - and mol2_descriptor.is_fingerprint()): + if not (mol1_descriptor.is_fingerprint() and mol2_descriptor.is_fingerprint()): raise ValueError( "Harris-Lahey similarity is only useful for bit strings " "generated from fingerprints. Consider using " @@ -1271,8 +1225,7 @@ def _get_hawkins_dotson(self, mol1_descriptor, mol2_descriptor): Returns: (float): Hawkins-Dotson similarity value """ - if not (mol1_descriptor.is_fingerprint() - and mol2_descriptor.is_fingerprint()): + if not (mol1_descriptor.is_fingerprint() and mol2_descriptor.is_fingerprint()): raise ValueError( "Hawkins-Dotson similarity is only useful for bit strings " "generated from fingerprints. Consider using " @@ -1282,8 +1235,9 @@ def _get_hawkins_dotson(self, mol1_descriptor, mol2_descriptor): p = a + b + c + d if a == p or d == p: return 1.0 - similarity_ = 0.5 * (a / (a + b + c + SMALL_NUMBER) - + d / (d + b + c + SMALL_NUMBER)) + similarity_ = 0.5 * ( + a / (a + b + c + SMALL_NUMBER) + d / (d + b + c + SMALL_NUMBER) + ) self.normalize_fn["shift_"] = 0.0 self.normalize_fn["scale_"] = 1.0 return self._normalize(similarity_) @@ -1300,8 +1254,7 @@ def _get_jaccard(self, mol1_descriptor, mol2_descriptor): Returns: (float): Jaccard similarity value """ - if not (mol1_descriptor.is_fingerprint() - and mol2_descriptor.is_fingerprint()): + if not (mol1_descriptor.is_fingerprint() and mol2_descriptor.is_fingerprint()): raise ValueError( "Jaccard similarity is only useful for bit strings " "generated from fingerprints. Consider using " @@ -1327,8 +1280,7 @@ def _get_kulczynski(self, mol1_descriptor, mol2_descriptor): Returns: (float): Kulczynski similarity value """ - if not (mol1_descriptor.is_fingerprint() - and mol2_descriptor.is_fingerprint()): + if not (mol1_descriptor.is_fingerprint() and mol2_descriptor.is_fingerprint()): raise ValueError( "Kulczynski similarity is only useful for bit strings " "generated from fingerprints. Consider using " @@ -1354,8 +1306,7 @@ def _get_michael(self, mol1_descriptor, mol2_descriptor): Returns: (float): Michael similarity value """ - if not (mol1_descriptor.is_fingerprint() - and mol2_descriptor.is_fingerprint()): + if not (mol1_descriptor.is_fingerprint() and mol2_descriptor.is_fingerprint()): raise ValueError( "Michael similarity is only useful for bit strings " "generated from fingerprints. Consider using " @@ -1383,8 +1334,7 @@ def _get_maxwell_pilliner(self, mol1_descriptor, mol2_descriptor): Returns: (float): Maxwell-Pilliner similarity value """ - if not (mol1_descriptor.is_fingerprint() - and mol2_descriptor.is_fingerprint()): + if not (mol1_descriptor.is_fingerprint() and mol2_descriptor.is_fingerprint()): raise ValueError( "Maxwell-Pilliner similarity is only useful for bit strings " "generated from fingerprints. Consider using " @@ -1415,8 +1365,7 @@ def _get_mountford(self, mol1_descriptor, mol2_descriptor): Returns: (float): Mountford similarity value """ - if not (mol1_descriptor.is_fingerprint() - and mol2_descriptor.is_fingerprint()): + if not (mol1_descriptor.is_fingerprint() and mol2_descriptor.is_fingerprint()): raise ValueError( "Mountford similarity is only useful for bit strings " "generated from fingerprints. Consider using " @@ -1445,8 +1394,7 @@ def _get_pearson_heron(self, mol1_descriptor, mol2_descriptor): Returns: (float): Pearson-Heron similarity value """ - if not (mol1_descriptor.is_fingerprint() - and mol2_descriptor.is_fingerprint()): + if not (mol1_descriptor.is_fingerprint() and mol2_descriptor.is_fingerprint()): raise ValueError( "Pearson-Heron similarity is only useful for bit strings " "generated from fingerprints. Consider using " @@ -1480,8 +1428,7 @@ def _get_peirce_1(self, mol1_descriptor, mol2_descriptor): Returns: (float): Peirce(1) similarity value """ - if not (mol1_descriptor.is_fingerprint() - and mol2_descriptor.is_fingerprint()): + if not (mol1_descriptor.is_fingerprint() and mol2_descriptor.is_fingerprint()): raise ValueError( "Peirce(1) similarity is only useful for bit strings " "generated from fingerprints. Consider using " @@ -1510,8 +1457,7 @@ def _get_peirce_2(self, mol1_descriptor, mol2_descriptor): Returns: (float): Peirce(2) similarity value """ - if not (mol1_descriptor.is_fingerprint() - and mol2_descriptor.is_fingerprint()): + if not (mol1_descriptor.is_fingerprint() and mol2_descriptor.is_fingerprint()): raise ValueError( "Peirce(2) similarity is only useful for bit strings " "generated from fingerprints. Consider using " @@ -1540,8 +1486,7 @@ def _get_rogers_tanimoto(self, mol1_descriptor, mol2_descriptor): Returns: (float): Rogers-Tanimoto similarity value """ - if not (mol1_descriptor.is_fingerprint() - and mol2_descriptor.is_fingerprint()): + if not (mol1_descriptor.is_fingerprint() and mol2_descriptor.is_fingerprint()): raise ValueError( "Rogers-Tanimoto similarity is only useful for bit strings " "generated from fingerprints. Consider using " @@ -1566,8 +1511,7 @@ def _get_rogot_goldberg(self, mol1_descriptor, mol2_descriptor): Returns: (float): Rogot-Goldberg similarity value """ - if not (mol1_descriptor.is_fingerprint() - and mol2_descriptor.is_fingerprint()): + if not (mol1_descriptor.is_fingerprint() and mol2_descriptor.is_fingerprint()): raise ValueError( "Rogot-Goldberg similarity is only useful for bit strings " "generated from fingerprints. Consider using " @@ -1594,8 +1538,7 @@ def _get_russel_rao(self, mol1_descriptor, mol2_descriptor): Returns: (float): Russel-Rao similarity value """ - if not (mol1_descriptor.is_fingerprint() - and mol2_descriptor.is_fingerprint()): + if not (mol1_descriptor.is_fingerprint() and mol2_descriptor.is_fingerprint()): raise ValueError( "Russel-Rao similarity is only useful for bit strings " "generated from fingerprints. Consider using " @@ -1620,8 +1563,7 @@ def _get_simple_matching(self, mol1_descriptor, mol2_descriptor): Returns: (float): Simple Matching similarity value """ - if not (mol1_descriptor.is_fingerprint() - and mol2_descriptor.is_fingerprint()): + if not (mol1_descriptor.is_fingerprint() and mol2_descriptor.is_fingerprint()): raise ValueError( "Simple Matching similarity is only useful for bit strings " "generated from fingerprints. Consider using " @@ -1646,8 +1588,7 @@ def _get_simpson(self, mol1_descriptor, mol2_descriptor): Returns: (float): Simpson similarity value """ - if not (mol1_descriptor.is_fingerprint() - and mol2_descriptor.is_fingerprint()): + if not (mol1_descriptor.is_fingerprint() and mol2_descriptor.is_fingerprint()): raise ValueError( "Simpson similarity is only useful for bit strings " "generated from fingerprints. Consider using " @@ -1673,8 +1614,7 @@ def _get_sokal_sneath(self, mol1_descriptor, mol2_descriptor): Returns: (float): Sokal-Sneath similarity value """ - if not (mol1_descriptor.is_fingerprint() - and mol2_descriptor.is_fingerprint()): + if not (mol1_descriptor.is_fingerprint() and mol2_descriptor.is_fingerprint()): raise ValueError( "Sokal-Sneath similarity is only useful for bit strings " "generated from fingerprints. Consider using " @@ -1700,8 +1640,7 @@ def _get_symmetric_sokal_sneath(self, mol1_descriptor, mol2_descriptor): Returns: (float): Symmetric Sokal-Sneath similarity value """ - if not (mol1_descriptor.is_fingerprint() - and mol2_descriptor.is_fingerprint()): + if not (mol1_descriptor.is_fingerprint() and mol2_descriptor.is_fingerprint()): raise ValueError( "Symmetric Sokal-Sneath similarity is only useful " "for bit strings generated from fingerprints. Consider " @@ -1727,8 +1666,7 @@ def _get_sokal_sneath_3(self, mol1_descriptor, mol2_descriptor): Returns: (float): Sokal-Sneath(3) similarity value """ - if not (mol1_descriptor.is_fingerprint() - and mol2_descriptor.is_fingerprint()): + if not (mol1_descriptor.is_fingerprint() and mol2_descriptor.is_fingerprint()): raise ValueError( "Sokal-Sneath(3) similarity is only useful for bit strings " "generated from fingerprints. Consider using " @@ -1740,10 +1678,12 @@ def _get_sokal_sneath_3(self, mol1_descriptor, mol2_descriptor): return 1.0 if a < SMALL_NUMBER and d < SMALL_NUMBER: return 0.0 - similarity_ = (1 / 4) * (a / (a + b + SMALL_NUMBER) - + a / (a + c + SMALL_NUMBER) - + d / (b + d + SMALL_NUMBER) - + d / (c + d + SMALL_NUMBER)) + similarity_ = (1 / 4) * ( + a / (a + b + SMALL_NUMBER) + + a / (a + c + SMALL_NUMBER) + + d / (b + d + SMALL_NUMBER) + + d / (c + d + SMALL_NUMBER) + ) self.normalize_fn["shift_"] = 0.0 self.normalize_fn["scale_"] = 1.0 return self._normalize(similarity_) @@ -1761,8 +1701,7 @@ def _get_sokal_sneath_4(self, mol1_descriptor, mol2_descriptor): Returns: (float): Sokal-Sneath(4) similarity value """ - if not (mol1_descriptor.is_fingerprint() - and mol2_descriptor.is_fingerprint()): + if not (mol1_descriptor.is_fingerprint() and mol2_descriptor.is_fingerprint()): raise ValueError( "Sokal-Sneath(4) similarity is only useful for bit strings " "generated from fingerprints. Consider using " @@ -1774,8 +1713,12 @@ def _get_sokal_sneath_4(self, mol1_descriptor, mol2_descriptor): return 1.0 if a < SMALL_NUMBER or d < SMALL_NUMBER: return 0.0 - similarity_ = a / (np.sqrt((a + b) * (a + c)) + SMALL_NUMBER) \ - * d / (np.sqrt((b + d) * (c + d) + SMALL_NUMBER)) + similarity_ = ( + a + / (np.sqrt((a + b) * (a + c)) + SMALL_NUMBER) + * d + / (np.sqrt((b + d) * (c + d) + SMALL_NUMBER)) + ) self.normalize_fn["shift_"] = 0.0 self.normalize_fn["scale_"] = 1.0 @@ -1793,8 +1736,7 @@ def _get_sorgenfrei(self, mol1_descriptor, mol2_descriptor): Returns: (float): Sorgenfrei similarity value """ - if not (mol1_descriptor.is_fingerprint() - and mol2_descriptor.is_fingerprint()): + if not (mol1_descriptor.is_fingerprint() and mol2_descriptor.is_fingerprint()): raise ValueError( "Sorgenfrei similarity is only useful " "for bit strings generated from fingerprints. Consider " @@ -1803,7 +1745,7 @@ def _get_sorgenfrei(self, mol1_descriptor, mol2_descriptor): a, b, c, d = self._get_abcd(mol1_descriptor, mol2_descriptor) if a < SMALL_NUMBER: return 0.0 - similarity_ = a ** 2 / ((a + b) * (a + c)) + similarity_ = a**2 / ((a + b) * (a + c)) self.normalize_fn["shift_"] = 0.0 self.normalize_fn["scale_"] = 1.0 return self._normalize(similarity_) @@ -1820,8 +1762,7 @@ def _get_yule_1(self, mol1_descriptor, mol2_descriptor): Returns: (float): Yule(1) similarity value """ - if not (mol1_descriptor.is_fingerprint() - and mol2_descriptor.is_fingerprint()): + if not (mol1_descriptor.is_fingerprint() and mol2_descriptor.is_fingerprint()): raise ValueError( "Yule(1) similarity is only useful " "for bit strings generated from fingerprints. Consider " @@ -1830,7 +1771,7 @@ def _get_yule_1(self, mol1_descriptor, mol2_descriptor): a, b, c, d = self._get_abcd(mol1_descriptor, mol2_descriptor) p = a + b + c + d denominator = a * d + b * c + SMALL_NUMBER - if a == p or d == p or b*c < SMALL_NUMBER: + if a == p or d == p or b * c < SMALL_NUMBER: return 1.0 similarity_ = (a * d - b * c) / denominator self.normalize_fn["shift_"] = 1.0 @@ -1850,8 +1791,7 @@ def _get_yule_2(self, mol1_descriptor, mol2_descriptor): Returns: (float): Yule(2) similarity value """ - if not (mol1_descriptor.is_fingerprint() - and mol2_descriptor.is_fingerprint()): + if not (mol1_descriptor.is_fingerprint() and mol2_descriptor.is_fingerprint()): raise ValueError( "Yule(2) similarity is only useful " "for bit strings generated from fingerprints. Consider " @@ -1887,8 +1827,7 @@ def _get_abcd(self, fingerprint1, fingerprint2): to the length of the smaller array. """ - arr1, arr2 = Descriptor.fold_to_equal_length( - fingerprint1, fingerprint2) + arr1, arr2 = Descriptor.fold_to_equal_length(fingerprint1, fingerprint2) not_arr1 = np.logical_not(arr1) not_arr2 = np.logical_not(arr2) a = np.sum(arr1 & arr2) @@ -2006,11 +1945,11 @@ def get_supported_binary_metrics(): "hawkins-dotson", "maxwell-pilliner", "harris-lahey", - "consonni−todeschini-1", - "consonni−todeschini-2", - "consonni−todeschini-3", - "consonni−todeschini-4", - "consonni−todeschini-5", + "consonni-todeschini-1", + "consonni-todeschini-2", + "consonni-todeschini-3", + "consonni-todeschini-4", + "consonni-todeschini-5", "yule-1", "yule_1", "yule_2", @@ -2027,8 +1966,8 @@ def get_supported_binary_metrics(): "cole_2", "dispersion", "choi", - "goodman−kruskal", - "pearson−heron", + "goodman-kruskal", + "pearson-heron", "sorgenfrei", "cohen", "peirce_1", @@ -2086,16 +2025,16 @@ def get_supported_metrics(): "hawkins-dotson", "maxwell-pilliner", "harris-lahey", - "consonni−todeschini-1", - "consonni−todeschini-2", - "consonni−todeschini-3", - "consonni−todeschini-4", - "consonni−todeschini-5", - "consonni−todeschini_1", - "consonni−todeschini_2", - "consonni−todeschini_3", - "consonni−todeschini_4", - "consonni−todeschini_5", + "consonni-todeschini-1", + "consonni-todeschini-2", + "consonni-todeschini-3", + "consonni-todeschini-4", + "consonni-todeschini-5", + "consonni-todeschini_1", + "consonni-todeschini_2", + "consonni-todeschini_3", + "consonni-todeschini_4", + "consonni-todeschini_5", "austin-colwell", "yule-1", "yule_1", @@ -2113,14 +2052,14 @@ def get_supported_metrics(): "cole_2", "dispersion", "choi", - "goodman−kruskal", - "pearson−heron", + "goodman-kruskal", + "pearson-heron", "sorgenfrei", "cohen", "peirce_1", "peirce-1", "peirce_2", - "peirce-2" + "peirce-2", ] @staticmethod @@ -2161,11 +2100,11 @@ def get_uniq_metrics(): "hawkins-dotson", "maxwell-pilliner", "harris-lahey", - "consonni−todeschini-1", - "consonni−todeschini-2", - "consonni−todeschini-3", - "consonni−todeschini-4", - "consonni−todeschini-5", + "consonni-todeschini-1", + "consonni-todeschini-2", + "consonni-todeschini-3", + "consonni-todeschini-4", + "consonni-todeschini-5", "austin-colwell", "yule-1", "yule_2", @@ -2174,8 +2113,8 @@ def get_uniq_metrics(): "cole-1", "cole-2", "dispersion", - "goodman−kruskal", - "pearson−heron", + "goodman-kruskal", + "pearson-heron", "sorgenfrei", "cohen", "peirce-1", diff --git a/docs/_sources/implemented_metrics.rst.txt b/docs/_sources/implemented_metrics.rst.txt index d3efad22..efe0ef4b 100644 --- a/docs/_sources/implemented_metrics.rst.txt +++ b/docs/_sources/implemented_metrics.rst.txt @@ -122,24 +122,24 @@ Supported Similarity Metrics - - - - * - 29 - - consonni−todeschini_1 - - consonni−todeschini-1 + - consonni-todeschini_1 + - consonni-todeschini-1 - Yes * - 30 - - consonni−todeschini_2 - - consonni−todeschini-2 + - consonni-todeschini_2 + - consonni-todeschini-2 - - * - 31 - - consonni−todeschini_3 - - consonni−todeschini-3 + - consonni-todeschini_3 + - consonni-todeschini-3 - - * - 32 - - consonni−todeschini_4 - - consonni−todeschini-4 + - consonni-todeschini_4 + - consonni-todeschini-4 - - * - 33 - - consonni−todeschini_5 - - consonni−todeschini-5 + - consonni-todeschini_5 + - consonni-todeschini-5 - Yes * - 34 - austin-colwell diff --git a/implemented_metrics.md b/implemented_metrics.md index 56692e38..92c5e65e 100644 --- a/implemented_metrics.md +++ b/implemented_metrics.md @@ -29,11 +29,11 @@ | 26 | hawkins-dotson | - | Yes | | 27 | maxwell-pilliner | - | Yes | | 28 | harris-lahey | - | - | -| 29 | consonni−todeschini\_1 | consonni−todeschini-1 | Yes | -| 30 | consonni−todeschini\_2 | consonni−todeschini-2 | - | -| 31 | consonni−todeschini\_3 | consonni−todeschini-3 | - | -| 32 | consonni−todeschini\_4 | consonni−todeschini-4 | - | -| 33 | consonni−todeschini\_5 | consonni−todeschini-5 | Yes | +| 29 | consonni-todeschini\_1 | consonni-todeschini-1 | Yes | +| 30 | consonni-todeschini\_2 | consonni-todeschini-2 | - | +| 31 | consonni-todeschini\_3 | consonni-todeschini-3 | - | +| 32 | consonni-todeschini\_4 | consonni-todeschini-4 | - | +| 33 | consonni-todeschini\_5 | consonni-todeschini-5 | Yes | | 34 | austin-colwell | - | Yes | | 35 | yule\_1 | yule-1 | - | | 36 | yule\_2 | yule-2 | Yes | From c5db64e8f8f1cbeecb827696cc16d10913aab3eb Mon Sep 17 00:00:00 2001 From: Jackson Burns <33505528+JacksonBurns@users.noreply.github.com> Date: Wed, 8 Feb 2023 14:35:10 -0500 Subject: [PATCH 30/35] whitespace formatting in molecule_set fix --- aimsim/chemical_datastructures/molecule_set.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aimsim/chemical_datastructures/molecule_set.py b/aimsim/chemical_datastructures/molecule_set.py index 8cf8a971..c187e745 100644 --- a/aimsim/chemical_datastructures/molecule_set.py +++ b/aimsim/chemical_datastructures/molecule_set.py @@ -800,7 +800,7 @@ def get_most_similar_pairs(self): n_samples = self.similarity_matrix.shape[0] for index, row in enumerate(self.similarity_matrix): post_diag_closest_index = ( - np.argmax(row[(index + 1) :]) + index + 1 + np.argmax(row[(index + 1):]) + index + 1 if index < n_samples - 1 else -1 ) From 1b34656e13004c589c9ac96e138959ab69578b44 Mon Sep 17 00:00:00 2001 From: Jackson Burns Date: Wed, 8 Feb 2023 14:50:01 -0500 Subject: [PATCH 31/35] formatting in measure search test, abspath for window --- tests/test_MeasureSearch.py | 115 +++++++++++++++++------------------- 1 file changed, 53 insertions(+), 62 deletions(-) diff --git a/tests/test_MeasureSearch.py b/tests/test_MeasureSearch.py index 33539026..c46410e9 100644 --- a/tests/test_MeasureSearch.py +++ b/tests/test_MeasureSearch.py @@ -48,84 +48,81 @@ def smiles_seq_to_textfile(self, property_seq=None): return text_fpath def test_msearch_init(self): - """Basic initialization test for the MeasureSearch class. - """ + """Basic initialization test for the MeasureSearch class.""" msearch = MeasureSearch() self.assertIsInstance(msearch, MeasureSearch) self.assertIsNone(msearch.log_fpath) self.assertIsInstance(msearch.__str__(), str) def test_msearch_init_error(self): - """Erroneous confirgurations should raise a config error. - """ + """Erroneous confirgurations should raise a config error.""" with self.assertRaises(InvalidConfigurationError): - msearch = MeasureSearch(correlation_type='invalid name') + msearch = MeasureSearch(correlation_type="invalid name") def test_msearch_completion(self): - """MeasureSearch should complete running, though output cannot be directly tested. - """ + """MeasureSearch should complete running, though output cannot be directly tested.""" properties = np.random.normal(size=len(self.test_smiles)) text_fpath = self.smiles_seq_to_textfile(property_seq=properties) msearch = MeasureSearch() try: msearch.get_best_measure( molecule_set_configs={ - 'molecule_database_src': text_fpath, - 'molecule_database_src_type': 'text', + "molecule_database_src": text_fpath, + "molecule_database_src_type": "text", }, - subsample_subset_size=1.0 + subsample_subset_size=1.0, ) except Exception as e: self.fail("MeasureSearch failed basic no-args test.") remove(text_fpath) def test_logfile_generation(self): - """When configured to do so, MeasureSearch should create a log file. - """ + """When configured to do so, MeasureSearch should create a log file.""" properties = np.random.normal(size=len(self.test_smiles)) text_fpath = self.smiles_seq_to_textfile(property_seq=properties) - log_dir_name = 'molSim_msearch_logs' - log_dir_path = join(getcwd(), log_dir_name) - log_file_path = join(log_dir_path, 'logs.json') + log_dir_name = "molSim_msearch_logs" + log_dir_path = join(abspath(getcwd()), log_dir_name) + log_file_path = join(log_dir_path, "logs.json") msearch = MeasureSearch(log_file_path=log_file_path) - _ = msearch(molecule_set_configs={ - 'molecule_database_src': text_fpath, - 'molecule_database_src_type': 'text'}, - subsample_subset_size=1.0) + _ = msearch( + molecule_set_configs={ + "molecule_database_src": text_fpath, + "molecule_database_src_type": "text", + }, + subsample_subset_size=1.0, + ) self.assertTrue(isfile(log_file_path)) self.assertTrue(isdir(log_dir_path)) rmtree(log_dir_path) def test_fixed_fprint(self): - """MeasureSearch should search for ideal metric when fingerprint is already chosen. - """ + """MeasureSearch should search for ideal metric when fingerprint is already chosen.""" properties = np.random.normal(size=len(self.test_smiles)) text_fpath = self.smiles_seq_to_textfile(property_seq=properties) msearch = MeasureSearch() try: msearch.get_best_measure( molecule_set_configs={ - 'molecule_database_src': text_fpath, - 'molecule_database_src_type': 'text', + "molecule_database_src": text_fpath, + "molecule_database_src_type": "text", }, subsample_subset_size=1.0, - fingerprint_type='morgan_fingerprint', + fingerprint_type="morgan_fingerprint", ) except Exception as e: self.fail("MeasureSearch failed fixed fingerprint test.") remove(text_fpath) def test_only_metric_search(self): - """Check that this configuration option is able to execute. - """ + """Check that this configuration option is able to execute.""" properties = np.random.normal(size=len(self.test_smiles)) text_fpath = self.smiles_seq_to_textfile(property_seq=properties) msearch = MeasureSearch() try: msearch.get_best_measure( molecule_set_configs={ - 'molecule_database_src': text_fpath, - 'molecule_database_src_type': 'text', + "molecule_database_src": text_fpath, + "molecule_database_src_type": "text", }, subsample_subset_size=1.0, only_metric=True, @@ -135,40 +132,38 @@ def test_only_metric_search(self): remove(text_fpath) def test_only_metric_fixed_measure_search(self): - """Check that this configuration option is able to execute. - """ + """Check that this configuration option is able to execute.""" properties = np.random.normal(size=len(self.test_smiles)) text_fpath = self.smiles_seq_to_textfile(property_seq=properties) msearch = MeasureSearch() try: msearch.get_best_measure( molecule_set_configs={ - 'molecule_database_src': text_fpath, - 'molecule_database_src_type': 'text', + "molecule_database_src": text_fpath, + "molecule_database_src_type": "text", }, subsample_subset_size=1.0, only_metric=True, - similarity_measure='tanimoto', + similarity_measure="tanimoto", ) except Exception as e: self.fail("MeasureSearch failed fixed metric test.") remove(text_fpath) def test_only_metric_fixed_fprint_search(self): - """Check that this configuration option is able to execute. - """ + """Check that this configuration option is able to execute.""" properties = np.random.normal(size=len(self.test_smiles)) text_fpath = self.smiles_seq_to_textfile(property_seq=properties) msearch = MeasureSearch() try: msearch.get_best_measure( molecule_set_configs={ - 'molecule_database_src': text_fpath, - 'molecule_database_src_type': 'text', + "molecule_database_src": text_fpath, + "molecule_database_src_type": "text", }, subsample_subset_size=1.0, only_metric=True, - fingerprint_type='morgan_fingerprint', + fingerprint_type="morgan_fingerprint", ) except Exception as e: self.fail("MeasureSearch failed fixed metric test.") @@ -176,7 +171,7 @@ def test_only_metric_fixed_fprint_search(self): def test_fixed_SimilarityMeasure(self): """MeasureSearch should search for ideal fingerprint when metric is - already chosen. + already chosen. """ properties = np.random.normal(size=len(self.test_smiles)) text_fpath = self.smiles_seq_to_textfile(property_seq=properties) @@ -184,28 +179,27 @@ def test_fixed_SimilarityMeasure(self): try: msearch.get_best_measure( molecule_set_configs={ - 'molecule_database_src': text_fpath, - 'molecule_database_src_type': 'text', + "molecule_database_src": text_fpath, + "molecule_database_src_type": "text", }, subsample_subset_size=1.0, - similarity_measure='tanimoto', + similarity_measure="tanimoto", ) except Exception as e: self.fail("MeasureSearch failed fixed metric test.") remove(text_fpath) def test_verbose_output(self): - """Ensure execution does not raise an exception with verbose and show_top. - """ + """Ensure execution does not raise an exception with verbose and show_top.""" properties = np.random.normal(size=len(self.test_smiles)) text_fpath = self.smiles_seq_to_textfile(property_seq=properties) msearch = MeasureSearch() try: msearch.get_best_measure( molecule_set_configs={ - 'molecule_database_src': text_fpath, - 'molecule_database_src_type': 'text', - 'is_verbose': True, + "molecule_database_src": text_fpath, + "molecule_database_src_type": "text", + "is_verbose": True, }, subsample_subset_size=1.0, show_top=5, @@ -217,57 +211,54 @@ def test_verbose_output(self): pass def test_max_optim_algo(self): - """Measure search using the "maximum" optimization algorithm. - """ + """Measure search using the "maximum" optimization algorithm.""" properties = np.random.normal(size=len(self.test_smiles)) text_fpath = self.smiles_seq_to_textfile(property_seq=properties) msearch = MeasureSearch() try: msearch.get_best_measure( molecule_set_configs={ - 'molecule_database_src': text_fpath, - 'molecule_database_src_type': 'text', + "molecule_database_src": text_fpath, + "molecule_database_src_type": "text", }, subsample_subset_size=1.0, - optim_algo='max', + optim_algo="max", ) except Exception as e: self.fail("MeasureSearch failed max optim_algo test.") remove(text_fpath) def test_min_optim_algo(self): - """Measure search using the "minimum" optimization algorithm. - """ + """Measure search using the "minimum" optimization algorithm.""" properties = np.random.normal(size=len(self.test_smiles)) text_fpath = self.smiles_seq_to_textfile(property_seq=properties) msearch = MeasureSearch() try: msearch.get_best_measure( molecule_set_configs={ - 'molecule_database_src': text_fpath, - 'molecule_database_src_type': 'text', + "molecule_database_src": text_fpath, + "molecule_database_src_type": "text", }, subsample_subset_size=1.0, - optim_algo='min', + optim_algo="min", ) except Exception as e: self.fail("MeasureSearch failed min optim_algo test.") remove(text_fpath) def test_error_optim_algo(self): - """Measure search should error with invalid optimization algorithm. - """ + """Measure search should error with invalid optimization algorithm.""" properties = np.random.normal(size=len(self.test_smiles)) text_fpath = self.smiles_seq_to_textfile(property_seq=properties) msearch = MeasureSearch() with self.assertRaises(InvalidConfigurationError): msearch.get_best_measure( molecule_set_configs={ - 'molecule_database_src': text_fpath, - 'molecule_database_src_type': 'text', + "molecule_database_src": text_fpath, + "molecule_database_src_type": "text", }, subsample_subset_size=1.0, - optim_algo='fake algo', + optim_algo="fake algo", ) remove(text_fpath) From 73c6157f8416bbe5751a139638a6ec91c829bea4 Mon Sep 17 00:00:00 2001 From: Jackson Burns Date: Wed, 8 Feb 2023 18:15:52 -0500 Subject: [PATCH 32/35] switch filepath to be cross-platform --- aimsim/tasks/measure_search.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aimsim/tasks/measure_search.py b/aimsim/tasks/measure_search.py index 8462e502..48fdcd30 100644 --- a/aimsim/tasks/measure_search.py +++ b/aimsim/tasks/measure_search.py @@ -4,7 +4,7 @@ from collections import namedtuple import json from os import makedirs -from posixpath import dirname +from os.path import dirname import numpy as np From 075238fd33e6c5cb2b65023e4f3cba6a5d9b3312 Mon Sep 17 00:00:00 2001 From: Jackson Burns Date: Wed, 8 Feb 2023 18:54:37 -0500 Subject: [PATCH 33/35] bump version --- aimsim/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aimsim/__init__.py b/aimsim/__init__.py index a7c082c0..c92bd7f7 100644 --- a/aimsim/__init__.py +++ b/aimsim/__init__.py @@ -3,4 +3,4 @@ from . import chemical_datastructures from . import utils -__version__ = "1.1.2" +__version__ = "2.0.0" From 762807546d218ed340e14e71aac08bb254f90046 Mon Sep 17 00:00:00 2001 From: Jackson Burns Date: Wed, 8 Feb 2023 19:04:26 -0500 Subject: [PATCH 34/35] remove python 3.6 from setup --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 607afb08..3276d0ff 100644 --- a/setup.py +++ b/setup.py @@ -27,7 +27,7 @@ def get_version(rel_path): setup( name="aimsim", - python_requires=">=3.6", + python_requires=">=3.7", version=get_version("aimsim/__init__.py"), description=desc, long_description=README, From bceaafb8afaa86b135eea3346296de2f53f58d02 Mon Sep 17 00:00:00 2001 From: Jackson Burns Date: Wed, 8 Feb 2023 19:05:58 -0500 Subject: [PATCH 35/35] bump patch version --- aimsim/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aimsim/__init__.py b/aimsim/__init__.py index c92bd7f7..9ef55638 100644 --- a/aimsim/__init__.py +++ b/aimsim/__init__.py @@ -3,4 +3,4 @@ from . import chemical_datastructures from . import utils -__version__ = "2.0.0" +__version__ = "2.0.1"