Skip to content

Commit

Permalink
Merge pull request #7 from dominiquesydow/cli
Browse files Browse the repository at this point in the history
Add CLI
  • Loading branch information
dominiquesydow authored Feb 24, 2021
2 parents e4f1960 + c3e27df commit e2fd3b7
Show file tree
Hide file tree
Showing 16 changed files with 429 additions and 78 deletions.
10 changes: 5 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,25 +24,25 @@ on macromolecule-side.
These interaction partners are called __environmental partners__.
Superfeatures and their environmental partners are monitored throughout an MD simulation.

#### Documentation
## Documentation

The documentation will be available soon.
The documentation will be available [here](https://dynophores.readthedocs.io/en/latest/).

#### Overview
## Overview

This Python library offers visualization schemes for dynophore data generated with the `DynophoreApp` (TODO: add link to software):

- Plot statistics on superfeatures and interactions (TODO: link to tutorial)
- Show superfeature clouds in 3D using the NGLviewer (TODO: link to tutorial)
- Show superfeatures mapped onto the ligand in 2D (TODO: link to tutorial)

#### License
## License

`dynophores` is a free software and is licensed under the MIT license.
Copyright (c) 2020, Dominique Sydow.


#### Acknowledgements
## Acknowledgements

Project based on the
[Computational Molecular Science Python Cookiecutter](https://github.com/molssi/cookiecutter-cms) version 1.3.
16 changes: 16 additions & 0 deletions docs/_static/stegosaurus.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
. .
/ `. .' \
.---. < > < > .---.
| \ \ - ~ ~ - / / |
~-..-~ ~-..-~
\~~~\.' `./~~~/
\__/ \__/
/ .- . \
_._ _.- .-~ ~-. / } \/~~~/
_.-'q }~ / } { ; \__/
{'__, / (" / { / `. ,~~| . .
`''''='~~-.__(" /_ | /- _ `..-' \\ //
/ \ =/ ~~--~~{ ./| ~-. `-..__\\_//_.-'
{ \ +\ \ =\ (" ~ - . _ _ _..---~
| | { } \ \_\
'---.o___,' .o___,'
32 changes: 19 additions & 13 deletions docs/installing.rst
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
Installing
==========

Install from the conda package
------------------------------
[WIP 🚧] Install from the conda package
---------------------------------------

Eventually, we will have a ``conda`` package, but for now you need to create a new environment manually.

Expand All @@ -22,23 +22,27 @@ Eventually, we will have a ``conda`` package, but for now you need to create a n

conda activate dynophores

3. Run ``dynophores -h`` to test that it works.
4. [WIP 🚧] Run ``dynophores start .`` to set up a new workspace. This step is not fully functional yet.
Please refer to "Install from the latest development snapshot" for manual steps.
3. Run ``dynoviz -h`` to test that it works.

4. Run ``dynoviz create --dyno path/to/dyno/folder --pdb path/to/pdb/file --dcd path/to/dcd/file
--workspace path/to/workspace/folder`` to explore your dynophore data in a new notebook.

5. Run ``dynoviz open path/to/your/dyno/notebook`` if you already have set up your dynophore
notebook (i.e. if you want to revisit a notebook created in step 4).
Note: This command is equivalent to ``jupyter lab path/to/your/dyno/notebook``.

Install from the latest development snapshot
--------------------------------------------

If you have already created a *conda environment* and it has been activated (see above),
If you have already created a *conda environment* and it has been activated (see above steps 1+2),
the next step is downloading a copy of the current state of the
`GitHub repository <https://github.com/dominiquesydow/dynophores>`_.

1. Download a zipfile of the repository using `this link <https://github.com/dominiquesydow/dynophores/archive/master.zip>`_.
2. Unzip to your location of choice.
3. Navigate to ``path/to/your/location/dynophores-master/docs``.
4. Start Jupyter Lab.
5. Double click on the lesson you want to start.
3. Navigate to ``path/to/your/location/``.
4. Run ``pip install dynophores``.
5. Start your dynophore notebook as described above in steps 3-5.


.. Unix instructions
Expand All @@ -53,8 +57,9 @@ the next step is downloading a copy of the current state of the
wget https://github.com/dominiquesydow/dynophores/archive/master.zip -O dynophores.zip
mkdir -p ~/Documents
unzip dynophores.zip -d ~/Documents
cd ~/Documents/dynophores-master/docs
jupyter lab
cd ~/Documents
pip install dynophores
dynoviz -h
.. raw:: html

Expand All @@ -72,8 +77,9 @@ the next step is downloading a copy of the current state of the
wget https://github.com/dominiquesydow/dynophores/archive/master.zip -O dynophores.zip
mkdir ~/Documents/
Expand-Archive dynophores.zip -d ~/Documents
cd ~/Documents/dynophores-master/docs
jupyter lab
cd ~/Documents
pip install dynophores
dynoviz -h
.. raw:: html

Expand Down
70 changes: 37 additions & 33 deletions docs/tutorials/dynophore.ipynb

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion docs/tutorials/explore_data.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@
"metadata": {},
"outputs": [],
"source": [
"DATA = Path(\"../../dynophores/tests/data/1KE7-1/DynophoreApp/data\")"
"DATA = Path(\"../../dynophores/tests/data/1KE7-1/DynophoreApp\")"
]
},
{
Expand Down
2 changes: 1 addition & 1 deletion docs/tutorials/explore_plots.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@
"metadata": {},
"outputs": [],
"source": [
"DATA = Path(\"../../dynophores/tests/data/1KE7-1/DynophoreApp/data\")"
"DATA = Path(\"../../dynophores/tests/data/1KE7-1/DynophoreApp\")"
]
},
{
Expand Down
2 changes: 1 addition & 1 deletion docs/tutorials/explore_view3d.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@
"metadata": {},
"outputs": [],
"source": [
"pml_path = DATA / \"DynophoreApp/1KE7-1_dynophore.pml\"\n",
"pml_path = DATA / \"DynophoreApp/dynophore.pml\"\n",
"pdb_path = DATA / \"startframe.pdb\"\n",
"dcd_path = DATA / \"trajectory.dcd\""
]
Expand Down
190 changes: 189 additions & 1 deletion dynophores/cli.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,191 @@
"""
Command line interface for dynophores.
Command Line Interface for the project.
"""

import argparse
from pathlib import Path
from shutil import copyfile
import subprocess

from . import _version


def main():
"""
Main CLI function with the following signatures:
dynoviz create
--dyno path/to/dyno/folder
--pdb path/to/pdb/file
--dcd path/to/dcd/file
--workspace path/to/workspace/folder
dynoviz open
--notebook path/to/existing/notebook
"""

_greet()

parser = argparse.ArgumentParser()
subparsers = parser.add_subparsers()

create_subparser = subparsers.add_parser("create")
open_subparser = subparsers.add_parser("open")

# Arguments and function to be called for sub-command encode
create_subparser.add_argument(
"-i",
"--dyno",
type=str,
help="Path to DynophoreApp output folder",
required=True,
)
create_subparser.add_argument(
"-p",
"--pdb",
type=str,
help="Path to pdb (topology) file from trajectory, e.g. first frame",
required=True,
)
create_subparser.add_argument(
"-d",
"--dcd",
type=str,
help="Path to dcd (trajectory) file",
required=True,
)
create_subparser.add_argument(
"-w",
"--workspace",
type=str,
help="Path to workspace folder",
required=True,
)
create_subparser.set_defaults(func=_create_viz)

# Arguments and function to be called for sub-command compare
open_subparser.add_argument(
"notebook",
help="Path to dynophore notebook file",
)
open_subparser.set_defaults(func=_open_viz)

args = parser.parse_args()
args.func(args)


def _greet():
"""
Print CLI greeting.
"""

logo_path = Path(_version.__file__).parent / "../docs/_static/stegosaurus.txt"
with open(logo_path, "r", encoding="ascii") as f:
print(f.read())
title_str = f"Dynophores CLI {_version.get_versions()['version']}"
print(f"\n{title_str:^64}")


def _create_viz(args):
"""
Create visualization notebook based on command line arguments.
"""

_copy_notebook(args.workspace, args.dyno, args.pdb, args.dcd)

notebook_path = Path(args.workspace) / "dynophore.ipynb"
_open_notebook(notebook_path)


def _open_viz(args):
"""
Open visualization notebook based on command line arguments.
"""

_open_notebook(args.notebook)


def _copy_notebook(workspace_path, dyno_path, pdb_path, dcd_path):
"""
Copy template dynophore notebook to user-defined workspace and update filepaths set in notebook
to user-defined filepaths.
"""

workspace_path = Path(workspace_path)
dyno_path = Path(dyno_path)
pdb_path = Path(pdb_path)
dcd_path = Path(dcd_path)

if not workspace_path.exists():
raise RuntimeError(f"Input file does not exist: `{workspace_path.absolute()}`")
if not dyno_path.exists():
raise RuntimeError(f"Input file does not exist: `{dyno_path.absolute()}`")
if not pdb_path.exists():
raise RuntimeError(f"Input file does not exist: `{pdb_path.absolute()}`")
if not dcd_path.exists():
raise RuntimeError(f"Input file does not exist: `{dcd_path.absolute()}`")

# Set template notebook and user notebook filepath
notebook_path = Path(_version.__file__).parent / "../docs/tutorials/dynophore.ipynb"
new_notebook_path = Path(workspace_path) / "dynophore.ipynb"

# Copy template notebook to user-defined workspace
if notebook_path.exists():
print("\nCopy dynophore notebook to user workspace...")
copyfile(notebook_path, new_notebook_path)
if new_notebook_path.exists():
print(f"Dynophore notebook location: `{new_notebook_path.absolute()}`")
else:
raise RuntimeError(
f"Could not create dynophore notebook at selected location f"
f"`{new_notebook_path.absolute()}`"
)
else:
raise RuntimeError(
f"Could not find dynophore notebook at expected location `{notebook_path.absolute()}`."
)

# Replace template filepaths in notebook with user-defined filepaths
print("\nUpdate filepaths in notebook to user filepaths...")
search_replace_tuples = [
("../../dynophores/tests/data/1KE7-1/DynophoreApp", str(dyno_path.absolute())),
("../../dynophores/tests/data/1KE7-1/startframe.pdb", str(pdb_path.absolute())),
("../../dynophores/tests/data/1KE7-1/trajectory.dcd", str(dcd_path.absolute())),
]
_update_paths_in_notebook(new_notebook_path, search_replace_tuples)


def _open_notebook(notebook_path):
"""
Open input notebook with Jupyter Lab.
Notes
-----
Same behaviour like `jupyter lab notebook_path`.
"""

notebook_path = Path(notebook_path)
if not notebook_path.exists():
raise RuntimeError(f"Input file does not exist: `{notebook_path.absolute()}`")

print("Open dynophore notebook with Jupyter Lab...")
subprocess.run(["jupyter", "lab", str(notebook_path.absolute())])


def _update_paths_in_notebook(notebook_path, search_replace_tuples):
"""
Read notebook file as string, replace all search instances (filepaths), and overwrite notebook
file with this updated string.
"""

# Read in the file
with open(notebook_path, "r") as f:
filedata = f.read()

# Replace the target string
for (search_str, replace_str) in search_replace_tuples:
filedata = filedata.replace(search_str, replace_str)

# Write the file out again
with open(notebook_path, "w") as f:
f.write(filedata)
6 changes: 4 additions & 2 deletions dynophores/core/dynophore.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,19 +34,21 @@ def __init__(self):
@classmethod
def from_files(cls, dynophore_path):
"""
Load dynophore data from DynophoreApp output files as Dynophore instance.
Load dynophore data from DynophoreApp directory as Dynophore instance.
Parameters
----------
dynophore_path : pathlib.Path
Path to folder with dynophore data.
Path to DynophoreApp folder.
Returns
-------
dynophores.Dynophore
Dynophore.
"""

dynophore_path = Path(dynophore_path) / "data"

dynophore = cls()

# Get all files and filename components
Expand Down
2 changes: 1 addition & 1 deletion dynophores/tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,5 +69,5 @@ def superfeature():
@pytest.fixture(scope="module")
def dynophore():

dynophore = Dynophore.from_files(PATH_TEST_DATA / "1KE7-1/DynophoreApp/data")
dynophore = Dynophore.from_files(PATH_TEST_DATA / "1KE7-1/DynophoreApp")
return dynophore
Loading

0 comments on commit e2fd3b7

Please sign in to comment.