Example #1
0
    def test_write_xml_parameters_methanol_ions_energy(self):
        """ Test writing XML parameter files from Charmm parameter files, reading them back into OpenMM ForceField, and computing energy of methanol and NaCl """

        params = openmm.OpenMMParameterSet.from_parameterset(
                pmd.charmm.CharmmParameterSet(get_fn('par_all36_cgenff.prm'),
                                              get_fn('top_all36_cgenff.rtf'),
                                              get_fn('toppar_water_ions.str')) # WARNING: contains duplicate water templates
        )
        del params.residues['TP3M'] # Delete to avoid duplicate water template topologies
        ffxml_filename = get_fn('charmm_conv.xml', written=True)
        params.write(ffxml_filename,
                     provenance=dict(
                         OriginalFile='par_all36_cgenff.prm, top_all36_cgenff.rtf, toppar_water_ions.str',
                         Reference='MacKerrell'
                     )
        )
        forcefield = app.ForceField(ffxml_filename)
        # Parameterize methanol and ions in vacuum
        pdbfile = app.PDBFile(get_fn('methanol_ions.pdb'))
        system = forcefield.createSystem(pdbfile.topology, nonbondedMethod=app.NoCutoff)
        integrator = mm.VerletIntegrator(1.0*u.femtoseconds)
        context = mm.Context(system, integrator, CPU)
        context.setPositions(pdbfile.positions)
        ffxml_potential = context.getState(getEnergy=True).getPotentialEnergy() / u.kilocalories_per_mole
        del context, integrator
        # Compute energy via ParmEd reader
        psf = CharmmPsfFile(get_fn('methanol_ions.psf'))
        system = psf.createSystem(params)
        integrator = mm.VerletIntegrator(1.0*u.femtoseconds)
        context = mm.Context(system, integrator, CPU)
        context.setPositions(pdbfile.positions)
        parmed_potential = context.getState(getEnergy=True).getPotentialEnergy() / u.kilocalories_per_mole
        del context, integrator
        # Ensure potentials are almost equal
        self.assertAlmostEqual(ffxml_potential, parmed_potential)
Example #2
0
    def test_write_xml_parameters_methanol_ions_energy(self):
        """ Test writing XML parameter files from Charmm parameter files, reading them back into OpenMM ForceField, and computing energy of methanol and NaCl """

        params = openmm.OpenMMParameterSet.from_parameterset(
                pmd.charmm.CharmmParameterSet(get_fn('par_all36_cgenff.prm'),
                                              get_fn('top_all36_cgenff.rtf'),
                                              get_fn('toppar_water_ions.str')) # WARNING: contains duplicate water templates
        )
        del params.residues['TP3M'] # Delete to avoid duplicate water template topologies
        ffxml_filename = get_fn('charmm_conv.xml', written=True)
        params.write(ffxml_filename,
                     provenance=dict(
                         OriginalFile='par_all36_cgenff.prm, top_all36_cgenff.rtf, toppar_water_ions.str',
                         Reference='MacKerrell'
                     )
        )
        forcefield = app.ForceField(ffxml_filename)
        # Parameterize methanol and ions in vacuum
        pdbfile = app.PDBFile(get_fn('methanol_ions.pdb'))
        system = forcefield.createSystem(pdbfile.topology, nonbondedMethod=app.NoCutoff)
        integrator = mm.VerletIntegrator(1.0*u.femtoseconds)
        context = mm.Context(system, integrator, CPU)
        context.setPositions(pdbfile.positions)
        ffxml_potential = context.getState(getEnergy=True).getPotentialEnergy() / u.kilocalories_per_mole
        del context, integrator
        # Compute energy via ParmEd reader
        psf = CharmmPsfFile(get_fn('methanol_ions.psf'))
        system = psf.createSystem(params)
        integrator = mm.VerletIntegrator(1.0*u.femtoseconds)
        context = mm.Context(system, integrator, CPU)
        context.setPositions(pdbfile.positions)
        parmed_potential = context.getState(getEnergy=True).getPotentialEnergy() / u.kilocalories_per_mole
        del context, integrator
        # Ensure potentials are almost equal
        self.assertAlmostEqual(ffxml_potential, parmed_potential)
 def test_add_charmm_psf(self):
     """ Test adding CHARMM PSF file to ParmList """
     parms = ParmList()
     ala3 = CharmmPsfFile(get_fn('ala3_solv.psf'))
     aaa = CharmmPsfFile(get_fn('ala_ala_ala.psf'))
     xaaa = CharmmPsfFile(get_fn('ala_ala_ala.psf.xplor'))
     aaaa = CharmmPsfFile(get_fn('ala_ala_ala_autopsf.psf'))
     parms.add_parm(ala3)
     parms.add_parm(aaa)
     parms.add_parm(xaaa)
     parms.add_parm(aaaa)
     # Check indexing
     self.assertIs(parms[0], ala3)
     self.assertIs(parms[1], aaa)
     self.assertIs(parms[2], xaaa)
     self.assertIs(parms[3], aaaa)
     # Test name indexing
     self.assertIs(parms[get_fn('ala3_solv.psf')], ala3)
     self.assertIs(parms[get_fn('ala_ala_ala.psf')], aaa)
     self.assertIs(parms[get_fn('ala_ala_ala.psf.xplor')], xaaa)
     self.assertIs(parms[get_fn('ala_ala_ala_autopsf.psf')], aaaa)
     # Check that the last parm added is active
     self.assertIs(parms.parm, parms[-1])
     # Set a new active topology
     parms.set_new_active(0)
     self.assertIs(parms.parm, ala3)
     parms.set_new_active(get_fn('ala_ala_ala.psf'))
     self.assertIs(parms.parm, aaa)
