diff --git a/CHANGELOG b/CHANGELOG new file mode 100644 index 00000000..2a8b363f --- /dev/null +++ b/CHANGELOG @@ -0,0 +1,11 @@ +## [0.6] - 2022-12-05 +### Removed +- Removed invalid docker code + +### Fixed +- Moved doc files out of package +- Cleaned up installation disorder + +### Added +- `MANIFEST.in` for two files which are required by the package +- Submodule `quick` for a quick download of the data as it appears on the site, which is what most folks want anyway \ No newline at end of file diff --git a/Dockerfile b/Dockerfile deleted file mode 100755 index 27f716a6..00000000 --- a/Dockerfile +++ /dev/null @@ -1,9 +0,0 @@ -FROM conda/miniconda3 -ADD . /code -RUN apt-get update -y -RUN apt-get install -y build-essential python-dev python-pmw libglew-dev freeglut3-dev libpng-dev libfreetype6-dev libxml2-dev libmsgpack-dev python-pyqt5.qtopengl libglm-dev libnetcdf-dev -RUN apt-get install -y git-all -RUN chmod 775 /code/docker_install.sh -RUN /code/docker_install.sh -RUN conda init bash -RUN cd /code; conda env create -f environment.yml diff --git a/MANIFEST.in b/MANIFEST.in new file mode 100644 index 00000000..594fb4fd --- /dev/null +++ b/MANIFEST.in @@ -0,0 +1,2 @@ +include fragalysis-api/fragalysis_api/xcglobalscripts/config.ini +include fragalysis_api/xcimporter/non_ligs.json \ No newline at end of file diff --git a/README.md b/README.md index fd91bf5c..b26850fd 100755 --- a/README.md +++ b/README.md @@ -4,50 +4,44 @@ [![Language grade: Python](https://img.shields.io/lgtm/grade/python/g/xchem/fragalysis-api.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/xchem/fragalysis-api/context:python) -Documentation: https://xchem.github.io/fragalysis-api/ +Documentation: [https://xchem.github.io/fragalysis-api/](https://xchem.github.io/fragalysis-api/) -This api aims to allow any user to upload pdb files from the pdb or that they have created themselves, +This API aims to allow any user to upload pdb files from the pdb or that they have created themselves, and analyse the ligand binding using the fragalysis webpage (https://fragalysis.diamond.ac.uk). +Namely: + +* Upload data, i.e. import into Fragalysis -> **xcimporter** functionality (_vide infra_) +* Download data, i.e. export from Fragalysis -> **xcexporter** functionality (_vide infra_) + +The full list of Fragalysis API endpoints can be found at [fragalysis.diamond.ac.uk/api](https://fragalysis.diamond.ac.uk/api/). ## Installation -Starting out by initialising an environment and activating it. -Clone the repository and cd to the relevant directory. -Install rdkit via conda, and the other dependencies via the setup.py file: +In order to manipulate the data for upload (e.g. aligning crystal maps), +some additional dependencies are required, +namely [xchem/gemmi_pandda](https://github.com/xchem/gemmi_pandda) and [xchem/pandda_gemmi](https://github.com/xchem/pandda_gemmi). ```bash -conda create -n fragalysis_env anaconda -y -conda activate fragalysis_env -conda install -c conda-forge rdkit -y - -# Install our-bespoke version of gemmi # Required -git clone https://github.com/xchem/gemmi_pandda.git -cd gemmi_pandda/ -pip install -U --force-reinstall . -cd .. - -# Also Required -git clone https://github.com/xchem/pandda_gemmi.git -cd pandda_gemmi/ -pip install -e . -cd .. - -# Finally install the api -git clone "https://github.com/xchem/fragalysis-api.git" -cd fragalysis-api/ -pip install -e . -cd .. -``` +# Install our-bespoke version of gemmi # Required for upload +# Do note this is a drop-in replacement for gemmi, so will interfere with other packages that use gemmi. +pip install -U --force-reinstall git+https://github.com/xchem/gemmi_pandda.git -You can check if it has installed using: `conda list` +# Also Required for upload +pip install -e git+https://github.com/xchem/pandda_gemmi.git +``` +The API itself can be installed via pypi or from the Git repo: +```bash +pip install fragalysis-api +# or (for a later version if available) +pip install git+https://github.com/xchem/fragalysis-api.git +``` ### How to use API -1. Set up environment -2. Download PDB files and query the PDB for structures of the same protein bound to the same or different ligands -3. Submit PDB files - you will be given a query ID -4. Push your files into fragalysis and view them online :construction: -5. Analyse the binding of ligands to your target protein! +1. Download PDB files and query the PDB for structures of the same protein bound to the same or different ligands +2. Submit PDB files - you will be given a query ID +3. Push your files into fragalysis and view them online :construction: +4. Analyse the binding of ligands to your target protein! Other functionalities that are available: @@ -59,9 +53,40 @@ Other functionalities that are available: ## Usage in Python +### Export from Fragalysis +> TL;DR: This is a Python package for accurately interacting with the Fragalysis API, +> if you simply want to download everything of a target, +> please see the [quick download notes](quick_download.md). + +Download relevant data off Fragalysis. + + +See also [extractor notes](extractor.md). + +```python +import fragalysis_api +import os +import pandas as pd + +hit_data: pd.DataFrame = fragalysis_api.xcextracter(target_name='NUDT5A') +``` +The columns in the dataframe are: + +* `id` +* `prot_id`: unique integer id per crystal, e.g. `protein_code`:`NUDT5A-x0114_1` and `protein_code`:`NUDT5A-x0114_2` have different `prot_id` but same `cmpd_id`. +* `protein_code`, a string form of the above (e.g. `NUDT5A-x0114_1`) +* `cmpd_id`, an integer, unique per ligand, but not per crystal +* `lig_id`, the chemical compounent name, generally `LIG` +* `chain_id`, the chain id of the ligand +* `smiles` and `sdf_info`, the SMILE-String and the SDF block of the ligand +* `molecule_protein`, the bound PDB file address +* `mw`, `logp`, `tpsa`, `ha`, `hacc`, `hdon`, `rots`, `rings`, `velec`: inferred chemical properties of the ligand + +### Import into Fragalysis To prepare input data-files using python you api can import the `xcimporer` or `import_single_file` functions and then provide the necessary values to the functions. + See also [importer notes](importer.md). -e.g +Example: ```python from fragalysis_api import xcimporter, import_single_file @@ -209,8 +234,8 @@ A description of the arguments are as follows: ### Enforced rules :scroll: -- The pdb file shall not be greater than 5mb. -- The pdb filename shall not contain non English language ascii characters +- The pdb file shall not be greater than 5MB. +- The pdb filename shall only contain non ASCII characters (e.g. Unicode characters such as é or ü). and shall be between 4 and 20 characters in length. - Each pdb file for alignment shall contain the same number of chains. - All pdb files to be aligned must be in the same directory. diff --git a/fragalysis_api/xcextracter/benzene.pdb b/data/benzene.pdb similarity index 100% rename from fragalysis_api/xcextracter/benzene.pdb rename to data/benzene.pdb diff --git a/docker_install.sh b/docker_install.sh deleted file mode 100755 index 4dd69165..00000000 --- a/docker_install.sh +++ /dev/null @@ -1,7 +0,0 @@ -#!/bin/bash - -git clone https://github.com/schrodinger/pymol-open-source.git -cd pymol-open-source -prefix=$HOME/pymol-open-source-build -# sudo apt-get install build-essential python-dev python-pmw libglew-dev freeglut3-dev libpng-dev libfreetype6-dev libxml2-dev libmsgpack-dev python-pyqt5.qtopengl libglm-dev libnetcdf-dev -python setup.py build install --home=$prefix diff --git a/fragalysis_api/xcextracter/README.md b/extractor.md similarity index 100% rename from fragalysis_api/xcextracter/README.md rename to extractor.md diff --git a/fragalysis_api/__init__.py b/fragalysis_api/__init__.py index 935c9896..067de7f4 100755 --- a/fragalysis_api/__init__.py +++ b/fragalysis_api/__init__.py @@ -1,15 +1,28 @@ -from .xcglobalscripts.set_config import ConfigSetup - -from .xcimporter.validate import Validate, ValidatePDB -from .xcimporter.conversion_pdb_mol import set_up, convert_small_AA_chains, copy_extra_files -from .xcimporter.align import Align -from .xcimporter.xc_utils import to_fragalysis_dir -from .xcimporter.sites import Sites, contextualize_crystal_ligands -from .xcimporter.xcimporter import xcimporter -from .xcimporter.single_import import import_single_file +from .xcglobalscripts.set_config import ConfigSetup # this requires `config.ini` in the working directory + +# import into Fragalysis requires gemmi +try: + from .xcimporter.validate import Validate, ValidatePDB + from .xcimporter.conversion_pdb_mol import set_up, convert_small_AA_chains, copy_extra_files + from .xcimporter.xc_utils import to_fragalysis_dir + from .xcimporter.sites import Sites, contextualize_crystal_ligands + from .xcimporter.xcimporter import xcimporter + from .xcimporter.single_import import import_single_file + from .xcimporter.align import Align +except ImportError: + import warnings + warnings.warn("The xcimporter functionality is unavailable without Gemmi", category=ImportWarning) + +# extract from Fragalysis does not require gemmi from .xcextracter.getdata import GetTargetsData, GetMoleculesData, GetPdbData, GetMolgroupData from .xcextracter.frag_web_live import can_connect from .xcextracter.xcextracter import xcextracter from .xcanalyser.graphcreator import GraphRequest, xcgraphcreator from .xcanalyser.xcanalyser import xcanalyser + +# this is not part of canonical Fragalysis wrapper, but a quick way to get the data. +from .quick import QuickDownloader + + + diff --git a/fragalysis_api/quick.py b/fragalysis_api/quick.py new file mode 100644 index 00000000..ef507614 --- /dev/null +++ b/fragalysis_api/quick.py @@ -0,0 +1,185 @@ +""" +A quick download functionality for the impatient. +""" + +import warnings +from typing import Optional, Tuple, List, Dict, Any + +import io +import os +import pandas as pd +import requests +import zipfile +from rdkit.Chem import PandasTools + + +class QuickDownloader: + """ + This is simply a polished interface to the `api/download_structures` endpoint, + which is the same as the download button on the Fragalysis website. + Namely, it lacks the extended functionality of the `xcexporter` module. + Instantiating it with the target name will download the zip file of these and can be interactive with via different + methods. + + :cvar: fragalysis_api_url: The URL of the Fragalysis API. + :cvar: api_data: The default options for the API endpoint. Can be also overridden in the constructor. + :ivar: target_name: The name of the target as on the main Fragalysis page, e.g. 'Mpro', case sensitive + :ivar: zf: The zip file object. see https://docs.python.org/3/library/zipfile.html + + The contents of the ``zipfile.ZipFile`` object stored in the attribute ``.zf`` can be written to disk + with ``.write_all()``. + + The contents of a file within the zipfile can be accessed by subscripting the ``QuickDownloader`` instance, + with a string that is contained in the filename, e.g. ``quick['metadata']``, will return the metadata.csv file + content without having to waste time with filepaths. + + .. code-block:: python + from fragalysis_api import QuickDownloader + import pandas as pd + from typing import List + print(f'Default settings are: {QuickDownloader.api_data}') + + # Check if the target name is right + target_names: List[str] = QuickDownloader.retrieve_target_names() + target_name='Mpro' + assert target_name in target_names, f'Target named "{target_name}" not found in the list of targets' + + # Download the data + quick = QuickDownloader(target_name=target_name) + quick.write_all(directory='downloads') + hits: pd.DataFrame = quick.to_pandas(star_dummy=True) + + # Not all files have the reference pdb block, so if it does not the template is returned: + reference_pdbblock: str = quick.reference_pdbblock + + The class method ``QuickDownloader.retrieve_target_data`` will download all the metadata for the targets. + while ``QuickDownloader.retrieve_target_names`` will return their names. + """ + fragalysis_api_url = 'fragalysis.diamond.ac.uk/api/download_structures/' + api_data = { + 'proteins': '', + 'event_info': False, + 'sigmaa_info': False, + 'diff_info': False, + 'trans_matrix_info': False, + 'NAN': False, + 'mtz_info': False, + 'cif_info': False, + 'NAN2': False, + 'map_info': False, + 'single_sdf_file': True, + 'sdf_info': False, + 'pdb_info': False, + 'bound_info': True, + 'metadata_info': True, + 'smiles_info': True, + 'static_link': False, + 'file_url': ''} + + def __init__(self, target_name: str, **options): + """ + Given a target download the zip file and store it in ``self.zf``. + + :param target_name: The name of the target as on the main Fragalysis page, e.g. 'Mpro', case sensitive + :param options: Any of the options for the endpoint, e.g. ``event_info=True``, cf. ``cls.api_data`` + """ + self.target_name = target_name + self.api_data = {options.get(k, v) for k, v in self.api_data.items()} + url_response: requests.Response = requests.post(f'https://{self.fragalysis_api_url}', + json={'target_name': self.target_name, **self.api_data}) + url_response.raise_for_status() + self.file_url: str = url_response.json()['file_url'] + response: requests.Response = requests.get(f"https://{self.fragalysis_api_url}?file_url={self.file_url}", + allow_redirects=True) + response.raise_for_status() + self.zf = zipfile.ZipFile(io.BytesIO(response.content), "r") + + def __getitem__(self, item: str) -> str: + """ + Subscript via filename, e.g. ``quick['metadata']`` will return the metadata.csv file content. + + :param item: Part of the filename whose contents will be returned + :return: The contents of the file whose name contains ``item`` + """ + for fileinfo in self.zf.infolist(): + if item in fileinfo.filename: + return self.zf.read(fileinfo.filename).decode('utf8') + else: + raise KeyError(f'No file with {item} in the name found.') + + def __iter__(self) -> Tuple[str, str]: + for fileinfo in self.zf.infolist(): + yield fileinfo.filename, self.zf.read(fileinfo.filename).decode('utf8') + + def __len__(self): + """ + :return: The number of molecules-protein PDBs in the zip file. + """ + return sum(['aligned/' in info.filename for info in self.zf.infolist()]) + + def write_all(self, directory: Optional[str] = None): + """ + Writes all the files within the zip file to disk in ``directory``. + """ + if directory is None: + directory = self.target_name + if not os.path.exists(directory): + os.makedirs(directory) + for fileinfo in self.zf.infolist(): + if os.path.split(fileinfo.filename)[0] != '': + os.makedirs(os.path.join(directory, os.path.split(fileinfo.filename)[0]), exist_ok=True) + with open(os.path.join(directory, fileinfo.filename), 'w') as f: + f.write(self.zf.read(fileinfo.filename).decode('utf8')) + + def to_pandas(self, star_dummy=True) -> pd.DataFrame: + """ + Combine the metadata (``self['metadata]``) with sdf block (``self['combined.sdf']``), + into a single pandas DataFrame. + Peculiarly, Fragalysis stores dummy atoms as `Xe` instead of `*` in older SMILES, which is the standard. + """ + # make a combined table + # Fragalysis does not give attributes in the sdf entries. This is instead stored in metadata.csv. + sdf_block = self['combined.sdf'] + df = PandasTools.LoadSDF(io.StringIO(sdf_block)).set_index('ID') + try: + metadata_block = self['metadata.csv'].replace('Xe', '*') if star_dummy else self['metadata.csv'] + df = pd.concat([df, + pd.read_csv(io.StringIO(metadata_block), index_col=0).set_index('crystal_name') + ], axis=1) + except KeyError: + warnings.warn('No metadata.csv found (legacy data). Returning only the sdf file.') + return df + + @property + def reference_pdbblock(self) -> str: + """ + Not all files have the reference pdb block, so if it does not the template is returned. + + :return: The reference PDB for the target. + """ + try: + return self['reference'] + except KeyError: + first_response: requests.Response = requests.get(f'https://{self.fragalysis_api_url}/api/targets/') + first_response.raise_for_status() + template_url = first_response.json()['results'][0]['template_protein'] + # /media/pdbs/ path: + second_response: requests.Response = requests.get(f'https://{self.fragalysis_api_url}/{template_url}') + second_response.raise_for_status() + return second_response.text + + @classmethod + def retrieve_target_data(cls) -> List[Dict[str, Any]]: + """ + :return: A list of all the target metadata available on the Fragalysis API. + """ + response: requests.Response = requests.get(f'https://{cls.fragalysis_api_url}/api/targets/') + response.raise_for_status() + return response.json()['results'] + + @classmethod + def retrieve_target_names(cls) -> List[str]: + """ + :return: A list of all the target names available on the Fragalysis API. + """ + return [target['title'] for target in cls.retrieve_target_data()] diff --git a/fragalysis_api/xcglobalscripts/set_config.py b/fragalysis_api/xcglobalscripts/set_config.py index d1154f27..9f35d73b 100755 --- a/fragalysis_api/xcglobalscripts/set_config.py +++ b/fragalysis_api/xcglobalscripts/set_config.py @@ -4,6 +4,7 @@ def ConfigSetup(): # use config parser to get settings from config.ini + # todo Do not read package files this way, use importlib/pkg_resources settings_file = os.path.join(os.path.dirname(__file__), "config.ini") settings = configparser.ConfigParser() settings._interpolation = configparser.ExtendedInterpolation() diff --git a/fragalysis_api/xcimporter/README.md b/importer.md similarity index 100% rename from fragalysis_api/xcimporter/README.md rename to importer.md diff --git a/fragalysis_api/xcextracter/example_notebooks/Pulling mol sdf and 'api' pdb.ipynb b/notebooks/Pulling-mol-sdf-pdb.ipynb similarity index 100% rename from fragalysis_api/xcextracter/example_notebooks/Pulling mol sdf and 'api' pdb.ipynb rename to notebooks/Pulling-mol-sdf-pdb.ipynb diff --git a/Tutorials.ipynb b/notebooks/Tutorials.ipynb similarity index 62% rename from Tutorials.ipynb rename to notebooks/Tutorials.ipynb index c4500327..841ee814 100644 --- a/Tutorials.ipynb +++ b/notebooks/Tutorials.ipynb @@ -16,6 +16,7 @@ "source": [ "import fragalysis_api\n", "import os\n", + "import pandas as pd\n", "from importlib import reload" ] }, @@ -261,7 +262,7 @@ "source": [ "# A way to see which targets are in the database?\n", "\n", - "graphs = fragalysis_api.xcextracter(target_name='NUDT5A')\n", + "graphs: pd.DataFrame = fragalysis_api.xcextracter(target_name='NUDT5A')\n", "display(graphs.head())\n", "\n", "# load molecule protein for wonka input (is this the correct input?)" @@ -300,21 +301,21 @@ "evalue": "cannot release un-acquired lock", "output_type": "error", "traceback": [ - "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[0;31mKeyboardInterrupt\u001b[0m Traceback (most recent call last)", - "\u001b[0;32m~/anaconda3/envs/fragalysis_env/lib/python3.7/site-packages/pymol/importing.py\u001b[0m in \u001b[0;36mload\u001b[0;34m(filename, object, state, format, finish, discrete, quiet, multiplex, zoom, partial, mimic, object_props, atom_props, _self)\u001b[0m\n\u001b[1;32m 718\u001b[0m \u001b[0;32mtry\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 719\u001b[0;31m \u001b[0m_self\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mlock\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0m_self\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 720\u001b[0m \u001b[0mplugin\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m''\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;32m~/anaconda3/envs/fragalysis_env/lib/python3.7/site-packages/pymol/locking.py\u001b[0m in \u001b[0;36mlock\u001b[0;34m(_self)\u001b[0m\n\u001b[1;32m 75\u001b[0m \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m \u001b[0;31m# we're not getting lucky, so block for real\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 76\u001b[0;31m \u001b[0m_self\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mlock_api\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0macquire\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 77\u001b[0m \u001b[0;32mbreak\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;31mKeyboardInterrupt\u001b[0m: ", + "\u001B[0;31m---------------------------------------------------------------------------\u001B[0m", + "\u001B[0;31mKeyboardInterrupt\u001B[0m Traceback (most recent call last)", + "\u001B[0;32m~/anaconda3/envs/fragalysis_env/lib/python3.7/site-packages/pymol/importing.py\u001B[0m in \u001B[0;36mload\u001B[0;34m(filename, object, state, format, finish, discrete, quiet, multiplex, zoom, partial, mimic, object_props, atom_props, _self)\u001B[0m\n\u001B[1;32m 718\u001B[0m \u001B[0;32mtry\u001B[0m\u001B[0;34m:\u001B[0m\u001B[0;34m\u001B[0m\u001B[0;34m\u001B[0m\u001B[0m\n\u001B[0;32m--> 719\u001B[0;31m \u001B[0m_self\u001B[0m\u001B[0;34m.\u001B[0m\u001B[0mlock\u001B[0m\u001B[0;34m(\u001B[0m\u001B[0m_self\u001B[0m\u001B[0;34m)\u001B[0m\u001B[0;34m\u001B[0m\u001B[0;34m\u001B[0m\u001B[0m\n\u001B[0m\u001B[1;32m 720\u001B[0m \u001B[0mplugin\u001B[0m \u001B[0;34m=\u001B[0m \u001B[0;34m''\u001B[0m\u001B[0;34m\u001B[0m\u001B[0;34m\u001B[0m\u001B[0m\n", + "\u001B[0;32m~/anaconda3/envs/fragalysis_env/lib/python3.7/site-packages/pymol/locking.py\u001B[0m in \u001B[0;36mlock\u001B[0;34m(_self)\u001B[0m\n\u001B[1;32m 75\u001B[0m \u001B[0;32melse\u001B[0m\u001B[0;34m:\u001B[0m \u001B[0;31m# we're not getting lucky, so block for real\u001B[0m\u001B[0;34m\u001B[0m\u001B[0;34m\u001B[0m\u001B[0m\n\u001B[0;32m---> 76\u001B[0;31m \u001B[0m_self\u001B[0m\u001B[0;34m.\u001B[0m\u001B[0mlock_api\u001B[0m\u001B[0;34m.\u001B[0m\u001B[0macquire\u001B[0m\u001B[0;34m(\u001B[0m\u001B[0;36m1\u001B[0m\u001B[0;34m)\u001B[0m\u001B[0;34m\u001B[0m\u001B[0;34m\u001B[0m\u001B[0m\n\u001B[0m\u001B[1;32m 77\u001B[0m \u001B[0;32mbreak\u001B[0m\u001B[0;34m\u001B[0m\u001B[0;34m\u001B[0m\u001B[0m\n", + "\u001B[0;31mKeyboardInterrupt\u001B[0m: ", "\nDuring handling of the above exception, another exception occurred:\n", - "\u001b[0;31mRuntimeError\u001b[0m Traceback (most recent call last)", - "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[1;32m 3\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 4\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 5\u001b[0;31m \u001b[0mfragalysis_api\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mxcimporter\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0min_dir\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0min_dir\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mout_dir\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mout_dir\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mtarget\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;34m'ATAD2'\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mvalidate\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;32mTrue\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;31m# Needs to delete tmp files\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 6\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 7\u001b[0m \u001b[0;31m# Change this dir into xcextractor format?\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;32m~/Documents/01_Projects/fragalysis-api/fragalysis_api/xcimporter/xcimporter.py\u001b[0m in \u001b[0;36mxcimporter\u001b[0;34m(in_dir, out_dir, target, validate)\u001b[0m\n\u001b[1;32m 61\u001b[0m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"Aligning protein structures\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 62\u001b[0m \u001b[0mstructure\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mAlign\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0min_dir\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mpdb_ref\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;34m\"\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 63\u001b[0;31m \u001b[0mstructure\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0malign\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mos\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mpath\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mjoin\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mout_dir\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m\"tmp\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 64\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 65\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;32m~/Documents/01_Projects/fragalysis-api/fragalysis_api/xcimporter/align.py\u001b[0m in \u001b[0;36malign\u001b[0;34m(self, out_dir)\u001b[0m\n\u001b[1;32m 130\u001b[0m \u001b[0mthe\u001b[0m \u001b[0mpdb\u001b[0m \u001b[0mfiles\u001b[0m \u001b[0mof\u001b[0m \u001b[0mthe\u001b[0m \u001b[0mstructure\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 131\u001b[0m \"\"\"\n\u001b[0;32m--> 132\u001b[0;31m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_save_align\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mout_dir\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", - "\u001b[0;32m~/Documents/01_Projects/fragalysis-api/fragalysis_api/xcimporter/align.py\u001b[0m in \u001b[0;36m_save_align\u001b[0;34m(self, path_save)\u001b[0m\n\u001b[1;32m 112\u001b[0m \u001b[0mpymol\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mpymol_argv\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m[\u001b[0m\u001b[0;34m'pymol'\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m'-qc'\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 113\u001b[0m \u001b[0mpymol\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mfinish_launching\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 114\u001b[0;31m \u001b[0mpymol_cmd\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_load_objs\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 115\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 116\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0mos\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mpath\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mexists\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mpath_save\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m \u001b[0;31m# Creating output directory if it doesn't already exist\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;32m~/Documents/01_Projects/fragalysis-api/fragalysis_api/xcimporter/align.py\u001b[0m in \u001b[0;36m_load_objs\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m 36\u001b[0m \u001b[0;31m# Looping through each pdb file in the directory and loading them into the cmd\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 37\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0mnum\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mfile\u001b[0m \u001b[0;32min\u001b[0m \u001b[0menumerate\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_get_files\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 38\u001b[0;31m \u001b[0mpymol\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mcmd\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mload\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mfile\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mos\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mpath\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0msplitext\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mos\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mpath\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mbasename\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mfile\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m0\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 39\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 40\u001b[0m \u001b[0;31m# deal with files that have no conect records\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;32m~/anaconda3/envs/fragalysis_env/lib/python3.7/site-packages/pymol/importing.py\u001b[0m in \u001b[0;36mload\u001b[0;34m(filename, object, state, format, finish, discrete, quiet, multiplex, zoom, partial, mimic, object_props, atom_props, _self)\u001b[0m\n\u001b[1;32m 818\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0mfunc\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m**\u001b[0m\u001b[0mkw\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 819\u001b[0m \u001b[0;32mfinally\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 820\u001b[0;31m \u001b[0m_self\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0munlock\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mr\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0m_self\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 821\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0m_self\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_raising\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mr\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0m_self\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m \u001b[0;32mraise\u001b[0m \u001b[0mpymol\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mCmdException\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 822\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0mr\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;32m~/anaconda3/envs/fragalysis_env/lib/python3.7/site-packages/pymol/locking.py\u001b[0m in \u001b[0;36munlock\u001b[0;34m(result, _self)\u001b[0m\n\u001b[1;32m 112\u001b[0m \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 113\u001b[0m \u001b[0;31m# print \"lock: released by 0x%x (not glut), waiting queue\"%thread.get_ident()\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 114\u001b[0;31m \u001b[0m_self\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mlock_api\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mrelease\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 115\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0m_cmd\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mwait_queue\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0m_self\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_COb\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m \u001b[0;31m# commands waiting to be executed?\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 116\u001b[0m \u001b[0me\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mthreading\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mEvent\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;31m# abdicate control for a 100 usec for quick tasks\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;31mRuntimeError\u001b[0m: cannot release un-acquired lock" + "\u001B[0;31mRuntimeError\u001B[0m Traceback (most recent call last)", + "\u001B[0;32m\u001B[0m in \u001B[0;36m\u001B[0;34m\u001B[0m\n\u001B[1;32m 3\u001B[0m \u001B[0;34m\u001B[0m\u001B[0m\n\u001B[1;32m 4\u001B[0m \u001B[0;34m\u001B[0m\u001B[0m\n\u001B[0;32m----> 5\u001B[0;31m \u001B[0mfragalysis_api\u001B[0m\u001B[0;34m.\u001B[0m\u001B[0mxcimporter\u001B[0m\u001B[0;34m(\u001B[0m\u001B[0min_dir\u001B[0m\u001B[0;34m=\u001B[0m\u001B[0min_dir\u001B[0m\u001B[0;34m,\u001B[0m \u001B[0mout_dir\u001B[0m\u001B[0;34m=\u001B[0m\u001B[0mout_dir\u001B[0m\u001B[0;34m,\u001B[0m \u001B[0mtarget\u001B[0m\u001B[0;34m=\u001B[0m\u001B[0;34m'ATAD2'\u001B[0m\u001B[0;34m,\u001B[0m \u001B[0mvalidate\u001B[0m\u001B[0;34m=\u001B[0m\u001B[0;32mTrue\u001B[0m\u001B[0;34m)\u001B[0m \u001B[0;31m# Needs to delete tmp files\u001B[0m\u001B[0;34m\u001B[0m\u001B[0;34m\u001B[0m\u001B[0m\n\u001B[0m\u001B[1;32m 6\u001B[0m \u001B[0;34m\u001B[0m\u001B[0m\n\u001B[1;32m 7\u001B[0m \u001B[0;31m# Change this dir into xcextractor format?\u001B[0m\u001B[0;34m\u001B[0m\u001B[0;34m\u001B[0m\u001B[0;34m\u001B[0m\u001B[0m\n", + "\u001B[0;32m~/Documents/01_Projects/fragalysis-api/fragalysis_api/xcimporter/xcimporter.py\u001B[0m in \u001B[0;36mxcimporter\u001B[0;34m(in_dir, out_dir, target, validate)\u001B[0m\n\u001B[1;32m 61\u001B[0m \u001B[0mprint\u001B[0m\u001B[0;34m(\u001B[0m\u001B[0;34m\"Aligning protein structures\"\u001B[0m\u001B[0;34m)\u001B[0m\u001B[0;34m\u001B[0m\u001B[0;34m\u001B[0m\u001B[0m\n\u001B[1;32m 62\u001B[0m \u001B[0mstructure\u001B[0m \u001B[0;34m=\u001B[0m \u001B[0mAlign\u001B[0m\u001B[0;34m(\u001B[0m\u001B[0min_dir\u001B[0m\u001B[0;34m,\u001B[0m \u001B[0mpdb_ref\u001B[0m\u001B[0;34m=\u001B[0m\u001B[0;34m\"\"\u001B[0m\u001B[0;34m)\u001B[0m\u001B[0;34m\u001B[0m\u001B[0;34m\u001B[0m\u001B[0m\n\u001B[0;32m---> 63\u001B[0;31m \u001B[0mstructure\u001B[0m\u001B[0;34m.\u001B[0m\u001B[0malign\u001B[0m\u001B[0;34m(\u001B[0m\u001B[0mos\u001B[0m\u001B[0;34m.\u001B[0m\u001B[0mpath\u001B[0m\u001B[0;34m.\u001B[0m\u001B[0mjoin\u001B[0m\u001B[0;34m(\u001B[0m\u001B[0mout_dir\u001B[0m\u001B[0;34m,\u001B[0m \u001B[0;34m\"tmp\"\u001B[0m\u001B[0;34m)\u001B[0m\u001B[0;34m)\u001B[0m\u001B[0;34m\u001B[0m\u001B[0;34m\u001B[0m\u001B[0m\n\u001B[0m\u001B[1;32m 64\u001B[0m \u001B[0;34m\u001B[0m\u001B[0m\n\u001B[1;32m 65\u001B[0m \u001B[0;34m\u001B[0m\u001B[0m\n", + "\u001B[0;32m~/Documents/01_Projects/fragalysis-api/fragalysis_api/xcimporter/align.py\u001B[0m in \u001B[0;36malign\u001B[0;34m(self, out_dir)\u001B[0m\n\u001B[1;32m 130\u001B[0m \u001B[0mthe\u001B[0m \u001B[0mpdb\u001B[0m \u001B[0mfiles\u001B[0m \u001B[0mof\u001B[0m \u001B[0mthe\u001B[0m \u001B[0mstructure\u001B[0m\u001B[0;34m.\u001B[0m\u001B[0;34m\u001B[0m\u001B[0;34m\u001B[0m\u001B[0m\n\u001B[1;32m 131\u001B[0m \"\"\"\n\u001B[0;32m--> 132\u001B[0;31m \u001B[0mself\u001B[0m\u001B[0;34m.\u001B[0m\u001B[0m_save_align\u001B[0m\u001B[0;34m(\u001B[0m\u001B[0mout_dir\u001B[0m\u001B[0;34m)\u001B[0m\u001B[0;34m\u001B[0m\u001B[0;34m\u001B[0m\u001B[0m\n\u001B[0m", + "\u001B[0;32m~/Documents/01_Projects/fragalysis-api/fragalysis_api/xcimporter/align.py\u001B[0m in \u001B[0;36m_save_align\u001B[0;34m(self, path_save)\u001B[0m\n\u001B[1;32m 112\u001B[0m \u001B[0mpymol\u001B[0m\u001B[0;34m.\u001B[0m\u001B[0mpymol_argv\u001B[0m \u001B[0;34m=\u001B[0m \u001B[0;34m[\u001B[0m\u001B[0;34m'pymol'\u001B[0m\u001B[0;34m,\u001B[0m \u001B[0;34m'-qc'\u001B[0m\u001B[0;34m]\u001B[0m\u001B[0;34m\u001B[0m\u001B[0;34m\u001B[0m\u001B[0m\n\u001B[1;32m 113\u001B[0m \u001B[0mpymol\u001B[0m\u001B[0;34m.\u001B[0m\u001B[0mfinish_launching\u001B[0m\u001B[0;34m(\u001B[0m\u001B[0;34m)\u001B[0m\u001B[0;34m\u001B[0m\u001B[0;34m\u001B[0m\u001B[0m\n\u001B[0;32m--> 114\u001B[0;31m \u001B[0mpymol_cmd\u001B[0m \u001B[0;34m=\u001B[0m \u001B[0mself\u001B[0m\u001B[0;34m.\u001B[0m\u001B[0m_load_objs\u001B[0m\u001B[0;34m(\u001B[0m\u001B[0;34m)\u001B[0m\u001B[0;34m\u001B[0m\u001B[0;34m\u001B[0m\u001B[0m\n\u001B[0m\u001B[1;32m 115\u001B[0m \u001B[0;34m\u001B[0m\u001B[0m\n\u001B[1;32m 116\u001B[0m \u001B[0;32mif\u001B[0m \u001B[0;32mnot\u001B[0m \u001B[0mos\u001B[0m\u001B[0;34m.\u001B[0m\u001B[0mpath\u001B[0m\u001B[0;34m.\u001B[0m\u001B[0mexists\u001B[0m\u001B[0;34m(\u001B[0m\u001B[0mpath_save\u001B[0m\u001B[0;34m)\u001B[0m\u001B[0;34m:\u001B[0m \u001B[0;31m# Creating output directory if it doesn't already exist\u001B[0m\u001B[0;34m\u001B[0m\u001B[0;34m\u001B[0m\u001B[0m\n", + "\u001B[0;32m~/Documents/01_Projects/fragalysis-api/fragalysis_api/xcimporter/align.py\u001B[0m in \u001B[0;36m_load_objs\u001B[0;34m(self)\u001B[0m\n\u001B[1;32m 36\u001B[0m \u001B[0;31m# Looping through each pdb file in the directory and loading them into the cmd\u001B[0m\u001B[0;34m\u001B[0m\u001B[0;34m\u001B[0m\u001B[0;34m\u001B[0m\u001B[0m\n\u001B[1;32m 37\u001B[0m \u001B[0;32mfor\u001B[0m \u001B[0mnum\u001B[0m\u001B[0;34m,\u001B[0m \u001B[0mfile\u001B[0m \u001B[0;32min\u001B[0m \u001B[0menumerate\u001B[0m\u001B[0;34m(\u001B[0m\u001B[0mself\u001B[0m\u001B[0;34m.\u001B[0m\u001B[0m_get_files\u001B[0m\u001B[0;34m)\u001B[0m\u001B[0;34m:\u001B[0m\u001B[0;34m\u001B[0m\u001B[0;34m\u001B[0m\u001B[0m\n\u001B[0;32m---> 38\u001B[0;31m \u001B[0mpymol\u001B[0m\u001B[0;34m.\u001B[0m\u001B[0mcmd\u001B[0m\u001B[0;34m.\u001B[0m\u001B[0mload\u001B[0m\u001B[0;34m(\u001B[0m\u001B[0mfile\u001B[0m\u001B[0;34m,\u001B[0m \u001B[0mos\u001B[0m\u001B[0;34m.\u001B[0m\u001B[0mpath\u001B[0m\u001B[0;34m.\u001B[0m\u001B[0msplitext\u001B[0m\u001B[0;34m(\u001B[0m\u001B[0mos\u001B[0m\u001B[0;34m.\u001B[0m\u001B[0mpath\u001B[0m\u001B[0;34m.\u001B[0m\u001B[0mbasename\u001B[0m\u001B[0;34m(\u001B[0m\u001B[0mfile\u001B[0m\u001B[0;34m)\u001B[0m\u001B[0;34m)\u001B[0m\u001B[0;34m[\u001B[0m\u001B[0;36m0\u001B[0m\u001B[0;34m]\u001B[0m\u001B[0;34m)\u001B[0m\u001B[0;34m\u001B[0m\u001B[0;34m\u001B[0m\u001B[0m\n\u001B[0m\u001B[1;32m 39\u001B[0m \u001B[0;34m\u001B[0m\u001B[0m\n\u001B[1;32m 40\u001B[0m \u001B[0;31m# deal with files that have no conect records\u001B[0m\u001B[0;34m\u001B[0m\u001B[0;34m\u001B[0m\u001B[0;34m\u001B[0m\u001B[0m\n", + "\u001B[0;32m~/anaconda3/envs/fragalysis_env/lib/python3.7/site-packages/pymol/importing.py\u001B[0m in \u001B[0;36mload\u001B[0;34m(filename, object, state, format, finish, discrete, quiet, multiplex, zoom, partial, mimic, object_props, atom_props, _self)\u001B[0m\n\u001B[1;32m 818\u001B[0m \u001B[0;32mreturn\u001B[0m \u001B[0mfunc\u001B[0m\u001B[0;34m(\u001B[0m\u001B[0;34m**\u001B[0m\u001B[0mkw\u001B[0m\u001B[0;34m)\u001B[0m\u001B[0;34m\u001B[0m\u001B[0;34m\u001B[0m\u001B[0m\n\u001B[1;32m 819\u001B[0m \u001B[0;32mfinally\u001B[0m\u001B[0;34m:\u001B[0m\u001B[0;34m\u001B[0m\u001B[0;34m\u001B[0m\u001B[0m\n\u001B[0;32m--> 820\u001B[0;31m \u001B[0m_self\u001B[0m\u001B[0;34m.\u001B[0m\u001B[0munlock\u001B[0m\u001B[0;34m(\u001B[0m\u001B[0mr\u001B[0m\u001B[0;34m,\u001B[0m\u001B[0m_self\u001B[0m\u001B[0;34m)\u001B[0m\u001B[0;34m\u001B[0m\u001B[0;34m\u001B[0m\u001B[0m\n\u001B[0m\u001B[1;32m 821\u001B[0m \u001B[0;32mif\u001B[0m \u001B[0m_self\u001B[0m\u001B[0;34m.\u001B[0m\u001B[0m_raising\u001B[0m\u001B[0;34m(\u001B[0m\u001B[0mr\u001B[0m\u001B[0;34m,\u001B[0m\u001B[0m_self\u001B[0m\u001B[0;34m)\u001B[0m\u001B[0;34m:\u001B[0m \u001B[0;32mraise\u001B[0m \u001B[0mpymol\u001B[0m\u001B[0;34m.\u001B[0m\u001B[0mCmdException\u001B[0m\u001B[0;34m\u001B[0m\u001B[0;34m\u001B[0m\u001B[0m\n\u001B[1;32m 822\u001B[0m \u001B[0;32mreturn\u001B[0m \u001B[0mr\u001B[0m\u001B[0;34m\u001B[0m\u001B[0;34m\u001B[0m\u001B[0m\n", + "\u001B[0;32m~/anaconda3/envs/fragalysis_env/lib/python3.7/site-packages/pymol/locking.py\u001B[0m in \u001B[0;36munlock\u001B[0;34m(result, _self)\u001B[0m\n\u001B[1;32m 112\u001B[0m \u001B[0;32melse\u001B[0m\u001B[0;34m:\u001B[0m\u001B[0;34m\u001B[0m\u001B[0;34m\u001B[0m\u001B[0m\n\u001B[1;32m 113\u001B[0m \u001B[0;31m# print \"lock: released by 0x%x (not glut), waiting queue\"%thread.get_ident()\u001B[0m\u001B[0;34m\u001B[0m\u001B[0;34m\u001B[0m\u001B[0;34m\u001B[0m\u001B[0m\n\u001B[0;32m--> 114\u001B[0;31m \u001B[0m_self\u001B[0m\u001B[0;34m.\u001B[0m\u001B[0mlock_api\u001B[0m\u001B[0;34m.\u001B[0m\u001B[0mrelease\u001B[0m\u001B[0;34m(\u001B[0m\u001B[0;34m)\u001B[0m\u001B[0;34m\u001B[0m\u001B[0;34m\u001B[0m\u001B[0m\n\u001B[0m\u001B[1;32m 115\u001B[0m \u001B[0;32mif\u001B[0m \u001B[0m_cmd\u001B[0m\u001B[0;34m.\u001B[0m\u001B[0mwait_queue\u001B[0m\u001B[0;34m(\u001B[0m\u001B[0m_self\u001B[0m\u001B[0;34m.\u001B[0m\u001B[0m_COb\u001B[0m\u001B[0;34m)\u001B[0m\u001B[0;34m:\u001B[0m \u001B[0;31m# commands waiting to be executed?\u001B[0m\u001B[0;34m\u001B[0m\u001B[0;34m\u001B[0m\u001B[0m\n\u001B[1;32m 116\u001B[0m \u001B[0me\u001B[0m \u001B[0;34m=\u001B[0m \u001B[0mthreading\u001B[0m\u001B[0;34m.\u001B[0m\u001B[0mEvent\u001B[0m\u001B[0;34m(\u001B[0m\u001B[0;34m)\u001B[0m \u001B[0;31m# abdicate control for a 100 usec for quick tasks\u001B[0m\u001B[0;34m\u001B[0m\u001B[0;34m\u001B[0m\u001B[0m\n", + "\u001B[0;31mRuntimeError\u001B[0m: cannot release un-acquired lock" ] } ], diff --git a/quick_download.md b/quick_download.md new file mode 100644 index 00000000..45476c58 --- /dev/null +++ b/quick_download.md @@ -0,0 +1,31 @@ +## Quick download + +This is not part of the regular package, which allows more precise control, but simply a wrapper to +the `api/download_structures` endpoint (which is used by the download modal) to download all the data +for a given target. + +This endpoint differs from the links in the `api/targets` endpoint response. Namely, +for say NUDT7A, the JSON response to https://fragalysis.diamond.ac.uk/api/targets/?title=NUDT7A +will feature `zip_archive` that will point to `https://fragalysis.diamond.ac.uk/media/targets/👾👾👾.zip` +and a `template_protein`, which is (possibly) the reference structure for molecular replacement and +not necessary for alignment. NUDT7 is an older target and actually lacks a reference structure in the download. + +```python +from fragalysis_api import QuickDownloader +import pandas as pd +from typing import List +print(f'Default settings are: {QuickDownloader.api_data}') + +# Check if the target name is right +target_names: List[str] = QuickDownloader.retrieve_target_names() +target_name='Mpro' +assert target_name in target_names, f'Target named "{target_name}" not found in the list of targets' + +# Download the data +quick = QuickDownloader(target_name=target_name) +quick.write_all(directory='downloads') +hits: pd.DataFrame = quick.to_pandas(star_dummy=True) + +# Not all files have the reference pdb block, so if it does not the template is returned: +reference_pdbblock: str = quick.reference_pdbblock +``` diff --git a/setup.py b/setup.py index 932a787c..d4a3db08 100755 --- a/setup.py +++ b/setup.py @@ -1,13 +1,16 @@ -import setuptools +import setuptools, os -with open("README.md", "r") as fh: - long_description = fh.read() +if os.path.exists("README.md"): + with open("README.md", "r") as fh: + long_description = fh.read() +else: + long_description = "" setuptools.setup( name='fragalysis_api', - version='0.0.5.1', - author='Fragment 5 + Tyler', + version='0.6', + author='XChem', author_email="", description="A package to load PDBs into fragalysis format.", long_description=long_description, # README_1.md file as description @@ -20,6 +23,7 @@ 'pypdb', 'matplotlib', 'scipy', + 'rdkit', 'fragalysis'], # Install requirements extracted from requirements.txt include_package_data=True, # Allow to include other files than .py in package package_data={ @@ -27,10 +31,13 @@ 'fragalysis_api/xcglobalscripts/config.ini'] }, # Define which additional files should be included in package classifiers=[ - 'Development Status :: 4 - Beta', + 'Development Status :: 5 - Production/Stable', # https://pypi.org/classifiers/ "Programming Language :: Python :: 3.7", "License :: OSI Approved :: MIT License", "Operating System :: OS Independent", + 'Intended Audience :: Science/Research', + 'Topic :: Scientific/Engineering :: Bio-Informatics', + 'Topic :: Scientific/Engineering :: Chemistry', ], python_requires='>=3.6', )