Source code for apdft.settings

#!/usr/bin/env python
""" Manages settings and config file parsing."""
import enum
import configparser
import basis_set_exchange as bse


[docs]class CodeEnum(enum.Enum): MRCC = "MRCC" G09 = "G09" PYSCF = "PYSCF" PSI4 = "PSI4" def __str__(self): return self.value
[docs] def get_calculator_class(self): if self.value == CodeEnum.MRCC.value: from apdft.calculator.mrcc import MrccCalculator return MrccCalculator if self.value == CodeEnum.G09.value: from apdft.calculator.gaussian import GaussianCalculator return GaussianCalculator if self.value == CodeEnum.PYSCF.value: from apdft.calculator.pyscf import PyscfCalculator return PyscfCalculator if self.value == CodeEnum.PSI4.value: from apdft.calculator.psi4 import Psi4Calculator return Psi4Calculator
[docs]def intelementrange(val): if val is None: return val if type(val) == list: return val ret = [] for part in val.split(","): if "-" in part: subparts = part.split("-") ret += list(range(int(subparts[0]), int(subparts[1]) + 1)) continue try: ret.append(int(part)) except ValueError: bse.lut.element_Z_from_sym(part) ret.append(part) return ret
[docs]def boolean(val): if val == "True": return True if val == "False": return False return bool(val)
[docs]class Option: """ Represents a single configuration option. """ def __init__(self, category, name, validator, default, description): self._category = category self._name = name self._description = description self._validator = validator self._value = self._validator(default)
[docs] def get_attribute_name(self): return "%s_%s" % (self._category, self._name)
[docs] def get_value(self): return self._value
[docs] def get_validator(self): return self._validator
[docs] def get_description(self): return self._description
[docs] def set_value(self, value): self._value = self._validator(value)
[docs]class Configuration: """ A complete set of configuration values. Merges settings and default values. Settings are referred to as category.variablename. """ def __init__(self): options = [ # Section apdft: relevant for all invocations Option( "apdft", "maxdz", int, 3, "Restricts target molecules to have at most this change in nuclear charge per atom", ), Option("apdft", "maxorder", int, 2, "Maximum alchemical expansion order"), Option( "apdft", "maxcharge", int, 0, "Restricts target molecules to have at most this total molecular charge", ), Option("apdft", "basisset", str, "def2-TZVP", "The basis set to be used"), Option("apdft", "method", str, "CCSD", "Method to be used"), Option( "apdft", "includeonly", intelementrange, None, "Include only these atom indices, e.g. 0,1,5,7 or these atom types, e.g. B,C,N. You can mix both.", ), Option( "debug", "validation", boolean, False, "Whether to perform validation calculations for all target molecules", ), Option( "debug", "superimpose", boolean, False, "Whether to superimpose atomic basis set functions from neighboring elements for fractional nuclear charges", ), Option("energy", "code", CodeEnum, "MRCC", "QM code to be used"), Option( "energy", "dryrun", boolean, False, "Whether to just estimate the number of targets", ), Option( "energy", "geometry", str, "inp.xyz", "XYZ file of the reference molecule", ), Option( "apdft", "targets", str, "", "List of targets to be evaluated (one target per line, comma separated nuclear charges).", ), ] self.__dict__["_options"] = {} for option in options: self.__dict__["_options"][option.get_attribute_name()] = option def __getattr__(self, attribute): """ Read access to configuration options.""" return self.__dict__["_options"][attribute].get_value() def __setattr__(self, attribute, value): """ Write access to configuration options.""" self.__dict__["_options"][attribute].set_value(value) def __getitem__(self, attribute): return self.__dict__["_options"][attribute]
[docs] def list_options(self, section=None): """ Gives all configurable options for a given section.""" options = [_ for _ in self.__dict__["_options"].keys()] if section is not None: options = [_ for _ in options if _.startswith("%s_" % section)] return options
[docs] def list_sections(self): """ Returns a list of all sections.""" return list(set([_.split("_")[0] for _ in self.__dict__["_options"].keys()]))
[docs] def from_file(self): config = configparser.ConfigParser() config.read("apdft.conf") for section in config.sections(): for option in config[section]: val = config[section][option] if val == "None": val = None self[option].set_value(val)
[docs] def to_file(self): config = configparser.ConfigParser() for section in sorted(self.list_sections()): vals = dict() for option in self.list_options(section): try: vals[option] = self[option].get_value().name except AttributeError: if type(self[option].get_value()) == list: vals[option] = ",".join( [str(_) for _ in self[option].get_value()] ) else: vals[option] = str(self[option].get_value()) config[section] = vals with open("apdft.conf", "w") as configfile: config.write(configfile)