示例#1
0
    def run_step(self, index):
        """Runs a single step of the job.
        
        @param index: the index of the step.
        @type index: int.

        @note: the argument index is the index of the loop note the index of the frame.      
        """

        # Read the current step in the xdatcar file.
        config = self._xdatcarFile.read_step(index)
        
        conf = Configuration(self._universe,config)
        
        conf.convertFromBoxCoordinates()
        
        self._universe.setConfiguration(conf)
                                        
        # The real coordinates are foled then into the simulation box (-L/2,L/2). 
        self._universe.foldCoordinatesIntoBox()

        time = index*self.configuration["time_step"]["value"]*Units.fs

        # A call to the snapshot generator produces the step corresponding to the current frame.
        self._snapshot(data = {'time': time})

        return index, None
示例#2
0
 def calc(self, frameIndex, trajectory):
     """Calculates the contribution for one frame.
     
     @param frameIndex: the index of the frame.
     @type frameIndex: integer.
     
     @param trajectory: the trajectory.
     @type trajectory: MMTK.Trajectory.Trajectory object
     """
     
     orderedAtoms = sorted(trajectory.universe.atomList(), key = operator.attrgetter('index'))
     selectedAtoms = Collection([orderedAtoms[ind] for ind in self.subset])
     
     targetAtoms = Collection([orderedAtoms[ind] for ind in self.target])
     
     initialConf = Configuration(trajectory.universe, self.initialConfArray)
     
     # First frame, nothing to do because the initialConf already stores the initial transformation.
     if frameIndex == self.firstFrame:
         trajectory.universe.setConfiguration(initialConf)
         
     else:
         trajectory.universe.setFromTrajectory(trajectory, frameIndex)                    
         # Find and apply the linear transformation that will minimize the RMS with the configuration
         # resulting from the principal axes transformation.
         tr, rms = selectedAtoms.findTransformation(initialConf)
         #selectedAtoms.applyTransformation(tr)
         trajectory.universe.applyTransformation(tr)
     
     globalMotionFilteredFrame = {}
     for at in targetAtoms:
         globalMotionFilteredFrame[at.index] = at.position()
                                                 
     return frameIndex, globalMotionFilteredFrame
示例#3
0
    def _prepare_ligand_CD(self):
        """Prepares the ligand for CD simulations

    Returns
    -------
    seeds : list of np.array
      Ligand configurations minimized in milestone D
    """
        if self.data['CD'].protocol == []:
            params_o = self.system.paramsFromAlpha(1.0, 'CD')
            self.system.setParams(params_o)

            if (self.args.params['CD']['pose'] == -1):
                seeds = self._get_confs_to_rescore(site=True, minimize=True)[0]
                self.data['CD'].confs['starting_poses'] = seeds
            else:
                # For pose BPMF, starting_poses is defined in _set_universe_evaluator
                seeds = self.data['CD'].confs['starting_poses']

            if seeds == []:
                seeds = None
            else:
                # initializes smart darting for CD and sets the universe
                # to the lowest energy configuration
                self.iterator.initializeSmartDartingConfigurations(
                    seeds, 'CD', self.log, self.data)
                if len(seeds) > 0:
                    self.top.universe.setConfiguration(\
                      Configuration(self.top.universe,np.copy(seeds[-1])))

                # Ramp up the temperature using HMC
                self._ramp_T(self.args.params['BC']['T_TARGET'],
                             normalize=False)

                seeds = [np.copy(self.top.universe.configuration().array) \
                  for n in range(self.args.params['CD']['seeds_per_state'])]
        return seeds
示例#4
0
  def _initial_sim_state(self, seeds, process, params_k):
    """
    Initializes a state, returning the configurations and potential energy.
    Attempts simulation up to 12 times, adjusting the time step.
    """

    if not 'delta_t' in params_k.keys():
      params_k[
        'delta_t'] = 1. * self.args.params[process]['delta_t'] * MMTK.Units.fs
    params_k['steps_per_trial'] = self.args.params[process]['steps_per_sweep']

    attempts_left = 12
    while (attempts_left > 0):
      # Get initial potential energy
      Es_o = []
      for seed in seeds:
        self.top.universe.setConfiguration(
          Configuration(self.top.universe, seed))
        Es_o.append(self.top.universe.energy())
      Es_o = np.array(Es_o)

      # Perform simulation
      results = []
      if self.args.cores > 1:
        # Multiprocessing code
        import multiprocessing
        m = multiprocessing.Manager()
        task_queue = m.Queue()
        done_queue = m.Queue()
        for k in range(len(seeds)):
          task_queue.put((seeds[k], process, params_k, True, k))
        processes = [multiprocessing.Process(target=self.iterator.iteration_worker, \
            args=(task_queue, done_queue)) for p in range(self.args.cores)]
        for p in range(self.args.cores):
          task_queue.put('STOP')
        for p in processes:
          p.start()
        for p in processes:
          p.join()
        results = [done_queue.get() for seed in seeds]
        for p in processes:
          p.terminate()
      else:
        # Single process code
        results = [self.iterator.iteration(\
          seeds[k], process, params_k, True, k) for k in range(len(seeds))]

      seeds = [result['confs'] for result in results]
      Es_n = np.array([result['Etot'] for result in results])
      deltaEs = Es_n - Es_o
      attempts_left -= 1

      # Get the time step
      delta_t = np.array([result['delta_t'] for result in results])
      if np.std(delta_t) > 1E-3:
        # If the integrator adapts the time step, take an average
        delta_t = min(max(np.mean(delta_t), \
          self.args.params[process]['delta_t']/5.0*MMTK.Units.fs), \
          self.args.params[process]['delta_t']*0.1*MMTK.Units.fs)
      else:
        delta_t = delta_t[0]

      # Adjust the time step
      if self.args.params[process]['sampler'] == 'HMC':
        # Adjust the time step for Hamiltonian Monte Carlo
        acc_rate = float(np.sum([r['acc_Sampler'] for r in results]))/\
          np.sum([r['att_Sampler'] for r in results])
        if acc_rate > 0.8:
          delta_t += 0.125 * MMTK.Units.fs
        elif acc_rate < 0.4:
          if delta_t < 2.0 * MMTK.Units.fs:
            params_k['steps_per_trial'] = max(
              int(params_k['steps_per_trial'] / 2.), 1)
          delta_t -= 0.25 * MMTK.Units.fs
          if acc_rate < 0.1:
            delta_t -= 0.25 * MMTK.Units.fs
        else:
          attempts_left = 0
      else:
        # For other integrators, make sure the time step
        # is small enough to see changes in the energy
        if (np.std(deltaEs) < 1E-3):
          delta_t -= 0.25 * MMTK.Units.fs
        else:
          attempts_left = 0

      if delta_t < 0.1 * MMTK.Units.fs:
        delta_t = 0.1 * MMTK.Units.fs

      params_k['delta_t'] = delta_t

    sampler_metrics = ''
    for s in ['ExternalMC', 'SmartDarting', 'Sampler']:
      if np.array(['acc_' + s in r.keys() for r in results]).any():
        acc = np.sum([r['acc_' + s] for r in results])
        att = np.sum([r['att_' + s] for r in results])
        time = np.sum([r['time_' + s] for r in results])
        if att > 0:
          sampler_metrics += '%s %d/%d=%.2f (%.1f s); '%(\
            s,acc,att,float(acc)/att,time)
    return (seeds, Es_n - Es_o, delta_t, sampler_metrics)
