diff --git a/pycgtool/bondset.py b/pycgtool/bondset.py index 11f0dc706bc420707672c7e6f1995db41935a376..a6f6f7b3e207472c75f166108e6b9f097506a597 100644 --- a/pycgtool/bondset.py +++ b/pycgtool/bondset.py @@ -345,30 +345,29 @@ class BondSet: bond.boltzmann_invert(temp=self._temperature, angle_default_fc=self._angle_default_fc) - def dump_values(self, target_number=100000): + def dump_values(self, target_number=10000): """ Output measured bond values to files for length, angles and dihedrals. :param target_number: Approx number of sample measurements to output. If None, all samples will be output """ + def write_bonds_to_file(bonds, filename): + with open(filename, "w") as f: + for row in transpose_and_sample((bond.values for bond in bonds), n=target_number): + print((len(row) * "{:12.5f}").format(*row), file=f) + for mol in self._molecules: if mol == "SOL": continue - with open("{0}_length.dat".format(mol), "w") as f: - bonds = self.get_bond_lengths(mol, with_constr=True) - for row in transpose_and_sample((bond.values for bond in bonds), n=target_number): - print((len(row) * "{:12.5f}").format(*row), file=f) + bonds = self.get_bond_lengths(mol, with_constr=True) + write_bonds_to_file(bonds, "{0}_length.dat".format(mol)) - with open("{0}_angle.dat".format(mol), "w") as f: - bonds = self.get_bond_angles(mol) - for row in transpose_and_sample((bond.values for bond in bonds), n=target_number): - print((len(row) * "{:12.5f}").format(*row), file=f) + bonds = self.get_bond_angles(mol) + write_bonds_to_file(bonds, "{0}_angle.dat".format(mol)) - with open("{0}_dihedral.dat".format(mol), "w") as f: - bonds = self.get_bond_dihedrals(mol) - for row in transpose_and_sample((bond.values for bond in bonds), n=target_number): - print((len(row) * "{:12.5f}").format(*row), file=f) + bonds = self.get_bond_dihedrals(mol) + write_bonds_to_file(bonds, "{0}_dihedral.dat".format(mol)) def __len__(self): return len(self._molecules) diff --git a/pycgtool/util.py b/pycgtool/util.py index c1acccebe21afccd9204a1d0249c66effa0c250e..3624529ed710121cfa14c217212b1570c80812e6 100644 --- a/pycgtool/util.py +++ b/pycgtool/util.py @@ -6,6 +6,7 @@ import os import itertools import random import math +import filecmp import numpy as np np.seterr(all="raise") @@ -307,3 +308,47 @@ def gaussian(xs, mean=0, sdev=1, amplitude=1): top_bit = (x - mean) * (x - mean) / (2 * sdev * sdev) return prefactor * np.exp(-top_bit) return map(gaussian_single, xs) + + +def cmp_whitespace_float(ref_filename, test_filename, float_rel_error=0.01): + """ + Compare two files ignoring spacing on a line and using a tolerance on floats + + :param ref_filename: Name of reference file + :param test_filename: Name of test file + :param float_rel_error: Acceptable relative error on floating point numbers + :return: True if files are the same, else False + """ + def float_or_string(string): + try: + int(string) + return string + except ValueError: + try: + return float(string) + except ValueError: + return string + + if filecmp.cmp(ref_filename, test_filename): + return True + with open(ref_filename) as ref_file, open(test_filename) as test_file: + for ref_line, test_line in itertools.zip_longest(ref_file, test_file): + if ref_line is None or test_line is None: + return False + if ref_line == test_line: + continue + + ref_toks = ref_line.split() + test_toks = test_line.split() + if len(ref_toks) != len(test_toks): + return False + for ref_tok, test_tok in zip(map(float_or_string, ref_toks), + map(float_or_string, test_toks)): + if ref_tok != test_tok: + if float == type(ref_tok) and float == type(test_tok): + if abs(ref_tok - test_tok) > ref_tok * float_rel_error: + return False + else: + return False + return True + diff --git a/test/test_bondset.py b/test/test_bondset.py index 5028dc810c13f64c326ca95ec9733c0ec052cc97..14f7ce22bdd2383a026df25a7f61983e0dc5867e 100644 --- a/test/test_bondset.py +++ b/test/test_bondset.py @@ -1,9 +1,9 @@ import unittest -import filecmp from pycgtool.bondset import BondSet from pycgtool.frame import Frame from pycgtool.mapping import Mapping +from pycgtool.util import cmp_whitespace_float class DummyOptions: @@ -118,4 +118,4 @@ class BondSetTest(unittest.TestCase): measure.boltzmann_invert() measure.write_itp("sugar_out.itp", mapping, exclude={"SOL"}) - self.assertTrue(filecmp.cmp("sugar_out.itp", "test/data/sugar_out.itp")) + self.assertTrue(cmp_whitespace_float("sugar_out.itp", "test/data/sugar_out.itp", float_rel_error=0.001))