Example #4
0
    def __init__(self, true_value=None, initial_value=None, n_increments=18, rj=True, sample_phase=False,
                 continuous=False):
        self._param = CharmmParameterSet(get_fun('toy.str'))
        self._struct = CharmmPsfFile(get_fun('toy.psf'))
        self._pdb = app.PDBFile(get_fun('toy.pdb'))
        self._topology = md.load_psf(get_fun('toy.psf'))
        self.synthetic_energy = units.Quantity()
        self._positions = units.Quantity()
        self._platform = mm.Platform.getPlatformByName('Reference')

        # Replace ('CG331', 'CG321', 'CG321', 'CG331') torsion with true_value
        self._dih_type = ('CG331', 'CG321', 'CG321', 'CG331')
        original_torsion = self._param.dihedral_types[self._dih_type]
        if true_value is not None:
            if type(true_value) == DihedralTypeList:
                dih_tlist = true_value
            elif type(true_value) == DihedralType:
                dih_tlist = DihedralTypeList()
                dih_tlist.append(true_value)
        else:
            dih_tlist = self._randomize_dih_param(return_dih=True)
        self.true_value = copy.deepcopy(dih_tlist)
        self._param.dihedral_types[self._dih_type] = dih_tlist

        # parametrize toy
        self._struct.load_parameters(self._param, copy_parameters=False)
        self._struct.positions = self._pdb.positions

        # generate synthetic torsion scan
        self._torsion_scan(n_increments=n_increments)

        # initialize parameter
        if initial_value is not None:
            if type(initial_value) == DihedralTypeList:
                dih_tlist = initial_value
            if type(initial_value) == DihedralType:
                dih_tlist = DihedralTypeList()
                dih_tlist.append(initial_value)
            elif initial_value == 'cgenff':
                dih_tlist = original_torsion
        else:
            dih_tlist = self._randomize_dih_param(return_dih=True)

        self.initial_value = copy.deepcopy(dih_tlist)
        self._param.dihedral_types[self._dih_type] = dih_tlist

        # create torsionfit.TorsionScanSet
        torsions = np.zeros((len(self._positions), 4))
        torsions[:] = [1, 2, 3, 4]
        direction = None
        steps = None
        self.scan_set = ScanSet.QMDataBase(positions=self._positions.value_in_unit(units.nanometers),
                                           topology=self._topology, structure=self._struct, torsions=torsions,
                                           steps=steps, directions=direction,
                                           qm_energies=self.synthetic_energy.value_in_unit(units.kilojoules_per_mole))

        self.model = model.TorsionFitModel(param=self._param, frags=self.scan_set, platform=self._platform,
                                           param_to_opt=[self._dih_type], rj=rj, continuous_phase=continuous,
                                           sample_phase=sample_phase)
Example #5
0
    def test_create_simple_system(self):
        psf = CharmmPsfFile(get_fn("ala3_solv_drude.psf"))
        crd = CharmmCrdFile(get_fn("ala3_solv_drude.crd"))

        params = CharmmParameterSet(
            get_fn("toppar_drude_master_protein_2013e.str"))

        system = psf.createSystem(params)
Example #6
0
 def test_no_parameters(self):
     """ Test proper error handling when parameters not present """
     parm = CharmmPsfFile(get_fn('ala_ala_ala.psf'))
     parm.rb_torsions.append(parm.dihedrals.pop())
     parm.urey_bradleys.append(UreyBradley(parm.angles[0].atom1, parm.angles[0].atom3))
     self.assertRaises(ParameterError, parm.omm_bond_force)
     self.assertRaises(ParameterError, parm.omm_angle_force)
     self.assertRaises(ParameterError, parm.omm_dihedral_force)
     self.assertRaises(ParameterError, parm.omm_rb_torsion_force)
     self.assertRaises(ParameterError, parm.omm_urey_bradley_force)
     self.assertRaises(ParameterError, parm.omm_improper_force)
     self.assertRaises(ParameterError, parm.omm_cmap_force)
Example #7
0
    def parse(filename):
        """ Read a CHARMM- or XPLOR-style PSF file

        Parameters
        ----------
        filename : str
            Name of the file to parse

        Returns
        -------
        psf_file : :class:`CharmmPsfFile`
            The PSF file instance with all information loaded
        """
        return CharmmPsfFile(filename)
Example #8
0
    def test_turn_off_param(self):
        """ Test turning off parameters """

        structure = CharmmPsfFile(get_fn('butane_charge_off.psf'))
        param = CharmmParameterSet(get_fn('par_all36_cgenff.prm'),
                                   get_fn('top_all36_cgenff.rtf'))

        par.turn_off_params(structure,
                            param,
                            bonds=True,
                            angles=True,
                            dihedral=True,
                            urey_bradley=True,
                            lj=True,
                            copy=False)

        scan = get_fn('MP2_torsion_scan/')
        butane_scan = qmdb.parse_psi4_out(scan,
                                          get_fn('butane_charge_off.psf'))
        butane_scan.compute_energy(param)

        self.assertTrue((butane_scan.mm_energy.value_in_unit(
            unit.kilojoule_per_mole) == 0).all())
