Skip to content
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

PyOpenSci REVIEW - Refactor code to meet PEP8 #40

Merged
merged 6 commits into from
Jan 17, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion pynteny/__init__.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
from pynteny.api import *
from pynteny.cli import main
from pynteny.cli import main
115 changes: 54 additions & 61 deletions pynteny/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,25 +11,26 @@
from pynteny.utils import CommandArgs
from pynteny.filter import SyntenyHits
from pynteny.subcommands import (
synteny_search, build_database,
download_hmms, parse_gene_ids, get_citation
)
synteny_search,
build_database,
download_hmms,
parse_gene_ids,
get_citation,
)

meta = metadata.metadata("pynteny")
__version__ = meta["Version"]
__author__ = meta["Author"]


class Command():
"""Parent class for Pynteny command
"""
class Command:
"""Parent class for Pynteny command"""

def __init__(self):
"""Parent class for Pynteny command
"""
"""Parent class for Pynteny command"""

def _repr_html_(self):
"""Executed by Jupyter to print Author and version in html
"""
"""Executed by Jupyter to print Author and version in html"""
return """
<table>
<tr>
Expand All @@ -38,8 +39,9 @@ def _repr_html_(self):
<td><strong>Author</strong></td><td>{author}</td>
</tr>
</table>
""".format(version=__version__,
author=__author__)
""".format(
version=__version__, author=__author__
)

def update(self, argname: str, value: str) -> None:
"""Update argument value in pynteny command.
Expand All @@ -49,22 +51,18 @@ def update(self, argname: str, value: str) -> None:
value (str): new argument value.
"""
setattr(self._args, argname, value)

@staticmethod
def cite():
"""Display Pynteny citation
"""
args = CommandArgs(
version=__version__,
author=__author__
)
"""Display Pynteny citation"""
args = CommandArgs(version=__version__, author=__author__)
citation = get_citation(args, silent=True)
print(citation)


class Search(Command):
"""Search command object.
"""
"""Search command object."""

def __init__(
self,
data: Path,
Expand All @@ -78,7 +76,8 @@ def __init__(
prefix: str = "",
hmmsearch_args: str = None,
logfile: Path = None,
processes: int = None):
processes: int = None,
):
"""Query sequence database for HMM hits arranged in provided synteny structure.

Args:
Expand All @@ -88,15 +87,15 @@ def __init__(

'>hmm_a N_ab hmm_b bc <hmm_c'

where N_ab corresponds to the maximum number of genes separating
gene found by hmm_a and gene found by hmm_b, and hmm_ corresponds
where N_ab corresponds to the maximum number of genes separating
gene found by hmm_a and gene found by hmm_b, and hmm_ corresponds
to the name of the hmm as provided in the keys of hmm_hits.
More than two hmms can be concatenated. Strand location may be
specificed by using '>' for sense and '<' for antisense.
gene_ids (bool, optional): whether gene symbols are used in synteny
specificed by using '>' for sense and '<' for antisense.
gene_ids (bool, optional): whether gene symbols are used in synteny
string instead of HMM names. Defaults to False.
unordered (bool, optional): whether the HMMs should be arranged in the
exact same order displayed in the synteny_structure or in
exact same order displayed in the synteny_structure or in
any order If ordered, the filters would filter collinear rather
than syntenic structures. Defaults to False.
reuse (bool, optional): if True then HMMER3 won't be run again for HMMs already
Expand All @@ -108,10 +107,10 @@ def __init__(
outdir (Path, optional): path to output directory. Defaults to None.
prefix (str, optional): prefix of output file names. Defaults to "".
hmmsearch_args (str, optional): additional arguments to hmmsearch or hmmscan. Each
element in the list is a string with additional arguments for each
input hmm (arranged in the same order), an element can also take a
value of None to avoid passing additional arguments for a specific
input hmm. A single string may also be passed, in which case the
element in the list is a string with additional arguments for each
input hmm (arranged in the same order), an element can also take a
value of None to avoid passing additional arguments for a specific
input hmm. A single string may also be passed, in which case the
same additional argument is passed to hmmsearch for all input hmms.
Defaults to None. Defaults to None.
logfile (Path, optional): path to log file. Defaults to None.
Expand All @@ -131,10 +130,10 @@ def __init__(
logfile=Path(logfile) if logfile is not None else logfile,
processes=processes,
unordered=unordered,
reuse=reuse
)
reuse=reuse,
)

def parseGeneIDs(self, synteny_struc: str) -> str:
def parse_genes(self, synteny_struc: str) -> str:
"""Parse gene IDs in synteny structure and find corresponding HMM names
in provided HMM database.

Expand All @@ -144,39 +143,39 @@ def parseGeneIDs(self, synteny_struc: str) -> str:

'>hmm_a N_ab hmm_b bc <hmm_c'

where N_ab corresponds to the maximum number of genes separating
gene found by hmm_a and gene found by hmm_b, and hmm_ corresponds
where N_ab corresponds to the maximum number of genes separating
gene found by hmm_a and gene found by hmm_b, and hmm_ corresponds
to the name of the hmm as provided in the keys of hmm_hits.
More than two hmms can be concatenated. Strand location may be
specificed by using '>' for sense and '<' for antisense.
specificed by using '>' for sense and '<' for antisense.

Returns:
str: parsed synteny structure in which gene symbols are replaced by
str: parsed synteny structure in which gene symbols are replaced by
corresponding HMM names.
"""
args = CommandArgs(
synteny_struc=synteny_struc,
hmm_meta=self._args.hmm_meta,
logfile=self._args.logfile
logfile=self._args.logfile,
)
return parse_gene_ids(args)

def run(self) -> SyntenyHits:
"""Run pynteny search
"""
"""Run pynteny search"""
return synteny_search(self._args)


class Build(Command):
"""Build command object.
"""
"""Build command object."""

def __init__(
self,
data: Path,
outfile: Path = None,
logfile: Path = None,
processes: int = None):
"""Translate nucleotide assembly file and assign contig and gene location
processes: int = None,
):
"""Translate nucleotide assembly file and assign contig and gene location
info to each identified ORF (using prodigal).

Args:
Expand All @@ -190,23 +189,18 @@ def __init__(
data=Path(data),
outfile=Path(outfile) if outfile is not None else outfile,
logfile=Path(logfile) if logfile is not None else logfile,
processes=processes
)
processes=processes,
)

def run(self) -> None:
"""Run pynteny search
"""
"""Run pynteny search"""
return build_database(self._args)


class Download(Command):
"""Download HMM database from NCBI.
"""
def __init__(
self,
outdir: Path = None,
logfile: Path = None,
unpack: bool = False):
"""Download HMM database from NCBI."""

