Adds Functionality to Logger
This commit is contained in:
@@ -0,0 +1,4 @@
|
||||
from diceplayer.shared.utils.logger import Logger
|
||||
|
||||
|
||||
logger = Logger(__name__)
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
from diceplayer.shared.interface.dice_interface import DiceInterface
|
||||
from diceplayer.player import Player
|
||||
from diceplayer import logger
|
||||
|
||||
from pathlib import Path
|
||||
import argparse
|
||||
@@ -40,6 +41,7 @@ def main():
|
||||
args = parser.parse_args()
|
||||
|
||||
# Open OUTFILE for writing and print keywords and initial info
|
||||
logger.set_logger(args.outfile, logging.INFO)
|
||||
|
||||
try:
|
||||
|
||||
@@ -55,12 +57,6 @@ def main():
|
||||
except Exception as err:
|
||||
sys.exit(err)
|
||||
|
||||
logging.basicConfig(
|
||||
filename=args.outfile,
|
||||
format='%(message)s',
|
||||
level=logging.INFO
|
||||
)
|
||||
|
||||
player = Player(args.infile)
|
||||
|
||||
player.start()
|
||||
|
||||
@@ -42,6 +42,29 @@ class System:
|
||||
raise TypeError("Error: nmols is not an integer")
|
||||
self.nmols.append(nmols)
|
||||
|
||||
def update_molecule(self, position: np.ndarray, fh: TextIO) -> None:
|
||||
"""Updates the position of the molecule in the Output file
|
||||
|
||||
Args:
|
||||
position (np.ndarray): numpy position vector
|
||||
fh (TextIO): Output file
|
||||
"""
|
||||
|
||||
position_in_ang = (position * BOHR2ANG).tolist()
|
||||
self.add_type(self.nmols[0], deepcopy(self.molecule[0]))
|
||||
|
||||
for atom in self.molecule[-1].atom:
|
||||
|
||||
atom.rx = position_in_ang.pop(0)
|
||||
atom.ry = position_in_ang.pop(0)
|
||||
atom.rz = position_in_ang.pop(0)
|
||||
|
||||
rmsd, self.molecule[0] = self.rmsd_fit(-1, 0)
|
||||
self.molecule.pop(-1)
|
||||
|
||||
fh.write("\nProjected new conformation of reference molecule with RMSD fit\n")
|
||||
fh.write("RMSD = {:>8.5f} Angstrom\n".format(rmsd))
|
||||
|
||||
def rmsd_fit(self, p_index: int, r_index: int) -> Tuple[float, Molecule]:
|
||||
|
||||
projecting_mol = self.molecule[p_index]
|
||||
@@ -176,65 +199,43 @@ class System:
|
||||
# self.molecule.pop(-1)
|
||||
#
|
||||
# return min_dist, nearestmol
|
||||
def update_molecule(self, position: np.ndarray, fh: TextIO) -> None:
|
||||
"""Updates the position of the molecule in the Output file
|
||||
|
||||
Args:
|
||||
position (np.ndarray): numpy position vector
|
||||
fh (TextIO): Output file
|
||||
"""
|
||||
|
||||
position_in_ang = (position * BOHR2ANG).tolist()
|
||||
self.add_type(self.nmols[0], deepcopy(self.molecule[0]))
|
||||
|
||||
for atom in self.molecule[-1].atom:
|
||||
|
||||
atom.rx = position_in_ang.pop(0)
|
||||
atom.ry = position_in_ang.pop(0)
|
||||
atom.rz = position_in_ang.pop(0)
|
||||
|
||||
rmsd, self.molecule[0] = self.rmsd_fit(-1, 0)
|
||||
self.molecule.pop(-1)
|
||||
|
||||
fh.write("\nProjected new conformation of reference molecule with RMSD fit\n")
|
||||
fh.write("RMSD = {:>8.5f} Angstrom\n".format(rmsd))
|
||||
|
||||
|
||||
def print_geom(self, cycle: int, fh: TextIO) -> None:
|
||||
"""
|
||||
Print the geometry of the molecule in the Output file
|
||||
|
||||
Args:
|
||||
cycle (int): Number of the cycle
|
||||
fh (TextIO): Output file
|
||||
"""
|
||||
|
||||
fh.write("Cycle # {}\n".format(cycle))
|
||||
fh.write("Number of site: {}\n".format(len(self.molecule[0].atom)))
|
||||
for atom in self.molecule[0].atom:
|
||||
symbol = atomsymb[atom.na]
|
||||
fh.write(
|
||||
"{:<2s} {:>10.6f} {:>10.6f} {:>10.6f}\n".format(
|
||||
symbol, atom.rx, atom.ry, atom.rz
|
||||
)
|
||||
)
|
||||
|
||||
def printChargesAndDipole(self, cycle: int, fh: TextIO) -> None:
|
||||
"""
|
||||
Print the charges and dipole of the molecule in the Output file
|
||||
|
||||
Args:
|
||||
cycle (int): Number of the cycle
|
||||
fh (TextIO): Output file
|
||||
"""
|
||||
|
||||
fh.write("Cycle # {}\n".format(cycle))
|
||||
fh.write("Number of site: {}\n".format(len(self.molecule[0].atom)))
|
||||
|
||||
chargesAndDipole = self.molecule[0].charges_and_dipole()
|
||||
|
||||
fh.write(
|
||||
"{:>10.6f} {:>10.6f} {:>10.6f} {:>10.6f} {:>10.6f}\n".format(
|
||||
chargesAndDipole[0], chargesAndDipole[1], chargesAndDipole[2], chargesAndDipole[3], chargesAndDipole[4]
|
||||
)
|
||||
)
|
||||
# def print_geom(self, cycle: int, fh: TextIO) -> None:
|
||||
# """
|
||||
# Print the geometry of the molecule in the Output file
|
||||
#
|
||||
# Args:
|
||||
# cycle (int): Number of the cycle
|
||||
# fh (TextIO): Output file
|
||||
# """
|
||||
#
|
||||
# fh.write("Cycle # {}\n".format(cycle))
|
||||
# fh.write("Number of site: {}\n".format(len(self.molecule[0].atom)))
|
||||
# for atom in self.molecule[0].atom:
|
||||
# symbol = atomsymb[atom.na]
|
||||
# fh.write(
|
||||
# "{:<2s} {:>10.6f} {:>10.6f} {:>10.6f}\n".format(
|
||||
# symbol, atom.rx, atom.ry, atom.rz
|
||||
# )
|
||||
# )
|
||||
#
|
||||
# def printChargesAndDipole(self, cycle: int, fh: TextIO) -> None:
|
||||
# """
|
||||
# Print the charges and dipole of the molecule in the Output file
|
||||
#
|
||||
# Args:
|
||||
# cycle (int): Number of the cycle
|
||||
# fh (TextIO): Output file
|
||||
# """
|
||||
#
|
||||
# fh.write("Cycle # {}\n".format(cycle))
|
||||
# fh.write("Number of site: {}\n".format(len(self.molecule[0].atom)))
|
||||
#
|
||||
# chargesAndDipole = self.molecule[0].charges_and_dipole()
|
||||
#
|
||||
# fh.write(
|
||||
# "{:>10.6f} {:>10.6f} {:>10.6f} {:>10.6f} {:>10.6f}\n".format(
|
||||
# chargesAndDipole[0], chargesAndDipole[1], chargesAndDipole[2], chargesAndDipole[3], chargesAndDipole[4]
|
||||
# )
|
||||
# )
|
||||
|
||||
@@ -1,27 +1,54 @@
|
||||
import logging
|
||||
|
||||
|
||||
def valid_logger(func):
|
||||
def wrapper(*args, **kwargs):
|
||||
logger = args[0]
|
||||
assert logger._was_set, \
|
||||
"Logger is not set. Please call set_logger() first."
|
||||
|
||||
return func(*args, **kwargs)
|
||||
|
||||
return wrapper
|
||||
|
||||
|
||||
class Logger:
|
||||
outfile = None
|
||||
|
||||
_logger = None
|
||||
_instance = None
|
||||
|
||||
def __new__(cls, *args, **kwargs):
|
||||
if not getattr(cls, '_instance'):
|
||||
cls._instance = super(Logger, cls).__new__(cls)
|
||||
return cls._instance
|
||||
_was_set = False
|
||||
|
||||
def set_logger(self, logger_name, outfile='run.log', level=logging.INFO):
|
||||
def __init__(self, logger_name):
|
||||
if self._logger is None:
|
||||
self._logger = logging.getLogger(logger_name)
|
||||
|
||||
def set_logger(self, outfile='run.log', level=logging.INFO):
|
||||
self.outfile = outfile
|
||||
|
||||
self._logger = logging.getLogger(logger_name)
|
||||
|
||||
if level is not None:
|
||||
self._logger.setLevel(level)
|
||||
|
||||
self._create_handlers()
|
||||
|
||||
self._was_set = True
|
||||
|
||||
@valid_logger
|
||||
def info(self, message):
|
||||
self._logger.info(message)
|
||||
|
||||
@valid_logger
|
||||
def debug(self, message):
|
||||
self._logger.debug(message)
|
||||
|
||||
@valid_logger
|
||||
def warning(self, message):
|
||||
self._logger.warning(message)
|
||||
|
||||
@valid_logger
|
||||
def error(self, message):
|
||||
self._logger.error(message)
|
||||
|
||||
def _create_handlers(self):
|
||||
handlers = []
|
||||
if self.outfile is not None:
|
||||
|
||||
@@ -1,34 +1,96 @@
|
||||
from diceplayer.shared.utils.logger import Logger
|
||||
from diceplayer.shared.utils.logger import Logger, valid_logger
|
||||
|
||||
import logging
|
||||
|
||||
from unittest import mock
|
||||
import unittest
|
||||
|
||||
|
||||
class TestValidateLogger(unittest.TestCase):
|
||||
def test_validate_logger(self):
|
||||
class MockLogger:
|
||||
_was_set = True
|
||||
|
||||
@valid_logger
|
||||
def test_func(self):
|
||||
pass
|
||||
|
||||
MockLogger().test_func()
|
||||
|
||||
def test_validate_logger_exception(self):
|
||||
class MockLogger:
|
||||
_was_set = False
|
||||
|
||||
@valid_logger
|
||||
def test_func(self):
|
||||
pass
|
||||
|
||||
with self.assertRaises(AssertionError):
|
||||
MockLogger().test_func()
|
||||
|
||||
|
||||
class TestLogger(unittest.TestCase):
|
||||
def test_class_instantiation(self):
|
||||
logger = Logger()
|
||||
logger = Logger('test')
|
||||
|
||||
self.assertIsInstance(logger, Logger)
|
||||
|
||||
def test_singleton(self):
|
||||
logger1 = Logger()
|
||||
logger2 = Logger()
|
||||
|
||||
self.assertIs(logger1, logger2)
|
||||
|
||||
@mock.patch('builtins.open', mock.mock_open())
|
||||
def test_set_logger(self):
|
||||
logger = Logger()
|
||||
logger.set_logger('test_logger')
|
||||
logger = Logger('test')
|
||||
logger.set_logger()
|
||||
|
||||
self.assertIsNotNone(logger._logger)
|
||||
self.assertEqual(logger._logger.name, 'test_logger')
|
||||
self.assertEqual(logger._logger.name, 'test')
|
||||
|
||||
@mock.patch('builtins.open', mock.mock_open())
|
||||
def test_close(self):
|
||||
logger = Logger()
|
||||
logger.set_logger('test_logger')
|
||||
logger = Logger('test')
|
||||
logger.set_logger()
|
||||
logger.close()
|
||||
|
||||
self.assertEqual(len(logger._logger.handlers), 0)
|
||||
|
||||
@mock.patch('builtins.open', mock.mock_open())
|
||||
def test_info(self):
|
||||
logger = Logger('test')
|
||||
logger.set_logger()
|
||||
|
||||
with self.assertLogs(level='INFO') as cm:
|
||||
logger.info('test')
|
||||
|
||||
self.assertEqual(cm.output, ['INFO:test:test'])
|
||||
|
||||
@mock.patch('builtins.open', mock.mock_open())
|
||||
def test_debug(self):
|
||||
logger = Logger('test')
|
||||
logger.set_logger(level=logging.DEBUG)
|
||||
|
||||
with self.assertLogs(level='DEBUG') as cm:
|
||||
logger.debug('test')
|
||||
|
||||
self.assertEqual(cm.output, ['DEBUG:test:test'])
|
||||
|
||||
@mock.patch('builtins.open', mock.mock_open())
|
||||
def test_warning(self):
|
||||
logger = Logger('test')
|
||||
logger.set_logger()
|
||||
|
||||
with self.assertLogs(level='WARNING') as cm:
|
||||
logger.warning('test')
|
||||
|
||||
self.assertEqual(cm.output, ['WARNING:test:test'])
|
||||
|
||||
@mock.patch('builtins.open', mock.mock_open())
|
||||
def test_error(self):
|
||||
logger = Logger('test')
|
||||
logger.set_logger()
|
||||
|
||||
with self.assertLogs(level='ERROR') as cm:
|
||||
logger.error('test')
|
||||
|
||||
self.assertEqual(cm.output, ['ERROR:test:test'])
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
|
||||
Reference in New Issue
Block a user