openmmtools icon indicating copy to clipboard operation
openmmtools copied to clipboard

Restoring integrators from CompoundIntegrators prevents resets

Open nathanmlim opened this issue 7 years ago • 6 comments

Example below, where my LangevinIntegrator contains the boolean for ._meaure_heat. I then pass it into a CompoundIntegrator and attempt to reset the LangevinIntegrator and get an error saying that it is missing the property.

from simtk.openmm import CompoundIntegrator
from openmmtools.utils import RestorableOpenMMObject
from openmmtools.integrators import *
temperature = 300*unit.kelvin
collision_rate = 1/unit.picoseconds
timestep = 1.0*unit.femtoseconds
n_steps = 100
alchemical_functions = {'lambda_sterics' : 'lambda'}
ncmc_integrator = AlchemicalNonequilibriumLangevinIntegrator(alchemical_functions, 
                                                             splitting='O { V R H R V } O',
                                                             temperature=temperature,
                                                             collision_rate=collision_rate,
                                                             timestep=timestep,
                                                             nsteps_neq=n_steps,
                                                            measure_heat=True)
integrator = LangevinIntegrator(temperature=temperature, 
                                        timestep=timestep,
                                       collision_rate=collision_rate,
                                       measure_heat=True)
print(integrator)
print(integrator._measure_heat)

compound_integrator = openmm.CompoundIntegrator()
compound_integrator.addIntegrator(ncmc_integrator)
compound_integrator.addIntegrator(integrator)
print(compound_integrator)

langevin_integrator = compound_integrator.getIntegrator(1)
RestorableOpenMMObject.restore_interface(langevin_integrator)

print(langevin_integrator)
langevin_integrator.reset()
#print(langevin_integrator._measure_heat)

Error below

>>> <openmmtools.integrators.LangevinIntegrator; proxy of <Swig Object of type 'OpenMM::CustomIntegrator *' at 0x15182b6480> >
>>> True
>>> <simtk.openmm.openmm.CompoundIntegrator; proxy of <Swig Object of type 'OpenMM::CompoundIntegrator *' at 0x15182e4060> >
>>> <openmmtools.integrators.LangevinIntegrator; proxy of <Swig Object of type 'OpenMM::CustomIntegrator *' at 0x15182e4600> >
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-6-9c345ca3462e> in <module>()
     30 
     31 print(langevin_integrator)
---> 32 langevin_integrator.reset()
     33 #print(langevin_integrator._measure_heat)

~/Research/Github/molssi-project/openmmtools/openmmtools/integrators.py in reset(self)
   1186         """Reset all statistics (heat, shadow work, acceptance rates, step).
   1187         """
-> 1188         self.reset_heat()
   1189         self.reset_shadow_work()
   1190         self.reset_ghmc_statistics()

~/Research/Github/molssi-project/openmmtools/openmmtools/integrators.py in reset_heat(self)
   1163     def reset_heat(self):
   1164         """Reset heat."""
-> 1165         if self._measure_heat:
   1166             self.setGlobalVariableByName('heat', 0.0)
   1167 

//anaconda/envs/molssi/lib/python3.5/site-packages/simtk/openmm/openmm.py in <lambda>(self, name)
  10724     for _s in [Integrator]:
  10725         __swig_getmethods__.update(getattr(_s, '__swig_getmethods__', {}))
> 10726     __getattr__ = lambda self, name: _swig_getattr(self, CustomIntegrator, name)
  10727     __repr__ = _swig_repr
  10728     ComputeGlobal = _openmm.CustomIntegrator_ComputeGlobal

//anaconda/envs/molssi/lib/python3.5/site-packages/simtk/openmm/openmm.py in _swig_getattr(self, class_type, name)
     72 
     73 def _swig_getattr(self, class_type, name):
---> 74     return _swig_getattr_nondynamic(self, class_type, name, 0)
     75 
     76 

//anaconda/envs/molssi/lib/python3.5/site-packages/simtk/openmm/openmm.py in _swig_getattr_nondynamic(self, class_type, name, static)
     67         return method(self)
     68     if (not static):
---> 69         return object.__getattr__(self, name)
     70     else:
     71         raise AttributeError(name)

AttributeError: type object 'object' has no attribute '__getattr__'

I can attempt to fix it, if someone could provide any pointers on where to start poking around?

nathanmlim avatar Sep 14 '18 17:09 nathanmlim

Looking at the error, I believe that the problem is that CompoundIntegrator.getIntegrator() does not preserve the Python class. I think Peter fixed it for Context.getIntegrator(), but apparently those changes did not affect CompoundIntegrator. Which OpenMM version are you using?

In any case, I'm all in favor of removing all pure-Python attributes from our integrator classes in favor of properties that read global variables since, as you noticed, including pure-Python attributes makes it impossible to reconstruct the integrator from its OpenMM XML serialization.

For example, changing LangevinIntegrator._measure_heat from a simple attribute to a property like

@property
def _measure_heat(self):
    try:
        self.getGlobalVariableByName('heat')
    except:
        return False
    return True

See also this section of the new tutorial (it still has to be pushed to the online docs but it should be already readable from github even if it uses RST syntax).

andrrizzi avatar Sep 14 '18 18:09 andrrizzi

Or maybe even better, removing _measure_heat completely and just implement get/set_heat (and other variables related to shadow work etc.) with something like

def get_heat(self):
    try:
        return self.getGlobalVariableByName('heat')
    except:
        raise Exception("This integrator must be constructed with 'measure_heat=True' in order to measure heat.")

andrrizzi avatar Sep 14 '18 19:09 andrrizzi

Looking at the error, I believe that the problem is that CompoundIntegrator.getIntegrator() does not preserve the Python class. I think Peter fixed it for Context.getIntegrator(), but apparently those changes did not affect CompoundIntegrator.

Can we make sure to report this to the OpenMM issue tracker if that needs to be fixed? There's still time to fix it in 7.3!

jchodera avatar Sep 14 '18 19:09 jchodera

I'll open the issue over there. It would still be a good idea to change the implementations though so that it would be possible to read OpenMM XML files and send our custom integrators over the network.

andrrizzi avatar Sep 14 '18 19:09 andrrizzi

Issue opened: pandegroup/openmm#2168 .

andrrizzi avatar Sep 14 '18 19:09 andrrizzi

See Peter's comment on the issue tracker. He did try to make it work in the past, but it's more complicated than it appears so the only way we have to fix this problem (and also support correctly XML deserialization) is to change the integrator's implementation to remove the Python attributes.

andrrizzi avatar Sep 14 '18 23:09 andrrizzi