Exemple #1
0
 def _load_improper_info(self):
     """ Loads the CHARMM Improper types and array """
     del self.impropers[:]
     del self.improper_types[:]
     for k, eq in zip(self.parm_data['CHARMM_IMPROPER_FORCE_CONSTANT'],
                      self.parm_data['CHARMM_IMPROPER_PHASE']):
         # Previous versions of ParmEd stored improper phases as degrees,
         # whereas it should really be stored in radians. So do a simple
         # heuristic check to see if a conversion is necessary so we support
         # all versions.
         eq = eq * RAD_TO_DEG if abs(eq) <= 2 * pi else eq
         self.improper_types.append(ImproperType(k, eq,
                                                 self.improper_types))
     it = iter(self.parm_data['CHARMM_IMPROPERS'])
     for i, j, k, l, m in zip(it, it, it, it, it):
         self.impropers.append(
             Improper(self.atoms[i - 1], self.atoms[j - 1],
                      self.atoms[k - 1], self.atoms[l - 1],
                      self.improper_types[m - 1]))
     # Make sure that if we have a comment in the CHARMM impropers, we fix it
     # to say the units are in radians
     for i in range(len(self.parm_comments.get('CHARMM_IMPROPER_PHASE',
                                               []))):
         comment = self.parm_comments['CHARMM_IMPROPER_PHASE'][i]
         if 'degrees' in comment:
             self.parm_comments['CHARMM_IMPROPER_PHASE'][i] = \
                     comment.replace('degrees', 'radians')
Exemple #2
0
 def _load_improper_info(self):
     """ Loads the CHARMM Improper types and array """
     del self.impropers[:]
     del self.improper_types[:]
     for k, eq in zip(self.parm_data['CHARMM_IMPROPER_FORCE_CONSTANT'],
                      self.parm_data['CHARMM_IMPROPER_PHASE']):
         self.improper_types.append(ImproperType(k, eq,
                                                 self.improper_types))
     it = iter(self.parm_data['CHARMM_IMPROPERS'])
     for i, j, k, l, m in zip(it, it, it, it, it):
         self.impropers.append(
             Improper(self.atoms[i - 1], self.atoms[j - 1],
                      self.atoms[k - 1], self.atoms[l - 1],
                      self.improper_types[m - 1]))
Exemple #3
0
def _process_improper(struct, force):
    """ Processes a CustomTorsionForce and looks at the energy expression to see
    if it's a quadratic improper torsion. Then adds the parameters if applicable

    Returns
    -------
    is_improper : bool
        Returns True if the energy expression is recognized as a quadratic
        improper, and False otherwise
    """
    eqn = force.getEnergyFunction().replace(' ', '')
    # Don't try to be fancy with regexes for fear of making a possible mistake.
    # ParmEd and OpenMM use only these two eqns for the improper torsions:
    #  k*(theta-theta0)^2 vs. 0.5*k*(theta-theta0)^2
    # So only recognize the above 2 forms
    if eqn not in ('0.5*k*(theta-theta0)^2', 'k*(theta-theta0)^2'):
        return False
    if eqn == '0.5*k*(theta-theta0)^2':
        fac = 0.5
    else:
        fac = 1
    typemap = dict()
    for ii in range(force.getNumTorsions()):
        # All formulations put k first and equilibrium angle second, in radians
        i, j, k, l, (psi_k, psi_eq) = force.getTorsionParameters(ii)
        ai, aj = struct.atoms[i], struct.atoms[j]
        ak, al = struct.atoms[k], struct.atoms[l]
        key = (psi_k, psi_eq)
        if key in typemap:
            imp_type = typemap[key]
        else:
            imp_type = ImproperType(
                psi_k * fac * u.kilojoule_per_mole / u.radian**2,
                psi_eq * u.radian)
            typemap[key] = imp_type
            struct.improper_types.append(imp_type)
        struct.impropers.append(Improper(ai, aj, ak, al, type=imp_type))
    struct.improper_types.claim()
    return True
