From b8e2b083a28d6869ce7894c75e47b9e4fced34e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=AD=20Municoy?= Date: Tue, 21 Jun 2022 13:13:06 +0200 Subject: [PATCH 1/5] FFLD_SERVER errors are reported to logger --- docs/conf.py | 2 +- peleffy/utils/toolkits.py | 10 +++++++--- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/docs/conf.py b/docs/conf.py index a48d96c0..ada2e663 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -85,7 +85,7 @@ def add_source_parser(_old_add_source_parser, self, *args, **kwargs): #import peleffy #version = peleffy.__version__ -version = '1.4.1' +version = '1.4.2' pygments_style = 'sphinx' diff --git a/peleffy/utils/toolkits.py b/peleffy/utils/toolkits.py index 23f3aee3..b4f896f4 100644 --- a/peleffy/utils/toolkits.py +++ b/peleffy/utils/toolkits.py @@ -1322,6 +1322,10 @@ def run_ffld_server(self, molecule): ffld_output : str The ffld_server output """ + from peleffy.utils import Logger + + # Initialize logger + logger = Logger() ffld_server_exec = self.path_to_ffld_server() @@ -1338,9 +1342,9 @@ def run_ffld_server(self, molecule): "parameters.txt"]) if errors: - raise SystemError('FFLD_SERVER has failed with the ' + - 'following error message: \n ' + - '{}'.format(errors.decode("utf-8"))) + logger.warning('FFLD_SERVER has produced the ' + + 'following error message: \n ' + + '{}'.format(errors.decode("utf-8"))) with open('parameters.txt') as parameters_file: return parameters_file.read() From 5d73d65d9efd30a6c44cb931869db4be1ebbc1d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=AD=20Municoy?= Date: Tue, 21 Jun 2022 13:33:05 +0200 Subject: [PATCH 2/5] Improve CLI parameters --- peleffy/main.py | 29 +++++++++++++++++++++-------- peleffy/utils/utils.py | 3 +++ 2 files changed, 24 insertions(+), 8 deletions(-) diff --git a/peleffy/main.py b/peleffy/main.py index 4b7e642b..bc6013a3 100644 --- a/peleffy/main.py +++ b/peleffy/main.py @@ -17,10 +17,9 @@ from peleffy.forcefield.selectors import ChargeCalculatorSelector -DEFAULT_OFF_FORCEFIELD = 'openff_unconstrained-1.3.0.offxml' +DEFAULT_OFF_FORCEFIELD = 'openff_unconstrained-2.0.0.offxml' DEFAULT_RESOLUTION = int(30) -DEFAULT_CHARGE_METHOD = 'am1bcc' -AVAILABLE_CHARGE_METHODS = ChargeCalculatorSelector()._AVAILABLE_TYPES.keys() +DEFAULT_CHARGE_METHOD = None # Use FF's default IMPACT_TEMPLATE_PATH = 'DataLocal/Templates/OFF/Parsley/HeteroAtoms/' ROTAMER_LIBRARY_PATH = 'DataLocal/LigandRotamerLibs/' SOLVENT_TEMPLATE_PATH = 'DataLocal/OBC/' @@ -66,8 +65,7 @@ def parse_args(args): "DataLocal hierarchy", action='store_true') parser.add_argument('-c', '--charge_method', metavar="NAME", type=str, help="The name of the method to use to " + - "compute charges", default=DEFAULT_CHARGE_METHOD, - choices=AVAILABLE_CHARGE_METHODS) + "compute charges", default=DEFAULT_CHARGE_METHOD) parser.add_argument('--charges_from_file', metavar="PATH", type=str, help="The path to the file with charges", default=None) @@ -92,6 +90,10 @@ def parse_args(args): action='store_true', help="Generate Impact template compatible with " + "PELE\'s AMBER implementation") + parser.add_argument('-v', '--version', + dest="version", + action='store_true', + help="Print version and quit") parser.set_defaults(as_datalocal=False) parser.set_defaults(with_solvent=False) @@ -99,6 +101,7 @@ def parse_args(args): parser.set_defaults(silent=False) parser.set_defaults(debug=False) parser.set_defaults(for_amber=False) + parser.set_defaults(version=False) parsed_args = parser.parse_args(args) @@ -157,11 +160,14 @@ def run_peleffy(pdb_file, + ' - Charge file: {}'.format(charges_from_file) charge_method = 'dummy' else: - charge_method_str = charge_method + if charge_method is None: + charge_method_str = "-" + else: + charge_method_str = charge_method log = Logger() log.info('-' * 60) - log.info('Open Force Field parameterizer for PELE', peleffy.__version__) + log.info('PELE Force Field Yielder', peleffy.__version__) log.info('-' * 60) log.info(' - General:') log.info(' - Input PDB:', pdb_file) @@ -319,4 +325,11 @@ def main(args): if __name__ == '__main__': import sys args = parse_args(sys.argv[1:]) - main(args) + + # Only print version + if args.version: + print('PELE Force Field Yielder (peleffy) -', peleffy.__version__) + + # Run main + else: + main(args) diff --git a/peleffy/utils/utils.py b/peleffy/utils/utils.py index 89a015b0..32756450 100644 --- a/peleffy/utils/utils.py +++ b/peleffy/utils/utils.py @@ -420,6 +420,9 @@ def __init__(self): # Add stream handler self.set_stdout_handler() + + # Disable backwards propagation + self._logger.propagate = False else: self._logger = logging.getLogger('peleffy_log') From 934c28d8291f587b00b7c07df7761807b07f2781 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=AD=20Municoy?= Date: Tue, 21 Jun 2022 14:36:52 +0200 Subject: [PATCH 3/5] Minor fixes in main, tests and selectors --- peleffy/forcefield/__init__.py | 2 +- peleffy/forcefield/selectors.py | 25 +++++++++++------- peleffy/main.py | 45 +++++++++++++++++++++++---------- peleffy/tests/test_main.py | 44 ++++++++++++++------------------ 4 files changed, 67 insertions(+), 49 deletions(-) diff --git a/peleffy/forcefield/__init__.py b/peleffy/forcefield/__init__.py index 8cd6e5cf..e730b97a 100644 --- a/peleffy/forcefield/__init__.py +++ b/peleffy/forcefield/__init__.py @@ -1,2 +1,2 @@ from .forcefield import * -from .selectors import ForceFieldSelector +from .selectors import * diff --git a/peleffy/forcefield/selectors.py b/peleffy/forcefield/selectors.py index 69ce78f1..67636d0b 100644 --- a/peleffy/forcefield/selectors.py +++ b/peleffy/forcefield/selectors.py @@ -4,11 +4,14 @@ """ +_ALL_ = ["ForceFieldSelector", "ChargeCalculatorSelector"] + + class ForceFieldSelector(object): """ It defines a force field selector. """ - _FF_TYPES = {'OPLS2005': ('OPLS2005'), + _FF_TYPES = {'OPLS2005': ('OPLS2005', ), 'OpenFF': ('openff_unconstrained-2.0.0.offxml', 'openff_unconstrained-1.3.0.offxml', 'openff_unconstrained-1.2.1.offxml', @@ -69,11 +72,16 @@ def get_list(self): Returns ------- - forcefields : dict - The complete list of available force fields grouped by - force field type + forcefields : list[str] + The complete list of available force fields """ - return self._FF_TYPES + forcefields = [] + + for ff_type in self._FF_TYPES: + forcefields.extend([ff_name.lower() for ff_name in + self._FF_TYPES[ff_type]]) + + return forcefields class ChargeCalculatorSelector(object): @@ -131,8 +139,7 @@ def get_list(self): Returns ------- - forcefields : dict - The complete list of available force fields grouped by - force field type + charge_methods : list[str] + The complete list of available charge methods """ - return self._FF_TYPES + return list(self._AVAILABLE_TYPES.keys()) diff --git a/peleffy/main.py b/peleffy/main.py index bc6013a3..2bdcb03c 100644 --- a/peleffy/main.py +++ b/peleffy/main.py @@ -40,9 +40,12 @@ def parse_args(args): parsed_args : argparse.Namespace It contains the command-line arguments that are supplied by the user """ - parser = ap.ArgumentParser() + import peleffy + + parser = ap.ArgumentParser(prog="PELE Force Field Yielder (peleffy)") parser.add_argument("pdb_file", metavar="PDB FILE", type=str, - help="Path PDB file to parameterize") + help="Path PDB file to parameterize", + default=None) parser.add_argument("-f", "--forcefield", metavar="NAME", type=str, help="OpenForceField's forcefield name. " + "Default is " + str(DEFAULT_OFF_FORCEFIELD), @@ -91,9 +94,8 @@ def parse_args(args): help="Generate Impact template compatible with " + "PELE\'s AMBER implementation") parser.add_argument('-v', '--version', - dest="version", - action='store_true', - help="Print version and quit") + action='version', + version='%(prog)s {}'.format(peleffy.__version__)) parser.set_defaults(as_datalocal=False) parser.set_defaults(with_solvent=False) @@ -101,9 +103,31 @@ def parse_args(args): parser.set_defaults(silent=False) parser.set_defaults(debug=False) parser.set_defaults(for_amber=False) - parser.set_defaults(version=False) parsed_args = parser.parse_args(args) + + # Check force field + from peleffy.forcefield import ForceFieldSelector + + selector = ForceFieldSelector() + available_ffs = selector.get_list() + + if parsed_args.forcefield.lower() not in available_ffs: + raise ValueError('Force field ' + + '\'{}\' '.format(parsed_args.forcefield) + + 'is unknown') + + # Check charge method + if parsed_args.charge_method is not None: + from peleffy.forcefield import ChargeCalculatorSelector + + selector = ChargeCalculatorSelector() + available_charge_methods = selector.get_list() + + if parsed_args.charge_method.lower() not in available_charge_methods: + raise ValueError('Charge method ' + + '\'{}\' '.format(parsed_args.charge_method) + + 'is unknown') return parsed_args @@ -325,11 +349,4 @@ def main(args): if __name__ == '__main__': import sys args = parse_args(sys.argv[1:]) - - # Only print version - if args.version: - print('PELE Force Field Yielder (peleffy) -', peleffy.__version__) - - # Run main - else: - main(args) + main(args) diff --git a/peleffy/tests/test_main.py b/peleffy/tests/test_main.py index 122b4f7e..316b33c9 100644 --- a/peleffy/tests/test_main.py +++ b/peleffy/tests/test_main.py @@ -63,11 +63,11 @@ def test_peleffy_argparse(self): assert parsed_args.as_datalocal is False, \ 'Unexpected as_datalocal settings were parsed' - assert parsed_args.charge_method == 'am1bcc', \ + assert parsed_args.charge_method == None, \ 'Unexpected charge_method settings were parsed' assert parsed_args.debug is False, \ 'Unexpected debug settings were parsed' - assert parsed_args.forcefield == 'openff_unconstrained-1.3.0.offxml', \ + assert parsed_args.forcefield == 'openff_unconstrained-2.0.0.offxml', \ 'Unexpected forcefield settings were parsed' assert parsed_args.include_terminal_rotamers is False, \ 'Unexpected include_terminal_rotamers settings were parsed' @@ -152,23 +152,20 @@ def test_peleffy_argparse(self): 'Unexpected for_amber settings were parsed' # Test unexpected charge method - with pytest.raises(SystemExit) as pytest_wrapped_e: + with pytest.raises(ValueError): parsed_args = parse_args(['toluene.pdb', '-c', 'unexpected']) - assert pytest_wrapped_e.type == SystemExit - assert pytest_wrapped_e.value.code == 2 - # Test as_datalocal argument parsed_args = parse_args(['methane.pdb', '--as_datalocal']) assert parsed_args.as_datalocal is True, \ 'Unexpected as_datalocal settings were parsed' - assert parsed_args.charge_method == 'am1bcc', \ + assert parsed_args.charge_method == None, \ 'Unexpected charge_method settings were parsed' assert parsed_args.debug is False, \ 'Unexpected debug settings were parsed' - assert parsed_args.forcefield == 'openff_unconstrained-1.3.0.offxml', \ + assert parsed_args.forcefield == 'openff_unconstrained-2.0.0.offxml', \ 'Unexpected forcefield settings were parsed' assert parsed_args.include_terminal_rotamers is False, \ 'Unexpected include_terminal_rotamers settings were parsed' @@ -193,11 +190,11 @@ def test_peleffy_argparse(self): assert parsed_args.as_datalocal is False, \ 'Unexpected as_datalocal settings were parsed' - assert parsed_args.charge_method == 'am1bcc', \ + assert parsed_args.charge_method == None, \ 'Unexpected charge_method settings were parsed' assert parsed_args.debug is False, \ 'Unexpected debug settings were parsed' - assert parsed_args.forcefield == 'openff_unconstrained-1.3.0.offxml', \ + assert parsed_args.forcefield == 'openff_unconstrained-2.0.0.offxml', \ 'Unexpected forcefield settings were parsed' assert parsed_args.include_terminal_rotamers is False, \ 'Unexpected include_terminal_rotamers settings were parsed' @@ -224,11 +221,11 @@ def test_peleffy_argparse(self): assert parsed_args.as_datalocal is False, \ 'Unexpected as_datalocal settings were parsed' - assert parsed_args.charge_method == 'am1bcc', \ + assert parsed_args.charge_method == None, \ 'Unexpected charge_method settings were parsed' assert parsed_args.debug is False, \ 'Unexpected debug settings were parsed' - assert parsed_args.forcefield == 'openff_unconstrained-1.3.0.offxml', \ + assert parsed_args.forcefield == 'openff_unconstrained-2.0.0.offxml', \ 'Unexpected forcefield settings were parsed' assert parsed_args.include_terminal_rotamers is True, \ 'Unexpected include_terminal_rotamers settings were parsed' @@ -253,11 +250,11 @@ def test_peleffy_argparse(self): assert parsed_args.as_datalocal is False, \ 'Unexpected as_datalocal settings were parsed' - assert parsed_args.charge_method == 'am1bcc', \ + assert parsed_args.charge_method == None, \ 'Unexpected charge_method settings were parsed' assert parsed_args.debug is False, \ 'Unexpected debug settings were parsed' - assert parsed_args.forcefield == 'openff_unconstrained-1.3.0.offxml', \ + assert parsed_args.forcefield == 'openff_unconstrained-2.0.0.offxml', \ 'Unexpected forcefield settings were parsed' assert parsed_args.include_terminal_rotamers is False, \ 'Unexpected include_terminal_rotamers settings were parsed' @@ -282,11 +279,11 @@ def test_peleffy_argparse(self): assert parsed_args.as_datalocal is False, \ 'Unexpected as_datalocal settings were parsed' - assert parsed_args.charge_method == 'am1bcc', \ + assert parsed_args.charge_method == None, \ 'Unexpected charge_method settings were parsed' assert parsed_args.debug is False, \ 'Unexpected debug settings were parsed' - assert parsed_args.forcefield == 'openff_unconstrained-1.3.0.offxml', \ + assert parsed_args.forcefield == 'openff_unconstrained-2.0.0.offxml', \ 'Unexpected forcefield settings were parsed' assert parsed_args.include_terminal_rotamers is False, \ 'Unexpected include_terminal_rotamers settings were parsed' @@ -311,11 +308,11 @@ def test_peleffy_argparse(self): assert parsed_args.as_datalocal is False, \ 'Unexpected as_datalocal settings were parsed' - assert parsed_args.charge_method == 'am1bcc', \ + assert parsed_args.charge_method == None, \ 'Unexpected charge_method settings were parsed' assert parsed_args.debug is True, \ 'Unexpected debug settings were parsed' - assert parsed_args.forcefield == 'openff_unconstrained-1.3.0.offxml', \ + assert parsed_args.forcefield == 'openff_unconstrained-2.0.0.offxml', \ 'Unexpected forcefield settings were parsed' assert parsed_args.include_terminal_rotamers is False, \ 'Unexpected include_terminal_rotamers settings were parsed' @@ -340,11 +337,11 @@ def test_peleffy_argparse(self): assert parsed_args.as_datalocal is False, \ 'Unexpected as_datalocal settings were parsed' - assert parsed_args.charge_method == 'am1bcc', \ + assert parsed_args.charge_method == None, \ 'Unexpected charge_method settings were parsed' assert parsed_args.debug is False, \ 'Unexpected debug settings were parsed' - assert parsed_args.forcefield == 'openff_unconstrained-1.3.0.offxml', \ + assert parsed_args.forcefield == 'openff_unconstrained-2.0.0.offxml', \ 'Unexpected forcefield settings were parsed' assert parsed_args.include_terminal_rotamers is False, \ 'Unexpected include_terminal_rotamers settings were parsed' @@ -369,11 +366,11 @@ def test_peleffy_argparse(self): assert parsed_args.as_datalocal is False, \ 'Unexpected as_datalocal settings were parsed' - assert parsed_args.charge_method == 'am1bcc', \ + assert parsed_args.charge_method == None, \ 'Unexpected charge_method settings were parsed' assert parsed_args.debug is False, \ 'Unexpected debug settings were parsed' - assert parsed_args.forcefield == 'openff_unconstrained-1.3.0.offxml', \ + assert parsed_args.forcefield == 'openff_unconstrained-2.0.0.offxml', \ 'Unexpected forcefield settings were parsed' assert parsed_args.include_terminal_rotamers is False, \ 'Unexpected include_terminal_rotamers settings were parsed' @@ -441,6 +438,3 @@ def test_PDB_checks(self): complex_path = get_data_file_path('complexes/complex_test.pdb') with pytest.raises(ValueError): _ = run_peleffy(complex_path, chain = 'C') - - - From 3b5fb8502c10014b4890e5fa2e638277eeb06371 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=AD=20Municoy?= Date: Tue, 21 Jun 2022 15:33:19 +0200 Subject: [PATCH 4/5] Update releasehistory.rst --- docs/releasehistory.rst | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/docs/releasehistory.rst b/docs/releasehistory.rst index 1733c993..ee910a81 100644 --- a/docs/releasehistory.rst +++ b/docs/releasehistory.rst @@ -8,6 +8,16 @@ Releases follow the ``major.minor.micro`` scheme recommended by `PEP440 `_: improvements for the CLI interface. Also, ffld_server will not raise an exception but any warning or error found will be raised by peleffy's logger + + 1.4.2 - Compatibility fixes for latest RDKit and Schrodinger versions --------------------------------------------------------------------- From 202ce2647a837f2ca2d875f1fe466c3a243f5610 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=AD=20Municoy?= Date: Tue, 21 Jun 2022 15:34:53 +0200 Subject: [PATCH 5/5] Upgrade to peleffy 1.4.3 --- docs/conf.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/conf.py b/docs/conf.py index ada2e663..c437ccaa 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -20,7 +20,7 @@ # -- Project information ----------------------------------------------------- project = 'Open Force Field for PELE' -copyright = '2020, Barcelona Supercomputing Center' +copyright = '2022, Barcelona Supercomputing Center' author = 'Martí Municoy' @@ -85,7 +85,7 @@ def add_source_parser(_old_add_source_parser, self, *args, **kwargs): #import peleffy #version = peleffy.__version__ -version = '1.4.2' +version = '1.4.3' pygments_style = 'sphinx'