示例#5
0
  def _random_CD(self):
    """
      Randomly places the ligand into the receptor and evaluates energies

      The first state of CD is sampled by randomly placing configurations
      from the high temperature ligand simulation into the binding site.
    """
    # Select samples from the high T unbound state
    E_MM = []
    E_OBC = []
    confs = []
    for k in range(1, len(self.data['BC'].Es[0])):
      E_MM += list(self.data['BC'].Es[0][k]['MM'])
      if ('OBC' in self.data['BC'].Es[0][k].keys()):
        E_OBC += list(self.data['BC'].Es[0][k]['OBC'])
      confs += list(self.data['BC'].confs['samples'][0][k])

    random_CD_inds = np.array(np.linspace(0,len(E_MM), \
      self.args.params['CD']['seeds_per_state'],endpoint=False),dtype=int)
    BC0_Es_MM = [E_MM[ind] for ind in random_CD_inds]
    BC0_Es_OBC = []
    if E_OBC != []:
      BC0_Es_OBC = [E_OBC[ind] for ind in random_CD_inds]
    BC0_confs = [confs[ind] for ind in random_CD_inds]

    # Do the random CD
    params_o = self.system.paramsFromAlpha(0.0, 'CD')
    params_o['delta_t'] = 1. * self.data['BC'].protocol[0]['delta_t']
    self.data['CD'].protocol = [params_o]

    # Set up the force field with full interaction grids
    self.system.setParams(self.system.paramsFromAlpha(1.0, 'CD'))

    # Either loads or generates the random translations and rotations for the first state of CD
    if not (hasattr(self, '_random_trans') and hasattr(self, '_random_rotT')):
      self.data['CD']._max_n_trans = 10000
      # Default density of points is 50 per nm**3
      self.data['CD']._n_trans = max(
        min(
          np.int(
            np.ceil(self._forceFields['site'].volume *
                    self.args.params['CD']['site_density'])),
          self.data['CD']._max_n_trans), 5)
      self.data['CD']._random_trans = np.ndarray(
        (self.data['CD']._max_n_trans), dtype=Vector)
      for ind in range(self.data['CD']._max_n_trans):
        self.data['CD']._random_trans[ind] = Vector(
          self._forceFields['site'].randomPoint())
      self.data['CD']._max_n_rot = 100
      self._n_rot = 100
      self._random_rotT = np.ndarray((self.data['CD']._max_n_rot, 3, 3))
      from AlGDock.Integrators.ExternalMC.ExternalMC import random_rotate
      for ind in range(self.data['CD']._max_n_rot):
        self._random_rotT[ind, :, :] = np.transpose(random_rotate())
    else:
      self.data['CD']._max_n_trans = self.data['CD']._random_trans.shape[0]
      self._n_rot = self._random_rotT.shape[0]

    # Get interaction energies.
    # Loop over configurations, random rotations, and random translations
    E = {}
    for term in (['MM', 'site'] + scalables):
      # Large array creation may cause MemoryError
      E[term] = np.zeros((self.args.params['CD']['seeds_per_state'], \
        self.data['CD']._max_n_rot,self.data['CD']._n_trans))
    self.log.tee("  allocated memory for interaction energies")

    from AlGDock.system import term_map

    converged = False
    n_trans_o = 0
    n_trans_n = self.data['CD']._n_trans
    while not converged:
      for c in range(self.args.params['CD']['seeds_per_state']):
        E['MM'][c, :, :] = BC0_Es_MM[c]
        if BC0_Es_OBC != []:
          E['OBC'][c, :, :] = BC0_Es_OBC[c]
        for i_rot in range(self._n_rot):
          conf_rot = Configuration(self.top.universe,\
            np.dot(BC0_confs[c], self._random_rotT[i_rot,:,:]))
          for i_trans in range(n_trans_o, n_trans_n):
            self.top.universe.setConfiguration(conf_rot)
            self.top.universe.translateTo(
              self.data['CD']._random_trans[i_trans])
            eT = self.top.universe.energyTerms()
            for (key, value) in eT.iteritems():
              if key != 'electrostatic':  # For some reason, MMTK double-counts electrostatic energies
                E[term_map[key]][c, i_rot, i_trans] += value
      E_c = {}
      for term in E.keys():
        # Large array creation may cause MemoryError
        E_c[term] = np.ravel(E[term][:, :self._n_rot, :n_trans_n])
      self.log.tee("  allocated memory for %d translations" % n_trans_n)
      (u_kln,N_k) = self._u_kln([E_c],\
        [params_o,self._next_CD_state(E=E_c, params_o=params_o, decoupling=False)])
      du = u_kln[0, 1, :] - u_kln[0, 0, :]
      bootstrap_reps = 50
      f_grid0 = np.zeros(bootstrap_reps)
      for b in range(bootstrap_reps):
        du_b = du[np.random.randint(0, len(du), len(du))]
        f_grid0[b] = -np.log(np.exp(-du_b + min(du_b)).mean()) + min(du_b)
      f_grid0_std = f_grid0.std()
      converged = f_grid0_std < 0.1
      if not converged:
        self.log.tee("  with %s translations "%n_trans_n + \
                 "the predicted free energy difference is %.5g (%.5g)"%(\
                 f_grid0.mean(),f_grid0_std))
        if n_trans_n == self.data['CD']._max_n_trans:
          break
        n_trans_o = n_trans_n
        n_trans_n = min(n_trans_n + 25, self.data['CD']._max_n_trans)
        for term in (['MM', 'site'] + scalables):
          # Large array creation may cause MemoryError
          E[term] = np.dstack((E[term], \
            np.zeros((self.args.params['CD']['seeds_per_state'],\
              self.data['CD']._max_n_rot,25))))

    if self.data['CD']._n_trans != n_trans_n:
      self.data['CD']._n_trans = n_trans_n

    self.log.tee("  %d ligand configurations "%len(BC0_Es_MM) + \
             "were randomly docked into the binding site using "+ \
             "%d translations and %d rotations "%(n_trans_n,self._n_rot))
    self.log.tee("  the predicted free energy difference between the" + \
             " first and second CD states is " + \
             "%.5g (%.5g)"%(f_grid0.mean(),f_grid0_std))

    self.log.recordStart('ravel')
    for term in E.keys():
      E[term] = np.ravel(E[term][:, :self._n_rot, :self.data['CD']._n_trans])
    self.log.tee("  raveled energy terms in " + \
      HMStime(self.log.timeSince('ravel')))

    return (BC0_confs, E)
    def __call__(self, **options):
        # Process the keyword arguments
        self.setCallOptions(options)
        # Check if the universe has features not supported by the integrator
        Features.checkFeatures(self, self.universe)
      
        RT = R*self.getOption('T')
        delta_t = self.getOption('delta_t')
        
        if 'steps_per_trial' in self.call_options.keys():
          steps_per_trial = self.getOption('steps_per_trial')
          ntrials = self.getOption('steps')/steps_per_trial
        else:
          steps_per_trial = self.getOption('steps')
          ntrials = 1
  
        if 'normalize' in self.call_options.keys():
          normalize = self.getOption('normalize')
        else:
          normalize = False          

        # Seed the random number generator
        if 'random_seed' in self.call_options.keys():
          np.random.seed(self.getOption('random_seed'))

        self.universe.initializeVelocitiesToTemperature(self.getOption('T'))
        
        # Get the universe variables needed by the integrator
        masses = self.universe.masses()
        fixed = self.universe.getAtomBooleanArray('fixed')
        nt = self.getOption('threads')
        comm = self.getOption('mpi_communicator')
        evaluator = self.universe.energyEvaluator(threads=nt,
                                                  mpi_communicator=comm)
        evaluator = evaluator.CEvaluator()

        late_args = (
                masses.array, fixed.array, evaluator,
                N.zeros((0, 2), N.Int), N.zeros((0, ), N.Float),
                N.zeros((1,), N.Int),
                N.zeros((0,), N.Float), N.zeros((2,), N.Float),
                N.zeros((0,), N.Float), N.zeros((1,), N.Float),
                delta_t, self.getOption('first_step'),
                steps_per_trial, self.getActions(),
                'Hamiltonian Monte Carlo step')

        # Variables for velocity assignment
        m3 = np.repeat(np.expand_dims(masses.array,1),3,axis=1)
        sigma_MB = np.sqrt((self.getOption('T')*Units.k_B)/m3)
        natoms = self.universe.numberOfAtoms()

        xs = []
        energies = []

        # Store initial configuration and potential energy
        xo = np.copy(self.universe.configuration().array)
        self.sampling_universe.configuration().array[-natoms:,:] = xo
        pe_o = self.sampling_universe.energy() # <- Using sampling Hamiltonian
                                            # rather than guidance Hamiltonian

        acc = 0
        for t in range(ntrials):
          # Initialize the velocity
          v = self.universe.velocities()
          v.array = np.multiply(sigma_MB,np.random.randn(natoms,3))
    
          # Store total energy
          eo = pe_o + 0.5*np.sum(np.multiply(m3,np.square(v.array)))

          # Run the velocity verlet integrator
          self.run(MMTK_dynamics.integrateVV,
            (self.universe,
             self.universe.configuration().array,
             self.universe.velocities().array) + late_args)

          # Decide whether to accept the move
          self.sampling_universe.configuration().array[-natoms:,:] = \
            self.universe.configuration().array
          pe_n = self.sampling_universe.energy() # <- Using sampling Hamiltonian
                                              # rather than guidance Hamiltonian
          en = pe_n + 0.5*np.sum(np.multiply(m3,np.square(v.array)))

          # TODO: Confirm acceptance criterion
          if ((en<eo) or (np.random.random()<N.exp(-(en-eo)/RT))) and \
             ((abs(pe_o-pe_n)/RT<250.) or (abs(eo-en)/RT<250.)):
            xo = np.copy(self.universe.configuration().array)
            pe_o = pe_n
            acc += 1
            if normalize:
              self.universe.normalizePosition()
          else:
            self.universe.setConfiguration(Configuration(self.universe,xo))
          
          xs.append(np.copy(self.universe.configuration().array))
          energies.append(pe_o)
  
        return (xs, energies, acc, ntrials, delta_t)
