Skip to content
Snippets Groups Projects
Commit 7cddfda4 authored by James Graham's avatar James Graham
Browse files

Give all measured values to FunctionalForm

- no longer limited to using mean, var
parent 8a46225a
No related branches found
No related tags found
No related merge requests found
...@@ -63,22 +63,21 @@ class Bond: ...@@ -63,22 +63,21 @@ class Bond:
if not self.values: if not self.values:
raise ValueError("No bonds were measured between atoms {0}".format(self.atoms)) raise ValueError("No bonds were measured between atoms {0}".format(self.atoms))
mean, var = stat_moments(self.values) values = np.array(self.values)
if len(self.atoms) > 2: if len(self.atoms) > 2:
mean_tmp = math.radians(mean) values = np.radians(values)
var *= (math.pi * math.pi) / (180. * 180.)
else:
mean_tmp = mean
self.eqm = mean
with np.errstate(divide="raise"): with np.errstate(divide="raise"):
self.eqm = self._func_form.eqm(values, temp)
try: try:
self.fconst = self._func_form(mean_tmp, var, temp) self.fconst = self._func_form.fconst(values, temp)
except FloatingPointError: except FloatingPointError:
# Happens when variance is 0, i.e. we only have one value # Happens when variance is 0, i.e. we only have one value
self.fconst = float("inf") self.fconst = float("inf")
if len(self.atoms) > 2:
self.eqm = math.degrees(self.eqm)
def __repr__(self): def __repr__(self):
try: try:
return "<Bond containing atoms {0} with r_0 {1:.3f} and force constant {2:.3e}>".format( return "<Bond containing atoms {0} with r_0 {1:.3f} and force constant {2:.3e}>".format(
......
import abc import abc
import math import math
import numpy as np
from pycgtool.util import SimpleEnum from pycgtool.util import SimpleEnum
...@@ -53,15 +55,26 @@ class FunctionalForm(object, metaclass=abc.ABCMeta): ...@@ -53,15 +55,26 @@ class FunctionalForm(object, metaclass=abc.ABCMeta):
New functional forms must define a static __call__ method. New functional forms must define a static __call__ method.
""" """
@staticmethod
def eqm(values, temp):
"""
Calculate equilibrium value.
May be overridden by functional forms.
:param values: Measured internal coordinate values from which to calculate equilibrium value
:param temp: Temperature of simulation
:return: Calculated equilibrium value
"""
return np.nanmean(values)
@staticmethod @staticmethod
@abc.abstractstaticmethod @abc.abstractstaticmethod
def __call__(mean, var, temp): def fconst(values, temp):
""" """
Calculate force constant. Calculate force constant.
Abstract static method to be defined by all functional forms. Abstract static method to be defined by all functional forms.
:param mean: Mean of internal coordinate distribution :param values: Measured internal coordinate values from which to calculate force constant
:param var: Variance of internal coordinate distribution
:param temp: Temperature of simulation :param temp: Temperature of simulation
:return: Calculated force constant :return: Calculated force constant
""" """
...@@ -70,31 +83,34 @@ class FunctionalForm(object, metaclass=abc.ABCMeta): ...@@ -70,31 +83,34 @@ class FunctionalForm(object, metaclass=abc.ABCMeta):
class Harmonic(FunctionalForm): class Harmonic(FunctionalForm):
@staticmethod @staticmethod
def __call__(mean, var, temp): def fconst(values, temp):
rt = 8.314 * temp / 1000. rt = 8.314 * temp / 1000.
var = np.nanvar(values)
return rt / var return rt / var
class CosHarmonic(FunctionalForm): class CosHarmonic(FunctionalForm):
@staticmethod @staticmethod
def __call__(mean, var, temp): def fconst(values, temp):
rt = 8.314 * temp / 1000. rt = 8.314 * temp / 1000.
mean = CosHarmonic.eqm(values, temp)
var = np.nanvar(values)
return rt / (math.sin(mean)**2 * var) return rt / (math.sin(mean)**2 * var)
class MartiniDefaultLength(FunctionalForm): class MartiniDefaultLength(FunctionalForm):
@staticmethod @staticmethod
def __call__(mean, var, temp): def fconst(values, temp):
return 1250. return 1250.
class MartiniDefaultAngle(FunctionalForm): class MartiniDefaultAngle(FunctionalForm):
@staticmethod @staticmethod
def __call__(mean, var, temp): def fconst(values, temp):
return 25. return 25.
class MartiniDefaultDihedral(FunctionalForm): class MartiniDefaultDihedral(FunctionalForm):
@staticmethod @staticmethod
def __call__(mean, var, temp): def fconst(values, temp):
return 50. return 50.
...@@ -14,12 +14,17 @@ class FunctionalFormTest(unittest.TestCase): ...@@ -14,12 +14,17 @@ class FunctionalFormTest(unittest.TestCase):
def test_functional_form_new(self): def test_functional_form_new(self):
class TestFunc(FunctionalForm): class TestFunc(FunctionalForm):
@staticmethod @staticmethod
def __call__(mean, var, temp): def eqm(values, temp):
return "TestResult" return "TestResultEqm"
@staticmethod
def fconst(values, temp):
return "TestResultFconst"
funcs = FunctionalForms() funcs = FunctionalForms()
self.assertIn("TestFunc", funcs) self.assertIn("TestFunc", funcs)
self.assertEqual("TestResult", funcs.TestFunc(None, None, None)) self.assertEqual("TestResultEqm", funcs.TestFunc.eqm(None, None))
self.assertEqual("TestResultFconst", funcs.TestFunc.fconst(None, None))
if __name__ == '__main__': if __name__ == '__main__':
unittest.main() unittest.main()
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment