Skip to content

Commit

Permalink
Merge pull request #50 from martimunicoy/devel
Browse files Browse the repository at this point in the history
0.3.1 release
  • Loading branch information
martimunicoy committed Sep 22, 2020
2 parents 3a94344 + 5294dde commit 64330ae
Show file tree
Hide file tree
Showing 11 changed files with 799 additions and 57 deletions.
25 changes: 25 additions & 0 deletions docs/releasehistory.rst
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,31 @@ Releases follow the ``major.minor.micro`` scheme recommended by `PEP440 <https:/
* ``micro`` increments represent bugfix releases or improvements in documentation


0.3.1 - Current development
---------------------------

This is a micro release that includes general bug fixes and stability improvements. It is still a preliminary version of the Open Force Field to PELE package which is under development.

New features
""""""""""""
- `PR #55 <https://github.com/martimunicoy/offpele/pull/55>`_: Standard output prints follow the logging hierarchy and can be modified by the user.
- `PR #59 <https://github.com/martimunicoy/offpele/pull/59>`_: Set alternative conformers to the offpele's molecule representation.

Bugfixes
""""""""
- `PR #48 <https://github.com/martimunicoy/offpele/pull/48>`_: Fixes CLI's default output paths.
- `PR #52 <https://github.com/martimunicoy/offpele/pull/52>`_: Molecule connectivity can be assigned from an RDKit molecular template when loading it from a PDB file without connectivity.
- `PR #58 <https://github.com/martimunicoy/offpele/pull/58>`_: Fixes unconsistencies between PDB residue name and molecule tag.