def __init__(self, outdir: Path = None, logfile: Path = None, unpack: bool = False):
"""Download HMM database from NCBI.

Args:
Expand All @@ -220,10 +214,9 @@ def __init__(
self._args = CommandArgs(
outdir=Path(outdir) if outdir is not None else outdir,
logfile=Path(logfile) if logfile is not None else logfile,
unpack=unpack
)
unpack=unpack,
)

def run(self) -> None:
"""Run pynteny download
"""
return download_hmms(self._args)
"""Run pynteny download"""
return download_hmms(self._args)
87 changes: 57 additions & 30 deletions pynteny/app/components.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,53 +18,74 @@ def show():
st.sidebar.image(
st.session_state.sidebar_icon,
use_column_width=True,
caption=f"Synteny-aware HMM searches made easy (v{__version__})"
caption=f"Synteny-aware HMM searches made easy (v{__version__})",
)

st.sidebar.text(" ")
st.sidebar.text(" ")

with st.sidebar.expander("Current output directory:", expanded=True):
if (st.session_state.outdir is not None) and (st.session_state.outdir.exists()):
if (st.session_state.outdir is not None) and (
st.session_state.outdir.exists()
):
files_div = st.empty()
with files_div.container():
FileManager.show_files_in_dir(st.session_state.outdir, sidebar=False)

FileManager.show_files_in_dir(
st.session_state.outdir, sidebar=False
)

st.text(" ")
st.button("Select directory", on_click=Callbacks.updateOutputDir)
col1, col2 = st.columns([.5, .5])
st.button("Select directory", on_click=Callbacks.update_output_dir)
col1, col2 = st.columns([0.5, 0.5])
with col1:
st.text_input("",
value="", max_chars=None,
key="subdirectory", on_change=Callbacks.updateOutputSubdirectory,
placeholder="Create subdirectory")
st.text_input(
"",
value="",
max_chars=None,
key="subdirectory",
on_change=Callbacks.update_output_subdirectory,
placeholder="Create subdirectory",
)
with col2:
st.text_input("",
value="", max_chars=None,
key="prefix", on_change=Callbacks.updateOutputPrefix,
placeholder="Enter output prefix")
st.text_input(
"",
value="",
max_chars=None,
key="prefix",
on_change=Callbacks.update_output_prefix,
placeholder="Enter output prefix",
)

with st.sidebar.expander("Advanced parameters:", expanded=False):

st.markdown("Select custom HMM database")
col1, col2 = st.columns([1, 1])
with col1:
st.button("HMM directory", on_click=Callbacks.selectHMMdir)
st.button("HMM directory", on_click=Callbacks.select_HMM_dir)
with col2:
st.button("HMM metadata", on_click=Callbacks.selectHMMmeta)
st.button("HMM metadata", on_click=Callbacks.select_HMM_meta)

col1, col2, col3 = st.columns([0.4, 0.3, 0.3])
with col1:
st.markdown(("Processes:"))
st.slider("Processes",
min_value=1, max_value=os.cpu_count(),
value=os.cpu_count() - 1, step=1,
on_change=Callbacks.setNumberOfProcesses, key="processes"
)
st.slider(
"Processes",
min_value=1,
max_value=os.cpu_count(),
value=os.cpu_count() - 1,
step=1,
on_change=Callbacks.set_number_of_processes,
key="processes",
)
with col2:
st.markdown(("Output log:"))
output_log = st.select_slider("", options=["No", "Yes"], value="Yes",
on_change=Callbacks.selectLogPath, key="log")
output_log = st.select_slider(
"",
options=["No", "Yes"],
value="Yes",
on_change=Callbacks.select_log_path,
key="log",
)
st.sidebar.text(" ")
col1, col2 = st.sidebar.columns([1, 1])
with col1:
Expand Down Expand Up @@ -94,7 +115,7 @@ def show():
with st.expander("", expanded=True):
col1, col2 = st.columns([1, 1])
with col1:
st.button("Upload file", on_click=Callbacks.uploadData)
st.button("Upload file", on_click=Callbacks.upload_data)
with col2:
st.button("Build database", on_click=Callbacks.build)

Expand All @@ -121,18 +142,24 @@ def show():
with st.expander("", expanded=True):
col1, col2, col3 = st.columns([0.7, 0.15, 0.15])
with col1:
st.session_state.search_state.synteny_struc = st.text_input("", "<leuD 0 <leuC 1 leuA")
st.session_state.search_state.synteny_struc = st.text_input(
"", "<leuD 0 <leuC 1 leuA"
)
with col2:
locus_repr = st.select_slider("", options=["Gene ID", "HMM"], value="Gene ID")
locus_repr = st.select_slider(
"", options=["Gene ID", "HMM"], value="Gene ID"
)
with col3:
ordered_struc = st.select_slider("", options=["ordered", "unordered"], value="ordered")
ordered_struc = st.select_slider(
"", options=["ordered", "unordered"], value="ordered"
)
gene_ids = True if locus_repr == "Gene ID" else False
unordered = False if ordered_struc == "ordered" else True
st.session_state.search_state.gene_ids = gene_ids
st.session_state.search_state.unordered = unordered
st.button("Search!", on_click=Callbacks.search)

if st.session_state.search_state.synteny_hits is not None:
results_file = f"{st.session_state.search_state.prefix}synteny_matched.tsv"
with st.expander(f"Results ({results_file}):", expanded=True):
Plotter.plot_dataframe(st.session_state.search_state.synteny_hits)
Plotter.plot_dataframe(st.session_state.search_state.synteny_hits)
Loading