示例#7
0
    def setParams(self, params):
        """Sets the universe evaluator to values appropriate for the parameters.

    Parameters
    ----------
    params : dict
      The elements in the dictionary params can be:
        MM - True, to turn on the Generalized AMBER force field
        site - True, to turn on the binding site
        sLJr - scaling of the soft Lennard-Jones repulsive grid
        sLJa - scaling of the soft Lennard-Jones attractive grid
        sELE - scaling of the soft electrostatic grid
        LJr - scaling of the Lennard-Jones repulsive grid
        LJa - scaling of the Lennard-Jones attractive grid
        ELE - scaling of the electrostatic grid
        k_angular_int - spring constant of flat-bottom wells for angular internal degrees of freedom (kJ/nm)
        k_spatial_ext - spring constant of flat-bottom wells for spatial external degrees of freedom (kJ/nm)
        k_angular_ext - spring constant of flat-bottom wells for angular external degrees of freedom (kJ/nm)
        T - the temperature in K
    """

        self.T = params['T']

        # Reuse evaluators that have been stored
        evaluator_key = ','.join(['%s:%s'%(k,params[k]) \
          for k in sorted(params.keys())])
        if evaluator_key in self._evaluators.keys():
            self.top.universe._evaluator[(None,None,None)] = \
              self._evaluators[evaluator_key]
            return

        # Otherwise create a new evaluator
        fflist = []
        if ('MM' in params.keys()) and params['MM']:
            fflist.append(self._forceFields['gaff'])
        if ('site' in params.keys()) and params['site']:
            # Set up the binding site in the force field
            append_site = True  # Whether to append the binding site to the force field
            if not 'site' in self._forceFields.keys():
                if (self.args.params['CD']['site']=='Sphere') and \
                   (self.args.params['CD']['site_center'] is not None) and \
                   (self.args.params['CD']['site_max_R'] is not None):
                    from AlGDock.ForceFields.Sphere.Sphere import SphereForceField
                    self._forceFields['site'] = SphereForceField(
                        center=self.args.params['CD']['site_center'],
                        max_R=self.args.params['CD']['site_max_R'],
                        name='site')
                elif (self.args.params['CD']['site']=='Cylinder') and \
                     (self.args.params['CD']['site_center'] is not None) and \
                     (self.args.params['CD']['site_direction'] is not None):
                    from AlGDock.ForceFields.Cylinder.Cylinder import CylinderForceField
                    self._forceFields['site'] = CylinderForceField(
                        origin=self.args.params['CD']['site_center'],
                        direction=self.args.params['CD']['site_direction'],
                        max_Z=self.args.params['CD']['site_max_Z'],
                        max_R=self.args.params['CD']['site_max_R'],
                        name='site')
                else:
                    # Do not append the site if it is not defined
                    print 'Binding site not defined!'
                    append_site = False
            if append_site:
                fflist.append(self._forceFields['site'])

        # Add scalable terms
        for scalable in scalables:
            if (scalable in params.keys()) and params[scalable] > 0:
                # Load the force field if it has not been loaded
                if not scalable in self._forceFields.keys():
                    if scalable == 'OBC':
                        from AlGDock.ForceFields.OBC.OBC import OBCForceField
                        if self.args.params['CD']['solvation']=='Fractional' and \
                            ('ELE' in params.keys()):
                            self.log.recordStart('grid_loading')
                            self._forceFields['OBC'] = OBCForceField(\
                              desolvationGridFN=self.args.FNs['grids']['desolv'])
                            self.log.tee('  %s grid loaded from %s in %s'%(scalable, \
                              os.path.basename(self.args.FNs['grids']['desolv']), \
                              HMStime(self.log.timeSince('grid_loading'))))
                        else:
                            self._forceFields['OBC'] = OBCForceField()
                    else:  # Grids
                        self.log.recordStart('grid_loading')
                        grid_FN = self.args.FNs['grids'][{
                            'sLJr': 'LJr',
                            'sLJa': 'LJa',
                            'sELE': 'ELE',
                            'LJr': 'LJr',
                            'LJa': 'LJa',
                            'ELE': 'ELE'
                        }[scalable]]
                        grid_scaling_factor = 'scaling_factor_' + \
                          {'sLJr':'LJr','sLJa':'LJa','sELE':'electrostatic', \
                           'LJr':'LJr','LJa':'LJa','ELE':'electrostatic'}[scalable]

                        # Determine the grid threshold
                        if scalable == 'sLJr':
                            grid_thresh = 10.0
                        elif scalable == 'sELE':
                            # The maximum value is set so that the electrostatic energy
                            # less than or equal to the Lennard-Jones repulsive energy
                            # for every heavy atom at every grid point
                            # TODO: For conversion to OpenMM, get ParticleProperties from the Force object
                            scaling_factors_ELE = np.array([ \
                              self.top.molecule.getAtomProperty(a, 'scaling_factor_electrostatic') \
                                for a in self.top.molecule.atomList()],dtype=float)
                            scaling_factors_LJr = np.array([ \
                              self.top.molecule.getAtomProperty(a, 'scaling_factor_LJr') \
                                for a in self.top.molecule.atomList()],dtype=float)
                            toKeep = np.logical_and(
                                scaling_factors_LJr > 10.,
                                abs(scaling_factors_ELE) > 0.1)
                            scaling_factors_ELE = scaling_factors_ELE[toKeep]
                            scaling_factors_LJr = scaling_factors_LJr[toKeep]
                            grid_thresh = min(
                                abs(scaling_factors_LJr * 10.0 /
                                    scaling_factors_ELE))
                        else:
                            grid_thresh = -1  # There is no threshold for grid points

                        from AlGDock.ForceFields.Grid.Interpolation \
                          import InterpolationForceField
                        self._forceFields[scalable] = InterpolationForceField(grid_FN, \
                          name=scalable, interpolation_type='Trilinear', \
                          strength=params[scalable], scaling_property=grid_scaling_factor,
                          inv_power=4 if scalable=='LJr' else None, \
                          grid_thresh=grid_thresh)
                        self.log.tee('  %s grid loaded from %s in %s'%(scalable, \
                          os.path.basename(grid_FN), \
                          HMStime(self.log.timeSince('grid_loading'))))

                # Set the force field strength to the desired value
                self._forceFields[scalable].set_strength(params[scalable])
                fflist.append(self._forceFields[scalable])

        if ('k_angular_int' in params.keys()) or \
           ('k_spatial_ext' in params.keys()) or \
           ('k_angular_ext' in params.keys()):

            # Load the force field if it has not been loaded
            if not ('ExternalRestraint' in self._forceFields.keys()):
                Xo = np.copy(self.top.universe.configuration().array)
                self.top.universe.setConfiguration(
                    Configuration(self.top.universe, self.starting_pose))
                import AlGDock.rigid_bodies
                rb = AlGDock.rigid_bodies.identifier(self.top.universe,
                                                     self.top.molecule)
                (TorsionRestraintSpecs, ExternalRestraintSpecs) = rb.poseInp()
                self.top.universe.setConfiguration(
                    Configuration(self.top.universe, Xo))

                # Create force fields
                from AlGDock.ForceFields.Pose.PoseFF import InternalRestraintForceField
                self._forceFields['InternalRestraint'] = \
                  InternalRestraintForceField(TorsionRestraintSpecs)
                from AlGDock.ForceFields.Pose.PoseFF import ExternalRestraintForceField
                self._forceFields['ExternalRestraint'] = \
                  ExternalRestraintForceField(*ExternalRestraintSpecs)

            # Set parameter values
            if ('k_angular_int' in params.keys()):
                self._forceFields['InternalRestraint'].set_k(\
                  params['k_angular_int'])
                fflist.append(self._forceFields['InternalRestraint'])

            if ('k_spatial_ext' in params.keys()):
                self._forceFields['ExternalRestraint'].set_k_spatial(\
                  params['k_spatial_ext'])
                fflist.append(self._forceFields['ExternalRestraint'])

            if ('k_angular_ext' in params.keys()):
                self._forceFields['ExternalRestraint'].set_k_angular(\
                  params['k_angular_ext'])

        compoundFF = fflist[0]
        for ff in fflist[1:]:
            compoundFF += ff
        self.top.universe.setForceField(compoundFF)

        if self.top_RL.universe is not None:
            if 'OBC_RL' in params.keys():
                if not 'OBC_RL' in self._forceFields.keys():
                    from AlGDock.ForceFields.OBC.OBC import OBCForceField
                    self._forceFields['OBC_RL'] = OBCForceField()
                self._forceFields['OBC_RL'].set_strength(params['OBC_RL'])
                if (params['OBC_RL'] > 0):
                    self.top_RL.universe.setForceField(
                        self._forceFields['OBC_RL'])

        eval = ForceField.EnergyEvaluator(\
          self.top.universe, self.top.universe._forcefield, None, None, None, None)
        eval.key = evaluator_key
        self.top.universe._evaluator[(None, None, None)] = eval
        self._evaluators[evaluator_key] = eval