Tests added
"""""""""""
- `PR #48 <https://github.com/martimunicoy/offpele/pull/48>`_: Adds tests to validate the assignment of the default output paths.
- `PR #52 <https://github.com/martimunicoy/offpele/pull/52>`_: Adds tests to validate the initialization using a connectivity template.
- `PR #55 <https://github.com/martimunicoy/offpele/pull/55>`_: Adds tests for the new Logger class.
- `PR #58 <https://github.com/martimunicoy/offpele/pull/58>`_: Adds tests to validate consistency between PDB residue name and molecule tag.
- `PR #59 <https://github.com/martimunicoy/offpele/pull/59>`_: Adds tests for the new conformer setter.


0.3.0 - Rotamers, OPLS2005, SMILES and stability improvements
-------------------------------------------------------------

Expand Down
35 changes: 35 additions & 0 deletions offpele/data/ligands/BNZ_without_connectivity.pdb
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
HEADER HYDROLASE 16-AUG-14 4W52
REMARK 4 4W52 COMPLIES WITH FORMAT V. 3.30,
REMARK 888
REMARK 888 WRITTEN BY MAESTRO (A PRODUCT OF SCHRODINGER, LLC)
TITLE T4 LYSOZYME L99A WITH BENZENE BOUND
EXPDTA X-RAY DIFFRACTION
REMARK 2 RESOLUTION. 1.50 ANGSTROMS
REMARK 3 R VALUE : 0.165000
REMARK 3 FREE R VALUE : 0.182000
REMARK 200 TEMPERATURE (KELVIN) : 100.00
REMARK 200 PH : 7.50
REMARK 350 BIOMOLECULE: 1
REMARK 350 APPLY THE FOLLOWING TO CHAINS: A
REMARK 350 BIOMT1 1 1.000000 0.000000 0.000000 0.000000
REMARK 350 BIOMT2 1 0.000000 1.000000 0.000000 0.000000
REMARK 350 BIOMT3 1 0.000000 0.000000 1.000000 0.000000
CRYST1 60.350 60.350 96.610 90.00 90.00 120.00 P 32 2 1 6
HET BNZ L 1 12
HETNAM BNZ BENZENE
FORMUL 1 BNZ C6 H6
MODEL 1
HETATM 1 C1 BNZ L 1 -32.969 6.196 2.877 0.70 15.06 C
HETATM 2 C2 BNZ L 1 -32.945 7.046 3.973 0.70 12.84 C
HETATM 3 C3 BNZ L 1 -33.719 6.798 5.113 0.70 12.24 C
HETATM 4 C4 BNZ L 1 -34.540 5.680 5.143 0.70 13.09 C
HETATM 5 C5 BNZ L 1 -34.545 4.825 4.044 0.70 12.54 C
HETATM 6 C6 BNZ L 1 -33.787 5.069 2.915 0.70 14.23 C
HETATM 7 H1 BNZ L 1 -32.360 6.413 2.012 1.00 0.00 H
HETATM 8 H2 BNZ L 1 -32.318 7.925 3.961 1.00 0.00 H
HETATM 9 H3 BNZ L 1 -33.672 7.473 5.955 1.00 0.00 H
HETATM 10 H4 BNZ L 1 -35.158 5.487 6.007 1.00 0.00 H
HETATM 11 H5 BNZ L 1 -35.156 3.935 4.055 1.00 0.00 H
HETATM 12 H6 BNZ L 1 -33.823 4.399 2.069 1.00 0.00 H
ENDMDL
END
74 changes: 47 additions & 27 deletions offpele/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
import argparse as ap

import offpele
from offpele.utils import check_if_path_exists, create_path
from offpele.utils import check_if_path_exists, create_path, Logger


DEFAULT_OFF_FORCEFIELD = 'openff_unconstrained-1.2.0.offxml'
Expand Down Expand Up @@ -73,12 +73,22 @@ def parse_args():
action='store_true',
help="Use OPLS to set the parameters for bonds "
+ "and angles")
parser.add_argument('-s', '--silent',
dest="silent",
action='store_true',
help="Activate silent mode")
parser.add_argument('-d', '--debug',
dest="debug",
action='store_true',
help="Activate debug mode")

parser.set_defaults(as_datalocal=False)
parser.set_defaults(with_solvent=False)
parser.set_defaults(include_terminal_rotamers=False)
parser.set_defaults(use_OPLS_nb_params=False)
parser.set_defaults(use_OPLS_bonds_and_angles=False)
parser.set_defaults(silent=False)
parser.set_defaults(debug=False)

args = parser.parse_args()

Expand Down Expand Up @@ -109,16 +119,16 @@ def handle_output_paths(molecule, output, as_datalocal):
The output path for the solvent template
"""
from pathlib import Path
name = molecule.name
tag = molecule.tag
output_path = Path(output)
check_if_path_exists(output_path)

rotlib_path = output_path
impact_path = output_path
solvent_path = output_path

rotlib_name = name.upper() + '.rot.assign'
impact_name = name.lower() + 'z'
rotlib_name = tag.upper() + '.rot.assign'
impact_name = tag.lower() + 'z'
solvent_name = 'ligandParams.txt'

