Source code for qcdb.psiutil

#
#@BEGIN LICENSE
#
# PSI4: an ab initio quantum chemistry software package
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
#
#@END LICENSE
#

r"""Stuff stolen from psi. Should import or not as necessary
or some better way. Apologies to the coders.

"""
from __future__ import absolute_import
from __future__ import print_function
import sys
import math
import re
import os
import string
from .vecutil import *


def _success(label):
    """Function to print a '*label*...PASSED' line to screen.
    Used by :py:func:`util.compare_values` family when functions pass.

    """
    print('\t{0:.<66}PASSED'.format(label))
    sys.stdout.flush()


[docs]def compare_values(expected, computed, digits, label, exitonfail=True): """Function to compare two values. Prints :py:func:`util.success` when value *computed* matches value *expected* to number of *digits* (or to *digits* itself when *digits* > 1 e.g. digits=0.04). Performs a system exit on failure unless *exitonfail* False, in which case returns error message. Used in input files in the test suite. """ thresh = 10 ** -digits if digits > 1 else digits if abs(expected - computed) > thresh: print("\t%s: computed value (%f) does not match (%f) to %f digits." % (label, computed, expected, digits)) if exitonfail: sys.exit(1) else: return if math.isnan(computed): print("\t%s: computed value (%f) does not match (%f)\n" % (label, computed, expected)) print("\tprobably because the computed value is nan.") if exitonfail: sys.exit(1) else: return _success(label)
[docs]def compare_integers(expected, computed, label): """Function to compare two integers. Prints :py:func:`util.success` when value *computed* matches value *expected*. Performs a system exit on failure. Used in input files in the test suite. """ if (expected != computed): print("\t%s: computed value (%d) does not match (%d)." % (label, computed, expected)) sys.exit(1) _success(label)
[docs]def compare_strings(expected, computed, label): """Function to compare two strings. Prints :py:func:`util.success` when string *computed* exactly matches string *expected*. Performs a system exit on failure. Used in input files in the test suite. """ if(expected != computed): print("\t%s: computed value (%s) does not match (%s)." % (label, computed, expected)) sys.exit(1) _success(label)
[docs]def compare_matrices(expected, computed, digits, label): """Function to compare two matrices. Prints :py:func:`util.success` when elements of matrix *computed* match elements of matrix *expected* to number of *digits*. Performs a system exit on failure to match symmetry structure, dimensions, or element values. Used in input files in the test suite. """ rows = len(expected) cols = len(expected[0]) failed = 0 for row in range(rows): for col in range(cols): if abs(expected[row][col] - computed[row][col]) > 10 ** (-digits): print("\t%s: computed value (%s) does not match (%s)." % (label, expected[row][col], computed[row][col])) failed = 1 break if failed: print("The Failed Test Matrices\n") show(computed) print('\n') show(expected) sys.exit(1) _success(label)
[docs]def query_yes_no(question, default=True): """Ask a yes/no question via raw_input() and return their answer. *question* is a string that is presented to the user. *default* is the presumed answer if the user just hits <Enter>. It must be yes (the default), no or None (meaning an answer is required of the user). The return value is one of True or False. """ yes = re.compile(r'^(y|yes|true|on|1)', re.IGNORECASE) no = re.compile(r'^(n|no|false|off|0)', re.IGNORECASE) if default == None: prompt = " [y/n] " elif default == True: prompt = " [Y/n] " elif default == False: prompt = " [y/N] " else: raise ValueError("invalid default answer: '%s'" % default) while True: sys.stdout.write(question + prompt) choice = raw_input().strip().lower() if default is not None and choice == '': return default elif yes.match(choice): return True elif no.match(choice): return False else: sys.stdout.write(" Please respond with 'yes' or 'no'.\n")
## {{{ http://code.activestate.com/recipes/52224/ (r1)
[docs]def search_file(filename, search_path): """Given an os.pathsep divided *search_path*, find first occurance of *filename*. Returns full path to file if found or None if unfound. """ file_found = False paths = string.split(search_path, os.pathsep) for path in paths: if os.path.exists(os.path.join(path, filename)): file_found = True break if file_found: return os.path.abspath(os.path.join(path, filename)) else: return None
## end of http://code.activestate.com/recipes/52224/ }}}
[docs]def drop_duplicates(seq): """Function that given an array *seq*, returns an array without any duplicate entries. There is no guarantee of which duplicate entry is dropped. """ #noDupes = [] #[noDupes.append(i) for i in seq if not noDupes.count(i)] #return noDupes noDupes = [] seq2 = sum(seq, []) [noDupes.append(i) for i in seq2 if not noDupes.count(i)] return noDupes
[docs]def all_casings(input_string): """Function to return a generator of all lettercase permutations of *input_string*. """ if not input_string: yield '' else: first = input_string[:1] if first.lower() == first.upper(): for sub_casing in all_casings(input_string[1:]): yield first + sub_casing else: for sub_casing in all_casings(input_string[1:]): yield first.lower() + sub_casing yield first.upper() + sub_casing
[docs]def getattr_ignorecase(module, attr): """Function to extract attribute *attr* from *module* if *attr* is available in any possible lettercase permutation. Returns attribute if available, None if not. """ array = None for per in list(all_casings(attr)): try: getattr(module, per) except AttributeError: pass else: array = getattr(module, per) break return array
[docs]def import_ignorecase(module): """Function to import *module* in any possible lettercase permutation. Returns module object if available, None if not. """ modobj = None for per in list(all_casings(module)): try: modobj = __import__(per) except ImportError: pass else: break return modobj
[docs]def findfile_ignorecase(fil, pre='', post=''): """Function to locate a file *pre* + *fil* + *post* in any possible lettercase permutation of *fil*. Returns *pre* + *fil* + *post* if available, None if not. """ afil = None for per in list(all_casings(fil)): if os.path.isfile(pre + per + post): afil = pre + per + post break else: pass return afil