Merge pull request #3 from HideyoshiNakazone/adds-pre-commit-and-formatter

Adds pre commit and formatter
This commit is contained in:
2023-06-11 16:07:19 -03:00
committed by GitHub
30 changed files with 1382 additions and 721 deletions

13
.pre-commit-config.yaml Normal file
View File

@@ -0,0 +1,13 @@
repos:
- repo: https://github.com/psf/black
rev: 23.3.0
hooks:
- id: black
args: [--config=pyproject.toml]
- repo: https://github.com/pycqa/isort
rev: 5.12.0
hooks:
- id: isort
files: "\\.(py)$"
args: [--settings-path=pyproject.toml]

View File

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

View File

@@ -1,12 +1,12 @@
from diceplayer.shared.interface.dice_interface import DiceInterface
from diceplayer.player import Player
from diceplayer import logger from diceplayer import logger
from diceplayer.player import Player
from diceplayer.shared.interface.dice_interface import DiceInterface
from pathlib import Path
import argparse import argparse
import logging import logging
import pickle import pickle
import sys import sys
from pathlib import Path
__VERSION = "v0.0.1" __VERSION = "v0.0.1"
@@ -25,18 +25,20 @@ def main():
"-v", "--version", action="version", version="diceplayer-" + __VERSION "-v", "--version", action="version", version="diceplayer-" + __VERSION
) )
parser.add_argument( parser.add_argument(
"-i", "--input", "-i",
"--input",
dest="infile", dest="infile",
default="control.yml", default="control.yml",
metavar="INFILE", metavar="INFILE",
help="input file of diceplayer [default = control.in]" help="input file of diceplayer [default = control.in]",
) )
parser.add_argument( parser.add_argument(
"-o", "--output", "-o",
"--output",
dest="outfile", dest="outfile",
default="run.log", default="run.log",
metavar="OUTFILE", metavar="OUTFILE",
help="output file of diceplayer [default = run.log]" help="output file of diceplayer [default = run.log]",
) )
args = parser.parse_args() args = parser.parse_args()

View File

@@ -1,24 +1,24 @@
from diceplayer.shared.interface.gaussian_interface import GaussianInterface from diceplayer import logger
from diceplayer.shared.interface.dice_interface import DiceInterface from diceplayer.shared.config.dice_config import DiceConfig
from diceplayer.shared.utils.dataclass_protocol import Dataclass
from diceplayer.shared.config.gaussian_config import GaussianDTO from diceplayer.shared.config.gaussian_config import GaussianDTO
from diceplayer.shared.config.player_config import PlayerConfig from diceplayer.shared.config.player_config import PlayerConfig
from diceplayer.shared.config.dice_config import DiceConfig from diceplayer.shared.environment.atom import Atom
from diceplayer.shared.utils.misc import weekday_date_time
from diceplayer.shared.environment.molecule import Molecule from diceplayer.shared.environment.molecule import Molecule
from diceplayer.shared.environment.system import System from diceplayer.shared.environment.system import System
from diceplayer.shared.environment.atom import Atom from diceplayer.shared.interface.dice_interface import DiceInterface
from diceplayer.shared.interface.gaussian_interface import GaussianInterface
from diceplayer.shared.utils.dataclass_protocol import Dataclass
from diceplayer.shared.utils.misc import weekday_date_time
from diceplayer.shared.utils.ptable import atomsymb from diceplayer.shared.utils.ptable import atomsymb
from diceplayer import logger
from dataclasses import fields
from typing import Type, Tuple
from pathlib import Path
import pickle
import yaml import yaml
import sys
import os
import os
import pickle
import sys
from dataclasses import fields
from pathlib import Path
from typing import Tuple, Type
ENV = ["OMP_STACKSIZE"] ENV = ["OMP_STACKSIZE"]
@@ -29,9 +29,7 @@ class Player:
raise ValueError("Must specify either infile or optimization") raise ValueError("Must specify either infile or optimization")
elif infile is not None: elif infile is not None:
self.config = self.set_config( self.config = self.set_config(self.read_keywords(infile))
self.read_keywords(infile)
)
self.system = System() self.system = System()
@@ -60,7 +58,6 @@ class Player:
) )
for cycle in range(self.initial_cycle, self.initial_cycle + self.config.maxcyc): for cycle in range(self.initial_cycle, self.initial_cycle + self.config.maxcyc):
logger.info( logger.info(
f"------------------------------------------------------------------------------------------\n" f"------------------------------------------------------------------------------------------\n"
f" Step # {cycle}\n" f" Step # {cycle}\n"
@@ -78,9 +75,7 @@ class Player:
def prepare_system(self): def prepare_system(self):
for i, mol in enumerate(self.system.molecule): for i, mol in enumerate(self.system.molecule):
logger.info( logger.info(f"Molecule {i + 1} - {mol.molname}")
f"Molecule {i + 1} - {mol.molname}"
)
mol.print_mol_info() mol.print_mol_info()
logger.info( logger.info(
@@ -113,7 +108,6 @@ class Player:
geoms_file_path.touch() geoms_file_path.touch()
def print_keywords(self) -> None: def print_keywords(self) -> None:
def log_keywords(config: Dataclass, dto: Type[Dataclass]): def log_keywords(config: Dataclass, dto: Type[Dataclass]):
for key in sorted(list(map(lambda f: f.name, fields(dto)))): for key in sorted(list(map(lambda f: f.name, fields(dto)))):
if getattr(config, key) is not None: if getattr(config, key) is not None:
@@ -162,9 +156,7 @@ class Player:
with open(self.config.dice.ljname) as file: with open(self.config.dice.ljname) as file:
ljc_data = file.readlines() ljc_data = file.readlines()
else: else:
raise RuntimeError( raise RuntimeError(f"Potential file {self.config.dice.ljname} not found.")
f"Potential file {self.config.dice.ljname} not found."
)
combrule = ljc_data.pop(0).split()[0] combrule = ljc_data.pop(0).split()[0]
if combrule not in ("*", "+"): if combrule not in ("*", "+"):
@@ -191,7 +183,6 @@ class Player:
) )
for i in range(ntypes): for i in range(ntypes):
try: try:
nsites, molname = ljc_data.pop(0).split()[:2] nsites, molname = ljc_data.pop(0).split()[:2]
except ValueError: except ValueError:
@@ -209,10 +200,7 @@ class Player:
atom_fields = ["lbl", "na", "rx", "ry", "rz", "chg", "eps", "sig"] atom_fields = ["lbl", "na", "rx", "ry", "rz", "chg", "eps", "sig"]
for j in range(nsites): for j in range(nsites):
new_atom = dict(zip( new_atom = dict(zip(atom_fields, ljc_data.pop(0).split()))
atom_fields,
ljc_data.pop(0).split()
))
self.system.molecule[i].add_atom( self.system.molecule[i].add_atom(
Atom(**self.validate_atom_dict(i, j, new_atom)) Atom(**self.validate_atom_dict(i, j, new_atom))
) )
@@ -227,16 +215,12 @@ class Player:
) )
logger.info(f"Combination rule: {self.config.dice.combrule}") logger.info(f"Combination rule: {self.config.dice.combrule}")
logger.info( logger.info(f"Types of molecules: {len(self.system.molecule)}\n")
f"Types of molecules: {len(self.system.molecule)}\n"
)
i = 0 i = 0
for mol in self.system.molecule: for mol in self.system.molecule:
i += 1 i += 1
logger.info( logger.info("{} atoms in molecule type {}:".format(len(mol.atom), i))
"{} atoms in molecule type {}:".format(len(mol.atom), i)
)
logger.info( logger.info(
"---------------------------------------------------------------------------------" "---------------------------------------------------------------------------------"
) )
@@ -285,42 +269,37 @@ class Player:
self.gaussian_interface.reset() self.gaussian_interface.reset()
if self.config.opt: if self.config.opt:
if 'position' not in result: if "position" not in result:
raise RuntimeError( raise RuntimeError("Optimization failed. No position found in result.")
'Optimization failed. No position found in result.'
)
self.system.update_molecule(result['position']) self.system.update_molecule(result["position"])
else: else:
if 'charges' not in result: if "charges" not in result:
raise RuntimeError( raise RuntimeError(
'Charges optimization failed. No charges found in result.' "Charges optimization failed. No charges found in result."
) )
diff = self.system.molecule[0] \ diff = self.system.molecule[0].update_charges(result["charges"])
.update_charges(result['charges'])
self.system.print_charges_and_dipole(cycle) self.system.print_charges_and_dipole(cycle)
self.print_geoms(cycle) self.print_geoms(cycle)
if diff < self.config.gaussian.chg_tol: if diff < self.config.gaussian.chg_tol:
logger.info( logger.info(f"Charges converged after {cycle} cycles.")
f'Charges converged after {cycle} cycles.'
)
raise StopIteration() raise StopIteration()
def print_geoms(self, cycle: int): def print_geoms(self, cycle: int):
with open(self.config.geoms_file, 'a') as file: with open(self.config.geoms_file, "a") as file:
file.write(f'Cycle # {cycle}\n') file.write(f"Cycle # {cycle}\n")
for atom in self.system.molecule[0].atom: for atom in self.system.molecule[0].atom:
symbol = atomsymb[atom.na] symbol = atomsymb[atom.na]
file.write( file.write(
f'{symbol:<2s} {atom.rx:>10.6f} {atom.ry:>10.6f} {atom.rz:>10.6f}\n' f"{symbol:<2s} {atom.rx:>10.6f} {atom.ry:>10.6f} {atom.rz:>10.6f}\n"
) )
file.write('\n') file.write("\n")
@staticmethod @staticmethod
def validate_atom_dict(molecule_type, molecule_site, atom_dict: dict) -> dict: def validate_atom_dict(molecule_type, molecule_site, atom_dict: dict) -> dict:
@@ -329,69 +308,69 @@ class Player:
if len(atom_dict) < 8: if len(atom_dict) < 8:
raise ValueError( raise ValueError(
f'Invalid number of fields for site {molecule_site} for molecule type {molecule_type}.' f"Invalid number of fields for site {molecule_site} for molecule type {molecule_type}."
) )
try: try:
atom_dict['lbl'] = int(atom_dict['lbl']) atom_dict["lbl"] = int(atom_dict["lbl"])
except Exception: except Exception:
raise ValueError( raise ValueError(
f'Invalid lbl fields for site {molecule_site} for molecule type {molecule_type}.' f"Invalid lbl fields for site {molecule_site} for molecule type {molecule_type}."
) )
try: try:
atom_dict['na'] = int(atom_dict['na']) atom_dict["na"] = int(atom_dict["na"])
except Exception: except Exception:
raise ValueError( raise ValueError(
f'Invalid na fields for site {molecule_site} for molecule type {molecule_type}.' f"Invalid na fields for site {molecule_site} for molecule type {molecule_type}."
) )
try: try:
atom_dict['rx'] = float(atom_dict['rx']) atom_dict["rx"] = float(atom_dict["rx"])
except Exception: except Exception:
raise ValueError( raise ValueError(
f'Invalid rx fields for site {molecule_site} for molecule type {molecule_type}. ' f"Invalid rx fields for site {molecule_site} for molecule type {molecule_type}. "
f'Value must be a float.' f"Value must be a float."
) )
try: try:
atom_dict['ry'] = float(atom_dict['ry']) atom_dict["ry"] = float(atom_dict["ry"])
except Exception: except Exception:
raise ValueError( raise ValueError(
f'Invalid ry fields for site {molecule_site} for molecule type {molecule_type}. ' f"Invalid ry fields for site {molecule_site} for molecule type {molecule_type}. "
f'Value must be a float.' f"Value must be a float."
) )
try: try:
atom_dict['rz'] = float(atom_dict['rz']) atom_dict["rz"] = float(atom_dict["rz"])
except Exception: except Exception:
raise ValueError( raise ValueError(
f'Invalid rz fields for site {molecule_site} for molecule type {molecule_type}. ' f"Invalid rz fields for site {molecule_site} for molecule type {molecule_type}. "
f'Value must be a float.' f"Value must be a float."
) )
try: try:
atom_dict['chg'] = float(atom_dict['chg']) atom_dict["chg"] = float(atom_dict["chg"])
except Exception: except Exception:
raise ValueError( raise ValueError(
f'Invalid chg fields for site {molecule_site} for molecule type {molecule_type}. ' f"Invalid chg fields for site {molecule_site} for molecule type {molecule_type}. "
f'Value must be a float.' f"Value must be a float."
) )
try: try:
atom_dict['eps'] = float(atom_dict['eps']) atom_dict["eps"] = float(atom_dict["eps"])
except Exception: except Exception:
raise ValueError( raise ValueError(
f'Invalid eps fields for site {molecule_site} for molecule type {molecule_type}. ' f"Invalid eps fields for site {molecule_site} for molecule type {molecule_type}. "
f'Value must be a float.' f"Value must be a float."
) )
try: try:
atom_dict['sig'] = float(atom_dict['sig']) atom_dict["sig"] = float(atom_dict["sig"])
except Exception: except Exception:
raise ValueError( raise ValueError(
f'Invalid sig fields for site {molecule_site} for molecule type {molecule_type}. ' f"Invalid sig fields for site {molecule_site} for molecule type {molecule_type}. "
f'Value must be a float.' f"Value must be a float."
) )
return atom_dict return atom_dict
@@ -400,9 +379,7 @@ class Player:
formatstr = "{:<3d} {:>3d} {:>10.5f} {:>10.5f} {:>10.5f} {:>10.6f} {:>9.5f} {:>7.4f} {:>9.4f}" formatstr = "{:<3d} {:>3d} {:>10.5f} {:>10.5f} {:>10.5f} {:>10.6f} {:>9.5f} {:>7.4f} {:>9.4f}"
mol = self.system.molecule[0] mol = self.system.molecule[0]
logger.info( logger.info("{} atoms in molecule type {}:".format(len(mol.atom), 1))
"{} atoms in molecule type {}:".format(len(mol.atom), 1)
)
logger.info( logger.info(
"---------------------------------------------------------------------------------" "---------------------------------------------------------------------------------"
) )
@@ -432,28 +409,21 @@ class Player:
def save_run_in_pickle(self, cycle): def save_run_in_pickle(self, cycle):
try: try:
with open('latest-step.pkl', 'wb') as pickle_file: with open("latest-step.pkl", "wb") as pickle_file:
pickle.dump( pickle.dump((self.config, self.system, cycle), pickle_file)
(self.config, self.system, cycle),
pickle_file
)
except Exception: except Exception:
raise RuntimeError( raise RuntimeError(f"Could not save pickle file latest-step.pkl.")
f'Could not save pickle file latest-step.pkl.'
)
@staticmethod @staticmethod
def load_run_from_pickle() -> Tuple[PlayerConfig, System, int]: def load_run_from_pickle() -> Tuple[PlayerConfig, System, int]:
pickle_path = Path("latest-step.pkl") pickle_path = Path("latest-step.pkl")
try: try:
with open(pickle_path, 'rb') as pickle_file: with open(pickle_path, "rb") as pickle_file:
save = pickle.load(pickle_file) save = pickle.load(pickle_file)
return save[0], save[1], save[2] + 1 return save[0], save[1], save[2] + 1
except Exception: except Exception:
raise RuntimeError( raise RuntimeError(f"Could not load pickle file {pickle_path}.")
f'Could not load pickle file {pickle_path}.'
)
@staticmethod @staticmethod
def set_config(data: dict) -> PlayerConfig: def set_config(data: dict) -> PlayerConfig:
@@ -461,18 +431,16 @@ class Player:
@staticmethod @staticmethod
def read_keywords(infile) -> dict: def read_keywords(infile) -> dict:
with open(infile, 'r') as yml_file: with open(infile, "r") as yml_file:
config = yaml.load(yml_file, Loader=yaml.SafeLoader) config = yaml.load(yml_file, Loader=yaml.SafeLoader)
if "diceplayer" in config: if "diceplayer" in config:
return config.get("diceplayer") return config.get("diceplayer")
raise RuntimeError( raise RuntimeError(f"Could not find diceplayer section in {infile}.")
f'Could not find diceplayer section in {infile}.'
)
@classmethod @classmethod
def from_file(cls, infile: str) -> 'Player': def from_file(cls, infile: str) -> "Player":
return cls(infile=infile) return cls(infile=infile)
@classmethod @classmethod

View File

@@ -1,7 +1,8 @@
from diceplayer.shared.utils.dataclass_protocol import Dataclass from diceplayer.shared.utils.dataclass_protocol import Dataclass
from dataclasses import dataclass
from dacite import from_dict from dacite import from_dict
from dataclasses import dataclass
from typing import List from typing import List
@@ -10,6 +11,7 @@ class DiceConfig(Dataclass):
""" """
Data Transfer Object for the Dice configuration. Data Transfer Object for the Dice configuration.
""" """
ljname: str ljname: str
outname: str outname: str
dens: float dens: float
@@ -22,24 +24,17 @@ class DiceConfig(Dataclass):
press: float = 1.0 press: float = 1.0
temp: float = 300.0 temp: float = 300.0
progname: str = "dice" progname: str = "dice"
randominit: str = 'first' randominit: str = "first"
def __post_init__(self): def __post_init__(self):
if not isinstance(self.ljname, str): if not isinstance(self.ljname, str):
raise ValueError( raise ValueError("Error: 'ljname' keyword not specified in config file")
"Error: 'ljname' keyword not specified in config file"
)
if not isinstance(self.outname, str): if not isinstance(self.outname, str):
raise ValueError( raise ValueError("Error: 'outname' keyword not specified in config file")
"Error: 'outname' keyword not specified in config file"
)
if not isinstance(self.dens, float): if not isinstance(self.dens, float):
raise ValueError( raise ValueError("Error: 'dens' keyword not specified in config file")
"Error: 'dens' keyword not specified in config file"
)
if not isinstance(self.nmol, list): if not isinstance(self.nmol, list):
raise ValueError( raise ValueError(

View File

@@ -1,31 +1,29 @@
from diceplayer.shared.utils.dataclass_protocol import Dataclass from diceplayer.shared.utils.dataclass_protocol import Dataclass
from dataclasses import dataclass
from dacite import from_dict from dacite import from_dict
from dataclasses import dataclass
@dataclass @dataclass
class GaussianDTO(Dataclass): class GaussianDTO(Dataclass):
""" """
Data Transfer Object for the Gaussian configuration. Data Transfer Object for the Gaussian configuration.
""" """
level: str level: str
qmprog: str qmprog: str
chgmult = [0, 1] chgmult = [0, 1]
pop: str = 'chelpg' pop: str = "chelpg"
chg_tol: float = 0.01 chg_tol: float = 0.01
keywords: str = None keywords: str = None
def __post_init__(self): def __post_init__(self):
if self.qmprog not in ("g03", "g09", "g16"): if self.qmprog not in ("g03", "g09", "g16"):
raise ValueError( raise ValueError("Error: invalid qmprog value.")
"Error: invalid qmprog value."
)
if self.level is None: if self.level is None:
raise ValueError( raise ValueError("Error: 'level' keyword not specified in config file.")
"Error: 'level' keyword not specified in config file."
)
@classmethod @classmethod
def from_dict(cls, param: dict): def from_dict(cls, param: dict):

View File

@@ -1,9 +1,10 @@
from diceplayer.shared.utils.dataclass_protocol import Dataclass
from diceplayer.shared.config.gaussian_config import GaussianDTO
from diceplayer.shared.config.dice_config import DiceConfig from diceplayer.shared.config.dice_config import DiceConfig
from diceplayer.shared.config.gaussian_config import GaussianDTO
from diceplayer.shared.utils.dataclass_protocol import Dataclass
from dacite import from_dict
from dataclasses import dataclass from dataclasses import dataclass
from dacite import from_dict
@dataclass @dataclass
@@ -11,6 +12,7 @@ class PlayerConfig(Dataclass):
""" """
Data Transfer Object for the player configuration. Data Transfer Object for the player configuration.
""" """
opt: bool opt: bool
maxcyc: int maxcyc: int
nprocs: int nprocs: int
@@ -21,10 +23,10 @@ class PlayerConfig(Dataclass):
mem: int = None mem: int = None
switchcyc: int = 3 switchcyc: int = 3
qmprog: str = 'g16' qmprog: str = "g16"
altsteps: int = 20000 altsteps: int = 20000
geoms_file = 'geoms.xyz' geoms_file = "geoms.xyz"
simulation_dir = 'simfiles' simulation_dir = "simfiles"
def __post_init__(self): def __post_init__(self):
MIN_STEP = 20000 MIN_STEP = 20000
@@ -33,16 +35,12 @@ class PlayerConfig(Dataclass):
@classmethod @classmethod
def from_dict(cls, param: dict): def from_dict(cls, param: dict):
if param['dice'] is None: if param["dice"] is None:
raise ValueError( raise ValueError("Error: 'dice' keyword not specified in config file.")
"Error: 'dice' keyword not specified in config file." param["dice"] = DiceConfig.from_dict(param["dice"])
)
param['dice'] = DiceConfig.from_dict(param['dice'])
if param['gaussian'] is None: if param["gaussian"] is None:
raise ValueError( raise ValueError("Error: 'gaussian' keyword not specified in config file.")
"Error: 'gaussian' keyword not specified in config file." param["gaussian"] = GaussianDTO.from_dict(param["gaussian"])
)
param['gaussian'] = GaussianDTO.from_dict(param['gaussian'])
return from_dict(PlayerConfig, param) return from_dict(PlayerConfig, param)

View File

@@ -1,18 +1,18 @@
from __future__ import annotations from __future__ import annotations
from diceplayer.shared.utils.ptable import ghost_number from diceplayer import logger
from diceplayer.shared.environment.atom import Atom from diceplayer.shared.environment.atom import Atom
from diceplayer.shared.utils.misc import BOHR2ANG from diceplayer.shared.utils.misc import BOHR2ANG
from diceplayer import logger from diceplayer.shared.utils.ptable import ghost_number
from nptyping import NDArray, Shape, Float
from numpy.linalg import linalg
import numpy as np import numpy as np
from nptyping import Float, NDArray, Shape
from numpy.linalg import linalg
from typing import List, Any, Tuple, Union
from copy import deepcopy
import logging import logging
import math import math
from copy import deepcopy
from typing import Any, List, Tuple, Union
class Molecule: class Molecule:
@@ -169,7 +169,9 @@ class Molecule:
try: try:
evals, evecs = linalg.eigh(self.inertia_tensor()) evals, evecs = linalg.eigh(self.inertia_tensor())
except ValueError: except ValueError:
raise RuntimeError("Error: diagonalization of inertia tensor did not converge") raise RuntimeError(
"Error: diagonalization of inertia tensor did not converge"
)
return evals, evecs return evals, evecs
@@ -355,7 +357,7 @@ class Molecule:
) )
) )
def minimum_distance(self, molec: 'Molecule') -> float: def minimum_distance(self, molec: "Molecule") -> float:
""" """
Return the minimum distance between two molecules Return the minimum distance between two molecules

View File

@@ -1,13 +1,14 @@
from diceplayer.shared.environment.molecule import Molecule
from diceplayer.shared.utils.ptable import atomsymb
from diceplayer.shared.utils.misc import BOHR2ANG
from diceplayer import logger from diceplayer import logger
from diceplayer.shared.environment.molecule import Molecule
from diceplayer.shared.utils.misc import BOHR2ANG
from diceplayer.shared.utils.ptable import atomsymb
from typing import List, Tuple, TextIO
from copy import deepcopy
from numpy import linalg
import numpy as np import numpy as np
from numpy import linalg
import math import math
from copy import deepcopy
from typing import List, TextIO, Tuple
class System: class System:
@@ -59,7 +60,6 @@ class System:
logger.info(f"RMSD = {rmsd:>8.5f} Angstrom") logger.info(f"RMSD = {rmsd:>8.5f} Angstrom")
def rmsd_fit(self, p_index: int, r_index: int) -> Tuple[float, Molecule]: def rmsd_fit(self, p_index: int, r_index: int) -> Tuple[float, Molecule]:
projecting_mol = self.molecule[p_index] projecting_mol = self.molecule[p_index]
reference_mol = self.molecule[r_index] reference_mol = self.molecule[r_index]
@@ -228,6 +228,10 @@ class System:
logger.info( logger.info(
"{:>10.6f} {:>10.6f} {:>10.6f} {:>10.6f} {:>10.6f}\n".format( "{:>10.6f} {:>10.6f} {:>10.6f} {:>10.6f} {:>10.6f}\n".format(
chargesAndDipole[0], chargesAndDipole[1], chargesAndDipole[2], chargesAndDipole[3], chargesAndDipole[4] chargesAndDipole[0],
chargesAndDipole[1],
chargesAndDipole[2],
chargesAndDipole[3],
chargesAndDipole[4],
) )
) )

View File

@@ -7,10 +7,7 @@ from abc import ABC, abstractmethod
class Interface(ABC): class Interface(ABC):
__slots__ = [ __slots__ = ["step", "system"]
'step',
'system'
]
def __init__(self): def __init__(self):
self.system: System | None = None self.system: System | None = None

View File

@@ -1,20 +1,21 @@
from __future__ import annotations from __future__ import annotations
from diceplayer import logger
from diceplayer.shared.config.player_config import PlayerConfig from diceplayer.shared.config.player_config import PlayerConfig
from diceplayer.shared.environment.system import System from diceplayer.shared.environment.system import System
from diceplayer.shared.interface import Interface from diceplayer.shared.interface import Interface
from diceplayer import logger
from multiprocessing import Process, connection
from setproctitle import setproctitle from setproctitle import setproctitle
from typing import Final, TextIO
from pathlib import Path
import subprocess
import shutil
import random
import time
import sys
import os import os
import random
import shutil
import subprocess
import sys
import time
from multiprocessing import Process, connection
from pathlib import Path
from typing import Final, TextIO
DICE_END_FLAG: Final[str] = "End of simulation" DICE_END_FLAG: Final[str] = "End of simulation"
DICE_FLAG_LINE: Final[int] = -2 DICE_FLAG_LINE: Final[int] = -2
@@ -74,19 +75,11 @@ class DiceInterface(Interface):
if not simulation_dir.exists(): if not simulation_dir.exists():
simulation_dir.mkdir(parents=True) simulation_dir.mkdir(parents=True)
proc_dir = Path( proc_dir = Path(simulation_dir, f"step{cycle:02d}", f"p{proc:02d}")
simulation_dir,
f"step{cycle:02d}",
f"p{proc:02d}"
)
proc_dir.mkdir(parents=True, exist_ok=True) proc_dir.mkdir(parents=True, exist_ok=True)
def _make_dice_inputs(self, cycle, proc): def _make_dice_inputs(self, cycle, proc):
proc_dir = Path( proc_dir = Path(self.step.simulation_dir, f"step{cycle:02d}", f"p{proc:02d}")
self.step.simulation_dir,
f"step{cycle:02d}",
f"p{proc:02d}"
)
self._make_potentials(proc_dir) self._make_potentials(proc_dir)
@@ -94,17 +87,17 @@ class DiceInterface(Interface):
# This is logic is used to make the initial configuration file # This is logic is used to make the initial configuration file
# for the next cycle using the last.xyz file from the previous cycle. # for the next cycle using the last.xyz file from the previous cycle.
if self.step.dice.randominit == 'first' and cycle > 1: if self.step.dice.randominit == "first" and cycle > 1:
last_xyz = Path( last_xyz = Path(
self.step.simulation_dir, self.step.simulation_dir,
f"step{(cycle - 1):02d}", f"step{(cycle - 1):02d}",
f"p{proc:02d}", f"p{proc:02d}",
"last.xyz" "last.xyz",
) )
if not last_xyz.exists(): if not last_xyz.exists():
raise FileNotFoundError(f"File {last_xyz} not found.") raise FileNotFoundError(f"File {last_xyz} not found.")
with open(last_xyz, 'r') as last_xyz_file: with open(last_xyz, "r") as last_xyz_file:
self._make_init_file(proc_dir, last_xyz_file) self._make_init_file(proc_dir, last_xyz_file)
last_xyz_file.seek(0) last_xyz_file.seek(0)
self.step.dice.dens = self._new_density(last_xyz_file) self.step.dice.dens = self._new_density(last_xyz_file)
@@ -122,11 +115,7 @@ class DiceInterface(Interface):
def _run_dice(self, cycle: int, proc: int): def _run_dice(self, cycle: int, proc: int):
working_dir = os.getcwd() working_dir = os.getcwd()
proc_dir = Path( proc_dir = Path(self.step.simulation_dir, f"step{cycle:02d}", f"p{proc:02d}")
self.step.simulation_dir,
f"step{cycle:02d}",
f"p{proc:02d}"
)
logger.info( logger.info(
f"Simulation process {str(proc_dir)} initiated with pid {os.getpid()}" f"Simulation process {str(proc_dir)} initiated with pid {os.getpid()}"
@@ -134,7 +123,7 @@ class DiceInterface(Interface):
os.chdir(proc_dir) os.chdir(proc_dir)
if not (self.step.dice.randominit == 'first' and cycle > 1): if not (self.step.dice.randominit == "first" and cycle > 1):
self.run_dice_file(cycle, proc, "NVT.ter") self.run_dice_file(cycle, proc, "NVT.ter")
if len(self.step.dice.nstep) == 2: if len(self.step.dice.nstep) == 2:
@@ -168,17 +157,16 @@ class DiceInterface(Interface):
SECONDARY_MOLECULE_LENGTH = 0 SECONDARY_MOLECULE_LENGTH = 0
for i in range(1, len(self.step.dice.nmol)): for i in range(1, len(self.step.dice.nmol)):
SECONDARY_MOLECULE_LENGTH += self.step.dice.nmol[i] * len(self.system.molecule[i].atom) SECONDARY_MOLECULE_LENGTH += self.step.dice.nmol[i] * len(
self.system.molecule[i].atom
)
xyz_lines = xyz_lines[-SECONDARY_MOLECULE_LENGTH:] xyz_lines = xyz_lines[-SECONDARY_MOLECULE_LENGTH:]
input_file = Path(proc_dir, self.step.dice.outname + ".xy") input_file = Path(proc_dir, self.step.dice.outname + ".xy")
with open(input_file, 'w') as f: with open(input_file, "w") as f:
for atom in self.system.molecule[0].atom: for atom in self.system.molecule[0].atom:
f.write( f.write(f"{atom.rx:>10.6f} {atom.ry:>10.6f} {atom.rz:>10.6f}\n")
f"{atom.rx:>10.6f} {atom.ry:>10.6f} {atom.rz:>10.6f}\n"
)
for line in xyz_lines: for line in xyz_lines:
atom = line.split() atom = line.split()
@@ -205,7 +193,7 @@ class DiceInterface(Interface):
def _make_nvt_ter(self, cycle, proc_dir): def _make_nvt_ter(self, cycle, proc_dir):
file = Path(proc_dir, "NVT.ter") file = Path(proc_dir, "NVT.ter")
with open(file, 'w') as f: with open(file, "w") as f:
f.write(f"title = {self.title} - NVT Thermalization\n") f.write(f"title = {self.title} - NVT Thermalization\n")
f.write(f"ncores = {self.step.ncores}\n") f.write(f"ncores = {self.step.ncores}\n")
f.write(f"ljname = {self.step.dice.ljname}\n") f.write(f"ljname = {self.step.dice.ljname}\n")
@@ -236,9 +224,8 @@ class DiceInterface(Interface):
f.write(f"upbuf = {self.step.dice.upbuf}") f.write(f"upbuf = {self.step.dice.upbuf}")
def _make_nvt_eq(self, cycle, proc_dir): def _make_nvt_eq(self, cycle, proc_dir):
file = Path(proc_dir, "NVT.eq") file = Path(proc_dir, "NVT.eq")
with open(file, 'w') as f: with open(file, "w") as f:
f.write(f"title = {self.title} - NVT Production\n") f.write(f"title = {self.title} - NVT Production\n")
f.write(f"ncores = {self.step.ncores}\n") f.write(f"ncores = {self.step.ncores}\n")
f.write(f"ljname = {self.step.dice.ljname}\n") f.write(f"ljname = {self.step.dice.ljname}\n")
@@ -269,9 +256,8 @@ class DiceInterface(Interface):
f.write("seed = {}\n".format(seed)) f.write("seed = {}\n".format(seed))
def _make_npt_ter(self, cycle, proc_dir): def _make_npt_ter(self, cycle, proc_dir):
file = Path(proc_dir, "NPT.ter") file = Path(proc_dir, "NPT.ter")
with open(file, 'w') as f: with open(file, "w") as f:
f.write(f"title = {self.title} - NPT Thermalization\n") f.write(f"title = {self.title} - NPT Thermalization\n")
f.write(f"ncores = {self.step.ncores}\n") f.write(f"ncores = {self.step.ncores}\n")
f.write(f"ljname = {self.step.dice.ljname}\n") f.write(f"ljname = {self.step.dice.ljname}\n")
@@ -303,7 +289,7 @@ class DiceInterface(Interface):
def _make_npt_eq(self, proc_dir): def _make_npt_eq(self, proc_dir):
file = Path(proc_dir, "NPT.eq") file = Path(proc_dir, "NPT.eq")
with open(file, 'w') as f: with open(file, "w") as f:
f.write(f"title = {self.title} - NPT Production\n") f.write(f"title = {self.title} - NPT Production\n")
f.write(f"ncores = {self.step.ncores}\n") f.write(f"ncores = {self.step.ncores}\n")
f.write(f"ljname = {self.step.dice.ljname}\n") f.write(f"ljname = {self.step.dice.ljname}\n")
@@ -332,7 +318,7 @@ class DiceInterface(Interface):
fstr = "{:<3d} {:>3d} {:>10.5f} {:>10.5f} {:>10.5f} {:>10.6f} {:>9.5f} {:>7.4f}\n" fstr = "{:<3d} {:>3d} {:>10.5f} {:>10.5f} {:>10.5f} {:>10.6f} {:>9.5f} {:>7.4f}\n"
file = Path(proc_dir, self.step.dice.ljname) file = Path(proc_dir, self.step.dice.ljname)
with open(file, 'w') as f: with open(file, "w") as f:
f.write(f"{self.step.dice.combrule}\n") f.write(f"{self.step.dice.combrule}\n")
f.write(f"{len(self.step.dice.nmol)}\n") f.write(f"{len(self.step.dice.nmol)}\n")
@@ -370,7 +356,9 @@ class DiceInterface(Interface):
) )
def run_dice_file(self, cycle: int, proc: int, file_name: str): def run_dice_file(self, cycle: int, proc: int, file_name: str):
with open(Path(file_name), 'r') as infile, open(Path(file_name + ".out"), 'w') as outfile: with open(Path(file_name), "r") as infile, open(
Path(file_name + ".out"), "w"
) as outfile:
if shutil.which("bash") is not None: if shutil.which("bash") is not None:
exit_status = subprocess.call( exit_status = subprocess.call(
[ [
@@ -385,11 +373,15 @@ class DiceInterface(Interface):
) )
if exit_status != 0: if exit_status != 0:
raise RuntimeError(f"Dice process step{cycle:02d}-p{proc:02d} did not exit properly") raise RuntimeError(
f"Dice process step{cycle:02d}-p{proc:02d} did not exit properly"
)
with open(Path(file_name + ".out"), 'r') as outfile: with open(Path(file_name + ".out"), "r") as outfile:
flag = outfile.readlines()[DICE_FLAG_LINE].strip() flag = outfile.readlines()[DICE_FLAG_LINE].strip()
if flag != DICE_END_FLAG: if flag != DICE_END_FLAG:
raise RuntimeError(f"Dice process step{cycle:02d}-p{proc:02d} did not exit properly") raise RuntimeError(
f"Dice process step{cycle:02d}-p{proc:02d} did not exit properly"
)
logger.info(f"Dice {file_name} - step{cycle:02d}-p{proc:02d} exited properly") logger.info(f"Dice {file_name} - step{cycle:02d}-p{proc:02d} exited properly")

View File

@@ -1,24 +1,23 @@
from __future__ import annotations from __future__ import annotations
from diceplayer import logger
from diceplayer.shared.config.player_config import PlayerConfig from diceplayer.shared.config.player_config import PlayerConfig
from diceplayer.shared.environment.atom import Atom
from diceplayer.shared.environment.molecule import Molecule from diceplayer.shared.environment.molecule import Molecule
from diceplayer.shared.environment.system import System from diceplayer.shared.environment.system import System
from diceplayer.shared.environment.atom import Atom from diceplayer.shared.interface import Interface
from diceplayer.shared.utils.misc import date_time from diceplayer.shared.utils.misc import date_time
from diceplayer.shared.utils.ptable import atomsymb from diceplayer.shared.utils.ptable import atomsymb
from diceplayer.shared.interface import Interface
from diceplayer import logger
from typing import Tuple, List, Dict, Any
from nptyping import NDArray
import numpy as np import numpy as np
from nptyping import NDArray
from pathlib import Path import os
import shutil
import subprocess import subprocess
import textwrap import textwrap
import shutil from pathlib import Path
import os from typing import Any, Dict, List, Tuple
class GaussianInterface(Interface): class GaussianInterface(Interface):
@@ -33,10 +32,7 @@ class GaussianInterface(Interface):
self._copy_chk_file_from_previous_step(cycle) self._copy_chk_file_from_previous_step(cycle)
asec_charges = self.populate_asec_vdw(cycle) asec_charges = self.populate_asec_vdw(cycle)
self._make_gaussian_input_file( self._make_gaussian_input_file(cycle, asec_charges)
cycle,
asec_charges
)
self._run_gaussian(cycle) self._run_gaussian(cycle)
self._run_formchk(cycle) self._run_formchk(cycle)
@@ -49,9 +45,7 @@ class GaussianInterface(Interface):
raise NotImplementedError("Optimization not implemented yet.") raise NotImplementedError("Optimization not implemented yet.")
else: else:
return_value['charges'] = np.array( return_value["charges"] = np.array(self._read_charges_from_fchk(cycle))
self._read_charges_from_fchk(cycle)
)
return return_value return return_value
@@ -60,36 +54,22 @@ class GaussianInterface(Interface):
del self.system del self.system
def _make_qm_dir(self, cycle: int): def _make_qm_dir(self, cycle: int):
qm_dir_path = Path( qm_dir_path = Path(self.step.simulation_dir, f"step{cycle:02d}", "qm")
self.step.simulation_dir,
f"step{cycle:02d}",
"qm"
)
if not qm_dir_path.exists(): if not qm_dir_path.exists():
qm_dir_path.mkdir() qm_dir_path.mkdir()
def _copy_chk_file_from_previous_step(self, cycle: int): def _copy_chk_file_from_previous_step(self, cycle: int):
current_chk_file_path = Path( current_chk_file_path = Path(
self.step.simulation_dir, self.step.simulation_dir, f"step{cycle:02d}", "qm", f"asec.chk"
f"step{cycle:02d}",
"qm",
f"asec.chk"
) )
if current_chk_file_path.exists(): if current_chk_file_path.exists():
raise FileExistsError( raise FileExistsError(f"File {current_chk_file_path} already exists.")
f"File {current_chk_file_path} already exists."
)
previous_chk_file_path = Path( previous_chk_file_path = Path(
self.step.simulation_dir, self.step.simulation_dir, f"step{(cycle - 1):02d}", "qm", f"asec.chk"
f"step{(cycle - 1):02d}",
"qm",
f"asec.chk"
) )
if not previous_chk_file_path.exists(): if not previous_chk_file_path.exists():
raise FileNotFoundError( raise FileNotFoundError(f"File {previous_chk_file_path} does not exist.")
f"File {previous_chk_file_path} does not exist."
)
shutil.copy(previous_chk_file_path, current_chk_file_path) shutil.copy(previous_chk_file_path, current_chk_file_path)
@@ -104,17 +84,19 @@ class GaussianInterface(Interface):
for proc in range(1, self.step.nprocs + 1): for proc in range(1, self.step.nprocs + 1):
proc_charges.append(self._read_charges_from_last_step(cycle, proc)) proc_charges.append(self._read_charges_from_last_step(cycle, proc))
asec_charges, thickness, picked_mols = \ asec_charges, thickness, picked_mols = self._evaluate_proc_charges(
self._evaluate_proc_charges(nsites_total, proc_charges) nsites_total, proc_charges
)
logger.info(f"In average, {(sum(picked_mols) / norm_factor):^7.2f} molecules\n" logger.info(
f"In average, {(sum(picked_mols) / norm_factor):^7.2f} molecules\n"
f"were selected from each of the {len(picked_mols)} configurations\n" f"were selected from each of the {len(picked_mols)} configurations\n"
f"of the production simulations to form the ASEC, comprising a shell with\n" f"of the production simulations to form the ASEC, comprising a shell with\n"
f"minimum thickness of {(sum(thickness) / norm_factor):>6.2f} Angstrom\n" f"minimum thickness of {(sum(thickness) / norm_factor):>6.2f} Angstrom\n"
) )
for charge in asec_charges: for charge in asec_charges:
charge['chg'] = charge['chg'] / norm_factor charge["chg"] = charge["chg"] / norm_factor
return asec_charges return asec_charges
@@ -135,23 +117,19 @@ class GaussianInterface(Interface):
def _read_charges_from_last_step(self, cycle: int, proc: int) -> list[str]: def _read_charges_from_last_step(self, cycle: int, proc: int) -> list[str]:
last_xyz_file_path = Path( last_xyz_file_path = Path(
self.step.simulation_dir, self.step.simulation_dir, f"step{cycle:02d}", f"p{proc:02d}", "last.xyz"
f"step{cycle:02d}",
f"p{proc:02d}",
"last.xyz"
) )
if not last_xyz_file_path.exists(): if not last_xyz_file_path.exists():
raise FileNotFoundError( raise FileNotFoundError(f"File {last_xyz_file_path} does not exist.")
f"File {last_xyz_file_path} does not exist."
)
with open(last_xyz_file_path, 'r') as last_xyz_file: with open(last_xyz_file_path, "r") as last_xyz_file:
lines = last_xyz_file.readlines() lines = last_xyz_file.readlines()
return lines return lines
def _evaluate_proc_charges(self, total_nsites: int, proc_charges: list[list[str]]) -> Tuple[ def _evaluate_proc_charges(
List[Dict[str, float | Any]], List[float], List[int]]: self, total_nsites: int, proc_charges: list[list[str]]
) -> Tuple[List[Dict[str, float | Any]], List[float], List[int]]:
asec_charges = [] asec_charges = []
thickness = [] thickness = []
@@ -164,9 +142,7 @@ class GaussianInterface(Interface):
f"Number of sites does not match total number of sites." f"Number of sites does not match total number of sites."
) )
thickness.append( thickness.append(self._calculate_proc_thickness(charges))
self._calculate_proc_thickness(charges)
)
nsites_ref_mol = len(self.system.molecule[0].atom) nsites_ref_mol = len(self.system.molecule[0].atom)
charges = charges[nsites_ref_mol:] charges = charges[nsites_ref_mol:]
@@ -183,7 +159,12 @@ class GaussianInterface(Interface):
for site in range(len(self.system.molecule[type].atom)): for site in range(len(self.system.molecule[type].atom)):
line = charges.pop(0).split() line = charges.pop(0).split()
if line[0].title() != atomsymb[self.system.molecule[type].atom[site].na].strip(): if (
line[0].title()
!= atomsymb[
self.system.molecule[type].atom[site].na
].strip()
):
raise SyntaxError( raise SyntaxError(
f"Error: Invalid Dice Output. Atom type does not match." f"Error: Invalid Dice Output. Atom type does not match."
) )
@@ -201,13 +182,18 @@ class GaussianInterface(Interface):
) )
) )
distance = self.system.molecule[0] \ distance = self.system.molecule[0].minimum_distance(new_molecule)
.minimum_distance(new_molecule)
if distance < thickness[-1]: if distance < thickness[-1]:
for atom in new_molecule.atom: for atom in new_molecule.atom:
asec_charges.append( asec_charges.append(
{"lbl": atomsymb[atom.na], "rx": atom.rx, "ry": atom.ry, "rz": atom.rz, "chg": atom.chg} {
"lbl": atomsymb[atom.na],
"rx": atom.rx,
"ry": atom.ry,
"rz": atom.rz,
"chg": atom.chg,
}
) )
mol_count += 1 mol_count += 1
@@ -230,18 +216,17 @@ class GaussianInterface(Interface):
def _make_gaussian_input_file(self, cycle: int, asec_charges: list[dict]) -> None: def _make_gaussian_input_file(self, cycle: int, asec_charges: list[dict]) -> None:
gaussian_input_file_path = Path( gaussian_input_file_path = Path(
self.step.simulation_dir, self.step.simulation_dir, f"step{cycle:02d}", "qm", f"asec.gjf"
f"step{cycle:02d}",
"qm",
f"asec.gjf"
) )
with open(gaussian_input_file_path, 'w') as gaussian_input_file: with open(gaussian_input_file_path, "w") as gaussian_input_file:
gaussian_input_file.writelines( gaussian_input_file.writelines(
self._generate_gaussian_input(cycle, asec_charges) self._generate_gaussian_input(cycle, asec_charges)
) )
def _generate_gaussian_input(self, cycle: int, asec_charges: list[dict]) -> list[str]: def _generate_gaussian_input(
self, cycle: int, asec_charges: list[dict]
) -> list[str]:
gaussian_input = ["%Chk=asec.chk\n"] gaussian_input = ["%Chk=asec.chk\n"]
if self.step.mem is not None: if self.step.mem is not None:
@@ -268,7 +253,9 @@ class GaussianInterface(Interface):
gaussian_input.append("\nForce calculation - Cycle number {}\n".format(cycle)) gaussian_input.append("\nForce calculation - Cycle number {}\n".format(cycle))
gaussian_input.append("\n") gaussian_input.append("\n")
gaussian_input.append(f"{self.step.gaussian.chgmult[0]},{self.step.gaussian.chgmult[1]}\n") gaussian_input.append(
f"{self.step.gaussian.chgmult[0]},{self.step.gaussian.chgmult[1]}\n"
)
for atom in self.system.molecule[0].atom: for atom in self.system.molecule[0].atom:
symbol = atomsymb[atom.na] symbol = atomsymb[atom.na]
@@ -283,7 +270,7 @@ class GaussianInterface(Interface):
for charge in asec_charges: for charge in asec_charges:
gaussian_input.append( gaussian_input.append(
"{:>10.5f} {:>10.5f} {:>10.5f} {:>11.8f}\n".format( "{:>10.5f} {:>10.5f} {:>10.5f} {:>11.8f}\n".format(
charge['rx'], charge['ry'], charge['rz'], charge['chg'] charge["rx"], charge["ry"], charge["rz"], charge["chg"]
) )
) )
@@ -292,11 +279,7 @@ class GaussianInterface(Interface):
return gaussian_input return gaussian_input
def _run_gaussian(self, cycle: int) -> None: def _run_gaussian(self, cycle: int) -> None:
qm_dir = Path( qm_dir = Path(self.step.simulation_dir, f"step{(cycle):02d}", "qm")
self.step.simulation_dir,
f"step{(cycle):02d}",
"qm"
)
working_dir = os.getcwd() working_dir = os.getcwd()
os.chdir(qm_dir) os.chdir(qm_dir)
@@ -319,7 +302,10 @@ class GaussianInterface(Interface):
"bash", "bash",
"-c", "-c",
"exec -a {}-step{} {} {}".format( "exec -a {}-step{} {} {}".format(
self.step.gaussian.qmprog, cycle, self.step.gaussian.qmprog, infile self.step.gaussian.qmprog,
cycle,
self.step.gaussian.qmprog,
infile,
), ),
] ]
) )
@@ -334,18 +320,16 @@ class GaussianInterface(Interface):
os.chdir(working_dir) os.chdir(working_dir)
def _run_formchk(self, cycle: int): def _run_formchk(self, cycle: int):
qm_dir = Path( qm_dir = Path(self.step.simulation_dir, f"step{(cycle):02d}", "qm")
self.step.simulation_dir,
f"step{(cycle):02d}",
"qm"
)
work_dir = os.getcwd() work_dir = os.getcwd()
os.chdir(qm_dir) os.chdir(qm_dir)
logger.info("Formatting the checkpoint file... \n") logger.info("Formatting the checkpoint file... \n")
exit_status = subprocess.call(["formchk", "asec.chk"], stdout=subprocess.DEVNULL) exit_status = subprocess.call(
["formchk", "asec.chk"], stdout=subprocess.DEVNULL
)
if exit_status != 0: if exit_status != 0:
raise SystemError("Formchk process did not exit properly") raise SystemError("Formchk process did not exit properly")
@@ -355,12 +339,7 @@ class GaussianInterface(Interface):
os.chdir(work_dir) os.chdir(work_dir)
def _read_charges_from_fchk(self, cycle: int): def _read_charges_from_fchk(self, cycle: int):
fchk_file_path = Path( fchk_file_path = Path("simfiles", f"step{cycle:02d}", "qm", "asec.fchk")
"simfiles",
f"step{cycle:02d}",
"qm",
"asec.fchk"
)
with open(fchk_file_path) as fchk: with open(fchk_file_path) as fchk:
fchkfile = fchk.readlines() fchkfile = fchk.readlines()

