Source code for prepmd.metadynamics
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Run metadynamics simulations - used in run.py
"""
from openmm.unit import *
import numpy as np
import MDAnalysis.analysis.rms as rms
[docs]
class StopSimulation(Exception):
""" Exception raised in order to stop simulation """
pass
[docs]
class RMSDIncrease(Exception):
pass
[docs]
class RMSDReporter(object):
def __init__(self, file, reportInterval, ref_positions, threshold_nm = 0.17, consecutive_frames=2):
self._out = open(file, 'w')
self._reportInterval = reportInterval
self._ref_positions = ref_positions.value_in_unit(nanometers)
self._threshold_nm = threshold_nm
self.max_consecutive_frames = consecutive_frames
self.current_consecutive_frames = 0
self.rmsd_log = []
self.reports = 0
def __del__(self):
self._out.close()
[docs]
def describeNextReport(self, simulation):
steps = self._reportInterval - simulation.currentStep%self._reportInterval
return {'steps': steps, 'periodic': None, 'include':['positions']}
[docs]
def report(self, simulation, state):
positions = state.getPositions(asNumpy=True).value_in_unit(nanometers)
# i think this measurement doesn't align whereas rmsdforce does
#rmsd = np.sqrt(((positions - self._ref_positions)**2).sum(-1).mean())
report_rmsd = rms.rmsd(positions, self._ref_positions, center=True, superposition=True)
print("rmsd = "+str(report_rmsd), end=" ")
self.rmsd_log.append(report_rmsd)
self._out.write(str(report_rmsd)+"\n")
if report_rmsd < self._threshold_nm:
self.current_consecutive_frames += 1
else:
self.current_consecutive_frames = 0
if self.current_consecutive_frames > self.max_consecutive_frames:
print(". RMSD below threshold value, stopping...")
raise StopSimulation()
if self.reports%5 == 0 and self.reports > 0:
if np.mean(np.gradient(self.rmsd_log)) > 0:
raise RMSDIncrease
self.reports += 1
[docs]
def get_representative_rmsd_frames(rmsd_log, num_frames):
num_frames -= 2
frames = [0]
change = 0
for frame in range(len(rmsd_log)-1):
change += abs(rmsd_log[frame+1] - rmsd_log[frame])
change_per_frame = change / num_frames
change = 0
for frame in range(len(rmsd_log)-1):
change += abs(rmsd_log[frame+1] - rmsd_log[frame])
if change > change_per_frame:
frames.append(frame)
change -= change_per_frame
frames.append(len(rmsd_log)-1)
return frames