示例#8
0
    def energyTerms(self, confs, E=None, process='CD'):
        """Calculates energy terms for a series of configurations

    Units are kJ/mol.

    Parameters
    ----------
    confs : list of np.array
      Configurations
    E : dict of np.array
      Dictionary to add to
    process : str
      Process, either 'BC' or 'CD'

    Returns
    -------
    E : dict of np.array
      Dictionary of energy terms
    """
        if E is None:
            E = {}

        params_full = self.paramsFromAlpha(alpha=1.0,
                                           process=process,
                                           site=(process == 'CD'))
        if process == 'CD':
            for scalable in scalables:
                params_full[scalable] = 1
        self.setParams(params_full)

        # Molecular mechanics and grid interaction energies
        E['MM'] = np.zeros(len(confs), dtype=float)
        if process == 'BC':
            if 'OBC' in params_full.keys():
                E['OBC'] = np.zeros(len(confs), dtype=float)
        if process == 'CD':
            for term in (scalables):
                E[term] = np.zeros(len(confs), dtype=float)
            if self.isForce('site'):
                E['site'] = np.zeros(len(confs), dtype=float)
            if self.isForce('InternalRestraint'):
                E['k_angular_int'] = np.zeros(len(confs), dtype=float)
            if self.isForce('ExternalRestraint'):
                E['k_angular_ext'] = np.zeros(len(confs), dtype=float)
                E['k_spatial_ext'] = np.zeros(len(confs), dtype=float)
        for c in range(len(confs)):
            self.top.universe.setConfiguration(
                Configuration(self.top.universe, confs[c]))
            eT = self.top.universe.energyTerms()
            for (key, value) in eT.iteritems():
                if key == 'electrostatic':
                    pass  # For some reason, MMTK double-counts electrostatic energies
                elif key.startswith('pose'):
                    # For pose restraints, the energy is per spring constant unit
                    E[term_map[key]][c] += value / params_full[term_map[key]]
                else:
                    try:
                        E[term_map[key]][c] += value
                    except KeyError:
                        print key
                        print 'Keys in eT', eT.keys()
                        print 'Keys in term map', term_map.keys()
                        print 'Keys in E', E.keys()
                        raise Exception('key not found in term map or E')
        return E
