Skip to content

Commit

Permalink
Merge pull request #55 from martimunicoy/prints_to_logs
Browse files Browse the repository at this point in the history
Logging integration
  • Loading branch information
martimunicoy committed Sep 14, 2020
2 parents 2c2ae85 + 3094021 commit 6b8a47d
Show file tree
Hide file tree
Showing 6 changed files with 352 additions and 39 deletions.
6 changes: 6 additions & 0 deletions docs/releasehistory.rst
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ Releases follow the ``major.minor.micro`` scheme recommended by `PEP440 <https:/

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.

Bugfixes
""""""""
- `PR #48 <https://github.com/martimunicoy/offpele/pull/48>`_: Fixes CLI's default output paths.
Expand All @@ -22,6 +26,8 @@ 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.


0.3.0 - Rotamers, OPLS2005, SMILES and stability improvements
-------------------------------------------------------------
Expand Down
64 changes: 42 additions & 22 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="silent",
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 @@ -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 @@ -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
4 changes: 3 additions & 1 deletion 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
151 changes: 151 additions & 0 deletions offpele/tests/test_utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
"""
This module contains the tests to check some handy classes and functions
of offpele.
"""


import pytest

import io
from contextlib import redirect_stdout
from offpele.utils import Logger


class TestLogger(object):
def test_logger_levels(self):
"""
It checks the correct behaviour of the different log levels.
"""
def push_messages(log):
"""Pull some messages at different levels."""
log.debug('Debug message')
log.info('Info message')
log.warning('Warn message')
log.error('Error message')
log.critical('Critical message')

import logging

# Initiate logger
log = Logger()

# Try the default level (INFO)
# Catch logger messages to string buffer
with io.StringIO() as buf:
# Add custom handler to logger
log_handler = logging.StreamHandler(buf)
log._logger.handlers = list()
log._logger.addHandler(log_handler)

# Push messages
push_messages(log)

# Get string from buffer
output = buf.getvalue()

assert output == 'Info message\nWarn message\n' \
+ 'Error message\nCritical message\n', \
'Unexpected logger message at standard output'

# Try DEBUG level
# Catch logger messages to string buffer
with io.StringIO() as buf:
# Add custom handler to logger
log_handler = logging.StreamHandler(buf)
log._logger.handlers = list()
log._logger.addHandler(log_handler)

# Try DEBUG level
log.set_level('DEBUG')

# Push messages
push_messages(log)

# Get string from buffer
output = buf.getvalue()

assert output == 'Debug message\nInfo message\n'\
+ 'Warn message\nError message\nCritical message\n', \
'Unexpected logger message at standard output'

# Try INFO level
# Catch logger messages to string buffer
with io.StringIO() as buf:
# Add custom handler to logger
log_handler = logging.StreamHandler(buf)
log._logger.handlers = list()
log._logger.addHandler(log_handler)

# Try INFO level
log.set_level('INFO')

# Push messages
push_messages(log)

# Get string from buffer
output = buf.getvalue()

assert output == 'Info message\nWarn message\n' \
+ 'Error message\nCritical message\n', \
'Unexpected logger message at standard output'

# Try WARNING level
# Catch logger messages to string buffer
with io.StringIO() as buf:
# Add custom handler to logger
log_handler = logging.StreamHandler(buf)
log._logger.handlers = list()
log._logger.addHandler(log_handler)

# Try WARNING level
log.set_level('WARNING')

# Push messages
push_messages(log)

# Get string from buffer
output = buf.getvalue()

assert output == 'Warn message\nError message\n' \
+ 'Critical message\n', \
'Unexpected logger message at standard output'

# Try ERROR level
# Catch logger messages to string buffer
with io.StringIO() as buf:
# Add custom handler to logger
log_handler = logging.StreamHandler(buf)
log._logger.handlers = list()
log._logger.addHandler(log_handler)

# Try ERROR level
log.set_level('ERROR')

# Push messages
push_messages(log)

# Get string from buffer
output = buf.getvalue()

assert output == 'Error message\nCritical message\n', \
'Unexpected logger message at standard output'

# Try CRITICAL level
# Catch logger messages to string buffer
with io.StringIO() as buf:
# Add custom handler to logger
log_handler = logging.StreamHandler(buf)
log._logger.handlers = list()
log._logger.addHandler(log_handler)

# Try CRITICAL level
log.set_level('CRITICAL')

# Push messages
push_messages(log)

# Get string from buffer
output = buf.getvalue()

assert output == 'Critical message\n', \
'Unexpected logger message at standard output'
Loading

0 comments on commit 6b8a47d

Please sign in to comment.