if as_datalocal:
Expand Down Expand Up @@ -177,27 +187,24 @@ def run_offpele(pdb_file, forcefield=DEFAULT_OFF_FORCEFIELD,
Whether to save output files following PELE's DataLocal hierarchy or
not
"""
print('-' * 60)
print('Open Force Field parameterizer for PELE', offpele.__version__)
print('-' * 60)
print(' - General:')
print(' - Input PDB:', pdb_file)
print(' - Output path:', output)
print(' - Write solvent parameters:', with_solvent)
print(' - DataLocal-like output:', as_datalocal)
print(' - Parameterization:')
print(' - Force field:', forcefield)
print(' - Charges method:', charges_method)
print(' - Use OPLS nonbonding parameters:', use_OPLS_nb_params)
print(' - Use OPLS bonds and angles:', use_OPLS_bonds_and_angles)
print(' - Rotamer library:')
print(' - Resolution:', resolution)
print(' - Exclude terminal rotamers:', exclude_terminal_rotamers)
print('-' * 60)

# Supress OpenForceField toolkit warnings
import logging
logging.getLogger().setLevel(logging.ERROR)
log = Logger()
log.info('-' * 60)
log.info('Open Force Field parameterizer for PELE', offpele.__version__)
log.info('-' * 60)
log.info(' - General:')
log.info(' - Input PDB:', pdb_file)
log.info(' - Output path:', output)
log.info(' - Write solvent parameters:', with_solvent)
log.info(' - DataLocal-like output:', as_datalocal)
log.info(' - Parameterization:')
log.info(' - Force field:', forcefield)
log.info(' - Charges method:', charges_method)
log.info(' - Use OPLS nonbonding parameters:', use_OPLS_nb_params)
log.info(' - Use OPLS bonds and angles:', use_OPLS_bonds_and_angles)
log.info(' - Rotamer library:')
log.info(' - Resolution:', resolution)
log.info(' - Exclude terminal rotamers:', exclude_terminal_rotamers)
log.info('-' * 60)

from offpele.topology import Molecule
from offpele.template import Impact
Expand Down Expand Up @@ -226,8 +233,8 @@ def run_offpele(pdb_file, forcefield=DEFAULT_OFF_FORCEFIELD,
solvent = OBC2(molecule)
solvent.to_json_file(solvent_out)

print(' - All files were generated successfully')
print('-' * 60)
log.info(' - All files were generated successfully')
log.info('-' * 60)


def main():
Expand All @@ -247,6 +254,19 @@ def main():

exclude_terminal_rotamers = not args.include_terminal_rotamers

# Supress OpenForceField toolkit warnings
import logging
logging.getLogger().setLevel(logging.ERROR)

# Set offpele logger to the corresponding level
logger = Logger()
if args.silent:
logger.set_level('CRITICAL')
elif args.debug:
logger.set_level('DEBUG')
else:
logger.set_level('INFO')

run_offpele(args.pdb_file, args.forcefield, args.resolution,
args.charges_method, args.use_OPLS_nb_params,
args.use_OPLS_bonds_and_angles, exclude_terminal_rotamers,
Expand Down
8 changes: 5 additions & 3 deletions offpele/solvent/solvent.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

from offpele.utils import get_data_file_path, warning_on_one_line
from offpele.utils.toolkits import OpenForceFieldToolkitWrapper
from offpele.utils import Logger


class _SolventWrapper(object):
Expand Down Expand Up @@ -42,7 +43,8 @@ def _initialize_from_molecule(self):
"""
Initializes a SolventWrapper object using an offpele's Molecule.
"""
print(' - Loading solvent parameters')
logger = Logger()
logger.info(' - Loading solvent parameters')

off_toolkit = OpenForceFieldToolkitWrapper()

Expand Down Expand Up @@ -82,15 +84,15 @@ def to_dict(self):
data['SolventParameters']['General']['surface_area_penalty'] = \
round(self.surface_area_penalty.value_in_unit(
unit.kilocalorie / (unit.angstrom**2 * unit.mole)), 8)
data['SolventParameters'][self.molecule.name] = dict()
data['SolventParameters'][self.molecule.tag] = dict()

atom_names = self.molecule.get_pdb_atom_names()

for atom, name in zip(self.molecule.rdkit_molecule.GetAtoms(),
atom_names):
name = name.replace(' ', '_')
index = atom.GetIdx()
data['SolventParameters'][self.molecule.name][name] = \
data['SolventParameters'][self.molecule.tag][name] = \
{'radius': round(self.radii[tuple((index, ))].value_in_unit(
unit.angstrom), 5),
'scale': round(self.scales[tuple((index, ))], 5)}
Expand Down
88 changes: 87 additions & 1 deletion offpele/tests/test_main.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@

import pytest

import os
import tempfile
from offpele.main import run_offpele
from offpele.main import run_offpele, handle_output_paths
from offpele.utils import get_data_file_path, temporary_cd
from offpele.topology import Molecule


FORCEFIELD_NAME = 'openff_unconstrained-1.2.0.offxml'
Expand All @@ -18,6 +20,9 @@ class TestMain(object):
"""

def test_offpele_default_call(self):
"""
It checks the default call of offpele's main function.
"""
LIGAND_PATH = 'ligands/BNZ.pdb'
ligand_path = get_data_file_path(LIGAND_PATH)

Expand All @@ -26,6 +31,9 @@ def test_offpele_default_call(self):
run_offpele(ligand_path, output=tmpdir)

def test_offpele_custom_call(self):
"""
It checks the custom call of offpele's main function.
"""
LIGAND_PATH = 'ligands/BNZ.pdb'
ligand_path = get_data_file_path(LIGAND_PATH)

Expand All @@ -38,3 +46,81 @@ def test_offpele_custom_call(self):
output=tmpdir,
with_solvent=True,
as_datalocal=True)