示例#9
0
    def __call__(self, **options):
        # Process the keyword arguments
        self.setCallOptions(options)
        # Check if the universe has features not supported by the integrator
        Features.checkFeatures(self, self.universe)

        RT = R * self.getOption('T')
        delta_t = self.getOption('delta_t')

        if 'steps_per_trial' in self.call_options.keys():
            steps_per_trial = self.getOption('steps_per_trial')
            ntrials = self.getOption('steps') / steps_per_trial
        else:
            steps_per_trial = self.getOption('steps')
            ntrials = 1

        if 'max_diff' in self.call_options.keys():
            max_diff = self.getOption('max_diff')
        else:
            max_diff = 1000.

        if 'normalize' in self.call_options.keys():
            normalize = self.getOption('normalize')
        else:
            normalize = False

        # Seed the random number generator
        if 'random_seed' in self.call_options.keys():
            np.random.seed(self.getOption('random_seed'))

        # Get the universe variables needed by the integrator
        masses = self.universe.masses()
        fixed = self.universe.getAtomBooleanArray('fixed')
        nt = self.getOption('threads')
        comm = self.getOption('mpi_communicator')
        evaluator = self.universe.energyEvaluator(threads=nt,
                                                  mpi_communicator=comm)
        evaluator = evaluator.CEvaluator()

        late_args = (masses.array, fixed.array, evaluator,
                     N.zeros((0, 2), N.Int), N.zeros(
                         (0, ), N.Float), N.zeros((1, ), N.Int),
                     N.zeros((0, ), N.Float), N.zeros(
                         (2, ), N.Float), N.zeros(
                             (0, ), N.Float), N.zeros((1, ), N.Float), delta_t,
                     self.getOption('first_step'), steps_per_trial,
                     self.getActions(), 'Velocity Verlet step')

        xs = []
        energies = []

        # Store initial configuration and potential energy
        xo = np.copy(self.universe.configuration().array)
        pe_o = self.universe.energy()

        acc = 0
        for t in range(ntrials):
            # Initialize the velocity
            self.universe.initializeVelocitiesToTemperature(
                self.getOption('T'))
            # Store total energy
            eo = pe_o + self.universe.kineticEnergy()

            # Run the velocity verlet integrator
            self.run(MMTK_dynamics.integrateVV,
                     (self.universe, self.universe.configuration().array,
                      self.universe.velocities().array) + late_args)

            # Decide whether to accept the move
            pe_n = self.universe.energy()
            en = pe_n + self.universe.kineticEnergy()

            diff = np.abs(en - eo)

            if (not np.isnan(en)) and (diff < max_diff):
                xo = np.copy(self.universe.configuration().array)
                pe_o = pe_n
                acc += 1
                if normalize:
                    self.universe.normalizePosition()
            else:
                # print diff
                self.universe.setConfiguration(Configuration(
                    self.universe, xo))

            xs.append(np.copy(self.universe.configuration().array))
            energies.append(pe_o)

        return (xs, energies, acc, ntrials, delta_t)
示例#10
0
    def _prepare_ligand_BC(self):
        """Prepares the ligand for BC simulations

    Returns
    -------
    seeds : list of np.array
      Ligand configurations minimized in milestone B
    """
        if self.data['BC'].protocol == []:

            # Set up the force field
            params_o = self.system.paramsFromAlpha(1.0, 'BC', site=False)
            self.system.setParams(params_o)

            # Get starting configurations
            basename = os.path.basename(self.args.FNs['score'])
            basename = basename[:basename.find('.')]
            dirname = os.path.dirname(self.args.FNs['score'])
            minimizedB_FN = os.path.join(dirname, basename + '_minB.nc')
            if os.path.isfile(minimizedB_FN):
                from netCDF4 import Dataset
                dock6_nc = Dataset(minimizedB_FN, 'r')
                minimizedConfigurations = [
                    dock6_nc.variables['confs'][n][
                        self.top.inv_prmtop_atom_order_L, :]
                    for n in range(dock6_nc.variables['confs'].shape[0])
                ]
                Es = dict([(key, dock6_nc.variables[key][:])
                           for key in dock6_nc.variables.keys()
                           if key != 'confs'])
                dock6_nc.close()
            else:
                (minimizedConfigurations,
                 Es) = self._get_confs_to_rescore(site=False, minimize=True)

                from netCDF4 import Dataset
                dock6_nc = Dataset(minimizedB_FN, 'w')
                dock6_nc.createDimension('n_confs',
                                         len(minimizedConfigurations))
                dock6_nc.createDimension('n_atoms',
                                         minimizedConfigurations[0].shape[0])
                dock6_nc.createDimension('n_cartesian', 3)
                dock6_nc.createDimension('one', 1)
                dock6_nc.createVariable('confs', 'f8',
                                        ('n_confs', 'n_atoms', 'n_cartesian'))
                for n in range(len(minimizedConfigurations)):
                    dock6_nc.variables['confs'][n] = minimizedConfigurations[
                        n][self.top.prmtop_atom_order_L, :]
                for key in Es.keys():
                    dock6_nc.createVariable(key, 'f8', ('one', 'n_confs'))
                    dock6_nc.variables[key][:] = Es[key]
                dock6_nc.close()

            # initializes smart darting for BC
            # and sets the universe to the lowest energy configuration
            self.iterator.initializeSmartDartingConfigurations(
                minimizedConfigurations, 'BC', self.log, self.data)
            if len(minimizedConfigurations) > 0:
                self.top.universe.setConfiguration(
                    Configuration(self.top.universe,
                                  minimizedConfigurations[-1]))
            self.data['BC'].confs['starting_poses'] = minimizedConfigurations

            # Ramp the temperature from 0 to the desired starting temperature using HMC
            self._ramp_T(params_o['T'], normalize=True)

            # Run at starting temperature
            seeds = [np.copy(self.top.universe.configuration().array) \
              for n in range(self.args.params['BC']['seeds_per_state'])]
        else:
            seeds = None
        return seeds
示例#11
0
    def _ramp_T(self, T_START, T_LOW=20., normalize=False):
        """Ramp the temperature from T_LOW to T_START

    Parameters
    ----------
    T_START : float
      The final temperature
    T_LOW : float
      The lowest temperature in the ramp
    normalize : bool
      If True, the ligand center of mass will be normalized
    """
        self.log.recordStart('T_ramp')

        # First minimize the energy
        from MMTK.Minimization import SteepestDescentMinimizer  # @UnresolvedImport
        minimizer = SteepestDescentMinimizer(self.top.universe)

        original_stderr = sys.stderr
        sys.stderr = NullDevice()  # Suppresses warnings for minimization

        x_o = np.copy(self.top.universe.configuration().array)
        e_o = self.top.universe.energy()
        for rep in range(5000):
            minimizer(steps=10)
            x_n = np.copy(self.top.universe.configuration().array)
            e_n = self.top.universe.energy()
            diff = abs(e_o - e_n)
            if np.isnan(e_n) or diff < 0.05 or diff > 1000.:
                self.top.universe.setConfiguration(
                    Configuration(self.top.universe, x_o))
                break
            else:
                x_o = x_n
                e_o = e_n

        sys.stderr = original_stderr
        self.log.tee("  minimized to %.3g kcal/mol over %d steps" %
                     (e_o, 10 * (rep + 1)))

        # Then ramp the energy to the starting temperature
        from AlGDock.Integrators.HamiltonianMonteCarlo.HamiltonianMonteCarlo \
          import HamiltonianMonteCarloIntegrator
        sampler = HamiltonianMonteCarloIntegrator(self.top.universe)

        e_o = self.top.universe.energy()
        T_LOW = 20.
        T_SERIES = T_LOW * (T_START / T_LOW)**(np.arange(30) / 29.)
        for T in T_SERIES:
            delta_t = 2.0 * MMTK.Units.fs
            steps_per_trial = 10
            attempts_left = 10
            while attempts_left > 0:
                random_seed = int(T*10000) + attempts_left + \
                  int(self.top.universe.configuration().array[0][0]*10000)
                if self.args.random_seed == 0:
                    random_seed += int(time.time() * 1000)
                random_seed = random_seed % 32767
                (xs, energies, acc, ntrials, delta_t) = \
                  sampler(steps = 2500, steps_per_trial = 10, T=T,\
                          delta_t=delta_t, random_seed=random_seed)
                attempts_left -= 1
                acc_rate = float(acc) / ntrials
                if acc_rate < 0.4:
                    delta_t -= 0.25 * MMTK.Units.fs
                else:
                    attempts_left = 0
                if delta_t < 0.1 * MMTK.Units.fs:
                    delta_t = 0.1 * MMTK.Units.fs
                    steps_per_trial = max(int(steps_per_trial / 2), 1)
            fmt = "  T = %d, delta_t = %.3f fs, steps_per_trial = %d, acc_rate = %.3f"
            if acc_rate < 0.01:
                print self.top.universe.energyTerms()
            self.log.tee(fmt % (T, delta_t * 1000, steps_per_trial, acc_rate))
        if normalize:
            self.top.universe.normalizePosition()
        e_f = self.top.universe.energy()

        self.log.tee("  ramped temperature from %d to %d K in %s, "%(\
          T_LOW, T_START, HMStime(self.log.timeSince('T_ramp'))) + \
          "changing energy to %.3g kcal/mol\n"%(e_f))
示例#12
0
    def iteration(self, seed, process, params_k, \
        initialize=False, reference=0):
        """Performs an iteration for a single thermodynamic state

    Parameters
    ----------
    seed : np.array
      Starting configuration
    process : str
      Process, either 'BC' or 'CD'
    params_k : dict of float
      Parameters describing a thermodynamic state
    """

        self.top.universe.setConfiguration(
            Configuration(self.top.universe, seed))

        self.system.setParams(params_k)
        if 'delta_t' in params_k.keys():
            delta_t = params_k['delta_t']
        else:
            raise Exception('No time step specified')
        if 'steps_per_trial' in params_k.keys():
            steps_per_trial = params_k['steps_per_trial']
        else:
            steps_per_trial = self.args.params[process]['steps_per_sweep']

        if initialize:
            steps = self.args.params[process]['steps_per_seed']
            ndarts = self.args.params[process]['darts_per_seed']
        else:
            steps = self.args.params[process]['steps_per_sweep']
            ndarts = self.args.params[process]['darts_per_sweep']

        random_seed = reference * reference + int(abs(seed[0][0] * 10000))
        if self.args.random_seed > 0:
            random_seed += self.args.random_seed
        else:
            random_seed += int(time.time() * 1000)

        results = {}

        # Execute external MCMC moves
        if (process == 'CD') and (self.args.params['CD']['MCMC_moves']>0) \
            and (params_k['alpha'] < 0.1) and (self.args.params['CD']['pose']==-1):
            time_start_ExternalMC = time.time()
            dat = self._samplers['ExternalMC'](ntrials=5, T=params_k['T'])
            results['acc_ExternalMC'] = dat[2]
            results['att_ExternalMC'] = dat[3]
            results['time_ExternalMC'] = (time.time() - time_start_ExternalMC)

        # Execute dynamics sampler
        time_start_sampler = time.time()
        dat = self._samplers[process](\
          steps=steps, steps_per_trial=steps_per_trial, \
          T=params_k['T'], delta_t=delta_t, \
          normalize=(process=='BC'), adapt=initialize, random_seed=random_seed)
        results['acc_Sampler'] = dat[2]
        results['att_Sampler'] = dat[3]
        results['delta_t'] = dat[4]
        results['time_Sampler'] = (time.time() - time_start_sampler)

        # Execute smart darting
        if (ndarts > 0) and not ((process == 'CD') and
                                 (params_k['alpha'] < 0.1)):
            time_start_SmartDarting = time.time()
            dat = self._samplers[process+'_SmartDarting'](\
              ntrials=ndarts, T=params_k['T'], random_seed=random_seed+5)
            results['acc_SmartDarting'] = dat[2]
            results['att_SmartDarting'] = dat[3]
            results['time_SmartDarting'] = (time.time() -
                                            time_start_SmartDarting)

        # Store and return results
        results['confs'] = np.copy(dat[0][-1])
        results['Etot'] = dat[1][-1]
        results['reference'] = reference

        return results
示例#13
0
 def do_gMC(nr_attempts, BAT_converter, state_indices_to_swap,
            torsion_threshold):
   """
   Assume self.top.universe, confs, protocol, state_inds, inv_state_inds exist as global variables
   when the function is called.
   If at least one of the torsions in the combination chosen for an crossover attempt
   changes more than torsion_threshold, the crossover will be attempted.
   The function will update confs.
   It returns the number of attempts and the number of accepted moves.
   """
   if nr_attempts < 0:
     raise Exception('Number of attempts must be nonnegative!')
   if torsion_threshold < 0.:
     raise Exception('Torsion threshold must be nonnegative!')
   #
   if len(BAT_converter.BAT_to_crossover) == 0:
     return 0., 0.
   #
   from random import randrange
   # get reduced energies and BAT for all configurations in confs
   BATs = []
   energies = np.zeros(K, dtype=float)
   for c_ind in range(K):
     s_ind = state_inds[c_ind]
     self.top.universe.setConfiguration(
       Configuration(self.top.universe, confs[c_ind]))
     BATs.append(np.array(BAT_converter.BAT(extended=True), dtype=float))
     self.system.setParams(protocol[s_ind])
     reduced_e = self.top.universe.energy() / (R * protocol[s_ind]['T'])
     energies[c_ind] = reduced_e
   #
   nr_sets_of_torsions = len(BAT_converter.BAT_to_crossover)
   #
   attempt_count, acc_count = 0, 0
   sweep_count = 0
   while True:
     sweep_count += 1
     if (sweep_count * K) > (1000 * nr_attempts):
       self.log.tee(
         '  GMC Sweep too many times, but few attempted. Consider reducing torsion_threshold.'
       )
       return attempt_count, acc_count
     #
     for state_pair in state_indices_to_swap:
       conf_ind_k0 = inv_state_inds[state_pair[0]]
       conf_ind_k1 = inv_state_inds[state_pair[1]]
       # check if it should attempt for this pair of states
       ran_set_torsions = BAT_converter.BAT_to_crossover[randrange(
         nr_sets_of_torsions)]
       do_crossover = np.any(
         np.abs(BATs[conf_ind_k0][ran_set_torsions] -
                BATs[conf_ind_k1][ran_set_torsions]) >= torsion_threshold)
       if do_crossover:
         attempt_count += 1
         # BAT and reduced energies before crossover
         BAT_k0_be = copy.deepcopy(BATs[conf_ind_k0])
         BAT_k1_be = copy.deepcopy(BATs[conf_ind_k1])
         e_k0_be = energies[conf_ind_k0]
         e_k1_be = energies[conf_ind_k1]
         # BAT after crossover
         BAT_k0_af = copy.deepcopy(BAT_k0_be)
         BAT_k1_af = copy.deepcopy(BAT_k1_be)
         for index in ran_set_torsions:
           tmp = BAT_k0_af[index]
           BAT_k0_af[index] = BAT_k1_af[index]
           BAT_k1_af[index] = tmp
         # Cartesian coord and reduced energies after crossover.
         BAT_converter.Cartesian(BAT_k0_af)
         self.system.setParams(protocol[state_pair[0]])
         e_k0_af = self.top.universe.energy() / (
           R * protocol[state_pair[0]]['T'])
         conf_k0_af = copy.deepcopy(self.top.universe.configuration().array)
         #
         BAT_converter.Cartesian(BAT_k1_af)
         self.system.setParams(protocol[state_pair[1]])
         e_k1_af = self.top.universe.energy() / (
           R * protocol[state_pair[1]]['T'])
         conf_k1_af = copy.deepcopy(self.top.universe.configuration().array)
         #
         de = (e_k0_be - e_k0_af) + (e_k1_be - e_k1_af)
         # update confs, energies, BATS
         if (de > 0) or (np.random.uniform() < np.exp(de)):
           acc_count += 1
           confs[conf_ind_k0] = conf_k0_af
           confs[conf_ind_k1] = conf_k1_af
           #
           energies[conf_ind_k0] = e_k0_af
           energies[conf_ind_k1] = e_k1_af
           #
           BATs[conf_ind_k0] = BAT_k0_af
           BATs[conf_ind_k1] = BAT_k1_af
         #
         if attempt_count == nr_attempts:
           return attempt_count, acc_count
 def _set_configuration(self, universe, conf_array):
     universe.setConfiguration(Configuration(universe, conf_array))
     return None