Example #9
0
def parse_psi4_log(logfiles, structure):
    """
    Parses output of psi4 torsion scan script
    :param logfiles: list of str
        logfiles of psi4 script
    :param structure: str
        Charmm psf file of structure
    :return:
    TorsionScanSet
    """
    topology = md.load_psf(structure)
    structure = CharmmPsfFile(structure)
    positions = np.ndarray((0, topology.n_atoms, 3))
    qm_energies = np.ndarray(0)
    torsions = np.ndarray((0, 4), dtype=int)
    directions = np.ndarray(0, dtype=int)
    angles = np.ndarray(0, dtype=float)

    if type(logfiles) != list:
        logfiles = [logfiles]

    for file in logfiles:
        qm = np.ndarray(0)
        fi = open(file, 'r')
        # check if log file is complete
        complete = False  # complete flag
        for line in fi:
            if line.startswith('Relative'):
                complete = True
        fi.seek(0)
        section = None
        torsion = np.ndarray((1, 4), dtype=int)
        angle = np.ndarray(0, dtype=float)
        for line in fi:
            # Flag if structure is optimized
            optimized = False
            if line.startswith('Optimizer'):
                optimized = True
                # Store Dihedral and position of optimized structures
                fi.next()
                l = filter(None, fi.next().strip().split(' '))
                dih = round(float(l[-2]))
                try:
                    t = l[-6:-2]
                    for i in range(len(t)):
                        torsion[0][i] = int(t[i]) - 1
                    torsions = np.append(torsions, torsion, axis=0)
                except ValueError:
                    pass
                angle = np.append(angle, dih)
                fi.next()
                pos = filter(None, re.split("[, \[\]]", fi.next().strip()))
                pos = [float(i) for i in pos]
                pos = np.asarray(pos).reshape((-1, 3))
                # convert angstroms to nanometers
                positions = np.append(positions, pos[np.newaxis] * 0.1, axis=0)
            if not complete and optimized:
                # Find line that starts with energy
                for line in fi:
                    if line.startswith('Energy'):
                        energy = filter(None, line.strip().split(' '))[-1]
                        # Convert to KJ/mol
                        energy = float(energy) * 2625.5
                        qm = np.append(qm, energy)
                        break
            if line.startswith('Relative'):
                section = 'Energy'
                fi.next()
                continue
            if section == 'Energy':
                line = filter(None, line.strip().split(' '))
                if line != []:
                    dih = round(float(line[0]))
                    if dih in angle:
                        # Only save energies of optimized structures
                        qm_energies = np.append(qm_energies, float(line[-1]))
        if qm.size is not 0:
            qm = qm - min(qm)
            qm_energies = np.append(qm_energies, qm)

        fi.close()
        angles = np.append(angles, angle, axis=0)
    return QMDataBase(positions, topology, structure, torsions, directions,
                      angles, qm_energies)
Example #10
0
def parse_gauss(logfiles, structure):
    """ parses Guassian09 torsion-scan log file

    parameters
    ----------
    logfiles: str of list of str
                Name of Guassian 09 torsion scan log file
    structure: charmm psf file

    returns
    -------
    TorsionScanSet
    """
    topology = md.load_psf(structure)
    structure = CharmmPsfFile(structure)
    positions = np.ndarray((0, topology.n_atoms, 3))
    qm_energies = np.ndarray(0)
    torsions = np.ndarray((0, 4), dtype=int)
    directions = np.ndarray(0, dtype=int)
    steps = np.ndarray((0, 3), dtype=int)

    if type(logfiles) != list:
        logfiles = [logfiles]

    for file in (logfiles):
        direction = np.ndarray(1)
        torsion = np.ndarray((1, 4), dtype=int)
        step = np.ndarray((0, 3), dtype=int)
        index = (2, 12, -1)
        log = Gaussian(file)
        data = log.parse()
        # convert angstroms to nanometers
        positions = np.append(positions, data.atomcoords * 0.1, axis=0)
        # Only add qm energies for structures that converged (because cclib throws out those coords but not other info)
        qm_energies = np.append(qm_energies, (convertor(
            data.scfenergies[:len(data.atomcoords)], "eV", "kJmol-1") - min(
                convertor(data.scfenergies[:len(data.atomcoords)], "eV",
                          "kJmol-1"))),
                                axis=0)

        fi = open(file, 'r')
        for line in fi:
            if re.search('   Scan   ', line):
                t = line.split()[2].split(',')
                t[0] = t[0][-1]
                t[-1] = t[-1][0]
                for i in range(len(t)):
                    torsion[0][i] = (int(t[i]) - 1)
            if re.search('^ D ', line):
                d = line.split()[-1]
                if d[0] == '-':
                    direction[0] = 0
                elif d[0] == '1':
                    direction[0] = 1
            if re.search('Step', line):
                try:
                    point = np.array(([int(line.rsplit()[j]) for j in index]))
                    point = point[np.newaxis, :]
                    step = np.append(step, point, axis=0)
                except:
                    pass

        fi.close()
        # only add scan points from converged structures
        steps = np.append(steps, step[:len(data.atomcoords)], axis=0)
        for i in range(len(data.atomcoords)):
            torsions = np.append(torsions, torsion, axis=0)
            directions = np.append(directions, direction, axis=0)
        del log
        del data
    return QMDataBase(positions=positions,
                      topology=topology,
                      structure=structure,
                      torsions=torsions,
                      steps=steps,
                      qm_energies=qm_energies,
                      directions=directions)