def test_default_output_paths(self):
"""
It checks the default output paths that are used for each parameter
file from offpele.
"""

def from_PosixPath_to_string(paths):
"""
Convert PosixPaths to strings
"""
return map(str, paths)

molecule = Molecule(smiles='c1ccccc1', name='benzene', tag='BNZ')

rotlib_path, impact_path, solvent_path = \
handle_output_paths(molecule, '', False)

# Convert PosixPaths to strings
rotlib_path, impact_path, solvent_path = map(
str, [rotlib_path, impact_path, solvent_path])

assert rotlib_path == 'BNZ.rot.assign', 'Unexpected default ' \
+ 'rotamer library path'
assert impact_path == 'bnzz', 'Unexpected default Impact ' \
+ 'template path'
assert solvent_path == 'ligandParams.txt', 'Unexpected default ' \
+ 'solvent parameters path'

with tempfile.TemporaryDirectory() as tmpdir:
with temporary_cd(tmpdir):
# To avoid the complain about unexistent folder
os.mkdir('output')
rotlib_path, impact_path, solvent_path = \
handle_output_paths(molecule, 'output', False)

# Convert PosixPaths to strings
rotlib_path, impact_path, solvent_path = map(
str, [rotlib_path, impact_path, solvent_path])

assert rotlib_path == 'output/BNZ.rot.assign', 'Unexpected default ' \
+ 'rotamer library path'
assert impact_path == 'output/bnzz', 'Unexpected default Impact ' \
+ 'template path'
assert solvent_path == 'output/ligandParams.txt', 'Unexpected ' \
+ 'default solvent parameters path'

rotlib_path, impact_path, solvent_path = \
handle_output_paths(molecule, '', True)

# Convert PosixPaths to strings
rotlib_path, impact_path, solvent_path = map(
str, [rotlib_path, impact_path, solvent_path])

assert rotlib_path == 'DataLocal/LigandRotamerLibs/' \
+ 'BNZ.rot.assign', 'Unexpected default rotamer library path'
assert impact_path == 'DataLocal/Templates/OFF/Parsley/' \
+ 'HeteroAtoms/bnzz', 'Unexpected default Impact template'
assert solvent_path == 'DataLocal/OBC/ligandParams.txt', \
'Unexpected default solvent parameters path'

with tempfile.TemporaryDirectory() as tmpdir:
with temporary_cd(tmpdir):
# To avoid the complain about unexistent folder
os.mkdir('output')
rotlib_path, impact_path, solvent_path = \
handle_output_paths(molecule, 'output', True)

# Convert PosixPaths to strings
rotlib_path, impact_path, solvent_path = map(
str, [rotlib_path, impact_path, solvent_path])

assert rotlib_path == 'output/DataLocal/LigandRotamerLibs/' \
+ 'BNZ.rot.assign', 'Unexpected default rotamer library path'
assert impact_path == 'output/DataLocal/Templates/OFF/Parsley/' \
+ 'HeteroAtoms/bnzz', 'Unexpected default Impact template path'
assert solvent_path == 'output/DataLocal/OBC/ligandParams.txt', \
'Unexpected default solvent parameters path'
Loading

0 comments on commit 64330ae

Please sign in to comment.