Commit ba924c54 authored by peastman's avatar peastman Committed by GitHub
Browse files

Merge pull request #4 from swails/bond

namedtuple and singleton
parents 7c7b945e 8f8dbd12
...@@ -229,8 +229,8 @@ def buildKeywordDictionary(major_version_num=MAJOR_VERSION_NUM, ...@@ -229,8 +229,8 @@ def buildKeywordDictionary(major_version_num=MAJOR_VERSION_NUM,
def main(): def main():
if sys.version_info < (2, 6): if sys.version_info < (2, 7):
reportError("OpenMM requires Python 2.6 or better.") reportError("OpenMM requires Python 2.7 or better.")
if platform.system() == 'Darwin': if platform.system() == 'Darwin':
macVersion = [int(x) for x in platform.mac_ver()[0].split('.')] macVersion = [int(x) for x in platform.mac_ver()[0].split('.')]
if tuple(macVersion) < (10, 5): if tuple(macVersion) < (10, 5):
......
...@@ -45,6 +45,7 @@ import simtk.openmm as mm ...@@ -45,6 +45,7 @@ import simtk.openmm as mm
import simtk.unit as unit import simtk.unit as unit
from . import element as elem from . import element as elem
from simtk.openmm.app import Topology from simtk.openmm.app import Topology
from simtk.openmm.app.internal.singleton import Singleton
def _convertParameterToNumber(param): def _convertParameterToNumber(param):
if unit.is_quantity(param): if unit.is_quantity(param):
...@@ -89,44 +90,44 @@ def _createFunctions(force, functions): ...@@ -89,44 +90,44 @@ def _createFunctions(force, functions):
# Enumerated values for nonbonded method # Enumerated values for nonbonded method
class NoCutoff(object): class NoCutoff(Singleton):
def __repr__(self): def __repr__(self):
return 'NoCutoff' return 'NoCutoff'
NoCutoff = NoCutoff() NoCutoff = NoCutoff()
class CutoffNonPeriodic(object): class CutoffNonPeriodic(Singleton):
def __repr__(self): def __repr__(self):
return 'CutoffNonPeriodic' return 'CutoffNonPeriodic'
CutoffNonPeriodic = CutoffNonPeriodic() CutoffNonPeriodic = CutoffNonPeriodic()
class CutoffPeriodic(object): class CutoffPeriodic(Singleton):
def __repr__(self): def __repr__(self):
return 'CutoffPeriodic' return 'CutoffPeriodic'
CutoffPeriodic = CutoffPeriodic() CutoffPeriodic = CutoffPeriodic()
class Ewald(object): class Ewald(Singleton):
def __repr__(self): def __repr__(self):
return 'Ewald' return 'Ewald'
Ewald = Ewald() Ewald = Ewald()
class PME(object): class PME(Singleton):
def __repr__(self): def __repr__(self):
return 'PME' return 'PME'
PME = PME() PME = PME()
# Enumerated values for constraint type # Enumerated values for constraint type
class HBonds(object): class HBonds(Singleton):
def __repr__(self): def __repr__(self):
return 'HBonds' return 'HBonds'
HBonds = HBonds() HBonds = HBonds()
class AllBonds(object): class AllBonds(Singleton):
def __repr__(self): def __repr__(self):
return 'AllBonds' return 'AllBonds'
AllBonds = AllBonds() AllBonds = AllBonds()
class HAngles(object): class HAngles(Singleton):
def __repr__(self): def __repr__(self):
return 'HAngles' return 'HAngles'
HAngles = HAngles() HAngles = HAngles()
......
"""
Creates a subclass for all classes intended to be a singleton. This
maintains the correctness of instance is instance even following
pickling/unpickling
"""
class Singleton(object):
_inst = None
def __new__(cls):
if cls._inst is None:
cls._inst = super(Singleton, cls).__new__(cls)
return cls._inst
def __reduce__(self):
return repr(self)
...@@ -32,35 +32,37 @@ from __future__ import absolute_import ...@@ -32,35 +32,37 @@ from __future__ import absolute_import
__author__ = "Peter Eastman" __author__ = "Peter Eastman"
__version__ = "1.0" __version__ = "1.0"
from collections import namedtuple
import os import os
import xml.etree.ElementTree as etree import xml.etree.ElementTree as etree
from simtk.openmm.vec3 import Vec3 from simtk.openmm.vec3 import Vec3
from simtk.openmm.app.internal.singleton import Singleton
from simtk.unit import nanometers, sqrt, is_quantity from simtk.unit import nanometers, sqrt, is_quantity
from copy import deepcopy from copy import deepcopy
# Enumerated values for bond type # Enumerated values for bond type
class Single(object): class Single(Singleton):
def __repr__(self): def __repr__(self):
return 'Single' return 'Single'
Single = Single() Single = Single()
class Double(object): class Double(Singleton):
def __repr__(self): def __repr__(self):
return 'Double' return 'Double'
Double = Double() Double = Double()
class Triple(object): class Triple(Singleton):
def __repr__(self): def __repr__(self):
return 'Triple' return 'Triple'
Triple = Triple() Triple = Triple()
class Aromatic(object): class Aromatic(Singleton):
def __repr__(self): def __repr__(self):
return 'Aromatic' return 'Aromatic'
Aromatic = Aromatic() Aromatic = Aromatic()
class Amide(object): class Amide(Singleton):
def __repr__(self): def __repr__(self):
return 'Amide' return 'Amide'
Amide = Amide() Amide = Amide()
...@@ -437,7 +439,7 @@ class Atom(object): ...@@ -437,7 +439,7 @@ class Atom(object):
def __repr__(self): def __repr__(self):
return "<Atom %d (%s) of chain %d residue %d (%s)>" % (self.index, self.name, self.residue.chain.index, self.residue.index, self.residue.name) return "<Atom %d (%s) of chain %d residue %d (%s)>" % (self.index, self.name, self.residue.chain.index, self.residue.index, self.residue.name)
class Bond(tuple): class Bond(namedtuple('Bond', ['atom1', 'atom2'])):
"""A Bond object represents a bond between two Atoms within a Topology. """A Bond object represents a bond between two Atoms within a Topology.
This class extends tuple, and may be interpreted as a 2 element tuple of Atom objects. This class extends tuple, and may be interpreted as a 2 element tuple of Atom objects.
...@@ -445,7 +447,7 @@ class Bond(tuple): ...@@ -445,7 +447,7 @@ class Bond(tuple):
def __new__(cls, atom1, atom2, type=None, order=None): def __new__(cls, atom1, atom2, type=None, order=None):
"""Create a new Bond. You should call addBond() on the Topology instead of calling this directly.""" """Create a new Bond. You should call addBond() on the Topology instead of calling this directly."""
bond = tuple.__new__(cls, (atom1, atom2)) bond = super(Bond, cls).__new__(cls, atom1, atom2)
bond.type = type bond.type = type
bond.order = order bond.order = order
return bond return bond
......
import pickle
import sys import sys
import unittest import unittest
from simtk.openmm.app import * from simtk.openmm.app import *
...@@ -26,6 +27,14 @@ class TestTopology(unittest.TestCase): ...@@ -26,6 +27,14 @@ class TestTopology(unittest.TestCase):
"""Test getters for number of atoms, residues, chains.""" """Test getters for number of atoms, residues, chains."""
self.check_pdbfile('systems/1T2Y.pdb', 271, 25, 1) self.check_pdbfile('systems/1T2Y.pdb', 271, 25, 1)
def test_bondtype_singleton(self):
""" Tests that the bond types are really singletons """
self.assertIs(Single, pickle.loads(pickle.dumps(Single)))
self.assertIs(Double, pickle.loads(pickle.dumps(Double)))
self.assertIs(Triple, pickle.loads(pickle.dumps(Triple)))
self.assertIs(Aromatic, pickle.loads(pickle.dumps(Aromatic)))
self.assertIs(Amide, pickle.loads(pickle.dumps(Amide)))
def test_residue_bonds(self): def test_residue_bonds(self):
"""Test retrieving bonds for a residue produces expected results.""" """Test retrieving bonds for a residue produces expected results."""
# Create a test topology # Create a test topology
......
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