Example #11
0
def parse_psi4_out(oufiles_dir, structure, pattern="*.out"):
    """
    Parse psi4 out files from distributed torsion scan (there are many output files, one for each structure)
    :param oufiles_dir: str
        path to directory where the psi4 output files are
    :param structure: str
        path to psf, mol2 or pbd file of structure
    :param pattern: str
        pattern for psi4 output file. Default is *.out
    :return: TorsionScanSet

    """
    # Check extension of structure file
    if structure.endswith('psf'):
        topology = md.load_psf(structure)
        structure = CharmmPsfFile(structure)
    else:
        topology = md.load(structure).topology
        structure = parmed.load_file(structure)

    positions = np.ndarray((0, topology.n_atoms, 3))
    qm_energies = np.ndarray(0)
    torsions = np.ndarray((0, 4), dtype=int)
    angles = np.ndarray(0, dtype=float)
    optimized = np.ndarray(0, dtype=bool)

    out_files = {}
    for path, subdir, files in os.walk(oufiles_dir):
        for name in files:
            if fnmatch(name, pattern):
                if name.startswith('timer'):
                    continue
                name_split = name.split('_')
                try:
                    torsion_angle = (name_split[1] + '_' + name_split[2] +
                                     '_' + name_split[3] + '_' + name_split[4])
                except IndexError:
                    warnings.warn(
                        "Do you only have one torsion scan? The output files will be treated as one scan"
                    )
                    torsion_angle = 'only_one_scan'
                try:
                    out_files[torsion_angle]
                except KeyError:
                    out_files[torsion_angle] = []
                path = os.path.join(os.getcwd(), path, name)
                out_files[torsion_angle].append(path)
    # Sort files in increasing angles order for each torsion
    sorted_files = []
    dih_angles = []
    for tor in out_files:
        dih_angle = []
        for file in out_files[tor]:
            dih_angle.append(int(file.split('_')[-1].split('.')[0]))
        sorted_files.append([
            out_file
            for (angle, out_file) in sorted(zip(dih_angle, out_files[tor]))
        ])
        dih_angle.sort()
        dih_angles.append(dih_angle)
    if not out_files:
        raise Exception(
            "There are no psi4 output files. Did you choose the right directory?"
        )

    # Parse files
    for f in itertools.chain.from_iterable(sorted_files):
        torsion = np.ndarray((1, 4), dtype=int)
        fi = open(f, 'r')
        for line in fi:
            if line.startswith('dih_string'):
                t = line.strip().split('"')[1].split(' ')[:4]
                for i in range(len(t)):
                    torsion[0][i] = int(t[i]) - 1
                torsions = np.append(torsions, torsion, axis=0)
        fi.close()
        optimizer = True
        log = Psi(f)
        data = log.parse()
        try:
            data.optdone
        except AttributeError:
            optimizer = False
            warnings.warn("Warning: Optimizer failed for {}".format(f))
        optimized = np.append(optimized, optimizer)

        positions = np.append(positions,
                              data.atomcoords[-1][np.newaxis] * 0.1,
                              axis=0)
        # Try MP2 energies. Otherwise take SCFenergies
        try:
            qm_energy = convertor(data.mpenergies[-1], "eV", "kJmol-1")
        except AttributeError:
            try:
                qm_energy = convertor(np.array([data.scfenergies[-1]]), "eV",
                                      "kJmol-1")
            except AttributeError:
                warnings.warn(
                    "Warning: Check if the file terminated before completing SCF"
                )
                qm_energy = np.array([np.nan])
        qm_energies = np.append(qm_energies, qm_energy, axis=0)

    # Subtract lowest energy to find relative energies
    qm_energies = qm_energies - min(qm_energies)
    angles = np.asarray(list(itertools.chain.from_iterable(dih_angles)))
    return QMDataBase(positions=positions,
                      topology=topology,
                      structure=structure,
                      torsions=torsions,
                      angles=angles,
                      qm_energies=qm_energies,
                      optimized=optimized)