Exemple #4
0
def create_random_structure(parametrized, novalence=False):
    """ Create a random Structure with random attributes

    Parameters
    ----------
    parametrized : bool
        If True, add at least two of all kinds of parameters to the
        generated random structure. If False, just fill in the atoms and
        residues and some random valence terms, but no "types"
    novalence : bool, optional
        If True, no valence terms will be added. Default is False. This is
        set to False if parametrized is True
    """
    from parmed.topologyobjects import (
        Atom, Bond, AtomType, BondType, AngleType, DihedralType, ImproperType,
        CmapType, OutOfPlaneBendType, StretchBendType, TorsionTorsionType,
        AmoebaNonbondedExceptionType, Angle, UreyBradley, Dihedral, Improper,
        Cmap, TrigonalAngle, OutOfPlaneBend, StretchBend, PiTorsion,
        TorsionTorsion, AcceptorDonor, Group, ChiralFrame, MultipoleFrame,
        NonbondedException, RBTorsionType)
    from parmed import structure
    from copy import copy
    if parametrized: novalence = False
    # Generate random atom and parameter types
    atom_types = [
        AtomType(''.join(random.sample(uppercase, 3)), i,
                 random.random() * 16 + 1, random.randint(1, 8))
        for i in range(random.randint(8, 20))
    ]
    bond_types = [
        BondType(random.random() * 2,
                 random.random() * 100) for i in range(random.randint(10, 20))
    ]
    angle_types = [
        AngleType(random.random() * 50,
                  random.random() * 120) for i in range(random.randint(10, 20))
    ]
    dihed_types = [
        DihedralType(random.random() * 10, random.randint(1, 6),
                     random.choice([0, 180]))
        for i in range(random.randint(10, 20))
    ]
    rb_types = [RBTorsionType(*[random.random() * 10 for i in range(6)])]
    imp_types = [
        ImproperType(random.random() * 100, random.choice([0, 180]))
        for i in range(random.randint(10, 20))
    ]
    cmap_types = [
        CmapType(24, [random.random() * 5 for i in range(24 * 24)])
        for i in range(random.randint(5, 10))
    ]
    oop_types = [
        OutOfPlaneBendType(random.random() * 100)
        for i in range(random.randint(10, 20))
    ]
    strbnd_types = [
        StretchBendType(random.random() * 10,
                        random.random() * 10,
                        random.random() * 2,
                        random.random() * 2,
                        random.random() * 120)
        for i in range(random.randint(10, 20))
    ]
    ang1, ang2 = list(range(-180, 180, 36)), list(range(-180, 180, 18))
    tortor_types = [
        TorsionTorsionType((10, 20), ang1[:], ang2[:],
                           [random.random() * 10 for j in range(200)])
        for i in range(random.randint(5, 10))
    ]
    for typ in atom_types:
        typ.set_lj_params(random.random() * 2, random.random() * 2)

    struct = structure.Structure()
    # Add atoms in residues
    for res in range(random.randint(20, 30)):
        resname = ''.join(random.sample(uppercase, 3))
        resid = res + 1
        for i in range(random.randint(10, 25)):
            name = ''.join(random.sample(uppercase, 4))
            if parametrized:
                typ = random.choice(atom_types)
                type = str(typ)
                mass = typ.mass
                atomic_number = typ.atomic_number
            else:
                type = ''.join(random.sample(uppercase, 3))
                mass = random.random() * 16 + 1
                atomic_number = random.randint(1, 8)
            charge = random.random() * 2 - 1
            solvent_radius = random.random() * 2
            screen = random.random() * 2
            atom = Atom(atomic_number=atomic_number,
                        type=type,
                        charge=charge,
                        mass=mass,
                        solvent_radius=solvent_radius,
                        screen=screen,
                        name=name)
            if parametrized:
                atom.atom_type = typ
            struct.add_atom(atom, resname, resid)
    if novalence:
        return struct
    # Possibly add parameter type lists
    if parametrized:
        struct.bond_types.extend([copy(x) for x in bond_types])
        struct.bond_types.claim()
        struct.angle_types.extend([copy(x) for x in angle_types])
        struct.angle_types.claim()
        struct.dihedral_types.extend([copy(x) for x in dihed_types])
        struct.dihedral_types.claim()
        struct.rb_torsion_types.extend([copy(x) for x in rb_types])
        struct.rb_torsion_types.claim()
        struct.urey_bradley_types.extend([copy(x) for x in bond_types])
        struct.urey_bradley_types.claim()
        struct.improper_types.extend([copy(x) for x in imp_types])
        struct.improper_types.claim()
        struct.cmap_types.extend([copy(x) for x in cmap_types])
        struct.cmap_types.claim()
        struct.trigonal_angle_types.extend([copy(x) for x in angle_types])
        struct.trigonal_angle_types.claim()
        struct.out_of_plane_bend_types.extend([copy(x) for x in oop_types])
        struct.out_of_plane_bend_types.claim()
        struct.pi_torsion_types.extend([copy(x) for x in dihed_types])
        struct.pi_torsion_types.claim()
        struct.stretch_bend_types.extend([copy(x) for x in strbnd_types])
        struct.stretch_bend_types.claim()
        struct.torsion_torsion_types.extend([copy(x) for x in tortor_types])
        struct.torsion_torsion_types.claim()
        struct.adjust_types.extend([
            AmoebaNonbondedExceptionType(0.5, 0.5, 0.6, 0.6, 0.7)
            for i in range(random.randint(10, 20))
        ])
        struct.adjust_types.claim()
    # Add valence terms with optional
    for i in range(random.randint(40, 50)):
        struct.bonds.append(Bond(*random.sample(struct.atoms, 2)))
        if parametrized:
            struct.bonds[-1].type = random.choice(struct.bond_types)
    for i in range(random.randint(35, 45)):
        struct.angles.append(Angle(*random.sample(struct.atoms, 3)))
        if parametrized:
            struct.angles[-1].type = random.choice(struct.angle_types)
    for i in range(random.randint(35, 45)):
        struct.urey_bradleys.append(
            UreyBradley(*random.sample(struct.atoms, 2)))
        if parametrized:
            struct.urey_bradleys[-1].type = random.choice(
                struct.urey_bradley_types)
    for i in range(random.randint(30, 40)):
        struct.dihedrals.append(
            Dihedral(*random.sample(struct.atoms, 4),
                     improper=random.choice([True, False])))
        if parametrized:
            struct.dihedrals[-1].type = random.choice(struct.dihedral_types)
    for i in range(random.randint(30, 40)):
        struct.rb_torsions.append(Dihedral(*random.sample(struct.atoms, 4)))
        if parametrized:
            struct.rb_torsions[-1].type = random.choice(
                struct.rb_torsion_types)
    for i in range(random.randint(10, 20)):
        struct.impropers.append(Improper(*random.sample(struct.atoms, 4)))
        if parametrized:
            struct.impropers[-1].type = random.choice(struct.improper_types)
    for i in range(random.randint(25, 35)):
        struct.cmaps.append(Cmap(*random.sample(struct.atoms, 5)))
        if parametrized:
            struct.cmaps[-1].type = random.choice(struct.cmap_types)
    for i in range(random.randint(30, 40)):
        struct.trigonal_angles.append(
            TrigonalAngle(*random.sample(struct.atoms, 4)))
        if parametrized:
            struct.trigonal_angles[-1].type = random.choice(
                struct.trigonal_angle_types)
    for i in range(random.randint(30, 40)):
        struct.out_of_plane_bends.append(
            OutOfPlaneBend(*random.sample(struct.atoms, 4)))
        if parametrized:
            struct.out_of_plane_bends[-1].type = random.choice(
                struct.out_of_plane_bend_types)
    for i in range(random.randint(30, 40)):
        struct.stretch_bends.append(
            StretchBend(*random.sample(struct.atoms, 3)))
        if parametrized:
            struct.stretch_bends[-1].type = random.choice(
                struct.stretch_bend_types)
    for i in range(random.randint(20, 30)):
        struct.pi_torsions.append(PiTorsion(*random.sample(struct.atoms, 6)))
        if parametrized:
            struct.pi_torsions[-1].type = random.choice(
                struct.pi_torsion_types)
    for i in range(random.randint(10, 20)):
        struct.torsion_torsions.append(
            TorsionTorsion(*random.sample(struct.atoms, 5)))
        if parametrized:
            struct.torsion_torsions[-1].type = random.choice(
                struct.torsion_torsion_types)
    # Now use some lesser-used features
    for i in range(random.randint(5, 10)):
        struct.acceptors.append(AcceptorDonor(*random.sample(struct.atoms, 2)))
        struct.donors.append(AcceptorDonor(*random.sample(struct.atoms, 2)))
        struct.groups.append(Group(random.choice(struct.atoms), 2, 0))
        struct.chiral_frames.append(
            ChiralFrame(*random.sample(struct.atoms, 2),
                        chirality=random.choice([-1, 1])))
        struct.multipole_frames.append(
            MultipoleFrame(random.choice(struct.atoms), 0, 1, 2, 3))
    for i in range(random.randint(20, 30)):
        struct.adjusts.append(
            NonbondedException(*random.sample(struct.atoms, 2)))
        if parametrized:
            struct.adjusts[-1].type = random.choice(struct.adjust_types)
    struct.prune_empty_terms()
    struct.unchange()
    struct.update_dihedral_exclusions()
    return struct
Exemple #5
0
 def __init__(self, psf_name=None):
     """
     Opens and parses a PSF file, then instantiates a CharmmPsfFile
     instance from the data.
     """
     global _resre
     Structure.__init__(self)
     # Bail out if we don't have a filename
     if psf_name is None:
         return
     conv = CharmmPsfFile._convert
     # Open the PSF and read the first line. It must start with "PSF"
     with closing(genopen(psf_name, 'r')) as psf:
         self.name = psf_name
         line = psf.readline()
         if not line.startswith('PSF'):
             raise CharmmError('Unrecognized PSF file. First line is %s' %
                               line.strip())
         # Store the flags
         psf_flags = line.split()[1:]
         # Now get all of the sections and store them in a dict
         psf.readline()
         # Now get all of the sections
         psfsections = _ZeroDict()
         while True:
             try:
                 sec, ptr, data = CharmmPsfFile._parse_psf_section(psf)
             except _FileEOF:
                 break
             psfsections[sec] = (ptr, data)
         # store the title
         self.title = psfsections['NTITLE'][1]
         # Next is the number of atoms
         natom = conv(psfsections['NATOM'][0], int, 'natom')
         # Parse all of the atoms
         for i in range(natom):
             words = psfsections['NATOM'][1][i].split()
             atid = int(words[0])
             if atid != i + 1:
                 raise CharmmError('Nonsequential atoms detected!')
             segid = words[1]
             rematch = _resre.match(words[2])
             if not rematch:
                 raise CharmmError('Could not interpret residue number %s'
                                   %  # pragma: no cover
                                   words[2])
             resid, inscode = rematch.groups()
             resid = conv(resid, int, 'residue number')
             resname = words[3]
             name = words[4]
             attype = words[5]
             # Try to convert the atom type to an integer a la CHARMM
             try:
                 attype = int(attype)
             except ValueError:
                 pass
             charge = conv(words[6], float, 'partial charge')
             mass = conv(words[7], float, 'atomic mass')
             props = words[8:]
             atom = Atom(name=name, type=attype, charge=charge, mass=mass)
             atom.props = props
             self.add_atom(atom,
                           resname,
                           resid,
                           chain=segid,
                           inscode=inscode,
                           segid=segid)
         # Now get the number of bonds
         nbond = conv(psfsections['NBOND'][0], int, 'number of bonds')
         if len(psfsections['NBOND'][1]) != nbond * 2:
             raise CharmmError(
                 'Got %d indexes for %d bonds' %  # pragma: no cover
                 (len(psfsections['NBOND'][1]), nbond))
         it = iter(psfsections['NBOND'][1])
         for i, j in zip(it, it):
             self.bonds.append(Bond(self.atoms[i - 1], self.atoms[j - 1]))
         # Now get the number of angles and the angle list
         ntheta = conv(psfsections['NTHETA'][0], int, 'number of angles')
         if len(psfsections['NTHETA'][1]) != ntheta * 3:
             raise CharmmError(
                 'Got %d indexes for %d angles' %  # pragma: no cover
                 (len(psfsections['NTHETA'][1]), ntheta))
         it = iter(psfsections['NTHETA'][1])
         for i, j, k in zip(it, it, it):
             self.angles.append(
                 Angle(self.atoms[i - 1], self.atoms[j - 1],
                       self.atoms[k - 1]))
             self.angles[-1].funct = 5  # urey-bradley
         # Now get the number of torsions and the torsion list
         nphi = conv(psfsections['NPHI'][0], int, 'number of torsions')
         if len(psfsections['NPHI'][1]) != nphi * 4:
             raise CharmmError(
                 'Got %d indexes for %d torsions' %  # pragma: no cover
                 (len(psfsections['NPHI']), nphi))
         it = iter(psfsections['NPHI'][1])
         for i, j, k, l in zip(it, it, it, it):
             self.dihedrals.append(
                 Dihedral(self.atoms[i - 1], self.atoms[j - 1],
                          self.atoms[k - 1], self.atoms[l - 1]))
         self.dihedrals.split = False
         # Now get the number of improper torsions
         nimphi = conv(psfsections['NIMPHI'][0], int, 'number of impropers')
         if len(psfsections['NIMPHI'][1]) != nimphi * 4:
             raise CharmmError(
                 'Got %d indexes for %d impropers' %  # pragma: no cover
                 (len(psfsections['NIMPHI'][1]), nimphi))
         it = iter(psfsections['NIMPHI'][1])
         for i, j, k, l in zip(it, it, it, it):
             self.impropers.append(
                 Improper(self.atoms[i - 1], self.atoms[j - 1],
                          self.atoms[k - 1], self.atoms[l - 1]))
         # Now handle the donors (what is this used for??)
         ndon = conv(psfsections['NDON'][0], int, 'number of donors')
         if len(psfsections['NDON'][1]) != ndon * 2:
             raise CharmmError(
                 'Got %d indexes for %d donors' %  # pragma: no cover
                 (len(psfsections['NDON'][1]), ndon))
         it = iter(psfsections['NDON'][1])
         for i, j in zip(it, it):
             self.donors.append(
                 AcceptorDonor(self.atoms[i - 1], self.atoms[j - 1]))
         # Now handle the acceptors (what is this used for??)
         nacc = conv(psfsections['NACC'][0], int, 'number of acceptors')
         if len(psfsections['NACC'][1]) != nacc * 2:
             raise CharmmError(
                 'Got %d indexes for %d acceptors' %  # pragma: no cover
                 (len(psfsections['NACC'][1]), nacc))
         it = iter(psfsections['NACC'][1])
         for i, j in zip(it, it):
             self.acceptors.append(
                 AcceptorDonor(self.atoms[i - 1], self.atoms[j - 1]))
         # Now get the group sections
         try:
             ngrp, nst2 = psfsections['NGRP NST2'][0]
         except ValueError:  # pragma: no cover
             raise CharmmError(
                 'Could not unpack GROUP pointers')  # pragma: no cover
         tmp = psfsections['NGRP NST2'][1]
         self.groups.nst2 = nst2
         # Now handle the groups
         if len(psfsections['NGRP NST2'][1]) != ngrp * 3:
             raise CharmmError(
                 'Got %d indexes for %d groups' %  # pragma: no cover
                 (len(tmp), ngrp))
         it = iter(psfsections['NGRP NST2'][1])
         for i, j, k in zip(it, it, it):
             self.groups.append(Group(self.atoms[i], j, k))
         # Assign all of the atoms to molecules recursively
         tmp = psfsections['MOLNT'][1]
         set_molecules(self.atoms)
         molecule_list = [a.marked for a in self.atoms]
         if len(tmp) == len(self.atoms):
             if molecule_list != tmp:
                 warnings.warn(
                     'Detected PSF molecule section that is WRONG. '
                     'Resetting molecularity.', CharmmWarning)
             # We have a CHARMM PSF file; now do NUMLP/NUMLPH sections
             numlp, numlph = psfsections['NUMLP NUMLPH'][0]
             if numlp != 0 or numlph != 0:
                 raise NotImplementedError(
                     'Cannot currently handle PSFs with '
                     'lone pairs defined in the NUMLP/'
                     'NUMLPH section.')
         # Now do the CMAPs
         ncrterm = conv(psfsections['NCRTERM'][0], int,
                        'Number of cross-terms')
         if len(psfsections['NCRTERM'][1]) != ncrterm * 8:
             raise CharmmError('Got %d CMAP indexes for %d cmap terms'
                               %  # pragma: no cover
                               (len(psfsections['NCRTERM']), ncrterm))
         it = iter(psfsections['NCRTERM'][1])
         for i, j, k, l, m, n, o, p in zip(it, it, it, it, it, it, it, it):
             self.cmaps.append(
                 Cmap.extended(self.atoms[i - 1], self.atoms[j - 1],
                               self.atoms[k - 1], self.atoms[l - 1],
                               self.atoms[m - 1], self.atoms[n - 1],
                               self.atoms[o - 1], self.atoms[p - 1]))
         self.unchange()
         self.flags = psf_flags