Skip to content

Commit

Permalink
Add CLI that creates dummy output files and validates input (#934)
Browse files Browse the repository at this point in the history
 new CLI tool perses-cli that takes in a yaml file and creates dummy output.
  • Loading branch information
mikemhenry authored Feb 25, 2022
1 parent 10ec6d9 commit f1dec28
Show file tree
Hide file tree
Showing 6 changed files with 235 additions and 5 deletions.
10 changes: 6 additions & 4 deletions .github/workflows/CI.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ on:
branches:
- main

concurrency:
group: "${{ github.workflow }}-${{ github.ref }}"
cancel-in-progress: true

jobs:
test:
name: Test on ubuntu-latest, Python ${{ matrix.python-version }}, OpenMM ${{ matrix.openmm }}
Expand Down Expand Up @@ -86,14 +90,12 @@ jobs:
shell: bash -l {0}
run: |
export TRAVIS=true
pushd .
pytest -v --cov-report xml --cov=perses --durations=0 -a "not advanced" -n auto -m "not gpu_needed"
popd
pytest -v --cov-report xml --cov=perses --durations=0 -a "not advanced" -n auto -m "not gpu_needed"
- name: Codecov
if: ${{ github.repository == 'choderalab/perses'
&& github.event != 'schedule' }}
uses: codecov/codecov-action@v1
with:
file: ./coverage.xml
fail_ci_if_error: true
fail_ci_if_error: true
3 changes: 2 additions & 1 deletion devtools/conda-envs/test_env.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ dependencies:
- pymbar
- openmm >=7.6
- openmoltools # may need to sort out ambermini/ambertools/parmed dependencies (we don't want ambertools)
- openmmtools # may need to sort out ambermini/ambertools/parmed dependencies
- openmmtools >=0.21.2 # may need to sort out ambermini/ambertools/parmed dependencies
- numba
- netcdf4
- matplotlib
Expand Down Expand Up @@ -47,3 +47,4 @@ dependencies:
- pytest-attrib
- pytest-xdist
- arsenic
- click
172 changes: 172 additions & 0 deletions perses/app/cli.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
# New cli for testing
import datetime
from pathlib import Path

import click
import openmmtools.utils
from perses.app.setup_relative_calculation import getSetupOptions

percy = """
MMMMMMMMMMMMXo:ccldOKNNWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMWxcxOkxdodddxxxk0XWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWWWWMMWNX0Okk0WMMMMMM
MMMMMMMMMMMWxlk0OkdddddxkxdoodONWNXK0OOOOOOOOO0KXNWMMMMN0kxxxxxxxxddoddockWMMMMM
MMMMMMMMMMMMKooOOxooooc;:ldOOxooddddodddddddddodddxxkOkoodkOOkxdodxO000kcxWMMMMM
MMMMMMMMMMMMMKolk0000OdoddllxOOkkO00000O000000000OkxdookOOdl:cloooxO00kloXMMMMMM
MMMMMMMMMMMMMMNklokO0OO000OkkO000000000000O000000000O00OdllollxO0000OdldXMMMMMMM
MMMMMMMMMMMMMMMWXkdodkO00O00O0000OdlxO000000000OxxkO000OxkO00OOO00Odlo0WMMMMMMMM
MMMMMMMMMMMMMMMMMMWKkdldOOOO00000kdxOO000000000OxldO0000OO000OOxdoox0NMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMXdldOOO0000O000kkO0000000O0OOOOO0O00000Odloxk0NMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMKook00000000000Odlk00000000kooO000O00000OxcxNMMMMMWX0KNMMMMMM
MMMMMMMMMMMMMMMMMMKloO00000000000O0OkxdooooodxkxkO000000000O0xlkWMMMNkloook0OkxO
MMMMMMMMMMMMMMMMMNolO000000000000OxlllodddddolloxO00000000O00Odl0MMMOcx0Okooddo:
MMMMMMMMMMMMMMMMMOcx0OO00000O000kocoxxkO000OOkkocoO0000O0O0000kldWMMxck0000000xc
MMMMMMMMMMMMMMMMWdlO00O000000OOOo:dd:,:x000xc;cxd:d0000OO000O0OolXMWxck00OO0Oxlx
MMMMMMMMMMMMMMMMXooOO0000OOOOxkkclkc,,lO000k:,,lxclO00000000000dl0MNdcO0000kolkN
MMMMMMMMMMMMMMMMXolO00000kolccxOlckxook0000Oxlokx:okdkkxkO00000dl0XxlxO000kloXWM
MMMMMMMMMMMMMMMMNdlO00000OOd:lO0xclk00000000O0Oxclkkc;loxO0000OocoookO000OolKMMM
MMMMMMMMMMMMMMMMMOcx00000000xclkOkocldkOOOOOxdlldOOocoOO000000Oc,lxO00000kcxWMMM
MMMMMMMMMMMMMMMMMNdlO000000O0kocokOkdoooooooooxOkdllxO000O000Od:oO00O000OooXMMMM
MMMMMMMMMMMMMMMMMMXolk00000O00OkollodxkkkkkkkxdlllxO00000OOOOd:oO000O00OdcOMMMMM
MMMMMMMMMMMMMMMMMMM0::xO0000000O0OkdooooooooooodkO000000000OocoO000O000xlxWMMMMM
MMMMMMMMMMMMMMMMMNOoccclxO00O000000000OOOOOOO00000000OO00OdclxO00O0000kldNMMMMMM
MMMMMMMMMMMMMMMWKdlxOOkolldkO0000000000000000000000000OxolldO0O000000kldNMMMMMMM
MMMMMMMMMMMMMMWOldO00O00OxollodxOO000000000000000OOkdolloxO000O0000OxlxNMMMMMMMM
MMMMMMMMMMMMMWkldO000O00000OkdoooooooodddddddoooooooodkO000OO0O000OdlOWMMMMMMMMM
MMMMMMMMMMMMWOldO00000000000000OOkxxddooooooooddxkO0000O000000O0kdoxKWMMMMMMMMMM
MMMMMMMMMMMMXooO000000O0000000O0000000000000000OO00000OO000000kooxKWMMMMMMMMMMMM
MMMMMMMMMMMWxck00000000000000O000000000000000000O00OO000000O00dcOMMMMMMMMMMMMMMM
MMMWKkkOKWMXooO000000OkkO000000000000000000000000O000000000O00xckMMMMMMMMMMMMMMM
WMKdlcccldKOcd000000OdcdO0000000000000000000000000000000000000klkMMMMMMMMMMMMMMM
odccocccdllolk000000d:oO00000000000000000000000000000000000000OlxWMMMMMMMMMMMMMM
;:;:c::oxllolk00000kclO000000000000000000000000000000000000000OcdWMMMMMMMMMMMMMM
Oollodxdl;lc:x0000Oo:x0000000000000000000000000000000000000000kcxWMMMMMMMMMMMMMM
MN0kxxo::odl:d0000Olck000000000000000000000000000000000000O000dcOMMMMMMMMMMMMMMM
MMMMMMWKkddo;cO000Olck0000000000000000000000000000000000000O0OloNMMMMMMMMMMMMMMM
MMMMMMMMMWWOcoO000OkclO0000000000000000000000000000000000000Ool0MMMMMMMMMMMMMMMM
MMMMMMMMMMWxck0OOO0Olck00O00000000000000000000000000000O000Ool0WMMMMMMMMMMMMMMMM
MMMMMMMMMMM0loxolool:oO000000O000000000000000000000000000OxldKMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMWKkxkKN0o;ck0000O000000000000000000000000OO0OxooONMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMWxck000O000OkkO000000000000000000Oxo:;xNMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMOcx0000000kloO0000000000000Okxoollolc0MMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMKld000O000d;codddddddddoooclooodkO0olKMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMNolO00000Oll00OOkkkkkkkO0OllO000O0OloNMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMWxck00000kckMMMMMMMMMMMMMMkcx00000kcxWMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMkcx00000dcOMMMMMMMMMMMMMMKld00O00xckMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMWdlk00000kckWMMMMMMMMMMMMM0ld0OOO0kldNMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMKlo0OkkO0OloNMMMMMMMMMMMMWxck0OOOO0dc0MMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMXocdoollxxcdNMMMMMMMMMMMMMkcxOdlloxlc0MMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMKolxXXxc:oKMMMMMMMMMMMMMMKl:::x0dcckNMMMMMMMMMMMMMMMMMMMMMM
"""


def _check_openeye_license():
import openeye

assert openeye.oechem.OEChemIsLicensed(), "OpenEye license checks failed!"


def _test_platform(platform_name):
import openmm.testInstallation

openmm.testInstallation.main()

# If a user asks for a platform, try and see if we can use it
if platform_name:
assert openmmtools.utils.platform_supports_precision(platform_name, 'mixed')
click.echo("🎉\t Platform test successful!")


def _write_out_files(path, options):

# Convert path to a pathlib object
yaml_path = Path(path)

# Generate parsed yaml name
yaml_name = yaml_path.name
time = datetime.datetime.now().strftime("%Y-%m-%d-%H:%M:%S")
yaml_parse_name = f"parsed-{time}-{yaml_name}"

# First make files in same dir as yaml
files_next_to_yaml = [
"debug.png",
"system.xml",
yaml_parse_name,
]

for _file in files_next_to_yaml:
with open(_file, "w") as fp:
pass

# Now we make the directory structure
trajectory_directory = Path(options["trajectory_directory"])
dirs_to_make = trajectory_directory.joinpath("xml")
Path(dirs_to_make).mkdir(parents=True, exist_ok=True)

# Now files that belong in the lower directories
files_in_lower_dir = [
"atom_mapping.png",
"out-complex_checkpoint.nc",
"out-complex.nc",
"out-complex.pdb",
"outhybrid_factory.npy.npz",
"out-solvent_checkpoint.nc",
"out-solvent.nc",
"out-solvent.pdb",
"out_topology_proposals.pkl",
"out-vacuum_checkpoint.nc",
"out-vacuum.nc",
]

# add the dir prefix
files_in_lower_dir = [
Path(trajectory_directory).joinpath(_) for _ in files_in_lower_dir
]

for _file in files_in_lower_dir:
with open(_file, "w") as fp:
pass

# Now the files in the 'xml' dir
files_in_xml_dir = [
"complex-hybrid-system.gz",
"complex-new-system.gz",
"complex-old-system.gz",
"solvent-hybrid-system.gz",
"solvent-new-system.gz",
"solvent-old-system.gz",
"vacuum-hybrid-system.gz",
"vacuum-new-system.gz",
"vacuum-old-system.gz",
]

# add the dir prefix
files_in_xml_dir = [dirs_to_make.joinpath(_) for _ in files_in_xml_dir]

for _file in files_in_lower_dir:
with open(_file, "w") as fp:
pass


@click.command()
@click.option("--yaml", type=click.Path(exists=True, dir_okay=False), required=True)
@click.option("--platform-name", type=str, default=None)
def cli(yaml, platform_name):
"""test"""
click.echo(click.style(percy, fg="bright_magenta"))
click.echo("📖\t Fetching simulation options ")
options = getSetupOptions(yaml)
click.echo("🖨️\t Printing options")
click.echo(options)
click.echo("🕵️\t Checking OpenEye license")
_check_openeye_license()
click.echo("✅\t OpenEye license good")
click.echo("🖥️⚡\t Checking whether requested compute platform is available")
_test_platform(platform_name)
click.echo("🖨️\t Writing out files")
trajectory_directory = options["trajectory_directory"]
_write_out_files(trajectory_directory, options)
click.echo("🧪\t Simulation over")


if __name__ == "__main__":
cli()
5 changes: 5 additions & 0 deletions perses/tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,8 @@ def pytest_collection_modifyitems(config, items):
for item in items:
if "slow" in item.keywords:
item.add_marker(skip_slow)

@pytest.fixture
def in_tmpdir(tmpdir):
with tmpdir.as_cwd():
yield
49 changes: 49 additions & 0 deletions perses/tests/test_cli.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
from click.testing import CliRunner
from perses.app.cli import cli

test_yaml = """
protein_pdb: Tyk2_protein.pdb
ligand_file: Tyk2_ligands_shifted.sdf
old_ligand_index: 0
new_ligand_index: 3
forcefield_files:
- amber/ff14SB.xml
- amber/tip3p_standard.xml
- amber/tip3p_HFE_multivalent.xml
- amber/phosaa10.xml
small_molecule_forcefield: openff-1.0.0
pressure: 1
temperature: 300
solvent_padding: 9
atom_expression:
- IntType
bond_expession:
- DefaultBonds
n_steps_per_move_application: 1
fe_type: repex
checkpoint_interval: 50
n_cycles: 1
n_states: 3
n_equilibration_iterations: 0
trajectory_directory: temp/offlig10to24
trajectory_prefix: out
atom_selection: not water
phases:
- complex
- solvent
- vacuum
timestep: 4
h_constraints: true
"""


def test_dummy_cli(in_tmpdir):
runner = CliRunner()
with runner.isolated_filesystem():
with open("test.yaml", "w") as f:
f.write(test_yaml)

result = runner.invoke(cli, ["--yaml", "test.yaml"])
print(result)
print(result.output)
assert result.exit_code == 0
1 change: 1 addition & 0 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ def find_package_data(data_root, package_root):
"console_scripts": [
"perses-relative = perses.app.setup_relative_calculation:run",
"perses-fah = perses.app.fah_generator:run",
"perses-cli = perses.app.cli:cli",
],
},
ext_modules=extensions,
Expand Down

0 comments on commit f1dec28

Please sign in to comment.