Example #12
0
class ToyModel(object):
    """
    Toy model of 4 carbons to test torsionfit

    Attributes
    ----------
    synthetic_energy: simtk.units.Quantity((n_increments), unit=kilojoule/mole)
    true_value: parmed.topologyobjects.DihedralTypeList (the dihedral parameters used to calculate synthetic energy)
    initital_value: parmed.topologyobjects.DihedralTypeList (dihedral parameters used to initialize pymc model)
    torsion_scan: torsionfit.TorsionScanSet
    model: torsionfit.TorsionFitModel

    The default toy model has randomized true and initial dihedral parameters. This can be changed by passing a
    parmed.topologyobjects.DihedralTypeList to true_value and/or initial_value when initializing a model instance.

    """

    def __init__(self, true_value=None, initial_value=None, n_increments=18, rj=True, sample_phase=False,
                 continuous=False):
        self._param = CharmmParameterSet(get_fun('toy.str'))
        self._struct = CharmmPsfFile(get_fun('toy.psf'))
        self._pdb = app.PDBFile(get_fun('toy.pdb'))
        self._topology = md.load_psf(get_fun('toy.psf'))
        self.synthetic_energy = units.Quantity()
        self._positions = units.Quantity()
        self._platform = mm.Platform.getPlatformByName('Reference')

        # Replace ('CG331', 'CG321', 'CG321', 'CG331') torsion with true_value
        self._dih_type = ('CG331', 'CG321', 'CG321', 'CG331')
        original_torsion = self._param.dihedral_types[self._dih_type]
        if true_value is not None:
            if type(true_value) == DihedralTypeList:
                dih_tlist = true_value
            elif type(true_value) == DihedralType:
                dih_tlist = DihedralTypeList()
                dih_tlist.append(true_value)
        else:
            dih_tlist = self._randomize_dih_param(return_dih=True)
        self.true_value = copy.deepcopy(dih_tlist)
        self._param.dihedral_types[self._dih_type] = dih_tlist

        # parametrize toy
        self._struct.load_parameters(self._param, copy_parameters=False)
        self._struct.positions = self._pdb.positions

        # generate synthetic torsion scan
        self._torsion_scan(n_increments=n_increments)

        # initialize parameter
        if initial_value is not None:
            if type(initial_value) == DihedralTypeList:
                dih_tlist = initial_value
            if type(initial_value) == DihedralType:
                dih_tlist = DihedralTypeList()
                dih_tlist.append(initial_value)
            elif initial_value == 'cgenff':
                dih_tlist = original_torsion
        else:
            dih_tlist = self._randomize_dih_param(return_dih=True)

        self.initial_value = copy.deepcopy(dih_tlist)
        self._param.dihedral_types[self._dih_type] = dih_tlist

        # create torsionfit.TorsionScanSet
        torsions = np.zeros((len(self._positions), 4))
        torsions[:] = [1, 2, 3, 4]
        direction = None
        steps = None
        self.scan_set = ScanSet.QMDataBase(positions=self._positions.value_in_unit(units.nanometers),
                                           topology=self._topology, structure=self._struct, torsions=torsions,
                                           steps=steps, directions=direction,
                                           qm_energies=self.synthetic_energy.value_in_unit(units.kilojoules_per_mole))

        self.model = model.TorsionFitModel(param=self._param, frags=self.scan_set, platform=self._platform,
                                           param_to_opt=[self._dih_type], rj=rj, continuous_phase=continuous,
                                           sample_phase=sample_phase)

    def _spher2cart(self, r, theta, phi):
        """convert spherical to cartesian coordinates

        Paramters:
        r: bond length
        theta: bond angle
        phi: dihedral angle

        returns:
        cartesian coordinates
        """
        x = r * np.sin(theta) * np.cos(phi)
        y = r * np.sin(theta) * np.sin(phi)
        z = r * np.cos(theta)
        return [x, y, z]

    def _torsion_scan(self, n_increments):
        """
        Generate positions and energy for torsion scan
        Parameters:
            n_increments: int. how many points to scan
        """
        n_increments = n_increments
        n_atoms = 4
        phis = np.arange(-np.pi, +np.pi, np.pi/n_increments)
        positions = np.zeros((len(phis), n_atoms, 3))

        # Get bond length in nm
        for bond in self._struct.bonds:
            if bond.atom1.type == bond.atom2.type:
                length = units.Quantity(value=bond.type.req * 0.1, unit=units.nanometers) # convert to nm
        # Get angle in radians
        for angle in self._struct.angles:
            if angle.atom1.type == angle.atom2.type:
                theta = units.Quantity(value=angle.type.theteq * (np.pi/180.0), unit=units.radians)

        atom1_coords = self._spher2cart(length.value_in_unit(units.nanometer), theta.value_in_unit(units.radian), phis[0])
        for i, phi in enumerate(phis):
            atom3_coords = self._spher2cart(length.value_in_unit(units.nanometer), theta.value_in_unit(units.radian), phi)
            atom3_coords[-1] = abs(atom3_coords[-1]) + length._value
            positions[i] = [atom1_coords,
                [0.000, 0.000, 0.000],
                [0.000, 0.000, length._value],
                atom3_coords]
        self._positions = units.Quantity(value=positions, unit=units.nanometer) # put units back in

        # calculate energy
        self.synthetic_energy = units.Quantity(value=np.zeros((len(positions))), unit=units.kilojoules_per_mole)
        platform = mm.Platform.getPlatformByName('Reference')
        integrator = mm.VerletIntegrator(0.004*units.picoseconds)
        system = self._struct.createSystem()
        context = mm.Context(system, integrator, platform)
        for i, conf in enumerate(self._positions):
            context.setPositions(conf)
            state = context.getState(getEnergy=True)
            energy = state.getPotentialEnergy()
            self.synthetic_energy[i] = energy + units.Quantity(value=np.random.normal(0, 1.0), unit=units.kilojoules_per_mole)

    def _randomize_dih_param(self, return_dih=False):
        """
        generates random dihedral parameters

        """
        dih_tlist = DihedralTypeList()
        multiplicities = [1, 2, 3, 4, 6]
        terms = np.random.randint(1, 5+1)
        np.random.shuffle(multiplicities)
        for i in range(terms):
            k = np.random.uniform(0.0, 20.0)
            n = multiplicities[i]
            phase = np.random.randint(0, 1+1)
            if phase == 1:
                phase = 180
            dih_tlist.append(DihedralType(k, n, phase, 1.00, 1.00))
        self._param.dihedral_types[self._dih_type] = dih_tlist
        if return_dih:
            _dih_tlist = copy.deepcopy(dih_tlist)
            return _dih_tlist

    def save_torsion_values(self, filename=None):
        """

        Parameters
        ----------
        filename : str
            file to save torsion values. Default is None. If None, return np.array

        Returns
        -------
        dih_param: np.array
            array containing torison parameters
        """
        dih_param = np.ones(shape=(2, 6, 3)) * np.nan
        for i, dih in enumerate(self.true_value):
            dih_param[0, i, 0] = dih.per
            dih_param[0, i, 1] = dih.phi_k
            dih_param[0, i, 2] = dih.phase

        for j, dih in enumerate(self.initial_value):
            dih_param[1, j, 0] = dih.per
            dih_param[1, j, 1] = dih.phi_k
            dih_param[1, j, 2] = dih.phase

        if filename is not None:
            np.save(filename, dih_param)
        else:
            return dih_param

    @staticmethod
    def from_dih_params(filename=None, dih_params=None, rj=False, continuous=False, n_increments=13, sample_phase=False):
        """

        Parameters
        ----------
        filename : str
            name of file with serialized dihedral parameters
        rj : bool
            Flag if using reversible jump. Default it True
        continuous : bool
            Flag if sampling continuous phase. Default is False
        n_increments : int
            incermentation of torsion drive
        sample_phase : bool
            Flag if sampling phase. Default is False (K is allowed to go negative when sample_phase is False)

        Returns
        -------
        ToyModel with true and initial value from saved file.

        """
        if filename is None and dih_params is None:
            msg = 'You must provide either an npy file or a numpy array with true and initial values for the toy model'
            raise Exception(msg)
        if filename is not None:
            dih_params = np.load(filename)
        dih_tlist_true = DihedralTypeList()
        dih_tlist_init = DihedralTypeList()

        true = dih_params[0]
        init = dih_params[1]

        for dih in true:
            if not np.isnan(dih[0]):
                dih_tlist_true.append(DihedralType(per=dih[0], phi_k=dih[1], phase=dih[2]))

        for dih in init:
            if not np.isnan(dih[0]):
                dih_tlist_init.append(DihedralType(per=dih[0], phi_k=dih[1], phase=dih[2]))

        return ToyModel(true_value=dih_tlist_true, initial_value=dih_tlist_init, rj=rj, continuous=continuous,
                        n_increments=n_increments, sample_phase=sample_phase)
