Commit a1a61127 authored by peastman's avatar peastman
Browse files

Merge pull request #1031 from rmcgibbo/units2

MAINT: Nicer swig wrappers
parents 6c82c11b b0baa00d
...@@ -163,7 +163,6 @@ set(SWIG_INPUT_FILES2 ...@@ -163,7 +163,6 @@ set(SWIG_INPUT_FILES2
"${SWIG_OPENMM_DIR}/swig_lib/python/header.i" "${SWIG_OPENMM_DIR}/swig_lib/python/header.i"
"${SWIG_OPENMM_DIR}/swig_lib/python/pythoncode.i" "${SWIG_OPENMM_DIR}/swig_lib/python/pythoncode.i"
"${SWIG_OPENMM_DIR}/swig_lib/python/typemaps.i" "${SWIG_OPENMM_DIR}/swig_lib/python/typemaps.i"
"${SWIG_OPENMM_DIR}/swig_lib/python/pythonprepend_all.i"
) )
# Create input files for swig # Create input files for swig
...@@ -176,6 +175,7 @@ add_custom_command( ...@@ -176,6 +175,7 @@ add_custom_command(
-o OpenMMSwigHeaders.i -o OpenMMSwigHeaders.i
-a swig_lib/python/pythonprepend.i -a swig_lib/python/pythonprepend.i
-z swig_lib/python/pythonappend.i -z swig_lib/python/pythonappend.i
-v "${SWIG_VERSION}"
WORKING_DIRECTORY "${SWIG_OPENMM_DIR}" WORKING_DIRECTORY "${SWIG_OPENMM_DIR}"
DEPENDS DEPENDS
"${SWIG_OPENMM_DIR}/swigInputConfig.py" "${SWIG_OPENMM_DIR}/swigInputConfig.py"
......
...@@ -123,17 +123,17 @@ class Element(object): ...@@ -123,17 +123,17 @@ class Element(object):
Element._elements_by_mass = OrderedDict() Element._elements_by_mass = OrderedDict()
for elem in sorted(Element._elements_by_symbol.values(), for elem in sorted(Element._elements_by_symbol.values(),
key=lambda x: x.mass): key=lambda x: x.mass):
Element._elements_by_mass[elem.mass] = elem Element._elements_by_mass[elem.mass.value_in_unit(daltons)] = elem
diff = mass diff = mass
best_guess = None best_guess = None
for elemmass, element in Element._elements_by_mass.iteritems(): for elemmass, element in Element._elements_by_mass.iteritems():
massdiff = abs(elemmass._value - mass) massdiff = abs(elemmass - mass)
if massdiff < diff: if massdiff < diff:
best_guess = element best_guess = element
diff = massdiff diff = massdiff
if elemmass._value > mass: if elemmass > mass:
# Elements are only getting heavier, so bail out early # Elements are only getting heavier, so bail out early
return best_guess return best_guess
......
...@@ -43,7 +43,9 @@ from simtk.openmm.app import Topology ...@@ -43,7 +43,9 @@ from simtk.openmm.app import Topology
def _convertParameterToNumber(param): def _convertParameterToNumber(param):
if unit.is_quantity(param): if unit.is_quantity(param):
return mm.stripUnits((param,))[0] if param.unit.is_compatible(unit.bar):
return param / unit.bar
return param.value_in_unit_system(unit.md_unit_system)
return float(param) return float(param)
# Enumerated values for nonbonded method # Enumerated values for nonbonded method
...@@ -3244,7 +3246,7 @@ class AmoebaVdwGenerator: ...@@ -3244,7 +3246,7 @@ class AmoebaVdwGenerator:
exclusionSet.add(i) exclusionSet.add(i)
force.setParticleExclusions(i, exclusionSet) force.setParticleExclusions(i, tuple(exclusionSet))
parsers["AmoebaVdwForce"] = AmoebaVdwGenerator.parseElement parsers["AmoebaVdwForce"] = AmoebaVdwGenerator.parseElement
...@@ -3896,12 +3898,12 @@ class AmoebaMultipoleGenerator: ...@@ -3896,12 +3898,12 @@ class AmoebaMultipoleGenerator:
newIndex = force.addMultipole(savedMultipoleDict['charge'], savedMultipoleDict['dipole'], savedMultipoleDict['quadrupole'], savedMultipoleDict['axisType'], newIndex = force.addMultipole(savedMultipoleDict['charge'], savedMultipoleDict['dipole'], savedMultipoleDict['quadrupole'], savedMultipoleDict['axisType'],
zaxis, xaxis, yaxis, savedMultipoleDict['thole'], savedMultipoleDict['pdamp'], savedMultipoleDict['polarizability']) zaxis, xaxis, yaxis, savedMultipoleDict['thole'], savedMultipoleDict['pdamp'], savedMultipoleDict['polarizability'])
if (atomIndex == newIndex): if (atomIndex == newIndex):
force.setCovalentMap(atomIndex, mm.AmoebaMultipoleForce.Covalent12, bonded12ParticleSets[atomIndex]) force.setCovalentMap(atomIndex, mm.AmoebaMultipoleForce.Covalent12, tuple(bonded12ParticleSets[atomIndex]))
force.setCovalentMap(atomIndex, mm.AmoebaMultipoleForce.Covalent13, bonded13ParticleSets[atomIndex]) force.setCovalentMap(atomIndex, mm.AmoebaMultipoleForce.Covalent13, tuple(bonded13ParticleSets[atomIndex]))
force.setCovalentMap(atomIndex, mm.AmoebaMultipoleForce.Covalent14, bonded14ParticleSets[atomIndex]) force.setCovalentMap(atomIndex, mm.AmoebaMultipoleForce.Covalent14, tuple(bonded14ParticleSets[atomIndex]))
force.setCovalentMap(atomIndex, mm.AmoebaMultipoleForce.Covalent15, bonded15ParticleSets[atomIndex]) force.setCovalentMap(atomIndex, mm.AmoebaMultipoleForce.Covalent15, tuple(bonded15ParticleSets[atomIndex]))
else: else:
raise ValueError("Atom %s of %s %d is out of synch!." %(atom.name, atom.residue.name, atom.residue.index)) raise ValueError("Atom %s of %s %d is out of sync!." %(atom.name, atom.residue.name, atom.residue.index))
else: else:
raise ValueError("Atom %s of %s %d was not assigned." %(atom.name, atom.residue.name, atom.residue.index)) raise ValueError("Atom %s of %s %d was not assigned." %(atom.name, atom.residue.name, atom.residue.index))
else: else:
......
%module openmm %module openmm
%include "factory.i" %include "factory.i"
%include "std_string.i" %include "std_string.i"
%include "std_iostream.i" %include "std_iostream.i"
%include "typemaps.i"
%include "std_map.i" %include "std_map.i"
%include "std_pair.i" %include "std_pair.i"
%include "std_set.i" %include "std_set.i"
%include "std_vector.i" %include "std_vector.i"
namespace std { namespace std {
%template(pairii) pair<int,int>; %template(pairii) pair<int,int>;
%template(vectord) vector<double>; %template(vectord) vector<double>;
...@@ -23,6 +22,7 @@ namespace std { ...@@ -23,6 +22,7 @@ namespace std {
%template(seti) set<int>; %template(seti) set<int>;
}; };
%include "typemaps.i"
%include "windows.i" %include "windows.i"
%{ %{
......
#!/usr/bin/env python #!/usr/bin/env python
#
#
"""Build swig imput file from xml encoded header files (see gccxml).""" """Build swig imput file from xml encoded header files (see gccxml)."""
__author__ = "Randall J. Radmer" __author__ = "Randall J. Radmer"
__version__ = "1.0" __version__ = "1.0"
...@@ -12,6 +9,7 @@ import time ...@@ -12,6 +9,7 @@ import time
import getopt import getopt
import re import re
import xml.etree.ElementTree as etree import xml.etree.ElementTree as etree
from distutils.version import LooseVersion
try: try:
from html.parser import HTMLParser from html.parser import HTMLParser
...@@ -19,6 +17,9 @@ except ImportError: ...@@ -19,6 +17,9 @@ except ImportError:
# python 2 # python 2
from HTMLParser import HTMLParser from HTMLParser import HTMLParser
INDENT = " "
docTags = {'emphasis':'i', 'bold':'b', 'itemizedlist':'ul', 'listitem':'li', 'preformatted':'pre', 'computeroutput':'tt', 'subscript':'sub'}
def striphtmltags(s): def striphtmltags(s):
"""Strip a couple html tags used inside docstrings in the C++ source """Strip a couple html tags used inside docstrings in the C++ source
...@@ -52,11 +53,6 @@ def striphtmltags(s): ...@@ -52,11 +53,6 @@ def striphtmltags(s):
return s return s
INDENT = " ";
docTags = {'emphasis':'i', 'bold':'b', 'itemizedlist':'ul', 'listitem':'li', 'preformatted':'pre', 'computeroutput':'tt', 'subscript':'sub'}
def trimToSingleSpace(text): def trimToSingleSpace(text):
if text is None or len(text) == 0: if text is None or len(text) == 0:
return "" return ""
...@@ -158,8 +154,10 @@ class SwigInputBuilder: ...@@ -158,8 +154,10 @@ class SwigInputBuilder:
docstringFilename=None, docstringFilename=None,
pythonprependFilename=None, pythonprependFilename=None,
pythonappendFilename=None, pythonappendFilename=None,
skipAdditionalMethods=[]): skipAdditionalMethods=[],
SWIG_VERSION='3.0.2'):
self.nodeByID={} self.nodeByID={}
self.SWIG_COMPACT_ARGUMENTS = LooseVersion(SWIG_VERSION) < LooseVersion('3.0.6')
self.configModule = __import__(os.path.splitext(configFilename)[0]) self.configModule = __import__(os.path.splitext(configFilename)[0])
...@@ -444,25 +442,20 @@ class SwigInputBuilder: ...@@ -444,25 +442,20 @@ class SwigInputBuilder:
key=(shortClassName, methName) key=(shortClassName, methName)
if key in self.configModule.STEAL_OWNERSHIP: if key in self.configModule.STEAL_OWNERSHIP:
for argNum in self.configModule.STEAL_OWNERSHIP[key]: for argNum in self.configModule.STEAL_OWNERSHIP[key]:
self.fOutPythonprepend.write("%pythonprepend") if self.SWIG_COMPACT_ARGUMENTS:
self.fOutPythonprepend.write(" OpenMM::%s::%s%s %%{\n" argName = 'args[%s]' % argNum
% (shortClassName, else:
methName, argName = getText('declname', paramList[argNum])
mArgsstring))
self.fOutPythonprepend.write(
"%sif not args[%s].thisown:\n"
% (INDENT, argNum))
s = 's = "the %s object does not own its'
s = '%s corresponding OpenMM object" \\' % s
self.fOutPythonprepend.write("%s %s\n" % (INDENT, s))
s = ' %% args[%s].__class__.__name__' % argNum
self.fOutPythonprepend.write("%s %s\n" % (INDENT, s))
s = "raise Exception(s)" text = '''
self.fOutPythonprepend.write("%s %s\n" % (INDENT, s)) %pythonprepend OpenMM::{shortClassName}::{methName}{mArgsstring} %{{
if not {argName}.thisown:
s = ("the %s object does not own its corresponding OpenMM object"
% self.__class__.__name__)
raise Exception(s)
%}}'''.format(argName=argName, shortClassName=shortClassName, methName=methName, mArgsstring=mArgsstring)
self.fOutPythonprepend.write(text)
self.fOutPythonprepend.write("%}\n\n")
#write pythonappend blocks #write pythonappend blocks
if self.fOutPythonappend \ if self.fOutPythonappend \
...@@ -505,8 +498,12 @@ class SwigInputBuilder: ...@@ -505,8 +498,12 @@ class SwigInputBuilder:
if key in self.configModule.STEAL_OWNERSHIP: if key in self.configModule.STEAL_OWNERSHIP:
for argNum in self.configModule.STEAL_OWNERSHIP[key]: for argNum in self.configModule.STEAL_OWNERSHIP[key]:
addText = "%s%sargs[%s].thisown=0\n" \ if self.SWIG_COMPACT_ARGUMENTS:
% (addText, INDENT, argNum) argName = 'args[%s]' % argNum
else:
argName = getText('declname', paramList[argNum])
addText = "%s%s%s.thisown=0\n" \
% (addText, INDENT, argName)
if addText: if addText:
self.fOutPythonappend.write("%pythonappend") self.fOutPythonappend.write("%pythonappend")
...@@ -592,7 +589,7 @@ class SwigInputBuilder: ...@@ -592,7 +589,7 @@ class SwigInputBuilder:
def parseCommandLine(): def parseCommandLine():
opts, args_proper = getopt.getopt(sys.argv[1:], 'hi:c:o:d:a:z:s:') opts, args_proper = getopt.getopt(sys.argv[1:], 'hi:c:o:d:a:z:s:v:')
inputDirname = None inputDirname = None
configFilename = None configFilename = None
outputFilename = "" outputFilename = ""
...@@ -600,6 +597,7 @@ def parseCommandLine(): ...@@ -600,6 +597,7 @@ def parseCommandLine():
pythonprependFilename = "" pythonprependFilename = ""
pythonappendFilename = "" pythonappendFilename = ""
skipAdditionalMethods = [] skipAdditionalMethods = []
swigVersion = '3.0.2'
for option, parameter in opts: for option, parameter in opts:
if option=='-h': usageError() if option=='-h': usageError()
if option=='-i': inputDirname = parameter if option=='-i': inputDirname = parameter
...@@ -609,19 +607,21 @@ def parseCommandLine(): ...@@ -609,19 +607,21 @@ def parseCommandLine():
if option=='-a': pythonprependFilename=parameter if option=='-a': pythonprependFilename=parameter
if option=='-z': pythonappendFilename=parameter if option=='-z': pythonappendFilename=parameter
if option=='-s': skipAdditionalMethods.append(parameter) if option=='-s': skipAdditionalMethods.append(parameter)
if option=='-v': swigVersion = parameter
if not inputDirname: usageError() if not inputDirname: usageError()
if not configFilename: usageError() if not configFilename: usageError()
return (args_proper, inputDirname, configFilename, outputFilename, return (args_proper, inputDirname, configFilename, outputFilename,
docstringFilename, docstringFilename, pythonprependFilename, pythonappendFilename,
pythonprependFilename, pythonappendFilename, skipAdditionalMethods) skipAdditionalMethods, swigVersion)
def main(): def main():
(args_proper, inputDirname, configFilename, outputFilename, (args_proper, inputDirname, configFilename, outputFilename,
docstringFilename, pythonprependFilename, pythonappendFilename, docstringFilename, pythonprependFilename, pythonappendFilename,
skipAdditionalMethods) = parseCommandLine() skipAdditionalMethods, swigVersion) = parseCommandLine()
sBuilder = SwigInputBuilder(inputDirname, configFilename, outputFilename, sBuilder = SwigInputBuilder(inputDirname, configFilename, outputFilename,
docstringFilename, pythonprependFilename, docstringFilename, pythonprependFilename,
pythonappendFilename, skipAdditionalMethods) pythonappendFilename, skipAdditionalMethods,
swigVersion)
#print "Calling writeSwigFile\n" #print "Calling writeSwigFile\n"
sBuilder.writeSwigFile() sBuilder.writeSwigFile()
#print "Done writeSwigFile\n" #print "Done writeSwigFile\n"
...@@ -644,6 +644,8 @@ def usageError(): ...@@ -644,6 +644,8 @@ def usageError():
% (' '*len(os.path.basename(sys.argv[0])))) % (' '*len(os.path.basename(sys.argv[0]))))
sys.stdout.write(' %s[-s skippedClasses]\n' \ sys.stdout.write(' %s[-s skippedClasses]\n' \
% (' '*len(os.path.basename(sys.argv[0])))) % (' '*len(os.path.basename(sys.argv[0]))))
sys.stdout.write(' %s[-v swigVersion]\n' \
% (' '*len(os.path.basename(sys.argv[0]))))
sys.exit(1) sys.exit(1)
if __name__=='__main__': if __name__=='__main__':
......
...@@ -307,7 +307,7 @@ UNITS = { ...@@ -307,7 +307,7 @@ UNITS = {
("Context", "getParameter") : (None, ()), ("Context", "getParameter") : (None, ()),
("Context", "getMolecules") : (None, ()), ("Context", "getMolecules") : (None, ()),
("CMAPTorsionForce", "getMapParameters") : (None, ()), ("CMAPTorsionForce", "getMapParameters") : (None, (None, 'unit.kilojoule_per_mole')),
("CMAPTorsionForce", "getTorsionParameters") : (None, ()), ("CMAPTorsionForce", "getTorsionParameters") : (None, ()),
("CMMotionRemover", "getFrequency") : (None, ()), ("CMMotionRemover", "getFrequency") : (None, ()),
("CustomAngleForce", "getNumPerAngleParameters") : (None, ()), ("CustomAngleForce", "getNumPerAngleParameters") : (None, ()),
......
...@@ -2,16 +2,6 @@ ...@@ -2,16 +2,6 @@
%include exceptions.i %include exceptions.i
%include extend.i %include extend.i
%include header.i %include header.i
%include pythonprepend_all.i
%include pythonprepend.i %include pythonprepend.i
%include pythonappend.i %include pythonappend.i
%include typemaps.i %include typemaps.i
/* SWIG 3.x resolved a bug in which all wrapped C++ functions took *args as its
* default argument list. OpenMM then exploited this bug by doing stuff like
* passing args to stripUnits (and all added code assumed that the arguments
* were in an "args" list). So in order to restore this arguably buggy behavior
* from SWIG 2, enable the "compactdefaultargs" feature globally.
*
* See https://github.com/swig/swig/issues/387
*/
%feature("compactdefaultargs");
...@@ -218,69 +218,6 @@ class State(_object): ...@@ -218,69 +218,6 @@ class State(_object):
raise TypeError('Parameters were not requested in getState() call, so are not available.') raise TypeError('Parameters were not requested in getState() call, so are not available.')
return self._paramMap return self._paramMap
def stripUnits(args):
"""
getState(self, quantity)
-> value with *no* units
Examples
>>> import simtk
>>> x = 5
>>> print x
5
>>> x = stripUnits((5*simtk.unit.nanometer,))
>>> x
(5,)
>>> arg1 = 5*simtk.unit.angstrom
>>> x = stripUnits((arg1,))
>>> x
(0.5,)
>>> arg1 = 5
>>> x = stripUnits((arg1,))
>>> x
(5,)
>>> arg1 = (1*simtk.unit.angstrom, 5*simtk.unit.angstrom)
>>> x = stripUnits((arg1,))
>>> x
((0.10000000000000001, 0.5),)
>>> arg1 = (1*simtk.unit.angstrom,
... 5*simtk.unit.kilojoule_per_mole,
... 1*simtk.unit.kilocalorie_per_mole)
>>> y = stripUnits((arg1,))
>>> y
((0.10000000000000001, 5, 4.1840000000000002),)
"""
newArgList=[]
for arg in args:
if 'numpy' in sys.modules and isinstance(arg, numpy.ndarray):
arg = arg.tolist()
elif unit.is_quantity(arg):
# JDC: Ugly workaround for OpenMM using 'bar' for fundamental pressure unit.
if arg.unit.is_compatible(unit.bar):
arg = arg / unit.bar
else:
arg = arg.value_in_unit_system(unit.md_unit_system)
# JDC: End workaround.
elif isinstance(arg, dict):
newKeys = stripUnits(arg.keys())
newValues = stripUnits(arg.values())
arg = dict(zip(newKeys, newValues))
elif not isinstance(arg, _string_types):
try:
# Reclusively strip units from all quantities
arg=stripUnits(arg)
except TypeError:
pass
newArgList.append(arg)
return tuple(newArgList)
%} %}
%pythonappend OpenMM::Context::Context %{ %pythonappend OpenMM::Context::Context %{
......
%pythonprepend %{
try: args=stripUnits(args)
except UnboundLocalError: pass
%}
%fragment("Py_StripOpenMMUnits", "header") {
/* Convert python list of tuples to C++ std::vector of Vec3 objects */ static PyObject *__s_Quantity = NULL;
%typemap(in) const std::vector<Vec3>& (std::vector<OpenMM::Vec3> vVec) { static PyObject *__s_md_unit_system_tuple = NULL;
// typemap -- %typemap(in) std::vector<Vec3>& (std::vector<OpenMM::Vec3> vVec) static PyObject *__s_bar_tuple = NULL;
int i, pLength, itemLength;
double x, y, z; PyObject* Py_StripOpenMMUnits(PyObject *input) {
PyObject *o; if (__s_Quantity == NULL) {
PyObject *o1; PyObject* module = NULL;
module = PyImport_ImportModule("simtk.unit");
pLength=(int)PySequence_Length($input); if (!module) {
for (i=0; i<pLength; i++) { PyErr_SetString(PyExc_ImportError, "simtk.unit"); Py_CLEAR(module); return NULL;
o=PySequence_GetItem($input, i); }
itemLength = (int) PySequence_Length(o);
if (itemLength != 3) { __s_Quantity = PyObject_GetAttrString(module, "Quantity");
PyErr_SetString(PyExc_TypeError, "Item must have length 3"); if (!__s_Quantity) {
PyErr_SetString(PyExc_AttributeError, "'module' object has no attribute 'Quantity'");
Py_CLEAR(module);
Py_CLEAR(__s_Quantity);
return NULL; return NULL;
} }
o1=PySequence_GetItem(o, 0); PyObject* bar = NULL;
x=PyFloat_AsDouble(o1); bar = PyObject_GetAttrString(module, "bar");
Py_DECREF(o1); if (!bar) {
PyErr_SetString(PyExc_AttributeError, "'module' object has no attribute 'bar'");
Py_CLEAR(module);
Py_CLEAR(__s_Quantity);
Py_CLEAR(bar);
return NULL;
}
o1=PySequence_GetItem(o, 1); PyObject* md_unit_system = NULL;
y=PyFloat_AsDouble(o1); md_unit_system = PyObject_GetAttrString(module, "md_unit_system");
Py_DECREF(o1); if (!md_unit_system) {
PyErr_SetString(PyExc_AttributeError, "'module' object has no attribute 'md_unit_system'");
Py_CLEAR(module);
Py_CLEAR(__s_Quantity);
Py_CLEAR(bar);
Py_CLEAR(md_unit_system);
}
__s_md_unit_system_tuple = PyTuple_Pack(1, md_unit_system);
__s_bar_tuple = PyTuple_Pack(1, bar);
Py_DECREF(md_unit_system);
Py_DECREF(bar);
Py_DECREF(module);
}
PyObject *val;
if (PyObject_IsInstance(input, __s_Quantity)) {
PyObject* input_unit = NULL, *is_compatible = NULL, *compatible_with_bar = NULL;
input_unit = PyObject_GetAttrString(input, "unit");
is_compatible = PyObject_GetAttrString(input_unit, "is_compatible");
compatible_with_bar = PyObject_Call(is_compatible, __s_bar_tuple, NULL);
if (PyObject_IsTrue(compatible_with_bar)) {
// input.in_units_of(unit.bar)
PyObject* value_in_unit = PyObject_GetAttrString(input, "value_in_unit");
val = PyObject_Call(value_in_unit, __s_bar_tuple, NULL);
Py_DECREF(value_in_unit);
} else {
// input.value_in_unit_system(md_unit_system_tuple)
PyObject* value_in_unit_system = PyObject_GetAttrString(input, "value_in_unit_system");
val = PyObject_Call(value_in_unit_system, __s_md_unit_system_tuple, NULL);
Py_DECREF(value_in_unit_system);
}
Py_CLEAR(input_unit);
Py_CLEAR(is_compatible);
Py_CLEAR(compatible_with_bar);
if (PyErr_Occurred() != NULL) {
return NULL;
}
} else {
val = input;
Py_INCREF(val);
}
return val;
}
}
%fragment("Py_SequenceToVec3", "header", fragment="Py_StripOpenMMUnits") {
OpenMM::Vec3 Py_SequenceToVec3(PyObject* obj, int& status) {
PyObject* s, *o, *o1;
double x[3];
int i, length;
s = Py_StripOpenMMUnits(obj);
if (s == NULL) {
status = SWIG_ERROR;
return OpenMM::Vec3(0, 0, 0);
}
o1=PySequence_GetItem(o, 2); length = (int) PySequence_Length(s);
z=PyFloat_AsDouble(o1); if (length != 3) {
Py_DECREF(s);
PyErr_SetString(PyExc_TypeError, "Item must have length 3");
status = SWIG_ERROR;
return OpenMM::Vec3(0, 0, 0);
}
for (i = 0; i < 3; i++ ) {
o = PySequence_GetItem(s, i);
o1 = Py_StripOpenMMUnits(o);
if (o1 != NULL) {
x[i] = PyFloat_AsDouble(o1);
}
if (o1 == NULL || PyErr_Occurred() != NULL) {
Py_DECREF(s);
Py_DECREF(o);
Py_XDECREF(o1);
status = SWIG_ERROR;
return OpenMM::Vec3(0, 0, 0);
}
Py_DECREF(o);
Py_DECREF(o1); Py_DECREF(o1);
}
status = SWIG_OK;
Py_DECREF(s);
return OpenMM::Vec3(x[0], x[1], x[2]);
}
}
%fragment("Py_SequenceToVecDouble", "header", fragment="Py_StripOpenMMUnits") {
int Py_SequenceToVecDouble(PyObject* obj, std::vector<double>& out) {
PyObject* stripped = NULL;
PyObject* item = NULL;
PyObject* item1 = NULL;
PyObject* iterator = NULL;
stripped = Py_StripOpenMMUnits(obj);
iterator = PyObject_GetIter(stripped);
if (iterator == NULL) {
Py_DECREF(stripped);
return SWIG_ERROR;
}
while ((item = PyIter_Next(iterator))) {
item1 = Py_StripOpenMMUnits(item);
if (item1 == NULL) {
Py_DECREF(item);
return SWIG_ERROR;
}
double d = PyFloat_AsDouble(item1);
Py_DECREF(item);
Py_DECREF(item1);
if (PyErr_Occurred() != NULL) {
return SWIG_ERROR;
}
out.push_back(d);
}
Py_DECREF(iterator);
Py_DECREF(stripped);
return SWIG_OK;
}
}
%typemap(typecheck, precedence=SWIG_TYPECHECK_DOUBLE, fragment="Py_StripOpenMMUnits") double {
double argp = 0;
PyObject* s = NULL;
s = Py_StripOpenMMUnits($input);
$1 = (s != NULL) ? SWIG_IsOK(SWIG_AsVal_double(s, &argp)) : 0;
Py_DECREF(s);
}
%typemap(in, noblock=1, fragment="Py_StripOpenMMUnits") double (double argp = 0, int res = 0,
PyObject* stripped = NULL) {
stripped = Py_StripOpenMMUnits($input);
if (stripped == NULL) { SWIG_fail; }
res = SWIG_AsVal_double(stripped, &argp);
if (!SWIG_IsOK(res)) {
PyErr_SetString(PyExc_ValueError, "in method $symname, argument $argnum could not be converted to type $type");
SWIG_fail;
}
$1 = ($ltype)(argp);
Py_CLEAR(stripped);
}
%typemap(in, fragment="Py_SequenceToVec3") Vec3 (int res=0){
// typemap -- %typemap(in) Vec3
$1 = Py_SequenceToVec3($input, res);
if (!SWIG_IsOK(res)) {
PyErr_SetString(PyExc_ValueError, "in method $symname, argument $argnum could not be converted to type $type");
SWIG_fail;
}
}
%typemap(in, fragment="Py_SequenceToVec3") const Vec3& (OpenMM::Vec3 myVec, int res=0) {
// typemap -- %typemap(in) Vec3
myVec = Py_SequenceToVec3($input, res);
if (!SWIG_IsOK(res)) {
PyErr_SetString(PyExc_ValueError, "in method $symname, argument $argnum could not be converted to type $type");
SWIG_fail;
}
$1 = &myVec;
}
/* Convert python list of tuples to C++ std::vector of Vec3 objects */
%typemap(in, fragment="Py_SequenceToVec3") const std::vector<Vec3>& (std::vector<OpenMM::Vec3> vVec, PyObject* s=NULL, PyObject* o=NULL) {
int i, pLength, ret;
s = Py_StripOpenMMUnits($input);
pLength = (int)PySequence_Length(s);
for (i = 0; i < pLength; i++) {
o = PySequence_GetItem(s, i);
OpenMM::Vec3 v = Py_SequenceToVec3(o, ret);
if (!SWIG_IsOK(ret)) {
Py_DECREF(s);
Py_DECREF(o); Py_DECREF(o);
vVec.push_back( OpenMM::Vec3(x, y, z) ); PyErr_SetString(PyExc_ValueError, "in method $symname, argument $argnum could not be converted to type $type");
SWIG_fail;
}
vVec.push_back(v);
} }
$1 = &vVec; $1 = &vVec;
Py_DECREF(s);
}
%typemap(in, fragment="Py_SequenceToVecDouble") const std::vector<double> & (std::vector<double> v, int res=0) {
res = Py_SequenceToVecDouble($input, v);
if (!SWIG_IsOK(res)) {
PyErr_SetString(PyExc_ValueError, "in method $symname, argument $argnum could not be converted to type $type");
SWIG_fail;
}
$1 = &v;
} }
/* The following two typemaps cause a non-const vector<Vec3>& to become a return value. */ /* The following two typemaps cause a non-const vector<Vec3>& to become a return value. */
...@@ -39,6 +236,7 @@ ...@@ -39,6 +236,7 @@
$1 = &temp; $1 = &temp;
} }
%typemap(argout) std::vector<Vec3>& { %typemap(argout) std::vector<Vec3>& {
int i, n; int i, n;
PyObject *pyList; PyObject *pyList;
...@@ -57,6 +255,7 @@ ...@@ -57,6 +255,7 @@
$result = pyList; $result = pyList;
} }
/* const vector<Vec3> should NOT become an output. */ /* const vector<Vec3> should NOT become an output. */
%typemap(argout) const std::vector<Vec3>& { %typemap(argout) const std::vector<Vec3>& {
} }
...@@ -66,49 +265,14 @@ ...@@ -66,49 +265,14 @@
// typemap -- %typemap(typecheck) Vec3 // typemap -- %typemap(typecheck) Vec3
$1 = (PySequence_Length($input) >= 3 ? 1 : 0); $1 = (PySequence_Length($input) >= 3 ? 1 : 0);
} }
%typemap(in) Vec3 {
// typemap -- %typemap(in) Vec3
double x, y, z;
PyObject *o;
o=PySequence_GetItem($input, 0);
x=PyFloat_AsDouble(o);
Py_DECREF(o);
o=PySequence_GetItem($input, 1);
y=PyFloat_AsDouble(o);
Py_DECREF(o);
o=PySequence_GetItem($input, 2);
z=PyFloat_AsDouble(o);
Py_DECREF(o);
$1 = OpenMM::Vec3(x, y, z);
}
%typemap(typecheck) const Vec3& { %typemap(typecheck) const Vec3& {
// typemap -- %typemap(typecheck) Vec3 // typemap -- %typemap(typecheck) Vec3
$1 = (PySequence_Length($input) >= 3 ? 1 : 0); $1 = (PySequence_Length($input) >= 3 ? 1 : 0);
} }
%typemap(in) const Vec3& (OpenMM::Vec3 myVec) {
// typemap -- %typemap(in) Vec3
double x, y, z;
PyObject *o;
o=PySequence_GetItem($input, 0);
x=PyFloat_AsDouble(o);
Py_DECREF(o);
o=PySequence_GetItem($input, 1);
y=PyFloat_AsDouble(o);
Py_DECREF(o);
o=PySequence_GetItem($input, 2);
z=PyFloat_AsDouble(o);
Py_DECREF(o);
myVec = OpenMM::Vec3(x, y, z);
$1 = &myVec;
}
%typemap(out) Vec3 { %typemap(out) Vec3 {
PyObject* mm = PyImport_AddModule("simtk.openmm"); PyObject* mm = PyImport_AddModule("simtk.openmm");
PyObject* vec3 = PyObject_GetAttrString(mm, "Vec3"); PyObject* vec3 = PyObject_GetAttrString(mm, "Vec3");
...@@ -117,6 +281,7 @@ ...@@ -117,6 +281,7 @@
Py_DECREF(args); Py_DECREF(args);
} }
%typemap(out) const Vec3& { %typemap(out) const Vec3& {
PyObject* mm = PyImport_AddModule("simtk.openmm"); PyObject* mm = PyImport_AddModule("simtk.openmm");
PyObject* vec3 = PyObject_GetAttrString(mm, "Vec3"); PyObject* vec3 = PyObject_GetAttrString(mm, "Vec3");
...@@ -139,6 +304,8 @@ ...@@ -139,6 +304,8 @@
Py_DECREF(args1); Py_DECREF(args1);
Py_DECREF(args2); Py_DECREF(args2);
Py_DECREF(args3); Py_DECREF(args3);
Py_DECREF(mm);
Py_DECREF(vec3);
PyObject *o, *o2, *o3; PyObject *o, *o2, *o3;
o = Py_BuildValue("[N, N, N]", pyVec1, pyVec2, pyVec3); o = Py_BuildValue("[N, N, N]", pyVec1, pyVec2, pyVec3);
if ((!$result) || ($result == Py_None)) { if ((!$result) || ($result == Py_None)) {
...@@ -158,12 +325,14 @@ ...@@ -158,12 +325,14 @@
} }
} }
%typemap(in, numinputs=0) (Vec3& a, Vec3& b, Vec3& c) (Vec3 tempA, Vec3 tempB, Vec3 tempC) { %typemap(in, numinputs=0) (Vec3& a, Vec3& b, Vec3& c) (Vec3 tempA, Vec3 tempB, Vec3 tempC) {
$1 = &tempA; $1 = &tempA;
$2 = &tempB; $2 = &tempB;
$3 = &tempC; $3 = &tempC;
} }
%typemap(out) std::string OpenMM::Context::createCheckpoint{ %typemap(out) std::string OpenMM::Context::createCheckpoint{
// createCheckpoint returns a bytes object // createCheckpoint returns a bytes object
$result = PyBytes_FromStringAndSize($1.c_str(), $1.length()); $result = PyBytes_FromStringAndSize($1.c_str(), $1.length());
......
...@@ -33,16 +33,17 @@ class TestElement(unittest.TestCase): ...@@ -33,16 +33,17 @@ class TestElement(unittest.TestCase):
""" """
min_diff = mass min_diff = mass
closest_element = None closest_element = None
for symbol, elem in element.Element._elements_by_symbol.items(): for elem in sorted(element.Element._elements_by_symbol.values(),
key=lambda x:x.mass):
diff = abs(elem.mass._value - mass) diff = abs(elem.mass._value - mass)
if diff < min_diff: if diff < min_diff:
min_diff = diff min_diff = diff
closest_element = elem closest_element = elem
return closest_element return closest_element
# Check 5000 random numbers between 0 and 300 # Check 500 random numbers between 0 and 200
for i in range(5000): for i in range(500):
mass = random.random() * 300 mass = random.random() * 200
elem = element.Element.getByMass(mass) elem = element.Element.getByMass(mass)
self.assertTrue(elem is exhaustive_search(mass)) self.assertTrue(elem is exhaustive_search(mass))
......
...@@ -74,6 +74,8 @@ class TestNumpyCompatibility(unittest.TestCase): ...@@ -74,6 +74,8 @@ class TestNumpyCompatibility(unittest.TestCase):
energy = np.random.randn(10*10) energy = np.random.randn(10*10)
f.addMap(10, energy) f.addMap(10, energy)
size, energy_out = f.getMapParameters(0) size, energy_out = f.getMapParameters(0)
energy_out = energy_out.value_in_unit_system(unit.md_unit_system)
self.assertEqual(size, 10) self.assertEqual(size, 10)
np.testing.assert_array_almost_equal(energy, np.asarray(energy_out)) np.testing.assert_array_almost_equal(energy, np.asarray(energy_out))
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment