def calculate(self, atoms, properties, system_changes): Calculator.calculate(self, atoms, properties, system_changes) if system_changes: if 'energy' in self.results: del self.results['energy'] if 'forces' in self.results: del self.results['forces'] if 'energy' not in self.results: if self.permutation is None: crd = np.reshape(atoms.get_positions(), (1, len(atoms), 3)) else: crd = np.reshape(atoms.get_positions()[self.permutation[0, :]], (1, len(atoms), 3)) sander.set_positions(crd) e, f = sander.energy_forces() self.results['energy'] = e.tot * units.kcal / units.mol if self.permutation is None: self.results['forces'] = (np.reshape(np.array(f), (len(atoms), 3)) * units.kcal / units.mol) else: ff = np.reshape(np.array(f), (len(atoms), 3)) * \ units.kcal / units.mol self.results['forces'] = ff[self.permutation[1, :]] if 'forces' not in self.results: if self.permutation is None: crd = np.reshape(atoms.get_positions(), (1, len(atoms), 3)) else: crd = np.reshape(atoms.get_positions()[self.permutation[0, :]], (1, len(atoms), 3)) sander.set_positions(crd) e, f = sander.energy_forces() self.results['energy'] = e.tot * units.kcal / units.mol if self.permutation is None: self.results['forces'] = (np.reshape(np.array(f), (len(atoms), 3)) * units.kcal / units.mol) else: ff = np.reshape(np.array(f), (len(atoms), 3)) * \ units.kcal / units.mol self.results['forces'] = ff[self.permutation[1, :]]
def calculate(self, atoms, properties, system_changes): Calculator.calculate(self, atoms, properties, system_changes) if system_changes: if 'energy' in self.results: del self.results['energy'] if 'forces' in self.results: del self.results['forces'] if 'energy' not in self.results: if self.permutation is None: crd = np.reshape(atoms.get_positions(), (1, len(atoms), 3)) else: crd = np.reshape(atoms.get_positions() [self.permutation[0, :]], (1, len(atoms), 3)) sander.set_positions(crd) e, f = sander.energy_forces() self.results['energy'] = e.tot * units.kcal / units.mol if self.permutation is None: self.results['forces'] = (np.reshape(np.array(f), (len(atoms), 3)) * units.kcal / units.mol) else: ff = np.reshape(np.array(f), (len(atoms), 3)) * \ units.kcal / units.mol self.results['forces'] = ff[self.permutation[1, :]] if 'forces' not in self.results: if self.permutation is None: crd = np.reshape(atoms.get_positions(), (1, len(atoms), 3)) else: crd = np.reshape(atoms.get_positions()[self.permutation[0, :]], (1, len(atoms), 3)) sander.set_positions(crd) e, f = sander.energy_forces() self.results['energy'] = e.tot * units.kcal / units.mol if self.permutation is None: self.results['forces'] = (np.reshape(np.array(f), (len(atoms), 3)) * units.kcal / units.mol) else: ff = np.reshape(np.array(f), (len(atoms), 3)) * \ units.kcal / units.mol self.results['forces'] = ff[self.permutation[1, :]]
import numpy as np import pytraj as pt import sander traj = pt.datafiles.load_tz2() inp = sander.gas_input(8) frcs = [] with sander.setup(traj.top.filename, traj[0].xyz, traj.top.box, inp): for frame in traj: sander.set_box(*frame.box.tolist()) sander.set_positions(frame.xyz) ene, frc = sander.energy_forces() frcs.append(np.array(frc).reshape(traj.n_atoms, 3)) def get_frame_with_force(traj, forces=frcs): frame0 = pt.Frame() crdinfo = dict(has_force=True) frame0._allocate_force_and_velocity(traj.top, crdinfo) for frame, frc in zip(traj, frcs): frame0.xyz[:] = frame.xyz frame0.force[:] = frc yield frame0 pt.write_traj('traj.nc',
def energy_function(xyz): sander.set_positions(xyz) e, f = sander.energy_forces() return e.tot, -np.array(f)
import pickle base = '1nie' # parm = AmberParm('4amber_%s.prmtop' %base) #topo rst = Rst7.open('4amber_%s.rst7' %base) #box coords1 = rst.coordinates coords2 = np.around( np.array(pickle.load(open('tmp2','rb') ) ), 3) #2nd coordinate set print coords1, coords1.shape print coords2, coords2.shape sander.setup('4amber_%s.prmtop' %base, rst.coordinates, rst.box, sander.pme_input()) ene, frc = sander.energy_forces() print frc[0] sander.set_positions(coords1) ene, frc = sander.energy_forces() print frc[0] sander.set_positions(coords2) ene, frc = sander.energy_forces() print frc[0] print max(frc) print ene.tot, ene.elec, ene.vdw # import code; code.interact(local=dict(globals(), **locals())) import boost.python sander.set_positions(rst.coordinates) ene, frc = sander.energy_forces() print frc[0]
base = '1nie' # parm = AmberParm('4amber_%s.prmtop' %base) #topo rst = Rst7.open('4amber_%s.rst7' % base) #box coords1 = rst.coordinates coords2 = np.around(np.array(pickle.load(open('tmp2', 'rb'))), 3) #2nd coordinate set print coords1, coords1.shape print coords2, coords2.shape sander.setup('4amber_%s.prmtop' % base, rst.coordinates, rst.box, sander.pme_input()) ene, frc = sander.energy_forces() print frc[0] sander.set_positions(coords1) ene, frc = sander.energy_forces() print frc[0] sander.set_positions(coords2) ene, frc = sander.energy_forces() print frc[0] print max(frc) print ene.tot, ene.elec, ene.vdw # import code; code.interact(local=dict(globals(), **locals())) import boost.python sander.set_positions(rst.coordinates) ene, frc = sander.energy_forces() print frc[0]
def energy_decomposition(traj=None, prmtop=None, igb=8, mm_options=None, qm_options=None, mode=None, dtype='dict', frame_indices=None, top=None): """energy decomposition by calling `libsander` Parameters ---------- traj : Trajectory-like or iterables that produce Frame if `traj` does not hold Topology information, `top` must be provided prmtop : str or Structure from ParmEd, default=None, optional To avoid any unexpected error, you should always provide original topology filename. If prmtop is None, pytraj will load Topology from traj.top.filename. - why do you need to load additional topology filename? Because cpptraj and sander use different Topology object, can not convert from one to another. igb : GB model, default=8 (GB-Neck2) If specify `mm_options`, this `igb` input will be ignored mm_options : InputOptions from `sander`, default=None, optional if `mm_options` is None, use `gas_input` with given igb. If `mm_options` is not None, use this qm_options : InputOptions from `sander` for QMMM, optional mode : str, default=None, optional if mode='minimal', get only 'bond', 'angle', 'dihedral' and 'total' energies top : pytraj.Topology or str, default=None, optional only need to specify this ``top`` if ``traj`` does not hold Topology dtype : str, {'dict', 'dataset', 'ndarray', 'dataframe'}, default='dict' return data type frame_indices : None or 1D array-like, default None if not None, only perform calculation for given frames Returns ------- Dict of energies (to be used with DataFrame) or DatasetList Examples -------- Examples are adapted from $AMBERHOME/test/sanderapi >>> import pytraj as pt >>> # GB energy >>> traj = pt.datafiles.load_ala3() >>> traj.n_frames 1 >>> data = pt.energy_decomposition(traj, igb=8) >>> data['gb'] array([-92.88577683]) >>> data['bond'] array([ 5.59350521]) >>> # PME >>> import os >>> from pytraj.testing import amberhome >>> import sander >>> topfile = os.path.join(amberhome, "test/4096wat/prmtop") >>> rstfile = os.path.join(amberhome, "test/4096wat/eq1.x") >>> traj = pt.iterload(rstfile, topfile) >>> options = sander.pme_input() >>> options.cut = 8.0 >>> edict = pt.energy_decomposition(traj=traj, mm_options=options) >>> edict['vdw'] array([ 6028.95167558]) >>> # GB + QMMM >>> topfile = os.path.join(amberhome, "test/qmmm2/lysine_PM3_qmgb2/prmtop") >>> rstfile = os.path.join(amberhome, "test/qmmm2/lysine_PM3_qmgb2/lysine.crd") >>> traj = pt.iterload(rstfile, topfile) >>> options = sander.gas_input(8) >>> options.cut = 99.0 >>> options.ifqnt = 1 >>> qm_options = sander.qm_input() >>> qm_options.iqmatoms[:3] = [8, 9, 10] >>> qm_options.qm_theory = "PM3" >>> qm_options.qmcharge = 0 >>> qm_options.qmgb = 2 >>> qm_options.adjust_q = 0 >>> edict = pt.energy_decomposition(traj=traj, mm_options=options, qm_options=qm_options) >>> edict['bond'] array([ 0.00160733]) >>> edict['scf'] array([-11.92177575]) Notes ----- This method does not work with `pytraj.pmap` when you specify mm_options and qm_options. Use `pytraj.pmap_mpi` with MPI instead. Work with ``pytraj.pmap``:: pt.pmap(pt.energy_decomposition, traj, igb=8, dtype='dict') Will NOT work with ``pytraj.pmap``:: import sander inp = sander.gas_input(8) pt.pmap(pt.energy_decomposition, traj, mm_options=inp, dtype='dict') Why? Because Python need to pickle each object to send to different cores and Python does not know how to pickle mm_options from sander.gas_input(8). This works with ``pytraj.pmap_mpi`` because pytraj explicitly create ``mm_options`` in each core without pickling. """ from collections import defaultdict, OrderedDict from pytraj.misc import get_atts import numpy as np try: import sander except ImportError: raise ImportError("need both `pysander` installed. Check Ambertools15") ddict = defaultdict(_default_func) if mm_options is None: inp = sander.gas_input(igb) elif igb is not None: inp = mm_options if isinstance(inp, string_types): # dangerous local_dict = {'sander': sander} exec(inp.lstrip(), local_dict) inp = local_dict['mm_options'] if isinstance(qm_options, string_types): # dangerous local_dict = {'sander': sander} exec(qm_options.lstrip(), local_dict) qm_options = local_dict['qm_options'] if prmtop is None: try: # try to load from file by taking top.filename prmtop_ = top.filename except AttributeError: raise ValueError("prmtop must be AmberParm object in ParmEd") else: # Structure, string prmtop_ = prmtop if not hasattr(prmtop_, 'coordinates') or prmtop_.coordinates is None: try: # if `traj` is Trajectory-like (not frame_iter), try to take 1st # coords coords = traj[0].xyz except (TypeError, AttributeError): # create fake list coords = [0. for _ in range(top.n_atoms * 3)] else: # use default coords in `AmberParm` coords = prmtop_.coordinates if top.has_box(): box = top.box.tolist() has_box = True else: box = None has_box = False with sander.setup(prmtop_, coords, box, inp, qm_options): for frame in iterframe_master(traj): if has_box: sander.set_box(*frame.box.tolist()) sander.set_positions(frame.xyz) ene, frc = sander.energy_forces() # potentially slow ene_atts = get_atts(ene) for att in ene_atts: ddict[att].append(getattr(ene, att)) new_dict = None if mode == 'minimal': new_dict = {} for key in ['bond', 'angle', 'dihedral', 'tot']: new_dict[key] = ddict[key] else: new_dict = ddict for key in new_dict.keys(): new_dict[key] = np.asarray(new_dict[key]) if dtype == 'dict': return OrderedDict(new_dict) else: from pytraj.datasets.c_datasetlist import DatasetList dslist = DatasetList() size = new_dict['tot'].__len__() for key in new_dict.keys(): dslist.add('double') dslist[-1].key = key dslist[-1].resize(size) dslist[-1].data[:] = new_dict[key] return get_data_from_dtype(dslist, dtype)
#! /usr/bin/env python import sander from chemistry.amber.readparm import AmberParm, Rst7 from chemistry.structure import Structure, read_PDB, write_PDB import numpy as np parm = AmberParm('4amber_1cby.prmtop') pdb = read_PDB('new.pdb') rst = Rst7.open('4amber_1cby.rst7') xyz = pdb.pdbxyz[0] sander.setup(parm,xyz, rst.box, sander.pme_input()) sander.set_positions(xyz) ene, frc = sander.energy_forces() #~ import code; code.interact(local=dict(globals(), **locals())) sander.cleanup()