Example #13
0
pdb_solvate = app.PDBFile('../structure/butane_solvated.pdb')

coords = pdb_solvate.positions
min_crds = [coords[0][0], coords[0][1], coords[0][2]]
max_crds = [coords[0][0], coords[0][1], coords[0][2]]

for coord in coords:
    min_crds[0] = min(min_crds[0], coord[0])
    min_crds[1] = min(min_crds[1], coord[1])
    min_crds[2] = min(min_crds[2], coord[2])
    max_crds[0] = max(max_crds[0], coord[0])
    max_crds[1] = max(max_crds[1], coord[1])
    max_crds[2] = max(max_crds[2], coord[2])

psf_solvate_1 = CharmmPsfFile('../structure/butane_solvated.psf')
psf_solvate_1.box = (max_crds[0] - min_crds[0], max_crds[1] - min_crds[1],
                     max_crds[2] - min_crds[2], 90.0, 90.0, 90.0)
database['solvated']['structure_1'] = psf_solvate_1
psf_solvate_1.load_parameters(param_1, copy_parameters=False)
system_solvate_1 = psf_solvate_1.createSystem(
    nonbondedMethod=app.PME,
    constraints=app.HBonds,
    nonbondedCutoff=12.0 * u.angstroms,
    switchDistance=10.0 * u.angstroms)
database['solvated']['system_1'] = system_solvate_1

psf_solvate_2 = CharmmPsfFile('../structure/butane_solvated.psf')
psf_solvate_2.box = (max_crds[0] - min_crds[0], max_crds[1] - min_crds[1],
                     max_crds[2] - min_crds[2], 90.0, 90.0, 90.0)
