Adds Functionality to Logger

This commit is contained in:
2023-04-27 05:14:07 -03:00
parent 2d488bd749
commit 9c822c6848
5 changed files with 177 additions and 87 deletions

View File

@@ -0,0 +1,4 @@
from diceplayer.shared.utils.logger import Logger
logger = Logger(__name__)

View File

@@ -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()

View File

@@ -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]
# )
# )

View File

@@ -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:

View File

@@ -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()