View File

@@ -1,4 +1,4 @@
from typing import runtime_checkable, Protocol from typing import Protocol, runtime_checkable
@runtime_checkable @runtime_checkable

View File

@@ -1,12 +1,11 @@
from pathlib import Path
import logging import logging
from pathlib import Path
def valid_logger(func): def valid_logger(func):
def wrapper(*args, **kwargs): def wrapper(*args, **kwargs):
logger = args[0] logger = args[0]
assert logger._was_set, \ assert logger._was_set, "Logger is not set. Please call set_logger() first."
"Logger is not set. Please call set_logger() first."
return func(*args, **kwargs) return func(*args, **kwargs)
@@ -24,7 +23,7 @@ class Logger:
if self._logger is None: if self._logger is None:
self._logger = logging.getLogger(logger_name) self._logger = logging.getLogger(logger_name)
def set_logger(self, outfile='run.log', level=logging.INFO, stream=None): def set_logger(self, outfile="run.log", level=logging.INFO, stream=None):
outfile_path = None outfile_path = None
if outfile is not None and stream is None: if outfile is not None and stream is None:
outfile_path = Path(outfile) outfile_path = Path(outfile)
@@ -57,14 +56,14 @@ class Logger:
def _create_handlers(self, outfile_path: Path, stream): def _create_handlers(self, outfile_path: Path, stream):
handlers = [] handlers = []
if outfile_path is not None: if outfile_path is not None:
handlers.append(logging.FileHandler(outfile_path, mode='a+')) handlers.append(logging.FileHandler(outfile_path, mode="a+"))
elif stream is not None: elif stream is not None:
handlers.append(logging.StreamHandler(stream)) handlers.append(logging.StreamHandler(stream))
else: else:
handlers.append(logging.StreamHandler()) handlers.append(logging.StreamHandler())
for handler in handlers: for handler in handlers:
handler.setFormatter(logging.Formatter('%(message)s')) handler.setFormatter(logging.Formatter("%(message)s"))
self._logger.addHandler(handler) self._logger.addHandler(handler)
def close(self): def close(self):

View File

@@ -14,6 +14,7 @@ ANG2BOHR: Final[float] = 1 / BOHR2ANG
####################################### functions ###################################### ####################################### functions ######################################
def weekday_date_time(): def weekday_date_time():
return time.strftime("%A, %d %b %Y at %H:%M:%S") return time.strftime("%A, %d %b %Y at %H:%M:%S")
@@ -31,8 +32,8 @@ def compress_files_1mb(path):
if os.path.getsize(file) > 1024 * 1024: ## If bigger than 1MB if os.path.getsize(file) > 1024 * 1024: ## If bigger than 1MB
filegz = file + ".gz" filegz = file + ".gz"
try: try:
with open(file, 'rb') as f_in: with open(file, "rb") as f_in:
with gzip.open(filegz, 'wb') as f_out: with gzip.open(filegz, "wb") as f_out:
shutil.copyfileobj(f_in, f_out) shutil.copyfileobj(f_in, f_out)
except: except:
sys.exit("Error: cannot compress file {}".format(file)) sys.exit("Error: cannot compress file {}".format(file))

View File

@@ -2,34 +2,222 @@
dice_ghost_label = "Xx" dice_ghost_label = "Xx"
#### Tuple of atom symbols #### Tuple of atom symbols
atomsymb = ( "00", atomsymb = (
"00",
"H ", "He", "H ",
"Li","Be", "B ","C ","N ","O ","F ","Ne", "He",
"Na","Mg", "Al","Si","P ","S ","Cl","Ar", "Li",
"K ","Ca","Sc","Ti","V ","Cr","Mn","Fe","Co","Ni","Cu","Zn","Ga","Ge","As","Se","Br","Kr", "Be",
"Rb","Sr","Y ","Zr","Nb","Mo","Tc","Ru","Rh","Pd","Ag","Cd","In","Sn","Sb","Te","I ","Xe", "B ",
"Cs","Ba", "C ",
"La","Ce","Pr","Nd","Pm","Sm","Eu","Gd","Tb","Dy","Ho","Er","Tm","Yb","Lu", "N ",
"Hf","Ta","W ","Re","Os","Ir","Pt","Au","Hg","Ti","Pb","Bi","Po","At","Rn", "O ",
"Fr","Ra", "F ",
"Ac","Th","Pa","U ","Np","Pu","Am","Cm","Bk","Cf","Es","Fm","Md","No","Lr", "Ne",
dice_ghost_label ) "Na",
"Mg",
"Al",
"Si",
"P ",
"S ",
"Cl",
"Ar",
"K ",
"Ca",
"Sc",
"Ti",
"V ",
"Cr",
"Mn",
"Fe",
"Co",
"Ni",
"Cu",
"Zn",
"Ga",
"Ge",
"As",
"Se",
"Br",
"Kr",
"Rb",
"Sr",
"Y ",
"Zr",
"Nb",
"Mo",
"Tc",
"Ru",
"Rh",
"Pd",
"Ag",
"Cd",
"In",
"Sn",
"Sb",
"Te",
"I ",
"Xe",
"Cs",
"Ba",
"La",
"Ce",
"Pr",
"Nd",
"Pm",
"Sm",
"Eu",
"Gd",
"Tb",
"Dy",
"Ho",
"Er",
"Tm",
"Yb",
"Lu",
"Hf",
"Ta",
"W ",
"Re",
"Os",
"Ir",
"Pt",
"Au",
"Hg",
"Ti",
"Pb",
"Bi",
"Po",
"At",
"Rn",
"Fr",
"Ra",
"Ac",
"Th",
"Pa",
"U ",
"Np",
"Pu",
"Am",
"Cm",
"Bk",
"Cf",
"Es",
"Fm",
"Md",
"No",
"Lr",
dice_ghost_label,
)
#### Tuple of atom masses #### Tuple of atom masses
atommass = ( 0.0, atommass = (
0.0,
1.0079, 4.0026, 1.0079,
6.9410,9.0122, 10.811,12.011,14.007,15.999,18.998,20.180, 4.0026,
22.990,24.305, 26.982,28.086,30.974,32.065,35.453,39.948, 6.9410,
39.098,40.078,44.956,47.867,50.942,51.996,54.938,55.845,58.933,58.693,63.546,65.409,69.723,72.640,74.922,78.960,79.904,83.798, 9.0122,
85.468,87.620,88.906,91.224,92.906,95.940,98.000,101.07,102.91,106.42,107.87,112.41,114.82,118.71,121.76,127.60,126.90,131.29, 10.811,
132.91,137.33, 12.011,
138.91,140.12,140.91,144.24,145.00,150.36,151.96,157.25,158.93,162.50,164.93,167.26,168.93,173.04,174.97, 14.007,
178.49,180.95,183.84,186.21,190.23,192.22,195.08,196.97,200.59,204.38,207.20,208.98,209.00,210.00,222.00, 15.999,
223.00,226.00, 18.998,
227.00,232.04,231.04,238.03,237.00,244.00,243.00,247.00,247.00,251.00,252.00,257.00,258.00,259.00,262.00, 20.180,
0.000 ) 22.990,
24.305,
26.982,
28.086,
30.974,
32.065,
35.453,
39.948,
39.098,
40.078,
44.956,
47.867,
50.942,
51.996,
54.938,
55.845,
58.933,
58.693,
63.546,
65.409,
69.723,
72.640,
74.922,
78.960,
79.904,
83.798,
85.468,
87.620,
88.906,
91.224,
92.906,
95.940,
98.000,
101.07,
102.91,
106.42,
107.87,
112.41,
114.82,
118.71,
121.76,
127.60,
126.90,
131.29,
132.91,
137.33,
138.91,
140.12,
140.91,
144.24,
145.00,
150.36,
151.96,
157.25,
158.93,
162.50,
164.93,
167.26,
168.93,
173.04,
174.97,
178.49,
180.95,
183.84,
186.21,
190.23,
192.22,
195.08,
196.97,
200.59,
204.38,
207.20,
208.98,
209.00,
210.00,
222.00,
223.00,
226.00,
227.00,
232.04,
231.04,
238.03,
237.00,
244.00,
243.00,
247.00,
247.00,
251.00,
252.00,
257.00,
258.00,
259.00,
262.00,
0.000,
)
#### Number of the ghost atom #### Number of the ghost atom
ghost_number = len(atomsymb) - 1 ghost_number = len(atomsymb) - 1

319
poetry.lock generated
View File

