diff --git a/choppa/cli/cli.py b/choppa/cli/cli.py index 196df04..8aa6d7e 100644 --- a/choppa/cli/cli.py +++ b/choppa/cli/cli.py @@ -1,20 +1,133 @@ import click +from typing import Optional +from choppa.IO.input import FitnessFactory, ComplexFactory +from choppa.align.align import AlignFactory +from choppa.render.render import PublicationView, InteractiveView @click.group() @click.version_option() def cli(): - "Demo of click-app-template-repository" + "Integrated mutational and structural biology data into a concerted HTML view." -@cli.command(name="command") -@click.argument( - "example" +@cli.command(name="render", help="Create fitness view as a publication-ready PyMOL session file and a read-for-sharing interactive HTML file. ", short_help="Create fitness view as a publication-ready PyMOL session file and a read-for-sharing interactive HTML file.") +@click.option( + "-p", + "--pdb-file", + type=click.Path(exists=True, file_okay=True, dir_okay=False, writable=True), + help="Path to a PDB file to create fitness view for.", + required=True, +) +@click.option( + "-f", + "--fitness-file", + type=click.Path(exists=True, file_okay=True, dir_okay=False, writable=True), + help="Path to a CSV file with fitness data to create fitness view for.", + required=True, +) +@click.option( + "-op", + "--outfile-publication", + type=click.Path(exists=False, file_okay=True, dir_okay=False, writable=True), + help="Name of output file to write publication-ready PyMOL session file to. Should end in '.pse'", + required=True, +) +@click.option( + "-oi", + "--outfile-interactive", + type=click.Path(exists=False, file_okay=True, dir_okay=False, writable=True), + help="Name of output file to write ready-to-share interactive HTML file to. Should end in '.html'", + required=True, +) +@click.option( + "-f", + "--fitness-file", + type=click.Path(exists=True, file_okay=True, dir_okay=False, writable=True), + help="Path to a CSV file with fitness data to create fitness view for.", + required=True, +) +@click.option( + "-f", + "--fitness-file", + type=click.Path(exists=False, file_okay=True, dir_okay=False, writable=True), + help="Path to a CSV file with fitness data to create fitness view for.", + required=True, +) +@click.option( + "-f", + "--fitness-file", + type=click.Path(exists=False, file_okay=True, dir_okay=False, writable=True), + help="Path to a CSV file with fitness data to create fitness view for.", + required=True, +) +@click.option( + "-fv", + "--fitness-column", + type=click.STRING, + help="Name of the column in the fitness-file (-f/--fitness-file) that contains fitness values (e.g. LogEffect). If not defined, will default to 'fitness'.", + required=False, +) +@click.option( + "-ri", + "--residue-index-column", + type=click.STRING, + help="Name of the column in the fitness-file (-f/--fitness-file) that contains residue indices (e.g. 1, 2, .. n). If not defined, will default to 'residue_index'.", + required=False, +) +@click.option( + "-wt", + "--wildtype-column", + type=click.STRING, + help="Name of the column in the fitness-file (-f/--fitness-file) that contains wildtype residues (e.g. L, G, N). If not defined, will default to 'wildtype'.", + required=False, +) +@click.option( + "-mu", + "--mutant-column", + type=click.STRING, + help="Name of the column in the fitness-file (-f/--fitness-file) that contains mutant residues (e.g. L, G, N). If not defined, will default to 'mutant'.", + required=False, ) @click.option( - "-o", - "--option", - help="An example option", + "-c", + "--confidence-column", + type=click.STRING, + help="Name of the column in the fitness-file (-f/--fitness-file) that contains confidence values (e.g. counts). If not defined then LogoPlots in the HTML view will not display confidences.", + required=False, ) -def first_command(example, option): - "Command description goes here" - click.echo("Here is some output") \ No newline at end of file +def render( + pdb_file: Optional[str] = None, + fitness_file: Optional[str] = None, + outfile_publication: Optional[str] = None, + outfile_interactive: Optional[str] = None, + fitness_column : Optional[str] = None, + residue_index_column : Optional[str] = None, + wildtype_column : Optional[str] = None, + mutant_column : Optional[str] = None, + confidence_column : Optional[str] = None, + ): + + if not outfile_publication[-4:] == ".pse": + raise ValueError("--op/--outfile-publication should end in '.pse'.") + elif not outfile_interactive[-5:] == ".html": + raise ValueError("--oi/--outfile-interactive should end in '.html'.") + + fitness_dict = FitnessFactory(fitness_file, + confidence_colname=confidence_column + ).get_fitness_basedict() + complex = ComplexFactory(pdb_file).load_pdb() + complex_rdkit = ComplexFactory(pdb_file).load_pdb_rdkit() + + filled_aligned_fitness_dict = AlignFactory(fitness_dict, complex).align_fitness() + + PublicationView(filled_aligned_fitness_dict, + complex, + complex_rdkit, + fitness_threshold=0.7, + output_session_file=outfile_publication).render() + + InteractiveView(filled_aligned_fitness_dict, + complex, + complex_rdkit, + fitness_threshold=0.7, + output_session_file=outfile_interactive).render() \ No newline at end of file diff --git a/choppa/render/Template.html b/choppa/data/templates/Template.html similarity index 100% rename from choppa/render/Template.html rename to choppa/data/templates/Template.html diff --git a/choppa/data/templates/resources.py b/choppa/data/templates/resources.py new file mode 100644 index 0000000..0ffb1c8 --- /dev/null +++ b/choppa/data/templates/resources.py @@ -0,0 +1,6 @@ +import pkg_resources + +HTML_TEMPLATE = pkg_resources.resource_filename( + __name__, "Template.html" +) + diff --git a/choppa/render/.DS_Store b/choppa/render/.DS_Store deleted file mode 100644 index 35dc4cf..0000000 Binary files a/choppa/render/.DS_Store and /dev/null differ diff --git a/choppa/render/out.html b/choppa/render/out.html deleted file mode 100644 index 2064a95..0000000 --- a/choppa/render/out.html +++ /dev/null @@ -1,4251 +0,0 @@ - - - - - - - - - - - - -
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/choppa/render/out.pse b/choppa/render/out.pse deleted file mode 100644 index 8532b98..0000000 Binary files a/choppa/render/out.pse and /dev/null differ diff --git a/choppa/render/render.py b/choppa/render/render.py index 42c3172..28d41fb 100644 --- a/choppa/render/render.py +++ b/choppa/render/render.py @@ -6,6 +6,7 @@ from choppa.render.utils import show_contacts, get_ligand_resnames_from_pdb_str, split_pdb_str, get_contacts_mda, biopython_to_mda from choppa.render.logoplots import LogoPlot, WHITE_EMPTY_SQUARE, render_singleres_logoplot +from choppa.data.templates.resources import HTML_TEMPLATE logging.basicConfig(stream=sys.stdout, level=logging.INFO) logger = logging.getLogger() @@ -414,7 +415,7 @@ def get_interaction_dict(self): return intn_dict - def inject_stuff_in_template(self, sdf_str, pdb_str, surface_coloring, logoplot_dict, template="Template.html", out_file="out.html"): + def inject_stuff_in_template(self, sdf_str, pdb_str, surface_coloring, logoplot_dict, template=HTML_TEMPLATE): """" Replaces parts of a template HTML with relevant bits of data to get to a HTML view of the (ligand-) protein, its fitness and its interactions (if any). @@ -452,7 +453,7 @@ def inject_stuff_in_template(self, sdf_str, pdb_str, surface_coloring, logoplot_ # add the PDB (protein) and SDF (ligand) with open(template, "rt") as fin: - with open(out_file, "wt") as fout: + with open(self.output_session_file, "wt") as fout: for line in fin: line = line.replace("{{PDB_INSERT}}", f"{pdb_str}") line = line.replace("{{SDF_INSERT}}", f"{sdf_str}")