Source code for pygromos.files.qmmm.qmmm

from copy import deepcopy
import warnings

from pygromos.files._basics import _general_gromos_file, parser
from pygromos.files.blocks import qmmm_blocks as blocks
from pygromos.utils.typing import List


[docs]class QMMM(_general_gromos_file._general_gromos_file): _gromos_file_ending: str = "qmmm" _orig_file_path: str path: str _required_blocks = [ "TITLE", "QMZONE", "QMUNIT", ] # Not yet implemented; taken from "class Imd", other blocks are e.g. "XTBELEMENTS" and "ORCAELEMENTS" # POSSIBLE GROMOS BLOCKS TITLE: blocks.TITLE QMZONE: blocks.QMZONE QMUNIT: blocks.QMUNIT # One of those blocks should be available # Consult the Gromos documentation for more details # Also consult the corresponding QMMM block in imd files MNDOELEMENTS: blocks.MNDOELEMENTS TURBOMOLEELEMENTS: blocks.TURBOMOLEELEMENTS DFTBELEMENTS: blocks.DFTBELEMENTS MOPACELEMENTS: blocks.MOPACELEMENTS ORCAELEMENTS: blocks.ORCAELEMENTS XTBELEMENTS: blocks.XTBELEMENTS def __init__(self, in_value: str, _future_file: bool = False): super().__init__(in_value=in_value, _future_file=_future_file) # TODO: maybe somebody can make a better solution for this. This is a ugly fix to unify the structure of the blocks for block in sorted(self.get_block_names()): setattr(self, block, deepcopy(getattr(self, block))) # Perform some sanity checks # only if not a future file and if there is at least one block # (to avoid being run while deep_copy) if not _future_file and len(self.get_block_names()) > 0: self._health_check() def __str__(self): text = "" if hasattr(self, "TITLE"): text += self.__getattribute__("TITLE").block_to_string() for block in sorted(self.get_block_names()): if block == "TITLE" or isinstance(block, type(None)): continue text += str(self.__getattribute__(block)) return text
[docs] def read_file(self): # Read blocks to string data = parser.read_general_gromos_file(self._orig_file_path) # translate the string subblocks blocks = {} for block_title in data: self.add_block(blocktitle=block_title, content=data[block_title]) blocks.update({block_title: self.__getattribute__(block_title)}) return blocks
[docs] def get_qm_engines(self) -> List[str]: """ Returns the QM engine used Returns ------- List[str] A list of strings (in case the user wanted for some reason specify more than one engine) """ engine = [element.replace("ELEMENTS", "") for element in self.get_block_names() if element.endswith("ELEMENTS")] return engine
[docs] def _health_check(self): """ Runs tests on the integrity of the file and spits out warnings members = [attr for attr in dir(self) if not callable(getattr(self, attr)) and attr.endswith("ELEMENTS")] """ members = [element for element in self.get_block_names() if element.endswith("ELEMENTS")] if len(members) > 1: warnings.warn( "Declaration of more than one (QMENGINE)ELEMENTS blocks in QM/MM specification file detected: " + ", ".join(members) ) elif len(members) < 1: warnings.warn("No (QMENGINE)ELEMENTS block in QM/MM specification file detected.")