database['solvated']['structure_2'] = psf_solvate_2
def compare_energies(system_name,
                     pdb_filename,
                     psf_filename,
                     ffxml_filenames,
                     toppar_filenames,
                     box_vectors_filename=None,
                     system_kwargs=None,
                     tolerance=1e-5,
                     units=u.kilojoules_per_mole,
                     write_serialized_xml=False):
    """
    Compare energies between (pdb, psf, toppar) loaded via ParmEd and (pdb, ffxml) loaded by OpenMM ForceField

    Parameters
    ----------
    system_name : str
        Name of the test system
    pdb_filename : str
        Name of PDB file that should contain CRYST entry and PDB format compliant CONECT records for HETATM residues.
    psf_filename : str
        CHARMM PSF file
    ffxml_filenames : list of str
        List of OpenMM ffxml files
    toppar_filenames : list of CHARMM toppar filenames to load into CharmmParameterSet
        List of CHARMM toppar files
    box_vectors_filename : str, optional, default=None
        If specified, read box vectors from a file like step2.1_waterbox.prm
    system_kwargs : dict, optional, default=None
        Keyword arguments to pass to CharmmPsfFile.createSystem() and ForceField.CreateSystem() when constructing System objects for energy comparison
    tolerance : float, optional, default=1e-5
        Relative energy discrepancy tolerance
    units : simtk.unit.Unit
        Unit to use for energy comparison
    write_serialized_xml : bool, optional, default=False
        If True, will write out serialized System XML files for OpenMM systems to aid debugging.

    """

    is_periodic = False
    if (system_kwargs is not None) and ('nonbondedMethod'
                                        in system_kwargs) and (
                                            system_kwargs['nonbondedMethod']
                                            in [app.CutoffPeriodic, app.PME]):
        is_periodic = True

    # Load PDB file
    pdbfile = app.PDBFile(pdb_filename)

    # Read box vectors
    if box_vectors_filename:
        box_vectors = read_box_vectors(box_vectors_filename)
        pdbfile.topology.setPeriodicBoxVectors(box_vectors)
    else:
        box_vectors = pdbfile.topology.getPeriodicBoxVectors()

    # Load CHARMM system through OpenMM
    openmm_toppar = app.CharmmParameterSet(*toppar_filenames)
    openmm_psf = app.CharmmPsfFile(psf_filename)
    # Set box vectors
    if is_periodic:
        openmm_psf.setBox(box_vectors[0][0], box_vectors[1][1],
                          box_vectors[2][2])
    openmm_system = openmm_psf.createSystem(openmm_toppar, **system_kwargs)
    openmm_structure = openmm.load_topology(openmm_psf.topology,
                                            openmm_system,
                                            xyz=pdbfile.positions)
    #openmm_energies = openmm.energy_decomposition_system(openmm_structure, openmm_system, nrg=units)
    #print('OpenMM CHARMM loader energy components : %s' % str(openmm_energies))
    openmm_total_energy = compute_potential(openmm_system,
                                            pdbfile.positions) / units

    # Load CHARMM system through ParmEd
    parmed_toppar = CharmmParameterSet(*toppar_filenames)
    parmed_structure = CharmmPsfFile(psf_filename)
    #structure.load_parameters(toppar)
    parmed_structure.positions = pdbfile.positions
    # Set box vectors
    if is_periodic:
        parmed_structure.box = (box_vectors[0][0] / u.angstroms,
                                box_vectors[1][1] / u.angstroms,
                                box_vectors[2][2] / u.angstroms, 90, 90, 90)
    parmed_system = parmed_structure.createSystem(parmed_toppar,
                                                  **system_kwargs)
    #parmed_energies = openmm.energy_decomposition_system(parmed_structure, parmed_system, nrg=units)
    #print('ParmEd CHARMM loader energy components : %s' % str(parmed_energies))
    parmed_total_energy = compute_potential(parmed_system,
                                            pdbfile.positions) / units

    # Delete H-H bonds from waters and retreive updated topology and positions
    modeller = app.Modeller(openmm_psf.topology, pdbfile.positions)
    hhbonds = [
        b for b in modeller.topology.bonds()
        if b[0].element == app.element.hydrogen
        and b[1].element == app.element.hydrogen
    ]
    modeller.delete(hhbonds)
    ffxml_topology = modeller.topology

    # OpenMM system with ffxml
    ff = app.ForceField(*ffxml_filenames)
    ffxml_system = ff.createSystem(ffxml_topology, **system_kwargs)
    ffxml_structure = openmm.load_topology(ffxml_topology,
                                           ffxml_system,
                                           xyz=pdbfile.positions)
    #ffxml_energies = openmm.energy_decomposition_system(ffxml_structure, ffxml_system, nrg=units)
    #print('ffxml energy components : %s' % str(ffxml_energies))
    ffxml_total_energy = compute_potential(ffxml_system,
                                           pdbfile.positions) / units

    write_serialized_xml = True  # DEBUG
    if write_serialized_xml:
        print('Writing serialized XML files...')
        write_serialized_system(system_name + '.charmm.system.xml',
                                openmm_system)
        write_serialized_system(system_name + '.parmed.system.xml',
                                parmed_system)
        write_serialized_system(system_name + '.openmm.system.xml',
                                ffxml_system)

    print('-' * 100)
    print('')
    print('OpenMM CHARMM reader total energy: %14.3f' % openmm_total_energy)
    print('ParmEd CHARMM reader total energy: %14.3f' % parmed_total_energy)
    print('OPENMM ffxml total energy:         %14.3f' % ffxml_total_energy)
    print('TOTAL ERROR:                       %14.3f' %
          (ffxml_total_energy - openmm_total_energy))
    print('')

    print('-' * 100)

    # TODO : Automate comparison
    return

    # calc rel energies and assert
    rel_energies = []
    for i, j in zip(ffxml_energies, parmed_energies):
        if i[0] != j[0]:
            raise Exception('Mismatch in energy tuples naming.')
        if abs(i[1]) > NEARLYZERO:
            rel_energies.append((i[0], abs((i[1] - j[1]) / i[1])))
        else:
            if abs(j[1]) > NEARLYZERO:
                raise AssertionError(
                    'One of the CHARMM %s energies (%s) for %s is zero, '
                    'while the corresponding OpenMM energy is non-zero' %
                    (system_name, i[0], ffxml))
            rel_energies.append((i[0], 0))

    dihedrals_done = False
    for i in rel_energies:
        if i[0] != 'PeriodicTorsionForce':
            if i[1] > tolerance:
                raise AssertionError(
                    '%s energies (%s, %f) outside of allowed tolerance (%f) for %s'
                    % (system_name, i[0], i[1], tolerance, ffxml))
        else:
            if not dihedrals_done:
                if i[1] > tolerance:
                    raise AssertionError(
                        '%s energies (%s, %f) outside of allowed tolerance (%f) for %s'
                        % (system_name, i[0], i[1], tolerance, ffxml))
                dihedrals_done = True
            else:  #impropers
                if i[1] > improper_tolerance:
                    raise AssertionError(
                        '%s energies (%s-impropers, %f) outside of allowed tolerance (%f) for %s'
                        % (system_name, i[0], i[1], improper_tolerance, ffxml))

    # logging
    if not no_log:
        charmm_energies_log = dict()
        omm_energies_log = dict()
        rel_energies_log = dict()
        charmm_energies_log['ffxml_name'] = ffxml
        charmm_energies_log['test_system'] = system_name
        charmm_energies_log['data_type'] = 'CHARMM'
        charmm_energies_log['units'] = units
        omm_energies_log['ffxml_name'] = ffxml
        omm_energies_log['test_system'] = system_name
        omm_energies_log['data_type'] = 'OpenMM'
        omm_energies_log['units'] = units
        rel_energies_log['ffxml_name'] = ffxml
        rel_energies_log['test_system'] = system_name
        rel_energies_log['data_type'] = 'abs((CHARMM-OpenMM)/CHARMM)'
        dihedrals_done = False
        for item in amber_energies:
            if item[0] == 'PeriodicTorsionForce' and not dihedrals_done:
                charmm_energies_log['PeriodicTorsionForce_dihedrals'] = item[1]
                dihedrals_done = True
            elif item[0] == 'PeriodicTorsionForce' and dihedrals_done:
                charmm_energies_log['PeriodicTorsionForce_impropers'] = item[1]
            elif item[0] == 'CMMotionRemover':
                continue
            else:
                charmm_energies_log[item[0]] = item[1]
        dihedrals_done = False
        for item in omm_energies:
            if item[0] == 'PeriodicTorsionForce' and not dihedrals_done:
                omm_energies_log['PeriodicTorsionForce_dihedrals'] = item[1]
                dihedrals_done = True
            elif item[0] == 'PeriodicTorsionForce' and dihedrals_done:
                omm_energies_log['PeriodicTorsionForce_impropers'] = item[1]
            elif item[0] == 'CMMotionRemover':
                continue
            else:
                omm_energies_log[item[0]] = item[1]
        dihedrals_done = False
        for item in rel_energies:
            if item[0] == 'PeriodicTorsionForce' and not dihedrals_done:
                rel_energies_log['PeriodicTorsionForce_dihedrals'] = item[1]
                dihedrals_done = True
            elif item[0] == 'PeriodicTorsionForce' and dihedrals_done:
                rel_energies_log['PeriodicTorsionForce_impropers'] = item[1]
            elif item[0] == 'CMMotionRemover':
                continue
            else:
                rel_energies_log[item[0]] = item[1]

        logger.log(charmm_energies_log)
        logger.log(omm_energies_log)
        logger.log(rel_energies_log)