@@ -12,6 +12,95 @@ files = [
{file = "argparse-1.4.0.tar.gz", hash = "sha256:62b089a55be1d8949cd2bc7e0df0bddb9e028faefc8c32038cc84862aefdd6e4"}, {file = "argparse-1.4.0.tar.gz", hash = "sha256:62b089a55be1d8949cd2bc7e0df0bddb9e028faefc8c32038cc84862aefdd6e4"},
] ]
[[package]]
name = "black"
version = "23.3.0"
description = "The uncompromising code formatter."
category = "main"
optional = false
python-versions = ">=3.7"
files = [
{file = "black-23.3.0-cp310-cp310-macosx_10_16_arm64.whl", hash = "sha256:0945e13506be58bf7db93ee5853243eb368ace1c08a24c65ce108986eac65915"},
{file = "black-23.3.0-cp310-cp310-macosx_10_16_universal2.whl", hash = "sha256:67de8d0c209eb5b330cce2469503de11bca4085880d62f1628bd9972cc3366b9"},
{file = "black-23.3.0-cp310-cp310-macosx_10_16_x86_64.whl", hash = "sha256:7c3eb7cea23904399866c55826b31c1f55bbcd3890ce22ff70466b907b6775c2"},
{file = "black-23.3.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:32daa9783106c28815d05b724238e30718f34155653d4d6e125dc7daec8e260c"},
{file = "black-23.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:35d1381d7a22cc5b2be2f72c7dfdae4072a3336060635718cc7e1ede24221d6c"},
{file = "black-23.3.0-cp311-cp311-macosx_10_16_arm64.whl", hash = "sha256:a8a968125d0a6a404842fa1bf0b349a568634f856aa08ffaff40ae0dfa52e7c6"},
{file = "black-23.3.0-cp311-cp311-macosx_10_16_universal2.whl", hash = "sha256:c7ab5790333c448903c4b721b59c0d80b11fe5e9803d8703e84dcb8da56fec1b"},
{file = "black-23.3.0-cp311-cp311-macosx_10_16_x86_64.whl", hash = "sha256:a6f6886c9869d4daae2d1715ce34a19bbc4b95006d20ed785ca00fa03cba312d"},
{file = "black-23.3.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6f3c333ea1dd6771b2d3777482429864f8e258899f6ff05826c3a4fcc5ce3f70"},
{file = "black-23.3.0-cp311-cp311-win_amd64.whl", hash = "sha256:11c410f71b876f961d1de77b9699ad19f939094c3a677323f43d7a29855fe326"},
{file = "black-23.3.0-cp37-cp37m-macosx_10_16_x86_64.whl", hash = "sha256:1d06691f1eb8de91cd1b322f21e3bfc9efe0c7ca1f0e1eb1db44ea367dff656b"},
{file = "black-23.3.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:50cb33cac881766a5cd9913e10ff75b1e8eb71babf4c7104f2e9c52da1fb7de2"},
{file = "black-23.3.0-cp37-cp37m-win_amd64.whl", hash = "sha256:e114420bf26b90d4b9daa597351337762b63039752bdf72bf361364c1aa05925"},
{file = "black-23.3.0-cp38-cp38-macosx_10_16_arm64.whl", hash = "sha256:48f9d345675bb7fbc3dd85821b12487e1b9a75242028adad0333ce36ed2a6d27"},
{file = "black-23.3.0-cp38-cp38-macosx_10_16_universal2.whl", hash = "sha256:714290490c18fb0126baa0fca0a54ee795f7502b44177e1ce7624ba1c00f2331"},
{file = "black-23.3.0-cp38-cp38-macosx_10_16_x86_64.whl", hash = "sha256:064101748afa12ad2291c2b91c960be28b817c0c7eaa35bec09cc63aa56493c5"},
{file = "black-23.3.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:562bd3a70495facf56814293149e51aa1be9931567474993c7942ff7d3533961"},
{file = "black-23.3.0-cp38-cp38-win_amd64.whl", hash = "sha256:e198cf27888ad6f4ff331ca1c48ffc038848ea9f031a3b40ba36aced7e22f2c8"},
{file = "black-23.3.0-cp39-cp39-macosx_10_16_arm64.whl", hash = "sha256:3238f2aacf827d18d26db07524e44741233ae09a584273aa059066d644ca7b30"},
{file = "black-23.3.0-cp39-cp39-macosx_10_16_universal2.whl", hash = "sha256:f0bd2f4a58d6666500542b26354978218a9babcdc972722f4bf90779524515f3"},
{file = "black-23.3.0-cp39-cp39-macosx_10_16_x86_64.whl", hash = "sha256:92c543f6854c28a3c7f39f4d9b7694f9a6eb9d3c5e2ece488c327b6e7ea9b266"},
{file = "black-23.3.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3a150542a204124ed00683f0db1f5cf1c2aaaa9cc3495b7a3b5976fb136090ab"},
{file = "black-23.3.0-cp39-cp39-win_amd64.whl", hash = "sha256:6b39abdfb402002b8a7d030ccc85cf5afff64ee90fa4c5aebc531e3ad0175ddb"},
{file = "black-23.3.0-py3-none-any.whl", hash = "sha256:ec751418022185b0c1bb7d7736e6933d40bbb14c14a0abcf9123d1b159f98dd4"},
{file = "black-23.3.0.tar.gz", hash = "sha256:1c7b8d606e728a41ea1ccbd7264677e494e87cf630e399262ced92d4a8dac940"},
]
[package.dependencies]
click = ">=8.0.0"
mypy-extensions = ">=0.4.3"
packaging = ">=22.0"
pathspec = ">=0.9.0"
platformdirs = ">=2"
tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""}
typing-extensions = {version = ">=3.10.0.0", markers = "python_version < \"3.10\""}
[package.extras]
colorama = ["colorama (>=0.4.3)"]
d = ["aiohttp (>=3.7.4)"]
jupyter = ["ipython (>=7.8.0)", "tokenize-rt (>=3.2.0)"]
uvloop = ["uvloop (>=0.15.2)"]
[[package]]
name = "cfgv"
version = "3.3.1"
description = "Validate configuration and produce human readable error messages."
category = "main"
optional = false
python-versions = ">=3.6.1"
files = [
{file = "cfgv-3.3.1-py2.py3-none-any.whl", hash = "sha256:c6a0883f3917a037485059700b9e75da2464e6c27051014ad85ba6aaa5884426"},
{file = "cfgv-3.3.1.tar.gz", hash = "sha256:f5a830efb9ce7a445376bb66ec94c638a9787422f96264c98edc6bdeed8ab736"},
]
[[package]]
name = "click"
version = "8.1.3"
description = "Composable command line interface toolkit"
category = "main"
optional = false
python-versions = ">=3.7"
files = [
{file = "click-8.1.3-py3-none-any.whl", hash = "sha256:bb4d8133cb15a609f44e8213d9b391b0809795062913b383c62be0ee95b1db48"},
{file = "click-8.1.3.tar.gz", hash = "sha256:7682dc8afb30297001674575ea00d1814d808d6a36af415a82bd481d37ba7b8e"},
]
[package.dependencies]
colorama = {version = "*", markers = "platform_system == \"Windows\""}
[[package]]
name = "colorama"
version = "0.4.6"
description = "Cross-platform colored terminal text."
category = "main"
optional = false
python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7"
files = [
{file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"},
{file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"},
]
[[package]] [[package]]
name = "coverage" name = "coverage"
version = "7.2.7" version = "7.2.7"
@@ -99,6 +188,94 @@ files = [
[package.extras] [package.extras]
dev = ["black", "coveralls", "mypy", "pre-commit", "pylint", "pytest (>=5)", "pytest-benchmark", "pytest-cov"] dev = ["black", "coveralls", "mypy", "pre-commit", "pylint", "pytest (>=5)", "pytest-benchmark", "pytest-cov"]
[[package]]
name = "distlib"
version = "0.3.6"
description = "Distribution utilities"
category = "main"
optional = false
python-versions = "*"
files = [
{file = "distlib-0.3.6-py2.py3-none-any.whl", hash = "sha256:f35c4b692542ca110de7ef0bea44d73981caeb34ca0b9b6b2e6d7790dda8f80e"},
{file = "distlib-0.3.6.tar.gz", hash = "sha256:14bad2d9b04d3a36127ac97f30b12a19268f211063d8f8ee4f47108896e11b46"},
]
[[package]]
name = "filelock"
version = "3.12.1"
description = "A platform independent file lock."
category = "main"
optional = false
python-versions = ">=3.7"
files = [
{file = "filelock-3.12.1-py3-none-any.whl", hash = "sha256:42f1e4ff2b497311213d61ad7aac5fed9050608e5309573f101eefa94143134a"},
{file = "filelock-3.12.1.tar.gz", hash = "sha256:82b1f7da46f0ae42abf1bc78e548667f484ac59d2bcec38c713cee7e2eb51e83"},
]
[package.extras]
docs = ["furo (>=2023.5.20)", "sphinx (>=7.0.1)", "sphinx-autodoc-typehints (>=1.23,!=1.23.4)"]
testing = ["covdefaults (>=2.3)", "coverage (>=7.2.7)", "diff-cover (>=7.5)", "pytest (>=7.3.1)", "pytest-cov (>=4.1)", "pytest-mock (>=3.10)", "pytest-timeout (>=2.1)"]
[[package]]
name = "identify"
version = "2.5.24"
description = "File identification library for Python"
category = "main"
optional = false
python-versions = ">=3.7"
files = [
{file = "identify-2.5.24-py2.py3-none-any.whl", hash = "sha256:986dbfb38b1140e763e413e6feb44cd731faf72d1909543178aa79b0e258265d"},
{file = "identify-2.5.24.tar.gz", hash = "sha256:0aac67d5b4812498056d28a9a512a483f5085cc28640b02b258a59dac34301d4"},
]
[package.extras]
license = ["ukkonen"]
[[package]]
name = "isort"
version = "5.12.0"
description = "A Python utility / library to sort Python imports."
category = "main"
optional = false
python-versions = ">=3.8.0"
files = [
{file = "isort-5.12.0-py3-none-any.whl", hash = "sha256:f84c2818376e66cf843d497486ea8fed8700b340f308f076c6fb1229dff318b6"},
{file = "isort-5.12.0.tar.gz", hash = "sha256:8bef7dde241278824a6d83f44a544709b065191b95b6e50894bdc722fcba0504"},
]
[package.extras]
colors = ["colorama (>=0.4.3)"]
pipfile-deprecated-finder = ["pip-shims (>=0.5.2)", "pipreqs", "requirementslib"]
plugins = ["setuptools"]
requirements-deprecated-finder = ["pip-api", "pipreqs"]
[[package]]
name = "mypy-extensions"
version = "1.0.0"
description = "Type system extensions for programs checked with the mypy type checker."
category = "main"
optional = false
python-versions = ">=3.5"
files = [
{file = "mypy_extensions-1.0.0-py3-none-any.whl", hash = "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d"},
{file = "mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"},
]
[[package]]
name = "nodeenv"
version = "1.8.0"
description = "Node.js virtual environment builder"
category = "main"
optional = false
python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*"
files = [
{file = "nodeenv-1.8.0-py2.py3-none-any.whl", hash = "sha256:df865724bb3c3adc86b3876fa209771517b0cfe596beff01a92700e0e8be4cec"},
{file = "nodeenv-1.8.0.tar.gz", hash = "sha256:d51e0c37e64fbf47d017feac3145cdbb58836d7eee8c6f6d3b6880c5456227d2"},
]
[package.dependencies]
setuptools = "*"
[[package]] [[package]]
name = "nptyping" name = "nptyping"
version = "2.5.0" version = "2.5.0"
@@ -160,6 +337,96 @@ files = [
{file = "numpy-1.24.3.tar.gz", hash = "sha256:ab344f1bf21f140adab8e47fdbc7c35a477dc01408791f8ba00d018dd0bc5155"}, {file = "numpy-1.24.3.tar.gz", hash = "sha256:ab344f1bf21f140adab8e47fdbc7c35a477dc01408791f8ba00d018dd0bc5155"},
] ]
[[package]]
name = "packaging"
version = "23.1"
description = "Core utilities for Python packages"
category = "main"
optional = false
python-versions = ">=3.7"
files = [
{file = "packaging-23.1-py3-none-any.whl", hash = "sha256:994793af429502c4ea2ebf6bf664629d07c1a9fe974af92966e4b8d2df7edc61"},
{file = "packaging-23.1.tar.gz", hash = "sha256:a392980d2b6cffa644431898be54b0045151319d1e7ec34f0cfed48767dd334f"},
]
[[package]]
name = "pastel"
version = "0.2.1"
description = "Bring colors to your terminal."
category = "main"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
files = [
{file = "pastel-0.2.1-py2.py3-none-any.whl", hash = "sha256:4349225fcdf6c2bb34d483e523475de5bb04a5c10ef711263452cb37d7dd4364"},
{file = "pastel-0.2.1.tar.gz", hash = "sha256:e6581ac04e973cac858828c6202c1e1e81fee1dc7de7683f3e1ffe0bfd8a573d"},
]
[[package]]
name = "pathspec"
version = "0.11.1"
description = "Utility library for gitignore style pattern matching of file paths."
category = "main"
optional = false
python-versions = ">=3.7"
files = [
{file = "pathspec-0.11.1-py3-none-any.whl", hash = "sha256:d8af70af76652554bd134c22b3e8a1cc46ed7d91edcdd721ef1a0c51a84a5293"},
{file = "pathspec-0.11.1.tar.gz", hash = "sha256:2798de800fa92780e33acca925945e9a19a133b715067cf165b8866c15a31687"},
]
[[package]]
name = "platformdirs"
version = "3.5.3"
description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"."
category = "main"
optional = false
python-versions = ">=3.7"
files = [
{file = "platformdirs-3.5.3-py3-none-any.whl", hash = "sha256:0ade98a4895e87dc51d47151f7d2ec290365a585151d97b4d8d6312ed6132fed"},
{file = "platformdirs-3.5.3.tar.gz", hash = "sha256:e48fabd87db8f3a7df7150a4a5ea22c546ee8bc39bc2473244730d4b56d2cc4e"},
]
[package.extras]
docs = ["furo (>=2023.5.20)", "proselint (>=0.13)", "sphinx (>=7.0.1)", "sphinx-autodoc-typehints (>=1.23,!=1.23.4)"]
test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.3.1)", "pytest-cov (>=4.1)", "pytest-mock (>=3.10)"]
[[package]]
name = "poethepoet"
version = "0.20.0"
description = "A task runner that works well with poetry."
category = "main"
optional = false
python-versions = ">=3.8"
files = [
{file = "poethepoet-0.20.0-py3-none-any.whl", hash = "sha256:cb37be15f3895ccc65ddf188c2e3d8fb79e26cc9d469a6098cb1c6f994659f6f"},
{file = "poethepoet-0.20.0.tar.gz", hash = "sha256:ca5a2a955f52dfb0a53fad3c989ef0b69ce3d5ec0f6bfa9b1da1f9e32d262e20"},
]
[package.dependencies]
pastel = ">=0.2.1,<0.3.0"
tomli = ">=1.2.2"
[package.extras]
poetry-plugin = ["poetry (>=1.0,<2.0)"]
[[package]]
name = "pre-commit"
version = "3.3.2"
description = "A framework for managing and maintaining multi-language pre-commit hooks."
category = "main"
optional = false
python-versions = ">=3.8"
files = [
{file = "pre_commit-3.3.2-py2.py3-none-any.whl", hash = "sha256:8056bc52181efadf4aac792b1f4f255dfd2fb5a350ded7335d251a68561e8cb6"},
{file = "pre_commit-3.3.2.tar.gz", hash = "sha256:66e37bec2d882de1f17f88075047ef8962581f83c234ac08da21a0c58953d1f0"},
]
[package.dependencies]
cfgv = ">=2.0.0"
identify = ">=1.0.0"
nodeenv = ">=0.11.1"
pyyaml = ">=5.1"
virtualenv = ">=20.10.0"
[[package]] [[package]]
name = "pyyaml" name = "pyyaml"
version = "6.0" version = "6.0"
@@ -295,6 +562,35 @@ files = [
[package.extras] [package.extras]
test = ["pytest"] test = ["pytest"]
[[package]]
name = "setuptools"
version = "67.8.0"
description = "Easily download, build, install, upgrade, and uninstall Python packages"
category = "main"
optional = false
python-versions = ">=3.7"
files = [
{file = "setuptools-67.8.0-py3-none-any.whl", hash = "sha256:5df61bf30bb10c6f756eb19e7c9f3b473051f48db77fddbe06ff2ca307df9a6f"},
{file = "setuptools-67.8.0.tar.gz", hash = "sha256:62642358adc77ffa87233bc4d2354c4b2682d214048f500964dbe760ccedf102"},
]
[package.extras]
docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-hoverxref (<2)", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (==0.8.3)", "sphinx-reredirects", "sphinxcontrib-towncrier"]
testing = ["build[virtualenv]", "filelock (>=3.4.0)", "flake8-2020", "ini2toml[lite] (>=0.9)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pip (>=19.1)", "pip-run (>=8.8)", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-mypy (>=0.9.1)", "pytest-perf", "pytest-ruff", "pytest-timeout", "pytest-xdist", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"]
testing-integration = ["build[virtualenv]", "filelock (>=3.4.0)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pytest", "pytest-enabler", "pytest-xdist", "tomli", "virtualenv (>=13.0.0)", "wheel"]
[[package]]
name = "tomli"
version = "2.0.1"
description = "A lil' TOML parser"
category = "main"
optional = false
python-versions = ">=3.7"
files = [
{file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"},
{file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"},
]
[[package]] [[package]]
name = "typing-extensions" name = "typing-extensions"
version = "4.6.3" version = "4.6.3"
@@ -307,7 +603,28 @@ files = [
{file = "typing_extensions-4.6.3.tar.gz", hash = "sha256:d91d5919357fe7f681a9f2b5b4cb2a5f1ef0a1e9f59c4d8ff0d3491e05c0ffd5"}, {file = "typing_extensions-4.6.3.tar.gz", hash = "sha256:d91d5919357fe7f681a9f2b5b4cb2a5f1ef0a1e9f59c4d8ff0d3491e05c0ffd5"},
] ]
[[package]]
name = "virtualenv"
version = "20.23.0"
description = "Virtual Python Environment builder"
category = "main"
optional = false
python-versions = ">=3.7"
files = [
{file = "virtualenv-20.23.0-py3-none-any.whl", hash = "sha256:6abec7670e5802a528357fdc75b26b9f57d5d92f29c5462ba0fbe45feacc685e"},
{file = "virtualenv-20.23.0.tar.gz", hash = "sha256:a85caa554ced0c0afbd0d638e7e2d7b5f92d23478d05d17a76daeac8f279f924"},
]
[package.dependencies]
distlib = ">=0.3.6,<1"
filelock = ">=3.11,<4"
platformdirs = ">=3.2,<4"
[package.extras]
docs = ["furo (>=2023.3.27)", "proselint (>=0.13)", "sphinx (>=6.1.3)", "sphinx-argparse (>=0.4)", "sphinxcontrib-towncrier (>=0.2.1a0)", "towncrier (>=22.12)"]
test = ["covdefaults (>=2.3)", "coverage (>=7.2.3)", "coverage-enable-subprocess (>=1)", "flaky (>=3.7)", "packaging (>=23.1)", "pytest (>=7.3.1)", "pytest-env (>=0.8.1)", "pytest-freezegun (>=0.4.2)", "pytest-mock (>=3.10)", "pytest-randomly (>=3.12)", "pytest-timeout (>=2.1)", "setuptools (>=67.7.1)", "time-machine (>=2.9)"]
[metadata] [metadata]
lock-version = "2.0" lock-version = "2.0"
python-versions = "^3.8" python-versions = "^3.8"
content-hash = "5767445dc10a28eeb01ba23bfbf781b68d8c158df80be696d53cb0c962d409ab" content-hash = "2527f460007c57ea9d99659a7dce34657b4cdbd8c9d05bcd3deb822474ae79c6"

View File

@@ -14,7 +14,13 @@ setproctitle = "^1.3.2"
pyyaml = "^6.0" pyyaml = "^6.0"
dacite = "^1.8.1" dacite = "^1.8.1"
nptyping = "^2.5.0" nptyping = "^2.5.0"
poethepoet = "^0.20.0"
pre-commit = "^3.3.2"
isort = "^5.12.0"
black = "^23.3.0"
[tool.poetry.scripts]
diceplayer = "diceplayer.__main__:main"
[tool.poetry.group.dev.dependencies] [tool.poetry.group.dev.dependencies]
coverage = "^7.2.7" coverage = "^7.2.7"
@@ -22,3 +28,31 @@ coverage = "^7.2.7"
[build-system] [build-system]
requires = ["poetry-core"] requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api" build-backend = "poetry.core.masonry.api"
[tool.poe.tasks]
hooks = "pre-commit install"
[tool.coverage.run]
omit = [
"mega_conversao/src/utilidades/trata.py",
"mega_conversao/src/modulos/*",
"tests/*",
]
data_file = "coverage/.coverage"
[tool.coverage.html]
directory = "coverage/html"
[tool.coverage.lcov]
output = "coverage/lcov.info"
[tool.isort]
profile = "black"
line_length = 79
sections=[
"FUTURE",
"FIRSTPARTY",
"LOCALFOLDER",
"THIRDPARTY",
"STDLIB",
]

View File

@@ -1,5 +1,5 @@
from typing import List
import itertools import itertools
from typing import List
class MockProc: class MockProc:
@@ -8,8 +8,8 @@ class MockProc:
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
self.pid = next(MockProc.pid_counter) self.pid = next(MockProc.pid_counter)
if 'exitcode' in kwargs: if "exitcode" in kwargs:
self.exitcode = kwargs['exitcode'] self.exitcode = kwargs["exitcode"]
else: else:
self.exitcode = 0 self.exitcode = 0

View File

@@ -6,8 +6,8 @@ import unittest
class TestDiceDto(unittest.TestCase): class TestDiceDto(unittest.TestCase):
def test_class_instantiation(self): def test_class_instantiation(self):
dice_dto = DiceConfig( dice_dto = DiceConfig(
ljname='test', ljname="test",
outname='test', outname="test",
dens=1.0, dens=1.0,
nmol=[1], nmol=[1],
nstep=[1, 1], nstep=[1, 1],
@@ -19,64 +19,78 @@ class TestDiceDto(unittest.TestCase):
with self.assertRaises(ValueError) as ex: with self.assertRaises(ValueError) as ex:
DiceConfig( DiceConfig(
ljname=None, ljname=None,
outname='test', outname="test",
dens=1.0, dens=1.0,
nmol=[1], nmol=[1],
nstep=[1, 1], nstep=[1, 1],
) )
self.assertEqual(ex.exception, "Error: 'ljname' keyword not specified in config file") self.assertEqual(
ex.exception, "Error: 'ljname' keyword not specified in config file"
)
def test_validate_outname(self): def test_validate_outname(self):
with self.assertRaises(ValueError) as ex: with self.assertRaises(ValueError) as ex:
DiceConfig( DiceConfig(
ljname='test', ljname="test",
outname=None, outname=None,
dens=1.0, dens=1.0,
nmol=[1], nmol=[1],
nstep=[1, 1], nstep=[1, 1],
) )
self.assertEqual(ex.exception, "Error: 'outname' keyword not specified in config file") self.assertEqual(
ex.exception, "Error: 'outname' keyword not specified in config file"
)
def test_validate_dens(self): def test_validate_dens(self):
with self.assertRaises(ValueError) as ex: with self.assertRaises(ValueError) as ex:
DiceConfig( DiceConfig(
ljname='test', ljname="test",
outname='test', outname="test",
dens=None, dens=None,
nmol=[1], nmol=[1],
nstep=[1, 1], nstep=[1, 1],
) )
self.assertEqual(ex.exception, "Error: 'dens' keyword not specified in config file") self.assertEqual(
ex.exception, "Error: 'dens' keyword not specified in config file"
)
def test_validate_nmol(self): def test_validate_nmol(self):
with self.assertRaises(ValueError) as ex: with self.assertRaises(ValueError) as ex:
DiceConfig( DiceConfig(
ljname='test', ljname="test",
outname='test', outname="test",
dens=1.0, dens=1.0,
nmol=0, nmol=0,
nstep=[1, 1], nstep=[1, 1],
) )
self.assertEqual(ex.exception, "Error: 'nmol' keyword not defined appropriately in config file") self.assertEqual(
ex.exception,
"Error: 'nmol' keyword not defined appropriately in config file",
)
def test_validate_nstep(self): def test_validate_nstep(self):
with self.assertRaises(ValueError) as ex: with self.assertRaises(ValueError) as ex:
DiceConfig( DiceConfig(
ljname='test', ljname="test",
outname='test', outname="test",
dens=1.0, dens=1.0,
nmol=[1], nmol=[1],
nstep=0, nstep=0,
) )
self.assertEqual(ex.exception, "Error: 'nstep' keyword not defined appropriately in config file") self.assertEqual(
ex.exception,
"Error: 'nstep' keyword not defined appropriately in config file",
)
def test_from_dict(self): def test_from_dict(self):
dice_dto = DiceConfig.from_dict({ dice_dto = DiceConfig.from_dict(
'ljname': 'test', {
'outname': 'test', "ljname": "test",
'dens': 1.0, "outname": "test",
'nmol': [1], "dens": 1.0,
'nstep': [1, 1], "nmol": [1],
}) "nstep": [1, 1],
}
)
self.assertIsInstance(dice_dto, DiceConfig) self.assertIsInstance(dice_dto, DiceConfig)

View File

@@ -6,9 +6,9 @@ import unittest
class TestGaussianDTO(unittest.TestCase): class TestGaussianDTO(unittest.TestCase):
def test_class_instantiation(self): def test_class_instantiation(self):
gaussian_dto = GaussianDTO( gaussian_dto = GaussianDTO(
level='test', level="test",
qmprog='g16', qmprog="g16",
keywords='test', keywords="test",
) )
self.assertIsInstance(gaussian_dto, GaussianDTO) self.assertIsInstance(gaussian_dto, GaussianDTO)
@@ -16,30 +16,30 @@ class TestGaussianDTO(unittest.TestCase):
def test_is_valid_qmprog(self): def test_is_valid_qmprog(self):
with self.assertRaises(ValueError): with self.assertRaises(ValueError):
gaussian_dto = GaussianDTO( gaussian_dto = GaussianDTO(
level='test', level="test",
qmprog='test', qmprog="test",
keywords='test', keywords="test",
) )
def test_is_valid_level(self): def test_is_valid_level(self):
with self.assertRaises(ValueError): with self.assertRaises(ValueError):
gaussian_dto = GaussianDTO( gaussian_dto = GaussianDTO(
level=None, level=None,
qmprog='g16', qmprog="g16",
keywords='test', keywords="test",
) )
def test_from_dict(self): def test_from_dict(self):
gaussian_dto = GaussianDTO.from_dict( gaussian_dto = GaussianDTO.from_dict(
{ {
'level': 'test', "level": "test",
'qmprog': 'g16', "qmprog": "g16",
'keywords': 'test', "keywords": "test",
} }
) )
self.assertIsInstance(gaussian_dto, GaussianDTO) self.assertIsInstance(gaussian_dto, GaussianDTO)
if __name__ == '__main__': if __name__ == "__main__":
unittest.main() unittest.main()

View File

@@ -1,45 +1,45 @@
from diceplayer.shared.config.dice_config import DiceConfig
from diceplayer.shared.config.gaussian_config import GaussianDTO from diceplayer.shared.config.gaussian_config import GaussianDTO
from diceplayer.shared.config.player_config import PlayerConfig from diceplayer.shared.config.player_config import PlayerConfig
from diceplayer.shared.config.dice_config import DiceConfig
import unittest import unittest
def get_config_dict(): def get_config_dict():
return { return {
'opt': True, "opt": True,
'mem': 12, "mem": 12,
'maxcyc': 100, "maxcyc": 100,
'nprocs': 4, "nprocs": 4,
'ncores': 4, "ncores": 4,
'dice': { "dice": {
'ljname': 'test', "ljname": "test",
'outname': 'test', "outname": "test",
'dens': 1.0, "dens": 1.0,
'nmol': [1], "nmol": [1],
'nstep': [1, 1], "nstep": [1, 1],
},
"gaussian": {
"level": "test",
"qmprog": "g16",
"keywords": "test",
}, },
'gaussian': {
'level': 'test',
'qmprog': 'g16',
'keywords': 'test',
}
} }
class TestPlayerDTO(unittest.TestCase): class TestPlayerDTO(unittest.TestCase):
def setUp(self) -> None: def setUp(self) -> None:
self.dice_dto = DiceConfig( self.dice_dto = DiceConfig(
ljname='test', ljname="test",
outname='test', outname="test",
dens=1.0, dens=1.0,
nmol=[1], nmol=[1],
nstep=[1, 1], nstep=[1, 1],
) )
self.gaussian_dto = GaussianDTO( self.gaussian_dto = GaussianDTO(
level='test', level="test",
qmprog='g16', qmprog="g16",
keywords='test', keywords="test",
) )
def test_class_instantiation(self): def test_class_instantiation(self):
@@ -50,7 +50,7 @@ class TestPlayerDTO(unittest.TestCase):
nprocs=4, nprocs=4,
ncores=4, ncores=4,
dice=self.dice_dto, dice=self.dice_dto,
gaussian=self.gaussian_dto gaussian=self.gaussian_dto,
) )
self.assertIsInstance(player_dto, PlayerConfig) self.assertIsInstance(player_dto, PlayerConfig)
@@ -66,20 +66,18 @@ class TestPlayerDTO(unittest.TestCase):
ncores=4, ncores=4,
altsteps=100, altsteps=100,
dice=self.dice_dto, dice=self.dice_dto,
gaussian=self.gaussian_dto gaussian=self.gaussian_dto,
) )
self.assertEqual(player_dto.altsteps, 20000) self.assertEqual(player_dto.altsteps, 20000)
def test_from_dict(self): def test_from_dict(self):
player_dto = PlayerConfig.from_dict( player_dto = PlayerConfig.from_dict(get_config_dict())
get_config_dict()
)
self.assertIsInstance(player_dto, PlayerConfig) self.assertIsInstance(player_dto, PlayerConfig)
self.assertIsInstance(player_dto.dice, DiceConfig) self.assertIsInstance(player_dto.dice, DiceConfig)
self.assertIsInstance(player_dto.gaussian, GaussianDTO) self.assertIsInstance(player_dto.gaussian, GaussianDTO)
if __name__ == '__main__': if __name__ == "__main__":
unittest.main() unittest.main()

