-
Notifications
You must be signed in to change notification settings - Fork 181
WIP: Motif search #1549
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
mkonstanty
wants to merge
11
commits into
prody:main
Choose a base branch
from
mkonstanty:motif_search
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
WIP: Motif search #1549
Changes from 5 commits
Commits
Show all changes
11 commits
Select commit
Hold shift + click to select a range
7933077
motif search initial commit
mkonstanty ce6e5c8
swiss-prot and refseq dbs added
mkonstanty e7541ec
save dbs to local disk
mkonstanty c62ef97
revoke style changes
mkonstanty ad3d13a
revoke style changes
mkonstanty 4fec6fc
local motif search feature added
mkonstanty 054ecb5
added pdb motif search
mkonstanty 76644cb
modified f-strings
mkonstanty 3a42183
replace f-strings
mkonstanty 07c30d4
motif search app added
mkonstanty d053635
Merge branch 'main' of github.com:prody/ProDy into motif_search
jamesmkrieger File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Some comments aren't visible on the classic Files Changed page.
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,160 @@ | ||
| # -*- coding: utf-8 -*- | ||
|
|
||
| """RefSeq database operations.""" | ||
|
|
||
| import os | ||
| import re | ||
| from concurrent.futures import ThreadPoolExecutor | ||
|
|
||
| import requests | ||
| from prody import LOGGER | ||
| from prody.utilities.helpers import downloadFile | ||
| from prody.utilities.pathtools import PRODY_DATA | ||
|
|
||
| __all__ = ["RefSeq"] | ||
|
|
||
|
|
||
| class RefSeq: | ||
| """RefSeq database.""" | ||
|
|
||
| RELEASE = "release.txt" | ||
| CHECK_SUMS = "files_installed.txt" | ||
|
|
||
| @classmethod | ||
| def getCurrentRelease(cls) -> str: | ||
| """Get current RefSeq db release version. | ||
|
|
||
| Raises: | ||
| Exception: No release version found. | ||
|
|
||
| Returns: | ||
| str: RefSeq db release version. | ||
| """ | ||
| rs_release = "" | ||
| url = "https://ftp.ncbi.nlm.nih.gov/refseq/release/RELEASE_NUMBER" | ||
| try: | ||
| response = requests.get(url) | ||
| except requests.exceptions.RequestException as exception: | ||
| LOGGER.error(str(exception)) | ||
| else: | ||
| rs_release = response.text | ||
| if not re.match(r"\d+", rs_release): | ||
| LOGGER.error("Could't determine release version.") | ||
| LOGGER.debug("RefSeq current release: {}".format(rs_release)) | ||
| return rs_release | ||
|
|
||
| @classmethod | ||
| def getInstalledFiles(cls) -> str: | ||
| """Reads installed files with corresponding check sums.""" | ||
| LOGGER.debug("Downloading installed files with check sums.") | ||
| current_release = cls.getCurrentRelease() | ||
| url = f"https://ftp.ncbi.nlm.nih.gov/refseq/release/release-catalog/release{current_release}.files.installed" | ||
| try: | ||
| response = requests.get(url) | ||
| except requests.exceptions.RequestException as exception: | ||
| LOGGER.error(str(exception)) | ||
| else: | ||
| result = "" | ||
| lines = response.text.split("\n") | ||
| for line in lines: | ||
| if re.search(r"complete\.(\d+\.){1,2}protein\.faa\.gz", line): | ||
| result += line + "\n" | ||
| return result | ||
|
|
||
| @classmethod | ||
| def saveInstalledFiles(cls) -> None: | ||
| """Saves installed files list with check sums locally.""" | ||
| installed_files = cls.getInstalledFiles() | ||
| path = os.path.join(PRODY_DATA, cls.__name__) | ||
| os.makedirs(path, exist_ok=True) | ||
| with open(f"{PRODY_DATA}/{cls.__name__}/{cls.CHECK_SUMS}", "w", encoding="utf-8") as file: | ||
| file.write(installed_files) | ||
| LOGGER.debug(f"{cls.CHECK_SUMS} file saved locally.") | ||
|
mkonstanty marked this conversation as resolved.
Outdated
|
||
|
|
||
| @classmethod | ||
| def getLocalFiles(cls) -> dict: | ||
| """Lists local RefSeq FASTA protein files and corresponding check sums. | ||
|
|
||
| Returns: | ||
| dict: file names and corresponding check sums. | ||
| """ | ||
| LOGGER.debug("Getting local RefSeq protein FASTA files") | ||
| path = os.path.join(PRODY_DATA, cls.__name__) | ||
| os.makedirs(path, exist_ok=True) | ||
| with open(f"{PRODY_DATA}/{cls.__name__}/{cls.CHECK_SUMS}", "r", encoding="utf-8") as file: | ||
| text = file.read() | ||
| results = re.findall(r"^(\d+)\s+(\S+)$", text, re.M) | ||
| return {result[1]: result[0] for result in results} | ||
|
|
||
| @classmethod | ||
| def getFiles(cls) -> dict: | ||
| """Lists all FASTA protein files on RefSeq ftp server. | ||
|
|
||
| Returns: | ||
| dict: FASTA protein files with check sums. | ||
| """ | ||
| LOGGER.debug("Getting protein FASTA file list from RefSeq.") | ||
| installed_files = cls.getInstalledFiles() | ||
| file_matcher = re.compile(r"^(\d+)\s+(\S+)$", re.M) | ||
| files = re.findall(file_matcher, installed_files) | ||
| return {file[1]: file[0] for file in files} if files else {} | ||
|
|
||
| @classmethod | ||
| def pepareDownloadFileList(cls) -> list: | ||
| """Prepare file list to be downloaded""" | ||
| LOGGER.debug("Preparing file list to be downloaded.") | ||
| remote_files = cls.getFiles() | ||
| local_files = cls.getLocalFiles() | ||
| download_list = [] | ||
| for filename in remote_files.keys(): | ||
| if filename in local_files.keys(): | ||
| if remote_files[filename] != local_files[filename]: | ||
| download_list.append(filename) | ||
| else: | ||
| download_list.append(filename) | ||
| return download_list | ||
|
|
||
| @classmethod | ||
| def downloadRelease(cls) -> None: | ||
| """Download latest RefSeq database release.""" | ||
| files = cls.pepareDownloadFileList() | ||
| url = "" | ||
| LOGGER.timeit() | ||
| with ThreadPoolExecutor(max_workers=3) as executor: | ||
| for file in files: | ||
| future = executor.submit(downloadFile, url, cls.__name__, file) | ||
| LOGGER.info(future.result()) | ||
| LOGGER.report() | ||
|
|
||
| @classmethod | ||
| def saveRelease(cls) -> None: | ||
| """Write current release version to disk.""" | ||
| current_release = cls.getCurrentRelease() | ||
| path = os.path.join(PRODY_DATA, cls.__name__) | ||
| os.makedirs(path, exist_ok=True) | ||
| with open(f"{PRODY_DATA}/{cls.__name__}/{cls.RELEASE}", "w", encoding="utf-8") as file: | ||
| file.write(current_release) | ||
| LOGGER.debug("RefSeq release {} saved.".format(current_release)) | ||
|
|
||
| @classmethod | ||
| def updateRelease(cls) -> None: | ||
| """Update release to the most recent one.""" | ||
| LOGGER.debug("Updating RefSeq release version.") | ||
| cls.downloadRelease() | ||
| cls.saveRelease() | ||
|
|
||
| @classmethod | ||
| def getLocalRelease(cls) -> str: | ||
| """Get release version from local disk.""" | ||
| LOGGER.debug("Getting RefSeq local release version.") | ||
| path = os.path.join(PRODY_DATA, cls.__name__) | ||
| os.makedirs(path, exist_ok=True) | ||
| with open(f"{PRODY_DATA}/{cls.__name__}/{cls.RELEASE}", "r", encoding="utf-8") as file: | ||
| return file.readline() | ||
|
|
||
| @classmethod | ||
| def checkForUpdates(cls) -> None: | ||
| """Check if local version is the recent one.""" | ||
| LOGGER.debug("RefSeq checking for updates.") | ||
| if cls.getCurrentRelease() != cls.getLocalRelease(): | ||
| cls.updateRelease() | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,94 @@ | ||
| # -*- coding: utf-8 -*- | ||
|
|
||
| """Swiss-Prot database operations.""" | ||
|
|
||
| import os | ||
| import re | ||
| from concurrent.futures import ThreadPoolExecutor | ||
|
|
||
| import requests | ||
| from prody import LOGGER | ||
| from prody.utilities.helpers import downloadFile | ||
| from prody.utilities.pathtools import PRODY_DATA | ||
|
|
||
| __all__ = ["SwissProt"] | ||
|
|
||
|
|
||
| class SwissProt: | ||
| """Swiss-Prot database.""" | ||
|
|
||
| RELEASE = "release.txt" | ||
| HEADERS = {"User-Agent": "Python pattern search agent", "Contact": "mkonstanty@gmail.com"} | ||
|
|
||
| @classmethod | ||
| def getCurrentRelease(cls) -> str: | ||
| """Get current swiss-prot db release version. | ||
|
|
||
| Raises: | ||
| Exception: No release version found. | ||
|
|
||
| Returns: | ||
| str: Swiss-prot db release version. | ||
| """ | ||
| sp_release = "" | ||
| url = "https://ftp.expasy.org/databases/swiss-prot/release/reldate.txt" | ||
| try: | ||
| response = requests.get(url, headers=cls.HEADERS) | ||
| except requests.exceptions.RequestException as exception: | ||
| LOGGER.error(str(exception)) | ||
| else: | ||
| sp_release = re.search(r"Swiss-Prot Release (\d{4}_\d{2})", response.text) | ||
| if not sp_release: | ||
| LOGGER.error("Could't determine release version.") | ||
| LOGGER.debug("Swiss-Prot current release: {}".format(sp_release[1])) | ||
| return sp_release[1] | ||
|
|
||
| @classmethod | ||
| def downloadRelease(cls, types=None) -> None: | ||
| """Download latest swiss-prot database release. | ||
|
|
||
| Args: | ||
| types (list, optional): Database file types. Defaults to None. | ||
| """ | ||
| types = types if types else ["xml", "dat", "fasta"] | ||
| files = [f"uniprot_sprot.{type}.gz" for type in types] | ||
| url = "https://ftp.expasy.org/databases/swiss-prot/release/" | ||
| LOGGER.timeit() | ||
| with ThreadPoolExecutor(max_workers=3) as executor: | ||
| for file in files: | ||
| future = executor.submit(downloadFile, url, cls.__name__, file, headers=cls.HEADERS) | ||
| LOGGER.info(future.result()) | ||
| LOGGER.report() | ||
|
|
||
| @classmethod | ||
| def saveRelease(cls) -> None: | ||
| """Write current release version to disk.""" | ||
| current_release = cls.getCurrentRelease() | ||
| path = os.path.join(PRODY_DATA, cls.__name__) | ||
| os.makedirs(path, exist_ok=True) | ||
| with open(f"{PRODY_DATA}/{cls.__name__}/{cls.RELEASE}", "w", encoding="utf-8") as file: | ||
| file.write(current_release) | ||
| LOGGER.debug("Swiss-Prot release {} saved.".format(current_release)) | ||
|
|
||
| @classmethod | ||
| def updateRelease(cls) -> None: | ||
| """Update release to the most recent one.""" | ||
| LOGGER.debug("Updating Swiss-Prot release version.") | ||
| cls.downloadRelease() | ||
| cls.saveRelease() | ||
|
|
||
| @classmethod | ||
| def getLocalRelease(cls) -> str: | ||
| """Get release version from local disk.""" | ||
| LOGGER.debug("Getting Swiss-Prot local release version.") | ||
| path = os.path.join(PRODY_DATA, cls.__name__) | ||
| os.makedirs(path, exist_ok=True) | ||
| with open(f"{PRODY_DATA}/{cls.__name__}/{cls.RELEASE}", "r", encoding="utf-8") as file: | ||
| return file.readline() | ||
|
|
||
| @classmethod | ||
| def checkForUpdates(cls) -> None: | ||
| """Check if local version is the recent one.""" | ||
| LOGGER.debug("Swiss-Prot checking for updates.") | ||
| if cls.getCurrentRelease() != cls.getLocalRelease(): | ||
| cls.updateRelease() |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.