Example #15
0
from __future__ import division, print_function

import sys

# OpenMM Imports
import simtk.openmm as mm
import simtk.openmm.app as app

# ParmEd Imports
from parmed.charmm import CharmmPsfFile, CharmmCrdFile, CharmmParameterSet
from parmed.openmm import StateDataReporter
from parmed import unit as u

# Load the CHARMM files
print('Loading CHARMM files...')
params = CharmmParameterSet('BNZ_2_PRD.prm')
ala5_gas = CharmmPsfFile('zero.psf')
ala5_crds = app.PDBFile('A2B_gas.pdb')
Example #16
0
                           CharmmParameterSet)
from parmed.exceptions import CharmmWarning, ParameterError
from parmed.openmm.utils import energy_decomposition
from parmed import unit as u, openmm, load_file, UreyBradley
from parmed.utils.six.moves import range
from copy import copy
from math import sqrt
import unittest
from utils import get_fn, TestCaseRelative, mm, app, has_openmm, CPU, Reference
import warnings

# Suppress warning output from bad psf file... sigh.
warnings.filterwarnings('ignore', category=CharmmWarning)

# System
charmm_gas = CharmmPsfFile(get_fn('ala_ala_ala.psf'))
charmm_gas_crds = load_file(get_fn('ala_ala_ala.pdb'))
charmm_nbfix = CharmmPsfFile(get_fn('ala3_solv.psf'))
charmm_nbfix_crds = CharmmCrdFile(get_fn('ala3_solv.crd'))
charmm_nbfix.box = [3.271195e1, 3.299596e1, 3.300715e1, 90, 90, 90]

# Parameter sets
param22 = CharmmParameterSet(get_fn('top_all22_prot.inp'),
                             get_fn('par_all22_prot.inp'))
param36 = CharmmParameterSet(get_fn('par_all36_prot.prm'),
                             get_fn('toppar_water_ions.str'))

@unittest.skipUnless(has_openmm, "Cannot test without OpenMM")
class TestCharmmFiles(TestCaseRelative):

    def test_gas_energy(self):
from parmed.openmm.utils import energy_decomposition
from parmed import unit as u, openmm, load_file
from parmed.utils.six.moves import range
from copy import copy
from math import sqrt
import unittest
from utils import get_fn, TestCaseRelative, mm, app, has_openmm, CPU, Reference
import warnings
    
# Suppress warning output from bad psf file... sigh.
warnings.filterwarnings('ignore', category=CharmmWarning)

# System
charmm_gas = CharmmPsfFile(get_fn('ala_ala_ala.psf'))
charmm_gas_crds = load_file(get_fn('ala_ala_ala.pdb'))
charmm_nbfix = CharmmPsfFile(get_fn('ala3_solv.psf'))
charmm_nbfix_crds = CharmmCrdFile(get_fn('ala3_solv.crd'))
charmm_nbfix.box = [3.271195e1, 3.299596e1, 3.300715e1, 90, 90, 90]

# Parameter sets
param22 = CharmmParameterSet(get_fn('top_all22_prot.inp'),
                             get_fn('par_all22_prot.inp'))
param36 = CharmmParameterSet(get_fn('par_all36_prot.prm'),
                             get_fn('toppar_water_ions.str'))

@unittest.skipUnless(has_openmm, "Cannot test without OpenMM")
class TestCharmmFiles(TestCaseRelative):

    def testGasEnergy(self):
        """ Compare OpenMM and CHARMM gas phase energies """
        parm = charmm_gas
Example #18
0
import parmed as pm
from parmed.charmm import CharmmPsfFile, CharmmCrdFile, CharmmParameterSet


print('Loading CHARMM files...')
params = CharmmParameterSet('toppar/par_all36m_prot.prm', 'toppar/par_all36_lipid.prm')

gram = CharmmPsfFile('../../simulations/themis_data/1jnoetaohh3o2.psf')

for atom in gram.atoms:
    print(atom.name, atom.idx, atom.charge, atom.rmin, atom.epsilon)