View File

@@ -1,30 +1,30 @@
import numpy as np
from diceplayer.shared.environment.molecule import Molecule
from diceplayer.shared.environment.atom import Atom from diceplayer.shared.environment.atom import Atom
from diceplayer.shared.environment.molecule import Molecule
import numpy as np
import numpy.testing as npt import numpy.testing as npt
import unittest import unittest
class TestMolecule(unittest.TestCase): class TestMolecule(unittest.TestCase):
def test_class_instantiation(self): def test_class_instantiation(self):
mol = Molecule('test') mol = Molecule("test")
self.assertIsInstance(mol, Molecule) self.assertIsInstance(mol, Molecule)
def test_add_atom(self): def test_add_atom(self):
mol = Molecule('test') mol = Molecule("test")
mol.add_atom( mol.add_atom(
Atom(lbl=1, na=1, rx=1.0, ry=1.0, rz=1.0, chg=1.0, eps=1.0, sig=1.0) Atom(lbl=1, na=1, rx=1.0, ry=1.0, rz=1.0, chg=1.0, eps=1.0, sig=1.0)
) )
self.assertEqual(len(mol.atom), 1) self.assertEqual(len(mol.atom), 1)
npt.assert_equal(mol.com, [1., 1., 1.]) npt.assert_equal(mol.com, [1.0, 1.0, 1.0])
def test_center_of_mass(self): def test_center_of_mass(self):
mol = Molecule('test') mol = Molecule("test")
mol.add_atom( mol.add_atom(
Atom(lbl=1, na=1, rx=1.0, ry=1.0, rz=1.0, chg=1.0, eps=1.0, sig=1.0) Atom(lbl=1, na=1, rx=1.0, ry=1.0, rz=1.0, chg=1.0, eps=1.0, sig=1.0)
@@ -33,10 +33,10 @@ class TestMolecule(unittest.TestCase):
Atom(lbl=1, na=1, rx=0.0, ry=0.0, rz=0.0, chg=1.0, eps=1.0, sig=1.0) Atom(lbl=1, na=1, rx=0.0, ry=0.0, rz=0.0, chg=1.0, eps=1.0, sig=1.0)
) )
npt.assert_equal(mol.com, [.5, .5, .5]) npt.assert_equal(mol.com, [0.5, 0.5, 0.5])
def test_center_of_mass_to_origin(self): def test_center_of_mass_to_origin(self):
mol = Molecule('test') mol = Molecule("test")
mol.add_atom( mol.add_atom(
Atom(lbl=1, na=1, rx=1.0, ry=1.0, rz=1.0, chg=1.0, eps=1.0, sig=1.0) Atom(lbl=1, na=1, rx=1.0, ry=1.0, rz=1.0, chg=1.0, eps=1.0, sig=1.0)
@@ -47,7 +47,7 @@ class TestMolecule(unittest.TestCase):
npt.assert_equal(mol.com, [0, 0, 0]) npt.assert_equal(mol.com, [0, 0, 0])
def test_charges_and_dipole(self): def test_charges_and_dipole(self):
mol = Molecule('test') mol = Molecule("test")
mol.add_atom( mol.add_atom(
Atom(lbl=1, na=1, rx=0.0, ry=0.0, rz=0.0, chg=1.0, eps=1.0, sig=1.0) Atom(lbl=1, na=1, rx=0.0, ry=0.0, rz=0.0, chg=1.0, eps=1.0, sig=1.0)
@@ -57,13 +57,10 @@ class TestMolecule(unittest.TestCase):
expected_charge_dipole_array = [1.0, 0.0, 0.0, 0.0, 0.0] expected_charge_dipole_array = [1.0, 0.0, 0.0, 0.0, 0.0]
npt.assert_equal( npt.assert_equal(actual_charge_dipole_array, expected_charge_dipole_array)
actual_charge_dipole_array,
expected_charge_dipole_array
)
def test_distances_between_atoms(self): def test_distances_between_atoms(self):
mol = Molecule('test') mol = Molecule("test")
mol.add_atom( mol.add_atom(
Atom(lbl=1, na=1, rx=0.0, ry=0.0, rz=0.0, chg=1.0, eps=1.0, sig=1.0) Atom(lbl=1, na=1, rx=0.0, ry=0.0, rz=0.0, chg=1.0, eps=1.0, sig=1.0)
@@ -76,12 +73,11 @@ class TestMolecule(unittest.TestCase):
actual_distance_between_atoms = mol.distances_between_atoms() actual_distance_between_atoms = mol.distances_between_atoms()
npt.assert_almost_equal( npt.assert_almost_equal(
expected_distance_between_atoms, expected_distance_between_atoms, actual_distance_between_atoms
actual_distance_between_atoms
) )
def test_inertia_tensor(self): def test_inertia_tensor(self):
mol = Molecule('test') mol = Molecule("test")
mol.add_atom( mol.add_atom(
Atom(lbl=1, na=1, rx=0.0, ry=0.0, rz=0.0, chg=1.0, eps=1.0, sig=1.0) Atom(lbl=1, na=1, rx=0.0, ry=0.0, rz=0.0, chg=1.0, eps=1.0, sig=1.0)
@@ -90,25 +86,28 @@ class TestMolecule(unittest.TestCase):
Atom(lbl=1, na=1, rx=1.0, ry=1.0, rz=1.0, chg=1.0, eps=1.0, sig=1.0) Atom(lbl=1, na=1, rx=1.0, ry=1.0, rz=1.0, chg=1.0, eps=1.0, sig=1.0)
) )
expected_inertia_tensor = [[1.00790, -0.50395, -0.50395], expected_inertia_tensor = [
[1.00790, -0.50395, -0.50395],
[-0.50395, 1.0079, -0.50395], [-0.50395, 1.0079, -0.50395],
[-0.50395, -0.50395, 1.0079]] [-0.50395, -0.50395, 1.0079],
]
actual_inertia_tensor = mol.inertia_tensor() actual_inertia_tensor = mol.inertia_tensor()
npt.assert_equal( npt.assert_equal(expected_inertia_tensor, actual_inertia_tensor)
expected_inertia_tensor,
actual_inertia_tensor
)
def test_principal_axes(self): def test_principal_axes(self):
mol = Molecule('test') mol = Molecule("test")
mol.add_atom( mol.add_atom(
Atom(lbl=1, na=1, rx=0.0, ry=0.0, rz=0.0, chg=1.0, eps=1.0, sig=1.0) Atom(lbl=1, na=1, rx=0.0, ry=0.0, rz=0.0, chg=1.0, eps=1.0, sig=1.0)
) )
expected_evals, expected_evecs = [0., 0., 0.], [[1., 0., 0.], [0., 1., 0.], [0., 0., 1.]] expected_evals, expected_evecs = [0.0, 0.0, 0.0], [
[1.0, 0.0, 0.0],
[0.0, 1.0, 0.0],
[0.0, 0.0, 1.0],
]
evals, evecs = mol.principal_axes() evals, evecs = mol.principal_axes()
@@ -116,7 +115,7 @@ class TestMolecule(unittest.TestCase):
npt.assert_equal(expected_evecs, evecs) npt.assert_equal(expected_evecs, evecs)
def test_read_position(self): def test_read_position(self):
mol = Molecule('test') mol = Molecule("test")
mol.add_atom( mol.add_atom(
Atom(lbl=1, na=1, rx=0.0, ry=0.0, rz=0.0, chg=1.0, eps=1.0, sig=1.0) Atom(lbl=1, na=1, rx=0.0, ry=0.0, rz=0.0, chg=1.0, eps=1.0, sig=1.0)
@@ -126,30 +125,24 @@ class TestMolecule(unittest.TestCase):
actual_position = mol.read_position() actual_position = mol.read_position()
npt.assert_equal( npt.assert_equal(expected_position, actual_position)
expected_position,
actual_position
)
def test_update_charges(self): def test_update_charges(self):
mol = Molecule('test') mol = Molecule("test")
mol.add_atom( mol.add_atom(
Atom(lbl=1, na=1, rx=0.0, ry=0.0, rz=0.0, chg=1.0, eps=1.0, sig=1.0) Atom(lbl=1, na=1, rx=0.0, ry=0.0, rz=0.0, chg=1.0, eps=1.0, sig=1.0)
) )
expected_charges = [2.] expected_charges = [2.0]
mol.update_charges(expected_charges) mol.update_charges(expected_charges)
actual_charges = list(map(lambda a: a.chg, mol.atom)) actual_charges = list(map(lambda a: a.chg, mol.atom))
npt.assert_equal( npt.assert_equal(expected_charges, actual_charges)
expected_charges,
actual_charges
)
def test_sizes_of_molecule(self): def test_sizes_of_molecule(self):
mol = Molecule('test') mol = Molecule("test")
mol.add_atom( mol.add_atom(
Atom(lbl=1, na=1, rx=0.0, ry=0.0, rz=0.0, chg=1.0, eps=1.0, sig=1.0) Atom(lbl=1, na=1, rx=0.0, ry=0.0, rz=0.0, chg=1.0, eps=1.0, sig=1.0)
@@ -162,7 +155,7 @@ class TestMolecule(unittest.TestCase):
npt.assert_equal(sizes, expected_sizes) npt.assert_equal(sizes, expected_sizes)
def test_standard_orientation(self): def test_standard_orientation(self):
mol = Molecule('test') mol = Molecule("test")
mol.add_atom( mol.add_atom(
Atom(lbl=1, na=1, rx=1.0, ry=1.0, rz=1.0, chg=1.0, eps=1.0, sig=1.0) Atom(lbl=1, na=1, rx=1.0, ry=1.0, rz=1.0, chg=1.0, eps=1.0, sig=1.0)
@@ -175,7 +168,7 @@ class TestMolecule(unittest.TestCase):
self.assertEqual(mol.read_position().tolist(), expected_position) self.assertEqual(mol.read_position().tolist(), expected_position)
def test_translate(self): def test_translate(self):
mol = Molecule('test') mol = Molecule("test")
mol.add_atom( mol.add_atom(
Atom(lbl=1, na=1, rx=1.0, ry=1.0, rz=1.0, chg=1.0, eps=1.0, sig=1.0) Atom(lbl=1, na=1, rx=1.0, ry=1.0, rz=1.0, chg=1.0, eps=1.0, sig=1.0)
@@ -185,18 +178,15 @@ class TestMolecule(unittest.TestCase):
expected_position = [0.0, 0.0, 0.0] expected_position = [0.0, 0.0, 0.0]
self.assertEqual( self.assertEqual(new_mol.read_position().tolist(), expected_position)
new_mol.read_position().tolist(),
expected_position
)
def test_minimum_distance(self): def test_minimum_distance(self):
mol1 = Molecule('test1') mol1 = Molecule("test1")
mol1.add_atom( mol1.add_atom(
Atom(lbl=1, na=1, rx=0.0, ry=0.0, rz=0.0, chg=1.0, eps=1.0, sig=1.0) Atom(lbl=1, na=1, rx=0.0, ry=0.0, rz=0.0, chg=1.0, eps=1.0, sig=1.0)
) )
mol2 = Molecule('test2') mol2 = Molecule("test2")
mol2.add_atom( mol2.add_atom(
Atom(lbl=1, na=1, rx=1.0, ry=0.0, rz=0.0, chg=1.0, eps=1.0, sig=1.0) Atom(lbl=1, na=1, rx=1.0, ry=0.0, rz=0.0, chg=1.0, eps=1.0, sig=1.0)
) )
@@ -208,5 +198,5 @@ class TestMolecule(unittest.TestCase):
self.assertEqual(expected_distance, actual_distance) self.assertEqual(expected_distance, actual_distance)
if __name__ == '__main__': if __name__ == "__main__":
unittest.main() unittest.main()

View File

@@ -13,15 +13,14 @@ class TestSystem(unittest.TestCase):
def test_add_type(self): def test_add_type(self):
system = System() system = System()
system.add_type(Molecule('test')) system.add_type(Molecule("test"))
self.assertIsInstance(system.molecule, list) self.assertIsInstance(system.molecule, list)
with self.assertRaises(TypeError) as ex: with self.assertRaises(TypeError) as ex:
system.add_type('test') system.add_type("test")
self.assertEqual(ex.exception, 'Error: molecule is not a Molecule instance') self.assertEqual(ex.exception, "Error: molecule is not a Molecule instance")
if __name__ == "__main__":
if __name__ == '__main__':
unittest.main() unittest.main()

View File

@@ -1,18 +1,17 @@
from diceplayer.shared.interface.dice_interface import DiceInterface from diceplayer import logger
from diceplayer.shared.config.player_config import PlayerConfig from diceplayer.shared.config.player_config import PlayerConfig
from diceplayer.shared.environment.atom import Atom
from diceplayer.shared.environment.molecule import Molecule from diceplayer.shared.environment.molecule import Molecule
from diceplayer.shared.environment.system import System from diceplayer.shared.environment.system import System
from diceplayer.shared.environment.atom import Atom from diceplayer.shared.interface.dice_interface import DiceInterface
from diceplayer import logger
import yaml
import io
from tests.mocks.mock_inputs import get_config_example from tests.mocks.mock_inputs import get_config_example
from tests.mocks.mock_proc import MockConnection, MockProc from tests.mocks.mock_proc import MockConnection, MockProc
from unittest import mock import yaml
import io
import unittest import unittest
from unittest import mock
class TestDiceInterface(unittest.TestCase): class TestDiceInterface(unittest.TestCase):
@@ -20,7 +19,7 @@ class TestDiceInterface(unittest.TestCase):
logger.set_logger(stream=io.StringIO()) logger.set_logger(stream=io.StringIO())
config = yaml.load(get_config_example(), Loader=yaml.Loader) config = yaml.load(get_config_example(), Loader=yaml.Loader)
self.config = PlayerConfig.from_dict(config['diceplayer']) self.config = PlayerConfig.from_dict(config["diceplayer"])
def test_class_instantiation(self): def test_class_instantiation(self):
dice = DiceInterface() dice = DiceInterface()
@@ -44,24 +43,26 @@ class TestDiceInterface(unittest.TestCase):
dice.configure(self.config, System()) dice.configure(self.config, System())
self.assertTrue(hasattr(dice, 'step')) self.assertTrue(hasattr(dice, "step"))
self.assertTrue(hasattr(dice, 'system')) self.assertTrue(hasattr(dice, "system"))
dice.reset() dice.reset()
self.assertFalse(hasattr(dice, 'step')) self.assertFalse(hasattr(dice, "step"))
self.assertFalse(hasattr(dice, 'system')) self.assertFalse(hasattr(dice, "system"))
@mock.patch('diceplayer.shared.interface.dice_interface.Process', MockProc()) @mock.patch("diceplayer.shared.interface.dice_interface.Process", MockProc())
@mock.patch('diceplayer.shared.interface.dice_interface.connection', MockConnection) @mock.patch("diceplayer.shared.interface.dice_interface.connection", MockConnection)
def test_start(self): def test_start(self):
dice = DiceInterface() dice = DiceInterface()
dice.configure(self.config, System()) dice.configure(self.config, System())
dice.start(1) dice.start(1)
@mock.patch('diceplayer.shared.interface.dice_interface.connection', MockConnection) @mock.patch("diceplayer.shared.interface.dice_interface.connection", MockConnection)
@mock.patch('diceplayer.shared.interface.dice_interface.Process', MockProc(exitcode=1)) @mock.patch(
"diceplayer.shared.interface.dice_interface.Process", MockProc(exitcode=1)
)
def test_start_with_process_error(self): def test_start_with_process_error(self):
dice = DiceInterface() dice = DiceInterface()
dice.configure(self.config, System()) dice.configure(self.config, System())
@@ -75,10 +76,16 @@ class TestDiceInterface(unittest.TestCase):
with self.assertRaises(SystemExit): with self.assertRaises(SystemExit):
dice._simulation_process(1, 1) dice._simulation_process(1, 1)
@mock.patch('diceplayer.shared.interface.dice_interface.DiceInterface._make_proc_dir') @mock.patch(
@mock.patch('diceplayer.shared.interface.dice_interface.DiceInterface._make_dice_inputs') "diceplayer.shared.interface.dice_interface.DiceInterface._make_proc_dir"
@mock.patch('diceplayer.shared.interface.dice_interface.DiceInterface._run_dice') )
def test_simulation_process(self, mock_run_dice, mock_make_dice_inputs, mock_make_proc_dir): @mock.patch(
"diceplayer.shared.interface.dice_interface.DiceInterface._make_dice_inputs"
)
@mock.patch("diceplayer.shared.interface.dice_interface.DiceInterface._run_dice")
def test_simulation_process(
self, mock_run_dice, mock_make_dice_inputs, mock_make_proc_dir
):
dice = DiceInterface() dice = DiceInterface()
dice._simulation_process(1, 1) dice._simulation_process(1, 1)
@@ -87,8 +94,8 @@ class TestDiceInterface(unittest.TestCase):
self.assertTrue(dice._make_dice_inputs.called) self.assertTrue(dice._make_dice_inputs.called)
self.assertTrue(dice._run_dice.called) self.assertTrue(dice._run_dice.called)
@mock.patch('diceplayer.shared.interface.dice_interface.Path.mkdir') @mock.patch("diceplayer.shared.interface.dice_interface.Path.mkdir")
@mock.patch('diceplayer.shared.interface.dice_interface.Path.exists') @mock.patch("diceplayer.shared.interface.dice_interface.Path.exists")
def test_make_proc_dir_if_simdir_exists(self, mock_path_exists, mock_path_mkdir): def test_make_proc_dir_if_simdir_exists(self, mock_path_exists, mock_path_mkdir):
dice = DiceInterface() dice = DiceInterface()
dice.configure(self.config, System()) dice.configure(self.config, System())
@@ -99,9 +106,11 @@ class TestDiceInterface(unittest.TestCase):
self.assertEqual(mock_path_mkdir.call_count, 2) self.assertEqual(mock_path_mkdir.call_count, 2)
@mock.patch('diceplayer.shared.interface.dice_interface.Path.mkdir') @mock.patch("diceplayer.shared.interface.dice_interface.Path.mkdir")
@mock.patch('diceplayer.shared.interface.dice_interface.Path.exists') @mock.patch("diceplayer.shared.interface.dice_interface.Path.exists")
def test_make_proc_dir_if_simdir_doesnt_exists(self, mock_path_exists, mock_path_mkdir): def test_make_proc_dir_if_simdir_doesnt_exists(
self, mock_path_exists, mock_path_mkdir
):
dice = DiceInterface() dice = DiceInterface()
dice.configure(self.config, System()) dice.configure(self.config, System())
@@ -145,9 +154,13 @@ class TestDiceInterface(unittest.TestCase):
self.assertFalse(dice._make_npt_ter.called) self.assertFalse(dice._make_npt_ter.called)
self.assertFalse(dice._make_npt_eq.called) self.assertFalse(dice._make_npt_eq.called)
@mock.patch('builtins.open', new_callable=mock.mock_open, read_data='test') @mock.patch("builtins.open", new_callable=mock.mock_open, read_data="test")
@mock.patch('diceplayer.shared.interface.dice_interface.Path.exists', return_value=True) @mock.patch(
def test_make_dice_inputs_nstep_len_two_with_randoninit_first_cycle_two(self, mock_path_exists, mock_open): "diceplayer.shared.interface.dice_interface.Path.exists", return_value=True
)
def test_make_dice_inputs_nstep_len_two_with_randoninit_first_cycle_two(
self, mock_path_exists, mock_open
):
dice = DiceInterface() dice = DiceInterface()
dice.configure(self.config, System()) dice.configure(self.config, System())
@@ -176,8 +189,12 @@ class TestDiceInterface(unittest.TestCase):
self.assertFalse(dice._make_npt_ter.called) self.assertFalse(dice._make_npt_ter.called)
self.assertFalse(dice._make_npt_eq.called) self.assertFalse(dice._make_npt_eq.called)
@mock.patch('diceplayer.shared.interface.dice_interface.Path.exists', return_value=False) @mock.patch(
def test_make_dice_inputs_raises_exception_on_last_not_found(self, mock_path_exists): "diceplayer.shared.interface.dice_interface.Path.exists", return_value=False
)
def test_make_dice_inputs_raises_exception_on_last_not_found(
self, mock_path_exists
):
dice = DiceInterface() dice = DiceInterface()
dice.configure(self.config, System()) dice.configure(self.config, System())
@@ -223,10 +240,14 @@ class TestDiceInterface(unittest.TestCase):
self.assertTrue(dice._make_npt_ter.called) self.assertTrue(dice._make_npt_ter.called)
self.assertTrue(dice._make_npt_eq.called) self.assertTrue(dice._make_npt_eq.called)
@mock.patch('diceplayer.shared.interface.dice_interface.os') @mock.patch("diceplayer.shared.interface.dice_interface.os")
@mock.patch('diceplayer.shared.interface.dice_interface.shutil') @mock.patch("diceplayer.shared.interface.dice_interface.shutil")
@mock.patch('diceplayer.shared.interface.dice_interface.Path.exists', return_value=True) @mock.patch(
def test_run_dice_on_first_cycle_run_successful(self, mock_path_exists, mock_shutils, mock_os): "diceplayer.shared.interface.dice_interface.Path.exists", return_value=True
)
def test_run_dice_on_first_cycle_run_successful(
self, mock_path_exists, mock_shutils, mock_os
):
dice = DiceInterface() dice = DiceInterface()
dice.configure(self.config, System()) dice.configure(self.config, System())
@@ -257,10 +278,14 @@ class TestDiceInterface(unittest.TestCase):
self.assertEqual(dice.run_dice_file.call_count, 2) self.assertEqual(dice.run_dice_file.call_count, 2)
self.assertTrue(mock_shutils.copy.called) self.assertTrue(mock_shutils.copy.called)
@mock.patch('diceplayer.shared.interface.dice_interface.os') @mock.patch("diceplayer.shared.interface.dice_interface.os")
@mock.patch('diceplayer.shared.interface.dice_interface.shutil') @mock.patch("diceplayer.shared.interface.dice_interface.shutil")
@mock.patch('diceplayer.shared.interface.dice_interface.Path.exists', return_value=True) @mock.patch(
def test_run_dice_on_second_cycle_run_successful(self, mock_path_exists, mock_shutils, mock_os): "diceplayer.shared.interface.dice_interface.Path.exists", return_value=True
)
def test_run_dice_on_second_cycle_run_successful(
self, mock_path_exists, mock_shutils, mock_os
):
dice = DiceInterface() dice = DiceInterface()
dice.configure(self.config, System()) dice.configure(self.config, System())
@@ -287,10 +312,14 @@ class TestDiceInterface(unittest.TestCase):
self.assertEqual(dice.run_dice_file.call_count, 1) self.assertEqual(dice.run_dice_file.call_count, 1)
self.assertTrue(mock_shutils.copy.called) self.assertTrue(mock_shutils.copy.called)
@mock.patch('diceplayer.shared.interface.dice_interface.os') @mock.patch("diceplayer.shared.interface.dice_interface.os")
@mock.patch('diceplayer.shared.interface.dice_interface.shutil') @mock.patch("diceplayer.shared.interface.dice_interface.shutil")
@mock.patch('diceplayer.shared.interface.dice_interface.Path.exists', return_value=False) @mock.patch(
def test_run_dice_on_second_cycle_run_successful(self, mock_path_exists, mock_shutils, mock_os): "diceplayer.shared.interface.dice_interface.Path.exists", return_value=False
)
def test_run_dice_on_second_cycle_run_successful(
self, mock_path_exists, mock_shutils, mock_os
):
dice = DiceInterface() dice = DiceInterface()
dice.configure(self.config, System()) dice.configure(self.config, System())
@@ -299,7 +328,7 @@ class TestDiceInterface(unittest.TestCase):
with self.assertRaises(FileNotFoundError): with self.assertRaises(FileNotFoundError):
dice._run_dice(1, 1) dice._run_dice(1, 1)
@mock.patch('builtins.open', new_callable=mock.mock_open) @mock.patch("builtins.open", new_callable=mock.mock_open)
def test_make_init_file(self, mock_open): def test_make_init_file(self, mock_open):
example_atom = Atom( example_atom = Atom(
lbl=1, lbl=1,
@@ -312,10 +341,10 @@ class TestDiceInterface(unittest.TestCase):
sig=1.0, sig=1.0,
) )
main_molecule = Molecule('main_molecule') main_molecule = Molecule("main_molecule")
main_molecule.add_atom(example_atom) main_molecule.add_atom(example_atom)
secondary_molecule = Molecule('secondary_molecule') secondary_molecule = Molecule("secondary_molecule")
secondary_molecule.add_atom(example_atom) secondary_molecule.add_atom(example_atom)
system = System() system = System()
@@ -328,15 +357,17 @@ class TestDiceInterface(unittest.TestCase):
dice.step.dice.nmol = [1, 1] dice.step.dice.nmol = [1, 1]
last_xyz_file = io.StringIO() last_xyz_file = io.StringIO()
last_xyz_file.writelines([ last_xyz_file.writelines(
' TEST\n', [
' Configuration number : TEST = TEST TEST TEST\n', " TEST\n",
' H 1.00000 1.00000 1.00000\n', " Configuration number : TEST = TEST TEST TEST\n",
' H 1.00000 1.00000 1.00000\n', " H 1.00000 1.00000 1.00000\n",
]) " H 1.00000 1.00000 1.00000\n",
]
)
last_xyz_file.seek(0) last_xyz_file.seek(0)
dice._make_init_file('test', last_xyz_file) dice._make_init_file("test", last_xyz_file)
mock_handler = mock_open() mock_handler = mock_open()
calls = mock_handler.write.call_args_list calls = mock_handler.write.call_args_list
@@ -344,14 +375,14 @@ class TestDiceInterface(unittest.TestCase):
lines = list(map(lambda x: x[0][0], calls)) lines = list(map(lambda x: x[0][0], calls))
expected_lines = [ expected_lines = [
' 1.000000 1.000000 1.000000\n', " 1.000000 1.000000 1.000000\n",
' 1.000000 1.000000 1.000000\n', " 1.000000 1.000000 1.000000\n",
'$end' "$end",
] ]
self.assertEqual(lines, expected_lines) self.assertEqual(lines, expected_lines)
@mock.patch('builtins.open', new_callable=mock.mock_open) @mock.patch("builtins.open", new_callable=mock.mock_open)
def test_new_density(self, mock_open): def test_new_density(self, mock_open):
example_atom = Atom( example_atom = Atom(
lbl=1, lbl=1,
@@ -364,10 +395,10 @@ class TestDiceInterface(unittest.TestCase):
sig=1.0, sig=1.0,
) )
main_molecule = Molecule('main_molecule') main_molecule = Molecule("main_molecule")
main_molecule.add_atom(example_atom) main_molecule.add_atom(example_atom)
secondary_molecule = Molecule('secondary_molecule') secondary_molecule = Molecule("secondary_molecule")
secondary_molecule.add_atom(example_atom) secondary_molecule.add_atom(example_atom)
system = System() system = System()
@@ -378,95 +409,166 @@ class TestDiceInterface(unittest.TestCase):
dice.configure(self.config, system) dice.configure(self.config, system)
last_xyz_file = io.StringIO() last_xyz_file = io.StringIO()
last_xyz_file.writelines([ last_xyz_file.writelines(
' TEST\n', [
' Configuration number : TEST = 1 1 1\n', " TEST\n",
' H 1.00000 1.00000 1.00000\n', " Configuration number : TEST = 1 1 1\n",
' H 1.00000 1.00000 1.00000\n', " H 1.00000 1.00000 1.00000\n",
]) " H 1.00000 1.00000 1.00000\n",
]
)
last_xyz_file.seek(0) last_xyz_file.seek(0)
density = dice._new_density(last_xyz_file) density = dice._new_density(last_xyz_file)
self.assertEqual(density, 85.35451545000001) self.assertEqual(density, 85.35451545000001)
@mock.patch('builtins.open', new_callable=mock.mock_open) @mock.patch("builtins.open", new_callable=mock.mock_open)
@mock.patch('diceplayer.shared.interface.dice_interface.random') @mock.patch("diceplayer.shared.interface.dice_interface.random")
def test_make_nvt_ter(self, mock_random, mock_open): def test_make_nvt_ter(self, mock_random, mock_open):
mock_random.random.return_value = 1 mock_random.random.return_value = 1
dice = DiceInterface() dice = DiceInterface()
dice.configure(self.config, System()) dice.configure(self.config, System())
dice._make_nvt_ter(1, 'test') dice._make_nvt_ter(1, "test")
mock_handler = mock_open() mock_handler = mock_open()
calls = mock_handler.write.call_args_list calls = mock_handler.write.call_args_list
lines = list(map(lambda x: x[0][0], calls)) lines = list(map(lambda x: x[0][0], calls))
expected_lines = ['title = Diceplayer run - NVT Thermalization\n', 'ncores = 4\n', 'ljname = phb.ljc\n', 'outname = phb\n', 'nmol = 1 50\n', 'dens = 0.75\n', 'temp = 300.0\n', 'init = yes\n', 'nstep = 2000\n', 'vstep = 0\n', 'mstop = 1\n', 'accum = no\n', 'iprint = 1\n', 'isave = 0\n', 'irdf = 0\n', 'seed = 1000000\n', 'upbuf = 360'] expected_lines = [
"title = Diceplayer run - NVT Thermalization\n",
"ncores = 4\n",
"ljname = phb.ljc\n",
"outname = phb\n",
"nmol = 1 50\n",
"dens = 0.75\n",
"temp = 300.0\n",
"init = yes\n",
"nstep = 2000\n",
"vstep = 0\n",
"mstop = 1\n",
"accum = no\n",
"iprint = 1\n",
"isave = 0\n",
"irdf = 0\n",
"seed = 1000000\n",
"upbuf = 360",
]
self.assertEqual(lines, expected_lines) self.assertEqual(lines, expected_lines)
@mock.patch('builtins.open', new_callable=mock.mock_open) @mock.patch("builtins.open", new_callable=mock.mock_open)
@mock.patch('diceplayer.shared.interface.dice_interface.random') @mock.patch("diceplayer.shared.interface.dice_interface.random")
def test_make_nvt_eq(self, mock_random, mock_open): def test_make_nvt_eq(self, mock_random, mock_open):
mock_random.random.return_value = 1 mock_random.random.return_value = 1
dice = DiceInterface() dice = DiceInterface()
dice.configure(self.config, System()) dice.configure(self.config, System())
dice._make_nvt_eq(1, 'test') dice._make_nvt_eq(1, "test")
mock_handler = mock_open() mock_handler = mock_open()
calls = mock_handler.write.call_args_list calls = mock_handler.write.call_args_list
lines = list(map(lambda x: x[0][0], calls)) lines = list(map(lambda x: x[0][0], calls))
expected_lines = ['title = Diceplayer run - NVT Production\n', 'ncores = 4\n', 'ljname = phb.ljc\n', 'outname = phb\n', 'nmol = 1 50\n', 'dens = 0.75\n', 'temp = 300.0\n', 'init = no\n', 'nstep = 3000\n', 'vstep = 0\n', 'mstop = 1\n', 'accum = no\n', 'iprint = 1\n', 'isave = 1000\n', 'irdf = 40\n', 'seed = 1000000\n'] expected_lines = [
"title = Diceplayer run - NVT Production\n",
"ncores = 4\n",
"ljname = phb.ljc\n",
"outname = phb\n",
"nmol = 1 50\n",
"dens = 0.75\n",
"temp = 300.0\n",
"init = no\n",
"nstep = 3000\n",
"vstep = 0\n",
"mstop = 1\n",
"accum = no\n",
"iprint = 1\n",
"isave = 1000\n",
"irdf = 40\n",
"seed = 1000000\n",
]
self.assertEqual(lines, expected_lines) self.assertEqual(lines, expected_lines)
@mock.patch('builtins.open', new_callable=mock.mock_open) @mock.patch("builtins.open", new_callable=mock.mock_open)
@mock.patch('diceplayer.shared.interface.dice_interface.random') @mock.patch("diceplayer.shared.interface.dice_interface.random")
def test_make_npt_ter(self, mock_random, mock_open): def test_make_npt_ter(self, mock_random, mock_open):
mock_random.random.return_value = 1 mock_random.random.return_value = 1
dice = DiceInterface() dice = DiceInterface()
dice.configure(self.config, System()) dice.configure(self.config, System())
dice._make_npt_ter(1, 'test') dice._make_npt_ter(1, "test")
mock_handler = mock_open() mock_handler = mock_open()
calls = mock_handler.write.call_args_list calls = mock_handler.write.call_args_list
lines = list(map(lambda x: x[0][0], calls)) lines = list(map(lambda x: x[0][0], calls))
expected_lines = ['title = Diceplayer run - NPT Thermalization\n', 'ncores = 4\n', 'ljname = phb.ljc\n', 'outname = phb\n', 'nmol = 1 50\n', 'press = 1.0\n', 'temp = 300.0\n', 'init = no\n', 'vstep = 600\n', 'nstep = 5\n', 'mstop = 1\n', 'accum = no\n', 'iprint = 1\n', 'isave = 0\n', 'irdf = 0\n', 'seed = 1000000\n'] expected_lines = [
"title = Diceplayer run - NPT Thermalization\n",
"ncores = 4\n",
"ljname = phb.ljc\n",
"outname = phb\n",
"nmol = 1 50\n",
"press = 1.0\n",
"temp = 300.0\n",
"init = no\n",
"vstep = 600\n",
"nstep = 5\n",
"mstop = 1\n",
"accum = no\n",
"iprint = 1\n",
"isave = 0\n",
"irdf = 0\n",
"seed = 1000000\n",
]
self.assertEqual(lines, expected_lines) self.assertEqual(lines, expected_lines)
@mock.patch('builtins.open', new_callable=mock.mock_open) @mock.patch("builtins.open", new_callable=mock.mock_open)
@mock.patch('diceplayer.shared.interface.dice_interface.random') @mock.patch("diceplayer.shared.interface.dice_interface.random")
def test_make_npt_eq(self, mock_random, mock_open): def test_make_npt_eq(self, mock_random, mock_open):
mock_random.random.return_value = 1 mock_random.random.return_value = 1
dice = DiceInterface() dice = DiceInterface()
dice.configure(self.config, System()) dice.configure(self.config, System())
dice._make_npt_eq('test') dice._make_npt_eq("test")
mock_handler = mock_open() mock_handler = mock_open()
calls = mock_handler.write.call_args_list calls = mock_handler.write.call_args_list
lines = list(map(lambda x: x[0][0], calls)) lines = list(map(lambda x: x[0][0], calls))
expected_lines = ['title = Diceplayer run - NPT Production\n', 'ncores = 4\n', 'ljname = phb.ljc\n', 'outname = phb\n', 'nmol = 1 50\n', 'press = 1.0\n', 'temp = 300.0\n', 'nstep = 5\n', 'vstep = 800\n', 'init = no\n', 'mstop = 1\n', 'accum = no\n', 'iprint = 1\n', 'isave = 1000\n', 'irdf = 40\n', 'seed = 1000000\n'] expected_lines = [
"title = Diceplayer run - NPT Production\n",
"ncores = 4\n",
"ljname = phb.ljc\n",
"outname = phb\n",
"nmol = 1 50\n",
"press = 1.0\n",
"temp = 300.0\n",
"nstep = 5\n",
"vstep = 800\n",
"init = no\n",
"mstop = 1\n",
"accum = no\n",
"iprint = 1\n",
"isave = 1000\n",
"irdf = 40\n",
"seed = 1000000\n",
]
self.assertEqual(lines, expected_lines) self.assertEqual(lines, expected_lines)
@mock.patch('builtins.open', new_callable=mock.mock_open) @mock.patch("builtins.open", new_callable=mock.mock_open)
def test_make_potentials(self, mock_open): def test_make_potentials(self, mock_open):
example_atom = Atom( example_atom = Atom(
lbl=1, lbl=1,
@@ -479,10 +581,10 @@ class TestDiceInterface(unittest.TestCase):
sig=1.0, sig=1.0,
) )
main_molecule = Molecule('main_molecule') main_molecule = Molecule("main_molecule")
main_molecule.add_atom(example_atom) main_molecule.add_atom(example_atom)
secondary_molecule = Molecule('secondary_molecule') secondary_molecule = Molecule("secondary_molecule")
secondary_molecule.add_atom(example_atom) secondary_molecule.add_atom(example_atom)
system = System() system = System()
@@ -492,49 +594,68 @@ class TestDiceInterface(unittest.TestCase):
dice = DiceInterface() dice = DiceInterface()
dice.configure(self.config, system) dice.configure(self.config, system)
dice._make_potentials('test') dice._make_potentials("test")
mock_handler = mock_open() mock_handler = mock_open()
calls = mock_handler.write.call_args_list calls = mock_handler.write.call_args_list
lines = list(map(lambda x: x[0][0], calls)) lines = list(map(lambda x: x[0][0], calls))
expected_lines = ['*\n', '2\n', '1 main_molecule\n', '1 1 1.00000 1.00000 1.00000 1.000000 1.00000 1.0000\n', '1 secondary_molecule\n', '1 1 1.00000 1.00000 1.00000 1.000000 1.00000 1.0000\n'] expected_lines = [
"*\n",
"2\n",
"1 main_molecule\n",
"1 1 1.00000 1.00000 1.00000 1.000000 1.00000 1.0000\n",
"1 secondary_molecule\n",
"1 1 1.00000 1.00000 1.00000 1.000000 1.00000 1.0000\n",
]
self.assertEqual(lines, expected_lines) self.assertEqual(lines, expected_lines)
@mock.patch('diceplayer.shared.interface.dice_interface.subprocess') @mock.patch("diceplayer.shared.interface.dice_interface.subprocess")
@mock.patch('builtins.open', new_callable=mock.mock_open, read_data='End of simulation\nBLABLA') @mock.patch(
"builtins.open",
new_callable=mock.mock_open,
read_data="End of simulation\nBLABLA",
)
def test_run_dice_file(self, mock_open, mock_subprocess): def test_run_dice_file(self, mock_open, mock_subprocess):
mock_subprocess.call.return_value = 0 mock_subprocess.call.return_value = 0
dice = DiceInterface() dice = DiceInterface()
dice.configure(self.config, System()) dice.configure(self.config, System())
dice.run_dice_file(1, 1, 'test') dice.run_dice_file(1, 1, "test")
self.assertTrue(mock_subprocess.call.called) self.assertTrue(mock_subprocess.call.called)
self.assertTrue(mock_open.called) self.assertTrue(mock_open.called)
@mock.patch('diceplayer.shared.interface.dice_interface.subprocess') @mock.patch("diceplayer.shared.interface.dice_interface.subprocess")
@mock.patch('builtins.open', new_callable=mock.mock_open, read_data='Error\nBLABLA') @mock.patch("builtins.open", new_callable=mock.mock_open, read_data="Error\nBLABLA")
def test_run_dice_file_raises_runtime_error_on_dice_file(self, mock_open, mock_subprocess): def test_run_dice_file_raises_runtime_error_on_dice_file(
self, mock_open, mock_subprocess
):
mock_subprocess.call.return_value = 0 mock_subprocess.call.return_value = 0
dice = DiceInterface() dice = DiceInterface()
dice.configure(self.config, System()) dice.configure(self.config, System())
with self.assertRaises(RuntimeError): with self.assertRaises(RuntimeError):
dice.run_dice_file(1, 1, 'test') dice.run_dice_file(1, 1, "test")
@mock.patch('diceplayer.shared.interface.dice_interface.subprocess') @mock.patch("diceplayer.shared.interface.dice_interface.subprocess")
@mock.patch('builtins.open', new_callable=mock.mock_open, read_data='End of simulation\nBLABLA') @mock.patch(
def test_run_dice_file_raises_runtime_error_of_dice_exit_code(self, mock_open, mock_subprocess): "builtins.open",
new_callable=mock.mock_open,
read_data="End of simulation\nBLABLA",
)
def test_run_dice_file_raises_runtime_error_of_dice_exit_code(
self, mock_open, mock_subprocess
):
mock_subprocess.call.return_value = 1 mock_subprocess.call.return_value = 1
dice = DiceInterface() dice = DiceInterface()
dice.configure(self.config, System()) dice.configure(self.config, System())
with self.assertRaises(RuntimeError): with self.assertRaises(RuntimeError):
dice.run_dice_file(1, 1, 'test') dice.run_dice_file(1, 1, "test")
if __name__ == '__main__': if __name__ == "__main__":
unittest.main() unittest.main()

View File

@@ -1,16 +1,14 @@
from diceplayer.shared.interface.gaussian_interface import GaussianInterface from diceplayer import logger
from diceplayer.shared.config.player_config import PlayerConfig from diceplayer.shared.config.player_config import PlayerConfig
from diceplayer.shared.environment.system import System from diceplayer.shared.environment.system import System
from diceplayer import logger from diceplayer.shared.interface.gaussian_interface import GaussianInterface
from tests.mocks.mock_inputs import get_config_example from tests.mocks.mock_inputs import get_config_example
import yaml import yaml
import io import io
from unittest import mock
import unittest import unittest
from unittest import mock
class TestGaussianInterface(unittest.TestCase): class TestGaussianInterface(unittest.TestCase):
@@ -18,7 +16,7 @@ class TestGaussianInterface(unittest.TestCase):
logger.set_logger(stream=io.StringIO()) logger.set_logger(stream=io.StringIO())
config = yaml.load(get_config_example(), Loader=yaml.Loader) config = yaml.load(get_config_example(), Loader=yaml.Loader)
self.config = PlayerConfig.from_dict(config['diceplayer']) self.config = PlayerConfig.from_dict(config["diceplayer"])
def test_class_instantiation(self): def test_class_instantiation(self):
gaussian_interface = GaussianInterface() gaussian_interface = GaussianInterface()
@@ -45,11 +43,11 @@ class TestGaussianInterface(unittest.TestCase):
gaussian_interface.reset() gaussian_interface.reset()
self.assertFalse(hasattr(gaussian_interface, 'step')) self.assertFalse(hasattr(gaussian_interface, "step"))
self.assertFalse(hasattr(gaussian_interface, 'system')) self.assertFalse(hasattr(gaussian_interface, "system"))
@mock.patch('diceplayer.shared.interface.gaussian_interface.Path.mkdir') @mock.patch("diceplayer.shared.interface.gaussian_interface.Path.mkdir")
@mock.patch('diceplayer.shared.interface.gaussian_interface.Path.exists') @mock.patch("diceplayer.shared.interface.gaussian_interface.Path.exists")
def test_make_qm_dir(self, mock_exists, mock_mkdir): def test_make_qm_dir(self, mock_exists, mock_mkdir):
mock_exists.return_value = False mock_exists.return_value = False
@@ -61,8 +59,8 @@ class TestGaussianInterface(unittest.TestCase):
mock_exists.assert_called_once() mock_exists.assert_called_once()
mock_mkdir.assert_called_once() mock_mkdir.assert_called_once()
@mock.patch('diceplayer.shared.interface.gaussian_interface.shutil.copy') @mock.patch("diceplayer.shared.interface.gaussian_interface.shutil.copy")
@mock.patch('diceplayer.shared.interface.gaussian_interface.Path.exists') @mock.patch("diceplayer.shared.interface.gaussian_interface.Path.exists")
def test_copy_chk_file_from_previous_step(self, mock_exists, mock_copy): def test_copy_chk_file_from_previous_step(self, mock_exists, mock_copy):
gaussian_interface = GaussianInterface() gaussian_interface = GaussianInterface()
gaussian_interface.configure(self.config, System()) gaussian_interface.configure(self.config, System())
@@ -74,9 +72,11 @@ class TestGaussianInterface(unittest.TestCase):
self.assertTrue(mock_exists.called) self.assertTrue(mock_exists.called)
self.assertTrue(mock_copy.called) self.assertTrue(mock_copy.called)
@mock.patch('diceplayer.shared.interface.gaussian_interface.shutil.copy') @mock.patch("diceplayer.shared.interface.gaussian_interface.shutil.copy")
@mock.patch('diceplayer.shared.interface.gaussian_interface.Path.exists') @mock.patch("diceplayer.shared.interface.gaussian_interface.Path.exists")
def test_copy_chk_file_from_previous_step_no_previous_step(self, mock_exists, mock_copy): def test_copy_chk_file_from_previous_step_no_previous_step(
self, mock_exists, mock_copy
):
gaussian_interface = GaussianInterface() gaussian_interface = GaussianInterface()
gaussian_interface.configure(self.config, System()) gaussian_interface.configure(self.config, System())
@@ -85,9 +85,11 @@ class TestGaussianInterface(unittest.TestCase):
with self.assertRaises(FileNotFoundError): with self.assertRaises(FileNotFoundError):
gaussian_interface._copy_chk_file_from_previous_step(2) gaussian_interface._copy_chk_file_from_previous_step(2)
@mock.patch('diceplayer.shared.interface.gaussian_interface.shutil.copy') @mock.patch("diceplayer.shared.interface.gaussian_interface.shutil.copy")
@mock.patch('diceplayer.shared.interface.gaussian_interface.Path.exists') @mock.patch("diceplayer.shared.interface.gaussian_interface.Path.exists")
def test_copy_chk_file_from_previous_step_current_exists(self, mock_exists, mock_copy): def test_copy_chk_file_from_previous_step_current_exists(
self, mock_exists, mock_copy
):
gaussian_interface = GaussianInterface() gaussian_interface = GaussianInterface()
gaussian_interface.configure(self.config, System()) gaussian_interface.configure(self.config, System())
@@ -109,5 +111,5 @@ class TestGaussianInterface(unittest.TestCase):
# gaussian_interface._copy_chk_file_from_previous_step.assert_called_once_with(2) # gaussian_interface._copy_chk_file_from_previous_step.assert_called_once_with(2)
if __name__ == '__main__': if __name__ == "__main__":
unittest.main() unittest.main()

View File

@@ -1,10 +1,9 @@
from diceplayer.shared.utils.logger import Logger, valid_logger from diceplayer.shared.utils.logger import Logger, valid_logger
import logging
import io import io
import logging
from unittest import mock
import unittest import unittest
from unittest import mock
class TestValidateLogger(unittest.TestCase): class TestValidateLogger(unittest.TestCase):
@@ -32,102 +31,102 @@ class TestValidateLogger(unittest.TestCase):
class TestLogger(unittest.TestCase): class TestLogger(unittest.TestCase):
def test_class_instantiation(self): def test_class_instantiation(self):
logger = Logger('test') logger = Logger("test")
self.assertIsInstance(logger, Logger) self.assertIsInstance(logger, Logger)
@mock.patch('builtins.open', mock.mock_open()) @mock.patch("builtins.open", mock.mock_open())
def test_set_logger_to_file(self): def test_set_logger_to_file(self):
logger = Logger('test') logger = Logger("test")
logger.set_logger(stream=io.StringIO()) logger.set_logger(stream=io.StringIO())
self.assertIsNotNone(logger._logger) self.assertIsNotNone(logger._logger)
self.assertEqual(logger._logger.name, 'test') self.assertEqual(logger._logger.name, "test")
def test_set_logger_to_stream(self): def test_set_logger_to_stream(self):
logger = Logger('test') logger = Logger("test")
logger.set_logger(stream=io.StringIO()) logger.set_logger(stream=io.StringIO())
self.assertIsNotNone(logger._logger) self.assertIsNotNone(logger._logger)
self.assertEqual(logger._logger.name, 'test') self.assertEqual(logger._logger.name, "test")
@mock.patch('builtins.open', mock.mock_open()) @mock.patch("builtins.open", mock.mock_open())
@mock.patch('diceplayer.shared.utils.logger.Path.exists') @mock.patch("diceplayer.shared.utils.logger.Path.exists")
@mock.patch('diceplayer.shared.utils.logger.Path.rename') @mock.patch("diceplayer.shared.utils.logger.Path.rename")
def test_set_logger_if_file_exists(self, mock_rename, mock_exists): def test_set_logger_if_file_exists(self, mock_rename, mock_exists):
logger = Logger('test') logger = Logger("test")
mock_exists.return_value = True mock_exists.return_value = True
logger.set_logger() logger.set_logger()
self.assertTrue(mock_rename.called) self.assertTrue(mock_rename.called)
self.assertIsNotNone(logger._logger) self.assertIsNotNone(logger._logger)
self.assertEqual(logger._logger.name, 'test') self.assertEqual(logger._logger.name, "test")
@mock.patch('builtins.open', mock.mock_open()) @mock.patch("builtins.open", mock.mock_open())
@mock.patch('diceplayer.shared.utils.logger.Path.exists') @mock.patch("diceplayer.shared.utils.logger.Path.exists")
@mock.patch('diceplayer.shared.utils.logger.Path.rename') @mock.patch("diceplayer.shared.utils.logger.Path.rename")
def test_set_logger_if_file_not_exists(self, mock_rename, mock_exists): def test_set_logger_if_file_not_exists(self, mock_rename, mock_exists):
logger = Logger('test') logger = Logger("test")
mock_exists.return_value = False mock_exists.return_value = False
logger.set_logger() logger.set_logger()
self.assertFalse(mock_rename.called) self.assertFalse(mock_rename.called)
self.assertIsNotNone(logger._logger) self.assertIsNotNone(logger._logger)
self.assertEqual(logger._logger.name, 'test') self.assertEqual(logger._logger.name, "test")
@mock.patch('builtins.open', mock.mock_open()) @mock.patch("builtins.open", mock.mock_open())
def test_close(self): def test_close(self):
logger = Logger('test') logger = Logger("test")
logger.set_logger() logger.set_logger()
logger.close() logger.close()
self.assertEqual(len(logger._logger.handlers), 0) self.assertEqual(len(logger._logger.handlers), 0)
@mock.patch('builtins.open', mock.mock_open()) @mock.patch("builtins.open", mock.mock_open())
def test_info(self): def test_info(self):
logger = Logger('test') logger = Logger("test")
logger.set_logger(stream=io.StringIO()) logger.set_logger(stream=io.StringIO())
with self.assertLogs(level='INFO') as cm: with self.assertLogs(level="INFO") as cm:
logger.info('test') logger.info("test")
self.assertEqual(cm.output, ['INFO:test:test']) self.assertEqual(cm.output, ["INFO:test:test"])
@mock.patch('builtins.open', mock.mock_open()) @mock.patch("builtins.open", mock.mock_open())
def test_debug(self): def test_debug(self):
logger = Logger('test') logger = Logger("test")
logger.set_logger(stream=io.StringIO(), level=logging.DEBUG) logger.set_logger(stream=io.StringIO(), level=logging.DEBUG)
with self.assertLogs(level='DEBUG') as cm: with self.assertLogs(level="DEBUG") as cm:
logger.debug('test') logger.debug("test")
self.assertEqual(cm.output, ['DEBUG:test:test']) self.assertEqual(cm.output, ["DEBUG:test:test"])
@mock.patch('builtins.open', mock.mock_open()) @mock.patch("builtins.open", mock.mock_open())
def test_warning(self): def test_warning(self):
logger = Logger('test') logger = Logger("test")
logger.set_logger(stream=io.StringIO()) logger.set_logger(stream=io.StringIO())
with self.assertLogs(level='WARNING') as cm: with self.assertLogs(level="WARNING") as cm:
logger.warning('test') logger.warning("test")
self.assertEqual(cm.output, ['WARNING:test:test']) self.assertEqual(cm.output, ["WARNING:test:test"])
@mock.patch('builtins.open', mock.mock_open()) @mock.patch("builtins.open", mock.mock_open())
def test_error(self): def test_error(self):
logger = Logger('test') logger = Logger("test")
logger.set_logger(stream=io.StringIO()) logger.set_logger(stream=io.StringIO())
with self.assertLogs(level='ERROR') as cm: with self.assertLogs(level="ERROR") as cm:
logger.error('test') logger.error("test")
self.assertEqual(cm.output, ['ERROR:test:test']) self.assertEqual(cm.output, ["ERROR:test:test"])
if __name__ == '__main__': if __name__ == "__main__":
unittest.main() unittest.main()

View File

@@ -1,12 +1,10 @@
from diceplayer.player import Player
from diceplayer import logger from diceplayer import logger
from diceplayer.player import Player
import io
from tests.mocks.mock_inputs import mock_open from tests.mocks.mock_inputs import mock_open
from unittest import mock import io
import unittest import unittest
from unittest import mock
class TestPlayer(unittest.TestCase): class TestPlayer(unittest.TestCase):
@@ -59,36 +57,36 @@ class TestPlayer(unittest.TestCase):
def test_print_keywords(self, mock_date_func, mock_sys): def test_print_keywords(self, mock_date_func, mock_sys):
player = Player("control.test.yml") player = Player("control.test.yml")
mock_sys.version = 'TEST' mock_sys.version = "TEST"
mock_date_func.return_value = '00 Test 0000 at 00:00:00' mock_date_func.return_value = "00 Test 0000 at 00:00:00"
with self.assertLogs() as cm: with self.assertLogs() as cm:
player.print_keywords() player.print_keywords()
expected_output = [ expected_output = [
'INFO:diceplayer:##########################################################################################\n############# Welcome to DICEPLAYER version 1.0 #############\n##########################################################################################\n', "INFO:diceplayer:##########################################################################################\n############# Welcome to DICEPLAYER version 1.0 #############\n##########################################################################################\n",
'INFO:diceplayer:Your python version is TEST\n', "INFO:diceplayer:Your python version is TEST\n",
'INFO:diceplayer:Program started on 00 Test 0000 at 00:00:00\n', "INFO:diceplayer:Program started on 00 Test 0000 at 00:00:00\n",
'INFO:diceplayer:Environment variables:', "INFO:diceplayer:Environment variables:",
'INFO:diceplayer:OMP_STACKSIZE = Not set\n', "INFO:diceplayer:OMP_STACKSIZE = Not set\n",
'INFO:diceplayer:------------------------------------------------------------------------------------------\n DICE variables being used in this run:\n------------------------------------------------------------------------------------------\n', "INFO:diceplayer:------------------------------------------------------------------------------------------\n DICE variables being used in this run:\n------------------------------------------------------------------------------------------\n",
'INFO:diceplayer:dens = 0.75', "INFO:diceplayer:dens = 0.75",
'INFO:diceplayer:isave = 1000', "INFO:diceplayer:isave = 1000",
'INFO:diceplayer:ljname = phb.ljc', "INFO:diceplayer:ljname = phb.ljc",
'INFO:diceplayer:nmol = [ 1 50 ]', "INFO:diceplayer:nmol = [ 1 50 ]",
'INFO:diceplayer:nstep = [ 2000 3000 4000 ]', "INFO:diceplayer:nstep = [ 2000 3000 4000 ]",
'INFO:diceplayer:outname = phb', "INFO:diceplayer:outname = phb",
'INFO:diceplayer:press = 1.0', "INFO:diceplayer:press = 1.0",
'INFO:diceplayer:progname = ~/.local/bin/dice', "INFO:diceplayer:progname = ~/.local/bin/dice",
'INFO:diceplayer:randominit = first', "INFO:diceplayer:randominit = first",
'INFO:diceplayer:temp = 300.0', "INFO:diceplayer:temp = 300.0",
'INFO:diceplayer:------------------------------------------------------------------------------------------\n GAUSSIAN variables being used in this run:\n------------------------------------------------------------------------------------------\n', "INFO:diceplayer:------------------------------------------------------------------------------------------\n GAUSSIAN variables being used in this run:\n------------------------------------------------------------------------------------------\n",
'INFO:diceplayer:chg_tol = 0.01', "INFO:diceplayer:chg_tol = 0.01",
'INFO:diceplayer:keywords = freq', "INFO:diceplayer:keywords = freq",
'INFO:diceplayer:level = MP2/aug-cc-pVDZ', "INFO:diceplayer:level = MP2/aug-cc-pVDZ",
'INFO:diceplayer:pop = chelpg', "INFO:diceplayer:pop = chelpg",
'INFO:diceplayer:qmprog = g16', "INFO:diceplayer:qmprog = g16",
'INFO:diceplayer:\n' "INFO:diceplayer:\n",
] ]
self.assertEqual(cm.output, expected_output) self.assertEqual(cm.output, expected_output)
@@ -99,12 +97,18 @@ class TestPlayer(unittest.TestCase):
molecule_type=0, molecule_type=0,
molecule_site=0, molecule_site=0,
atom_dict={ atom_dict={
"lbl": 0, "na": 1, "rx": 1.0, "ry": 1.0, "rz": 1.0, "chg": 1.0, "eps": 1.0 "lbl": 0,
} "na": 1,
"rx": 1.0,
"ry": 1.0,
"rz": 1.0,
"chg": 1.0,
"eps": 1.0,
},
) )
self.assertEqual( self.assertEqual(
str(context.exception), str(context.exception),
"Invalid number of fields for site 1 for molecule type 1." "Invalid number of fields for site 1 for molecule type 1.",
) )
with self.assertRaises(ValueError) as context: with self.assertRaises(ValueError) as context:
@@ -112,12 +116,18 @@ class TestPlayer(unittest.TestCase):
molecule_type=0, molecule_type=0,
molecule_site=0, molecule_site=0,
atom_dict={ atom_dict={
"lbl": '', "na": 1, "rx": 1.0, "ry": 1.0, "rz": 1.0, "chg": 1.0, "eps": 1.0, "sig": 1.0 "lbl": "",
} "na": 1,
"rx": 1.0,
"ry": 1.0,
"rz": 1.0,
"chg": 1.0,
"eps": 1.0,
"sig": 1.0,
},
) )
self.assertEqual( self.assertEqual(
str(context.exception), str(context.exception), "Invalid lbl fields for site 1 for molecule type 1."
"Invalid lbl fields for site 1 for molecule type 1."
) )
with self.assertRaises(ValueError) as context: with self.assertRaises(ValueError) as context:
@@ -125,12 +135,18 @@ class TestPlayer(unittest.TestCase):
molecule_type=0, molecule_type=0,
molecule_site=0, molecule_site=0,
atom_dict={ atom_dict={
"lbl": 1.0, "na": '', "rx": 1.0, "ry": 1.0, "rz": 1.0, "chg": 1.0, "eps": 1.0, "sig": 1.0 "lbl": 1.0,
} "na": "",
"rx": 1.0,
"ry": 1.0,
"rz": 1.0,
"chg": 1.0,
"eps": 1.0,
"sig": 1.0,
},
) )
self.assertEqual( self.assertEqual(
str(context.exception), str(context.exception), "Invalid na fields for site 1 for molecule type 1."
"Invalid na fields for site 1 for molecule type 1."
) )
with self.assertRaises(ValueError) as context: with self.assertRaises(ValueError) as context:
@@ -138,12 +154,19 @@ class TestPlayer(unittest.TestCase):
molecule_type=0, molecule_type=0,
molecule_site=0, molecule_site=0,
atom_dict={ atom_dict={
"lbl": 1.0, "na": 1, "rx": '', "ry": 1.0, "rz": 1.0, "chg": 1.0, "eps": 1.0, "sig": 1.0 "lbl": 1.0,
} "na": 1,
"rx": "",
"ry": 1.0,
"rz": 1.0,
"chg": 1.0,
"eps": 1.0,
"sig": 1.0,
},
) )
self.assertEqual( self.assertEqual(
str(context.exception), str(context.exception),
"Invalid rx fields for site 1 for molecule type 1. Value must be a float." "Invalid rx fields for site 1 for molecule type 1. Value must be a float.",
) )
with self.assertRaises(ValueError) as context: with self.assertRaises(ValueError) as context:
@@ -151,12 +174,19 @@ class TestPlayer(unittest.TestCase):
molecule_type=0, molecule_type=0,
molecule_site=0, molecule_site=0,
atom_dict={ atom_dict={
"lbl": 1.0, "na": 1, "rx": 1.0, "ry": '', "rz": 1.0, "chg": 1.0, "eps": 1.0, "sig": 1.0 "lbl": 1.0,
} "na": 1,
"rx": 1.0,
"ry": "",
"rz": 1.0,
"chg": 1.0,
"eps": 1.0,
"sig": 1.0,
},
) )
self.assertEqual( self.assertEqual(
str(context.exception), str(context.exception),
"Invalid ry fields for site 1 for molecule type 1. Value must be a float." "Invalid ry fields for site 1 for molecule type 1. Value must be a float.",
) )
with self.assertRaises(ValueError) as context: with self.assertRaises(ValueError) as context:
@@ -164,12 +194,19 @@ class TestPlayer(unittest.TestCase):
molecule_type=0, molecule_type=0,
molecule_site=0, molecule_site=0,
atom_dict={ atom_dict={
"lbl": 1.0, "na": 1, "rx": 1.0, "ry": 1.0, "rz": '', "chg": 1.0, "eps": 1.0, "sig": 1.0 "lbl": 1.0,
} "na": 1,
"rx": 1.0,
"ry": 1.0,
"rz": "",
"chg": 1.0,
"eps": 1.0,
"sig": 1.0,
},
) )
self.assertEqual( self.assertEqual(
str(context.exception), str(context.exception),
"Invalid rz fields for site 1 for molecule type 1. Value must be a float." "Invalid rz fields for site 1 for molecule type 1. Value must be a float.",
) )
with self.assertRaises(ValueError) as context: with self.assertRaises(ValueError) as context:
@@ -177,12 +214,19 @@ class TestPlayer(unittest.TestCase):
molecule_type=0, molecule_type=0,
molecule_site=0, molecule_site=0,
atom_dict={ atom_dict={
"lbl": 1.0, "na": 1, "rx": 1.0, "ry": 1.0, "rz": 1.0, "chg": '', "eps": 1.0, "sig": 1.0 "lbl": 1.0,
} "na": 1,
"rx": 1.0,
"ry": 1.0,
"rz": 1.0,
"chg": "",
"eps": 1.0,
"sig": 1.0,
},
) )
self.assertEqual( self.assertEqual(
str(context.exception), str(context.exception),
"Invalid chg fields for site 1 for molecule type 1. Value must be a float." "Invalid chg fields for site 1 for molecule type 1. Value must be a float.",
) )
with self.assertRaises(ValueError) as context: with self.assertRaises(ValueError) as context:
@@ -190,12 +234,19 @@ class TestPlayer(unittest.TestCase):
molecule_type=0, molecule_type=0,
molecule_site=0, molecule_site=0,
atom_dict={ atom_dict={
"lbl": 1.0, "na": 1, "rx": 1.0, "ry": 1.0, "rz": 1.0, "chg": 1.0, "eps": '', "sig": 1.0 "lbl": 1.0,
} "na": 1,
"rx": 1.0,
"ry": 1.0,
"rz": 1.0,
"chg": 1.0,
"eps": "",
"sig": 1.0,
},
) )
self.assertEqual( self.assertEqual(
str(context.exception), str(context.exception),
"Invalid eps fields for site 1 for molecule type 1. Value must be a float." "Invalid eps fields for site 1 for molecule type 1. Value must be a float.",
) )
with self.assertRaises(ValueError) as context: with self.assertRaises(ValueError) as context:
@@ -203,12 +254,19 @@ class TestPlayer(unittest.TestCase):
molecule_type=0, molecule_type=0,
molecule_site=0, molecule_site=0,
atom_dict={ atom_dict={
"lbl": 1.0, "na": 1, "rx": 1.0, "ry": 1.0, "rz": 1.0, "chg": 1.0, "eps": 1.0, "sig": '' "lbl": 1.0,
} "na": 1,
"rx": 1.0,
"ry": 1.0,
"rz": 1.0,
"chg": 1.0,
"eps": 1.0,
"sig": "",
},
) )
self.assertEqual( self.assertEqual(
str(context.exception), str(context.exception),
"Invalid sig fields for site 1 for molecule type 1. Value must be a float." "Invalid sig fields for site 1 for molecule type 1. Value must be a float.",
) )
@mock.patch("builtins.open", mock_open) @mock.patch("builtins.open", mock_open)
@@ -234,10 +292,7 @@ class TestPlayer(unittest.TestCase):
with self.assertRaises(RuntimeError) as context: with self.assertRaises(RuntimeError) as context:
player.read_potentials() player.read_potentials()
self.assertEqual( self.assertEqual(str(context.exception), "Potential file phb.ljc not found.")
str(context.exception),
"Potential file phb.ljc not found."
)
# Enabling file found for next tests # Enabling file found for next tests
mock_path_exists.return_value = True mock_path_exists.return_value = True
@@ -249,7 +304,7 @@ class TestPlayer(unittest.TestCase):
self.assertEqual( self.assertEqual(
str(context.exception), str(context.exception),
"Error: expected a '*' or a '+' sign in 1st line of file phb.error.combrule.ljc" "Error: expected a '*' or a '+' sign in 1st line of file phb.error.combrule.ljc",
) )
# Testing ntypes error # Testing ntypes error
@@ -259,7 +314,7 @@ class TestPlayer(unittest.TestCase):
self.assertEqual( self.assertEqual(
str(context.exception), str(context.exception),
"Error: expected an integer in the 2nd line of file phb.error.ntypes.ljc" "Error: expected an integer in the 2nd line of file phb.error.ntypes.ljc",
) )
# Testing ntypes error on config # Testing ntypes error on config
@@ -270,7 +325,7 @@ class TestPlayer(unittest.TestCase):
self.assertEqual( self.assertEqual(
str(context.exception), str(context.exception),
"Error: number of molecule types in file phb.error.ntypes.config.ljc " "Error: number of molecule types in file phb.error.ntypes.config.ljc "
"must match that of 'nmol' keyword in config file" "must match that of 'nmol' keyword in config file",
) )
# Testing nsite error # Testing nsite error
@@ -280,7 +335,7 @@ class TestPlayer(unittest.TestCase):
self.assertEqual( self.assertEqual(
str(context.exception), str(context.exception),
"Error: expected nsites to be an integer for molecule type 1" "Error: expected nsites to be an integer for molecule type 1",
) )
# Testing molname error # Testing molname error
@@ -290,7 +345,7 @@ class TestPlayer(unittest.TestCase):
self.assertEqual( self.assertEqual(
str(context.exception), str(context.exception),
"Error: expected nsites and molname for the molecule type 1" "Error: expected nsites and molname for the molecule type 1",
) )
@mock.patch("builtins.open", mock_open) @mock.patch("builtins.open", mock_open)
@@ -299,31 +354,28 @@ class TestPlayer(unittest.TestCase):
player = Player("control.test.yml") player = Player("control.test.yml")
player.read_potentials() player.read_potentials()
with self.assertLogs(level='INFO') as context: with self.assertLogs(level="INFO") as context:
player.print_potentials() player.print_potentials()
expected_output = [ expected_output = [
'INFO:diceplayer:==========================================================================================\n Potential parameters from file phb.ljc:\n------------------------------------------------------------------------------------------\n', "INFO:diceplayer:==========================================================================================\n Potential parameters from file phb.ljc:\n------------------------------------------------------------------------------------------\n",
'INFO:diceplayer:Combination rule: *', "INFO:diceplayer:Combination rule: *",
'INFO:diceplayer:Types of molecules: 2\n', "INFO:diceplayer:Types of molecules: 2\n",
'INFO:diceplayer:1 atoms in molecule type 1:', "INFO:diceplayer:1 atoms in molecule type 1:",
'INFO:diceplayer:---------------------------------------------------------------------------------', "INFO:diceplayer:---------------------------------------------------------------------------------",
'INFO:diceplayer:Lbl AN X Y Z Charge Epsilon Sigma Mass', "INFO:diceplayer:Lbl AN X Y Z Charge Epsilon Sigma Mass",
'INFO:diceplayer:---------------------------------------------------------------------------------', "INFO:diceplayer:---------------------------------------------------------------------------------",
'INFO:diceplayer:1 1 0.00000 0.00000 0.00000 0.000000 0.00000 0.0000 1.0079', "INFO:diceplayer:1 1 0.00000 0.00000 0.00000 0.000000 0.00000 0.0000 1.0079",
'INFO:diceplayer:\n', "INFO:diceplayer:\n",
'INFO:diceplayer:1 atoms in molecule type 2:', "INFO:diceplayer:1 atoms in molecule type 2:",
'INFO:diceplayer:---------------------------------------------------------------------------------', "INFO:diceplayer:---------------------------------------------------------------------------------",
'INFO:diceplayer:Lbl AN X Y Z Charge Epsilon Sigma Mass', "INFO:diceplayer:Lbl AN X Y Z Charge Epsilon Sigma Mass",
'INFO:diceplayer:---------------------------------------------------------------------------------', "INFO:diceplayer:---------------------------------------------------------------------------------",
'INFO:diceplayer:1 1 0.00000 0.00000 0.00000 0.000000 0.00000 0.0000 1.0079', "INFO:diceplayer:1 1 0.00000 0.00000 0.00000 0.000000 0.00000 0.0000 1.0079",
'INFO:diceplayer:\n' "INFO:diceplayer:\n",
] ]
self.assertEqual( self.assertEqual(context.output, expected_output)
context.output,
expected_output
)
@mock.patch("builtins.open", mock_open) @mock.patch("builtins.open", mock_open)
def test_dice_start(self): def test_dice_start(self):
@@ -336,5 +388,5 @@ class TestPlayer(unittest.TestCase):
player.dice_interface.start.assert_called_once() player.dice_interface.start.assert_called_once()
if __name__ == '__main__': if __name__ == "__main__":
unittest.main() unittest.main()