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')
def _compareInputOutputPDBs(self, pdbfile, pdbfile2, reordered=False, altloc_option='all'): # Now go through all atoms and compare their attributes for a1, a2 in zip(pdbfile.atoms, pdbfile2.atoms): if altloc_option in ('first', 'all'): self.assertEqual(a1.occupancy, a2.occupancy) a1idx = a1.idx elif altloc_option == 'occupancy': a, occ = a1, a1.occupancy for key, oa in iteritems(a1.other_locations): if oa.occupancy > occ: occ = oa.occupancy a = oa a1idx = a1.idx a1 = a # This is the atom we want to compare with self.assertEqual(a1.atomic_number, a2.atomic_number) self.assertEqual(a1.name, a2.name) self.assertEqual(a1.type, a2.type) self.assertEqual(a1.mass, a2.mass) self.assertEqual(a1.charge, a2.charge) self.assertEqual(a1.bfactor, a2.bfactor) self.assertEqual(a1.altloc, a2.altloc) self.assertEqual(a1idx, a2.idx) if altloc_option == 'all': self.assertEqual(set(a1.other_locations.keys()), set(a2.other_locations.keys())) self.assertEqual(a1.xx, a2.xx) self.assertEqual(a1.xy, a2.xy) self.assertEqual(a1.xz, a2.xz) if altloc_option != 'all': # There should be no alternate locations unless we keep them all self.assertEqual(len(a2.other_locations), 0) if not reordered: self.assertEqual(a1.number, a2.number) # Search all alternate locations as well for k1, k2 in zip(sorted(a1.other_locations.keys()), sorted(a2.other_locations.keys())): self.assertEqual(k1, k2) oa1 = a1.other_locations[k1] oa2 = a2.other_locations[k2] self.assertEqual(oa1.atomic_number, oa2.atomic_number) self.assertEqual(oa1.name, oa2.name) self.assertEqual(oa1.type, oa2.type) self.assertEqual(oa1.mass, oa2.mass) self.assertEqual(oa1.charge, oa2.charge) self.assertEqual(oa1.occupancy, oa2.occupancy) self.assertEqual(oa1.bfactor, oa2.bfactor) self.assertEqual(oa1.altloc, oa2.altloc) self.assertEqual(oa1.idx, oa2.idx) if not reordered: self.assertEqual(oa1.number, oa2.number) # Now compare all residues for r1, r2 in zip(pdbfile.residues, pdbfile2.residues): self.assertEqual(r1.name, r2.name) self.assertEqual(r1.idx, r2.idx) self.assertEqual(r1.ter, r2.ter) self.assertEqual(len(r1), len(r2)) self.assertEqual(r1.insertion_code, r2.insertion_code) if not reordered: self.assertEqual(r1.number, r2.number)
def test_gas_energy_conf_2(self): """ Compare Amber and OpenMM gas phase energies and forces (topology 2) """ parm = AmberParm(get_fn('hydrogen-peroxide_T0_2.prmtop'), get_fn('hydrogen-peroxide_T0_2.rst7')) self.assertEqual(parm.combining_rule, 'lorentz') system = parm.createSystem() # Default, no cutoff integrator = mm.VerletIntegrator(1.0*u.femtoseconds) sim = app.Simulation(parm.topology, system, integrator, platform=CPU) sim.context.setPositions(parm.positions) energies = energy_decomposition(parm, sim.context) #BOND = 0.0319 ANGLE = 2.1690 DIHED = -2.7931 #VDWAALS = 0.0000 EEL = 0.0000 HBOND = 0.0000 #1-4 VDW = 0.0000 1-4 EEL = 0.0000 RESTRAINT = 0.0000 # Compare OpenMM energies with the Amber energies (above) self.assertAlmostEqual(energies['bond'], 0.0319, places=4) self.assertAlmostEqual(energies['angle'], 2.1690, places=4) self.assertAlmostEqual(energies['dihedral'],-2.7931, places=4) self.assertRelativeEqual(energies['nonbonded'], 0.0, places=3) # Now test the forces to make sure that they are computed correctly in # the presence of extra points pstate = sim.context.getState(getForces=True) pf = pstate.getForces().value_in_unit(u.kilojoule_per_mole/u.nanometer) # gmx forces: # f[ 0]={ 3.14357e+02, -5.90363e+02, 2.11410e+02} # f[ 1]={-3.14357e+02, 5.90363e+02, 2.11410e+02} # f[ 2]={ 2.70641e+02, 5.90363e+02, -2.11410e+02} # f[ 3]={-2.70641e+02, -5.90363e+02, -2.11410e+02} gf = [ ( 3.14357e+02, -5.90363e+02, 2.11410e+02), (-3.14357e+02, 5.90363e+02, 2.11410e+02), ( 2.70641e+02, 5.90363e+02, -2.11410e+02), (-2.70641e+02, -5.90363e+02, -2.11410e+02)] for p, s in zip(pf, gf): for x1, x2 in zip(p, s): self.assertAlmostEqual(x1, x2, places=3)
def testAdd(self): """ Tests combining AmberParm instances """ parm1 = readparm.AmberParm(get_fn('phenol.prmtop')) parm2 = readparm.AmberParm(get_fn('biphenyl.prmtop')) comb = parm1 + parm2 self.assertEqual(len(comb.atoms), len(parm1.atoms) + len(parm2.atoms)) for a1, a2 in zip(comb.atoms, parm1.atoms + parm2.atoms): self.assertEqual(a1.name, a2.name) self.assertEqual(a1.mass, a2.mass) self.assertEqual(a1.charge, a2.charge) self.assertEqual(a1.radii, a2.radii) self.assertEqual(len(comb.residues), len(parm1.residues) + len(parm2.residues)) for r1, r2 in zip(comb.residues, parm1.residues + parm2.residues): self.assertEqual(len(r1), len(r2)) self.assertEqual(r1.name, r2.name) self.assertEqual(r1.chain, r2.chain) # In-place now parm1 += parm2 self.assertEqual(len(parm1.atoms), len(comb.atoms)) for a1, a2 in zip(comb.atoms, parm1.atoms): self.assertEqual(a1.name, a2.name) self.assertEqual(a1.mass, a2.mass) self.assertEqual(a1.charge, a2.charge) self.assertEqual(a1.radii, a2.radii) self.assertEqual(len(parm1.residues), len(comb.residues)) for r1, r2 in zip(comb.residues, parm1.residues): self.assertEqual(len(r1), len(r2)) self.assertEqual(r1.name, r2.name) self.assertEqual(r1.chain, r2.chain)
def testMult(self): """ Tests replicating AmberParm instances """ parm = readparm.AmberParm(get_fn('phenol.prmtop')) mult = parm * 5 self.assertEqual(len(mult.atoms), 5*len(parm.atoms)) self.assertEqual(len(mult.residues), 5*len(parm.residues)) for i, a1 in enumerate(mult.atoms): a2 = parm[i%len(parm.atoms)] self.assertEqual(a1.name, a2.name) self.assertEqual(a1.mass, a2.mass) self.assertEqual(a1.charge, a2.charge) self.assertEqual(a1.radii, a2.radii) for i, r1 in enumerate(mult.residues): r2 = parm.residues[i%len(parm.residues)] self.assertEqual(len(r1), len(r2)) self.assertEqual(r1.name, r2.name) self.assertEqual(r1.chain, r2.chain) # In-place now parm *= 5 self.assertEqual(len(parm.atoms), len(mult.atoms)) for a1, a2 in zip(mult.atoms, parm.atoms): self.assertEqual(a1.name, a2.name) self.assertEqual(a1.mass, a2.mass) self.assertEqual(a1.charge, a2.charge) self.assertEqual(a1.radii, a2.radii) self.assertEqual(len(parm.residues), len(mult.residues)) for r1, r2 in zip(mult.residues, parm.residues): self.assertEqual(len(r1), len(r2)) self.assertEqual(r1.name, r2.name) self.assertEqual(r1.chain, r2.chain)
def _check_rst(self, rst, written=False): """ Checks various restart properties """ self.assertAlmostEqual(rst.time, 30.1) self.assertEqual(rst.Conventions, 'AMBERRESTART') self.assertEqual(rst.title, 'ACE') if written: self.assertEqual(rst.application, 'AmberTools') self.assertEqual(rst.program, 'ParmEd') self.assertEqual(rst.programVersion, __version__) else: self.assertEqual(rst.application, 'AMBER') self.assertEqual(rst.program, 'sander') self.assertEqual(rst.programVersion, '11.0') self.assertAlmostEqual(rst.cell_lengths[0], 30.2642725) self.assertAlmostEqual(rst.cell_lengths[1], 30.2642725) self.assertAlmostEqual(rst.cell_lengths[2], 30.2642725) self.assertAlmostEqual(rst.cell_angles[0], 109.471219) self.assertAlmostEqual(rst.cell_angles[1], 109.471219) self.assertAlmostEqual(rst.cell_angles[2], 109.471219) self.assertTrue( all([ round(x - y, 7) == 0 for x, y in zip(rst.cell_lengths, rst.box[:3]) ])) self.assertTrue( all([ round(x - y, 7) == 0 for x, y in zip(rst.cell_angles, rst.box[3:]) ]))
def testMoleculeCombine(self): """ Tests selective molecule combination in Gromacs topology files """ warnings.filterwarnings('ignore', category=GromacsWarning) parm = load_file(os.path.join(get_fn('12.DPPC'), 'topol3.top')) fname = get_fn('combined.top', written=True) # Make sure that combining non-adjacent molecules fails self.assertRaises(ValueError, lambda: parm.write(fname, combine=[[1, 3]])) self.assertRaises(ValueError, lambda: parm.write(fname, combine='joey')) self.assertRaises(ValueError, lambda: parm.write(fname, combine=[1, 2, 3])) self.assertRaises(TypeError, lambda: parm.write(fname, combine=1)) parm.write(fname, combine=[[3, 4], [126, 127, 128, 129, 130]]) with open(fname, 'r') as f: for line in f: if line.startswith('[ molecules ]'): break molecule_list = [] for line in f: if line[0] == ';': continue words = line.split() molecule_list.append((words[0], int(words[1]))) parm2 = load_file(fname) self.assertEqual(molecule_list, [('DPPC', 3), ('system1', 1), ('SOL', 121), ('system2', 1), ('SOL', 121)]) self.assertEqual(len(parm2.atoms), len(parm.atoms)) self.assertEqual(len(parm2.residues), len(parm2.residues)) for a1, a2 in zip(parm.atoms, parm2.atoms): self._equal_atoms(a1, a2) for r1, r2 in zip(parm.residues, parm2.residues): self.assertEqual(len(r1), len(r2)) for a1, a2 in zip(r1, r2): self._equal_atoms(a1, a2)
def chk_valence(val1, val2): self.assertIs(type(val1[0]), type(val2[0])) self.assertEqual(len(val1), len(val2)) attrs = [attr for attr in dir(val1[0]) if attr.startswith('atom')] for v1, v2 in zip(val1, val2): at1 = [getattr(v1, attr) for attr in attrs] at2 = [getattr(v2, attr) for attr in attrs] self.assertIsNot(v1, v2) for a1, a2 in zip(at1, at2): cmp_atoms(a1, a2)
def _load_urey_brad_info(self): """ Loads the Urey-Bradley types and array """ del self.urey_bradleys[:] del self.urey_bradley_types[:] for k, req in zip( self.parm_data["CHARMM_UREY_BRADLEY_FORCE_CONSTANT"], self.parm_data["CHARMM_UREY_BRADLEY_EQUIL_VALUE"] ): self.urey_bradley_types.append(BondType(k, req, self.urey_bradley_types)) it = iter(self.parm_data["CHARMM_UREY_BRADLEY"]) for i, j, k in zip(it, it, it): self.urey_bradleys.append(UreyBradley(self.atoms[i - 1], self.atoms[j - 1], self.urey_bradley_types[k - 1]))
def testCoordinates(self): """ Tests coordinate handling in Structure """ s = create_random_structure(parametrized=False) self.assertIs(s.coordinates, None) natom = len(s.atoms) # Make sure coordinates will be generated from Atom.xx, xy, xz if not # otherwise generated xyz = np.random.random((natom, 3)) for a, x in zip(s.atoms, xyz): a.xx, a.xy, a.xz = x self.assertEqual(s.coordinates.shape, (natom, 3)) np.testing.assert_equal(s.coordinates, xyz[:,:]) self.assertIs(s._coordinates, None) # Now set multiple frames xyz = np.random.random((5, natom, 3)).tolist() s.coordinates = xyz self.assertIsInstance(s.coordinates, np.ndarray) self.assertEqual(s.coordinates.shape, (natom, 3)) for a, x in zip(s.atoms, xyz[0]): self.assertEqual(a.xx, x[0]) self.assertEqual(a.xy, x[1]) self.assertEqual(a.xz, x[2]) np.testing.assert_equal(s.get_coordinates('all'), xyz) for i in range(5): np.testing.assert_equal(s.get_coordinates(i), xyz[i]) # Now try setting with units xyz = u.Quantity(np.random.random((3, natom, 3)), u.nanometers) s.coordinates = xyz self.assertIsInstance(s.coordinates, np.ndarray) self.assertEqual(s.coordinates.shape, (natom, 3)) for a, x in zip(s.atoms, xyz[0]._value): self.assertEqual(a.xx, x[0]*10) self.assertEqual(a.xy, x[1]*10) self.assertEqual(a.xz, x[2]*10) # Now check setting None s.coordinates = None for a in s.atoms: self.assertFalse(hasattr(a, 'xx')) self.assertFalse(hasattr(a, 'xy')) self.assertFalse(hasattr(a, 'xz')) self.assertIs(s.coordinates, None) # Now check setting flattened arrays s.coordinates = np.random.random((natom, 3)) self.assertEqual(s.coordinates.shape, (natom, 3)) s.coordinates = np.random.random(natom*3) self.assertEqual(s.coordinates.shape, (natom, 3)) s.coordinates = np.random.random(natom*3*10) self.assertEqual(s.coordinates.shape, (natom, 3)) # Now check other iterables old_crds = s.coordinates s.coordinates = (random.random() for i in range(3*len(s.atoms))) self.assertEqual(s.coordinates.shape, (natom, 3)) diff = (old_crds - s.coordinates).ravel()**2 self.assertGreater(diff.sum(), 0.01)
def testSimpleSlice(self): """ Tests simple slicing of AmberParm """ parm1 = readparm.AmberParm(get_fn("trx.prmtop")) parm2 = readparm.AmberParm(get_fn("trx.prmtop")) parm2.strip("!@CA,C,O,N,HA,H") selection = parm1["@CA,C,O,N,HA,H"] self.assertIs(type(parm1), readparm.AmberParm) self.assertIs(type(parm2), readparm.AmberParm) self.assertIs(type(selection), readparm.AmberParm) self.assertEqual(len(parm2.atoms), len(selection.atoms)) self.assertEqual(len(parm2.residues), len(selection.residues)) self.assertLess(len(parm2.atoms), len(parm1.atoms)) def cmp_atoms(a1, a2): self.assertEqual(a1.name, a2.name) self.assertEqual(a1.type, a2.type) self.assertEqual(a1.charge, a2.charge) self.assertEqual(a1.tree, a2.tree) self.assertEqual(a1.radii, a2.radii) self.assertEqual(a1.screen, a2.screen) self.assertEqual(a1.join, a2.join) self.assertEqual(a1.mass, a2.mass) self.assertEqual(a1.atomic_number, a2.atomic_number) self.assertEqual(a1.residue.name, a2.residue.name) self.assertEqual(a1.residue.idx, a2.residue.idx) self.assertEqual(a1.nb_idx, a2.nb_idx) for a1, a2 in zip(parm2.atoms, selection.atoms): cmp_atoms(a1, a2) # Now check valence terms self.assertEqual(len(parm2.bonds), len(selection.bonds)) self.assertEqual(len(parm2.angles), len(selection.angles)) self.assertEqual(len(parm2.dihedrals), len(selection.dihedrals)) self.assertGreater(len(parm2.bonds), 0) self.assertGreater(len(parm2.angles), 0) self.assertGreater(len(parm2.dihedrals), 0) for b1, b2 in zip(parm2.bonds, selection.bonds): cmp_atoms(b1.atom1, b2.atom1) cmp_atoms(b1.atom2, b2.atom2) self.assertEqual(b1.type, b2.type) for a1, a2 in zip(parm2.angles, selection.angles): cmp_atoms(a1.atom1, a2.atom1) cmp_atoms(a1.atom2, a2.atom2) cmp_atoms(a1.atom3, a2.atom3) self.assertEqual(a1.type, a2.type) for d1, d2 in zip(parm2.dihedrals, selection.dihedrals): cmp_atoms(d1.atom1, d2.atom1) cmp_atoms(d1.atom2, d2.atom2) cmp_atoms(d1.atom3, d2.atom3) cmp_atoms(d1.atom4, d2.atom4) self.assertEqual(d1.ignore_end, d2.ignore_end) self.assertEqual(d1.improper, d2.improper) self.assertEqual(d1.type, d2.type)
def testMoleculeOrdering(self): """ Tests non-contiguous atoms in Gromacs topology file writes """ warnings.filterwarnings('ignore', category=GromacsWarning) parm = load_file(os.path.join(get_fn('12.DPPC'), 'topol3.top')) parm.write(get_fn('topol3.top', written=True)) parm2 = load_file(get_fn('topol3.top', written=True)) self.assertEqual(len(parm.atoms), len(parm2.atoms)) self.assertEqual(len(parm.residues), len(parm2.residues)) for r1, r2 in zip(parm.residues, parm2.residues): self.assertEqual(r1.name, r2.name) for a1, a2 in zip(r1.atoms, r2.atoms): self.assertEqual(a1.name, a2.name) self.assertEqual(a1.type, a2.type)
def check_aniso(pdbfile): aniso1 = [2066, 1204, 1269, 44, 126, 191] aniso2 = [2090, 1182, 921, 46, 64, 60] aniso3 = [3057, 3932, 5304, 126, -937, -661] self.assertEqual(len(aniso1), len(pdbfile.atoms[0].anisou)) for x, y in zip(aniso1, pdbfile.atoms[0].anisou): self.assertEqual(x/10000, y) self.assertEqual(len(aniso2), len(pdbfile.atoms[1].anisou)) for x, y in zip(aniso2, pdbfile.atoms[1].anisou): self.assertEqual(x/10000, y) self.assertEqual(len(aniso3), len(pdbfile.atoms[-1].anisou)) for x, y in zip(aniso3, pdbfile.atoms[-1].anisou): self.assertEqual(x/10000, y)
def _load_urey_brad_info(self): """ Loads the Urey-Bradley types and array """ del self.urey_bradleys[:] del self.urey_bradley_types[:] for k, req in zip(self.parm_data['CHARMM_UREY_BRADLEY_FORCE_CONSTANT'], self.parm_data['CHARMM_UREY_BRADLEY_EQUIL_VALUE']): self.urey_bradley_types.append( BondType(k, req, self.urey_bradley_types)) it = iter(self.parm_data['CHARMM_UREY_BRADLEY']) for i, j, k in zip(it, it, it): self.urey_bradleys.append( UreyBradley(self.atoms[i - 1], self.atoms[j - 1], self.urey_bradley_types[k - 1]))
def _check4lzt(self, cif): pdb = read_PDB(self.lztpdb) self.assertEqual(len(cif.atoms), len(pdb.atoms)) nextra = 0 for a1, a2 in zip(cif.atoms, pdb.atoms): self.assertEqual(a1.name, a2.name) self.assertEqual(a1.number + nextra, a2.number) self.assertEqual(len(a1.anisou), len(a2.anisou)) for x, y in zip(a1.anisou, a2.anisou): self.assertEqual(x, y) self.assertEqual(a1.altloc, a2.altloc) self.assertEqual(len(a1.other_locations), len(a2.other_locations)) self.assertEqual(a1.residue.name, a2.residue.name) self.assertEqual(a1.residue.number, a2.residue.number) # TER cards consume a serial number in the PDB file, but *not* in a # CIF file. if a2.residue.ter and a2 is a2.residue.atoms[-1]: nextra += 1 # Check the unit cell info self.assertEqual(cif.box[0], 27.240) self.assertEqual(cif.box[1], 31.870) self.assertEqual(cif.box[2], 34.230) self.assertEqual(cif.box[3], 88.520) self.assertEqual(cif.box[4], 108.53) self.assertEqual(cif.box[5], 111.89) # Check the metadata now self.assertEqual(cif.experimental, 'X-RAY DIFFRACTION') self.assertEqual(cif.authors, 'Walsh, M.A., Schneider, T., Sieker, L.C., Dauter, Z., ' 'Lamzin, V., Wilson, K.S.') self.assertEqual(cif.title, 'Refinement of triclinic hen egg-white lysozyme at atomic ' 'resolution.; Refinement of Triclinic Lysozyme: I. Fourier ' 'and Least-Squares Methods; Refinement of Triclinic Lysozyme: ' 'II. The Method of Stereochemically Restrained Least Squares') self.assertEqual(cif.journal, 'Acta Crystallogr.,Sect.D; Acta Crystallogr.,Sect.B; ' 'Acta Crystallogr.,Sect.B') self.assertEqual(cif.journal_authors, 'Walsh, M.A., Schneider, T.R., Sieker, L.C., Dauter, Z., ' 'Lamzin, V.S., Wilson, K.S., Hodsdon, J.M., Brown, G.M., ' 'Jensen, L.H., Ramanadham, M.') self.assertEqual(cif.year, '1998, 1990, 1990') self.assertEqual(cif.page, '522, 54, 63') self.assertEqual(cif.keywords, ['HYDROLASE', 'O-GLYCOSYL', 'GLYCOSIDASE']) self.assertEqual(cif.volume, '54, 46, 46') self.assertEqual(cif.doi, '10.1107/S0907444997013656') self.assertEqual(cif.pmid, '9761848') self.assertEqual(cif.resolution, 0.95)
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]))
def chk_valence(val1, val2): self.assertIs(type(val1[0]), type(val2[0])) self.assertEqual(len(val1), len(val2)) attrs = [attr for attr in dir(val1[0]) if attr.startswith('atom')] for v1, v2 in zip(val1, val2): at1 = [getattr(v1, attr) for attr in attrs] at2 = [getattr(v2, attr) for attr in attrs] self.assertIsNot(v1, v2) for a1, a2 in zip(at1, at2): cmp_atoms(a1, a2) if hasattr(v1, 'type'): self.assertEqual(v1.type, v2.type) if not isinstance(v1.type, integer_types): self.assertIsNot(v1.type, v2.type)
def test_gas_energy_conf_4(self): """ Compare Amber and OpenMM gas phase energies and forces (topology 4) """ parm = AmberParm(get_fn('ethanol_T0.prmtop'), get_fn('ethanol_T0.rst7')) self.assertEqual(parm.combining_rule, 'geometric') system = parm.createSystem() # Default, no cutoff integrator = mm.VerletIntegrator(1.0 * u.femtoseconds) sim = app.Simulation(parm.topology, system, integrator, platform=CPU) sim.context.setPositions(parm.positions) energies = energy_decomposition(parm, sim.context) #BOND = 0.0239 ANGLE = 0.0298 DIHED = 0.0093 #VDWAALS = 0.0000 EEL = 6.7526 HBOND = 0.0000 #1-4 VDW = 0.0492 1-4 EEL = -6.0430 RESTRAINT = 0.0000 # Compare OpenMM energies with the Amber energies (above) self.assertAlmostEqual(energies['bond'], 0.0239, places=4) self.assertAlmostEqual(energies['angle'], 0.0298, places=4) self.assertAlmostEqual(energies['dihedral'], 0.0093, places=4) self.assertRelativeEqual(energies['nonbonded'], 0.0000 + 6.7526 + 0.0492 - 6.0430, places=3) # Now test the forces to make sure that they are computed correctly in # the presence of extra points pstate = sim.context.getState(getForces=True) pf = pstate.getForces().value_in_unit(u.kilojoule_per_mole / u.nanometer) # gmx forces: # f[ 0]={ 1.73101e+02, 5.67250e+01, -4.02950e+01} # f[ 1]={-8.13704e+00, -1.79612e+01, 9.88537e+01} # f[ 2]={-2.83120e+01, 6.23352e+00, -5.47393e+00} # f[ 3]={-1.03312e+01, -1.00966e+01, -5.12129e+00} # f[ 4]={-1.69636e+02, 3.34850e+01, -1.73612e+02} # f[ 5]={ 4.19932e+00, -2.58283e+00, 1.29999e+02} # f[ 6]={ 3.02865e+01, -6.68331e+00, -2.99153e+01} # f[ 7]={ 1.00113e+02, -5.22480e+01, 4.80526e+01} # f[ 8]={-9.12828e+01, -6.87157e+00, -2.24877e+01} gf = [(1.73101e+02, 5.67250e+01, -4.02950e+01), (-8.13704e+00, -1.79612e+01, 9.88537e+01), (-2.83120e+01, 6.23352e+00, -5.47393e+00), (-1.03312e+01, -1.00966e+01, -5.12129e+00), (-1.69636e+02, 3.34850e+01, -1.73612e+02), (4.19932e+00, -2.58283e+00, 1.29999e+02), (3.02865e+01, -6.68331e+00, -2.99153e+01), (1.00113e+02, -5.22480e+01, 4.80526e+01), (-9.12828e+01, -6.87157e+00, -2.24877e+01)] for p, s in zip(pf, gf): for x1, x2 in zip(p, s): self.assertAlmostEqual(x1, x2, places=3)
def testAnisouRead(self): """ Tests that read_PDB properly reads ANISOU records """ pdbfile = read_PDB(self.pdb) aniso1 = [2066, 1204, 1269, 44, 126, 191] # first atom's ANISOU record aniso2 = [2090, 1182, 921, 46, 64, 60] # second atom's ANISOU record aniso3 = [3057, 3932, 5304, 126, -937, -661] # last atom's ANISOU self.assertEqual(len(aniso1), len(pdbfile.atoms[0].anisou)) for x, y in zip(aniso1, pdbfile.atoms[0].anisou): self.assertEqual(x/10000, y) self.assertEqual(len(aniso2), len(pdbfile.atoms[1].anisou)) for x, y in zip(aniso2, pdbfile.atoms[1].anisou): self.assertEqual(x/10000, y) self.assertEqual(len(aniso3), len(pdbfile.atoms[-1].anisou)) for x, y in zip(aniso3, pdbfile.atoms[-1].anisou): self.assertEqual(x/10000, y)
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]) )
def energy_decomposition_system(structure, system, platform=None, nrg=u.kilocalories_per_mole): """ This function computes the energy contribution for all of the different force groups. Parameters ---------- structure : Structure The Structure with the coordinates for this system system : mm.System The OpenMM System object to get decomposed energies from platform : str The platform to use. Options are None (default), 'CPU', 'Reference', 'CUDA', and 'OpenCL'. None will pick default OpenMM platform for this installation and computer nrg : energy unit, optional The unit to convert all energies into. Default is kcal/mol Returns ------- energies : list of tuple Each entry is a tuple with the name of the force followed by its contribution """ import simtk.openmm as mm # First get all of the old force groups so we can restore them old_groups = [f.getForceGroup() for f in system.getForces()] old_recip_group = [] def _ene(context, grp): st = context.getState(getEnergy=True, groups=1 << grp) return (type(system.getForce(grp)).__name__, st.getPotentialEnergy().value_in_unit(nrg)) try: for i, f in enumerate(system.getForces()): if isinstance(f, mm.NonbondedForce): old_recip_group.append(f.getReciprocalSpaceForceGroup()) f.setReciprocalSpaceForceGroup(i) f.setForceGroup(i) if platform is None: con = mm.Context(system, mm.VerletIntegrator(0.001)) else: con = mm.Context(system, mm.VerletIntegrator(0.001), mm.Platform.getPlatformByName(platform)) con.setPositions(structure.positions) if structure.box is not None: con.setPeriodicBoxVectors(*structure.box_vectors) return list(map(lambda x: _ene(con, x), range(system.getNumForces()))) finally: idx = 0 for grp, force in zip(old_groups, system.getForces()): if isinstance(force, mm.NonbondedForce): force.setReciprocalSpaceForceGroup(old_recip_group[idx]) idx += 1 force.setForceGroup(grp)
def testXyz(self): """ Tests parsing Tinker XYZ files """ self.assertTrue(tinkerfiles.XyzFile.id_format(get_fn('nma.xyz'))) self.assertTrue( tinkerfiles.XyzFile.id_format(get_fn('2igd_924wat.xyz'))) xyz = tinkerfiles.XyzFile(get_fn('nma.xyz')) np.testing.assert_allclose(xyz.box, [30.735, 30.876, 28.485, 90.0, 90.0, 90.0]) self.assertEqual(len(xyz.atoms), 2466) self.assertEqual(xyz.atoms[0].name, 'C') self.assertEqual(xyz.atoms[0].type, '221') self.assertEqual(len(xyz.atoms[0].bond_partners), 4) self.assertEqual(xyz.atoms[-1].name, 'H') self.assertEqual(xyz.atoms[-1].atomic_number, 1) self.assertEqual(xyz.atoms[-1].type, '248') xyz = pmd.load_file(get_fn('2igd_924wat.xyz'), get_fn('2igd_924wat.pdb')) pdb = pmd.load_file(get_fn('2igd_924wat.pdb')) self.assertEqual(len(pdb.atoms), len(xyz.atoms)) self.assertEqual(len(pdb.residues), len(xyz.residues)) for r1, r2 in zip(pdb.residues, xyz.residues): self.assertEqual(len(r1), len(r2)) self.assertEqual(r1.chain, r2.chain) self.assertEqual(r1.name, r2.name) self.assertEqual(r1.insertion_code, r2.insertion_code)
def testPdbWriteXtal(self): """ Test PDB file writing from a Xtal structure """ pdbfile = read_PDB(self.pdb) self._check4lzt(pdbfile) output = StringIO() pdbfile.write_pdb(output, renumber=False) output.seek(0) pdbfile2 = read_PDB(output) self._check4lzt(pdbfile2, check_meta=False) self._compareInputOutputPDBs(pdbfile, pdbfile2) output = reset_stringio(output) write_PDB(pdbfile, output) output.seek(0) pdbfile3 = read_PDB(output) self._check4lzt(pdbfile3, check_meta=False) self._compareInputOutputPDBs(pdbfile, pdbfile3, True) # Now check that renumbering is done correctly. 4lzt skips residues 130 # through 200 for res1, res2 in zip(pdbfile.residues, pdbfile3.residues): if res1.idx < 129: self.assertEqual(res1.number, res2.number) elif res1.idx < 135: self.assertEqual(res1.number, res2.number + 71) else: # Some residue numbers are skipped in the water numbering self.assertGreaterEqual(res1.number, res2.number + 71 + 794)
def _check_written_mdcrds(self, box): # Now try to read them and verify the information crd = asciicrd.AmberMdcrd(get_fn('testc.mdcrd', written=True), 15, False, 'r') self.assertEqual(crd.title, 'Test file') self.assertFalse(crd.hasbox) for i in range(crd.frame): shape = crd.coordinates[i].shape refcrd = np.arange(45) + i np.testing.assert_equal(crd.coordinates[i], refcrd.reshape(shape)) for i, array in enumerate(crd.coordinates): refcrd = (np.arange(45) + i).reshape(array.shape) np.testing.assert_equal(array, refcrd) crd.close() crd = asciicrd.AmberMdcrd(get_fn('testcb.mdcrd', written=True), 18, True, 'r') self.assertEqual(crd.title, 'Test file') self.assertTrue(crd.hasbox) for i in range(crd.frame): refcrd = (np.arange(54) + i).reshape(crd.coordinates[i].shape) np.testing.assert_equal(crd.coordinates[i], refcrd) np.testing.assert_equal(crd.box[i], box) for i, (coords, mybox) in enumerate(zip(crd.coordinates, crd.box)): np.testing.assert_equal(coords, (np.arange(54)+i).reshape(coords.shape)) np.testing.assert_equal(mybox, box)
def detailed_diff(l1, l2, absolute_error=None, relative_error=None, spacechar=None): """ Check individual fields to make sure numbers are numerically equal if the lines differ. Also ignore fields that appear to be a file name, since those will be system-dependent """ fdir = os.path.split(get_fn('writes'))[0] if spacechar is not None: for char in spacechar: l1 = l1.replace(char, ' ') l2 = l2.replace(char, ' ') w1 = l1.split() w2 = l2.split() if len(w1) != len(w2): return False for wx, wy in zip(w1, w2): try: wx = float(wx) wy = float(wy) except ValueError: if isinstance(wx, float) or (wx != wy and not (wx.startswith(fdir) or wy.startswith(fdir))): return False else: if wx != wy: if absolute_error is not None and abs(wx-wy) > absolute_error: return False elif relative_error is not None: if wx == 0 or wy == 0 and abs(wx-wy) > relative_error: return False if abs((wx / wy) - 1) > relative_error: return False elif absolute_error is None and relative_error is None: return False return True
def test_dihedral_type_list(self): """ Tests the DihedralTypeList class """ dihed_types = TrackedList() dihed_types.append(DihedralTypeList(list=dihed_types)) dihed_types[0].append(DihedralType(5.0, 2, 0.0, 1.2, 2.0)) dihed_types[0].append(DihedralType(1.0, 3, 180.0, 1.2, 2.0)) dihed_types[0].append(DihedralType(2.0, 4, 180.0, 1.2, 2.0)) dihed_types[0].append(DihedralType(10.0, 1, 180.0, 0., 0.)) self.assertIs(dihed_types[0].list, dihed_types) self.assertEqual(len(dihed_types), 1) self.assertEqual(dihed_types[0].idx, 0) self.assertEqual(len(dihed_types[0]), 4) # Now test DihedralTypeList.__copy__ cp = copy(dihed_types[0]) self.assertIsNot(cp, dihed_types[0]) self.assertIs(cp.list, None) self.assertEqual(cp.idx, -1) self.assertEqual(len(cp), 4) i = 0 for t1, t2 in zip(cp, dihed_types[0]): self.assertIsNot(t1, t2) self.assertEqual(t1.phi_k, t2.phi_k) self.assertEqual(t1.per, t2.per) self.assertEqual(t1.phase, t2.phase) self.assertEqual(t1.scee, t2.scee) self.assertEqual(t1.scnb, t2.scnb) i += 1 self.assertEqual(i, 4)
def testReportersPBC(self): """ Test NetCDF and ASCII restart and trajectory reporters (w/ PBC) """ system = amber_solv.createSystem(nonbondedMethod=app.PME, nonbondedCutoff=8*u.angstroms) integrator = mm.LangevinIntegrator(300*u.kelvin, 5.0/u.picoseconds, 1.0*u.femtoseconds) sim = app.Simulation(amber_solv.topology, system, integrator) sim.context.setPositions(amber_solv.positions) sim.reporters.extend([ NetCDFReporter(get_fn('traj.nc', written=True), 1, vels=True, frcs=True), MdcrdReporter(get_fn('traj.mdcrd', written=True), 1), RestartReporter(get_fn('restart.ncrst', written=True), 1, netcdf=True), RestartReporter(get_fn('restart.rst7', written=True), 1) ]) sim.step(5) for reporter in sim.reporters: reporter.finalize() ntraj = NetCDFTraj.open_old(get_fn('traj.nc', written=True)) atraj = AmberMdcrd(get_fn('traj.mdcrd', written=True), amber_solv.ptr('natom'), True, mode='r') nrst = NetCDFRestart.open_old(get_fn('restart.ncrst', written=True)) arst = AmberAsciiRestart(get_fn('restart.rst7', written=True), 'r') self.assertEqual(ntraj.frame, 5) self.assertEqual(atraj.frame, 5) self.assertTrue(ntraj.hasvels) self.assertTrue(ntraj.hasfrcs) for i in range(ntraj.frame): for x1, x2 in zip(ntraj.box[i], atraj.box[i]): self.assertAlmostEqual(x1, x2, places=3) self.assertEqual(len(nrst.box), 6) self.assertEqual(len(arst.box), 6)
def cmp_valence(val1, val2, typeattrs=None): self.assertEqual(len(val1), len(val2)) for v1, v2 in zip(val1, val2): self.assertIs(type(v1), type(v2)) attrs = [attr for attr in dir(v1) if attr.startswith('atom')] atoms1 = [getattr(v1, attr) for attr in attrs] atoms2 = [getattr(v2, attr) for attr in attrs] for a1, a2 in zip(atoms1, atoms2): cmp_atoms(a1, a2) # Check the type lists if typeattrs is not None: for attr in typeattrs: self.assertAlmostEqual(getattr(v1.type, attr), getattr(v2.type, attr), places=5) else: self.assertEqual(v1.type, v2.type)
def test_residue(self): """ Tests the Residue object """ atoms = TrackedList() atoms.extend([Atom(list=atoms) for i in range(10)]) res = Residue('ALA') for atom in atoms: res.add_atom(atom) self.assertEqual(len(res), len(atoms)) for atom in atoms: self.assertIs(atom.residue, res) for x, y in zip(atoms, res): self.assertIs(x, y) for atom in atoms: self.assertIn(atom, res) # Try deleting all of our atoms while len(res): lenres = len(res) atom = random.choice(atoms) is_inside = atom in res res.delete_atom(atom) self.assertEqual(lenres-len(res), is_inside) self.assertIs(atom.residue, None) self.assertEqual(len(res), 0) for atom in atoms: self.assertIs(atom.residue, None) self.assertTrue(res.is_empty())
def test_xyz(self): """ Tests parsing Tinker XYZ files """ self.assertTrue(tinkerfiles.XyzFile.id_format(get_fn('nma.xyz'))) self.assertTrue(tinkerfiles.XyzFile.id_format(get_fn('2igd_924wat.xyz'))) xyz = tinkerfiles.XyzFile(get_fn('nma.xyz')) np.testing.assert_allclose(xyz.box, [30.735, 30.876, 28.485, 90.0, 90.0, 90.0]) self.assertEqual(len(xyz.atoms), 2466) self.assertEqual(xyz.atoms[0].name, 'C') self.assertEqual(xyz.atoms[0].type, '221') self.assertEqual(len(xyz.atoms[0].bond_partners), 4) self.assertEqual(xyz.atoms[-1].name, 'H') self.assertEqual(xyz.atoms[-1].atomic_number, 1) self.assertEqual(xyz.atoms[-1].type, '248') xyz = pmd.load_file(get_fn('2igd_924wat.xyz'), get_fn('2igd_924wat.pdb')) pdb = pmd.load_file(get_fn('2igd_924wat.pdb')) xyz2 = pmd.load_file(get_fn('2igd_924wat.xyz')) self.assertEqual(len(pdb.atoms), len(xyz.atoms)) self.assertEqual(len(pdb.residues), len(xyz.residues)) for r1, r2 in zip(pdb.residues, xyz.residues): self.assertEqual(len(r1), len(r2)) self.assertEqual(r1.chain, r2.chain) self.assertEqual(r1.name, r2.name) self.assertEqual(r1.insertion_code, r2.insertion_code) # Make sure NA ions are atomic number of sodium for atom in xyz.view['NA',:].atoms: self.assertEqual(atom.atomic_number, pmd.periodic_table.AtomicNum['Na']) # Now make sure that NA ions are atomic number of sodium even if we # don't load a PDB file for atom in xyz2.view[:,'Na+']: self.assertEqual(atom.atomic_number, pmd.periodic_table.AtomicNum['Na'])
def _check_rst(self, rst): """ Checks various restart properties """ self.assertAlmostEqual(rst.time, 30.1) self.assertEqual(rst.Conventions, "AMBERRESTART") self.assertEqual(rst.title, "ACE") self.assertEqual(rst.application, "AMBER") self.assertEqual(rst.program, "sander") self.assertEqual(rst.programVersion, "11.0") self.assertAlmostEqual(rst.cell_lengths[0], 30.2642725) self.assertAlmostEqual(rst.cell_lengths[1], 30.2642725) self.assertAlmostEqual(rst.cell_lengths[2], 30.2642725) self.assertAlmostEqual(rst.cell_angles[0], 109.471219) self.assertAlmostEqual(rst.cell_angles[1], 109.471219) self.assertAlmostEqual(rst.cell_angles[2], 109.471219) self.assertTrue(all([round(x - y, 7) == 0 for x, y in zip(rst.cell_lengths, rst.box[:3])])) self.assertTrue(all([round(x - y, 7) == 0 for x, y in zip(rst.cell_angles, rst.box[3:])]))
def testAnisouWrite(self): """ Tests that write_PDB properly writes ANISOU records """ def check_aniso(pdbfile): aniso1 = [2066, 1204, 1269, 44, 126, 191] aniso2 = [2090, 1182, 921, 46, 64, 60] aniso3 = [3057, 3932, 5304, 126, -937, -661] self.assertEqual(len(aniso1), len(pdbfile.atoms[0].anisou)) for x, y in zip(aniso1, pdbfile.atoms[0].anisou): self.assertEqual(x/10000, y) self.assertEqual(len(aniso2), len(pdbfile.atoms[1].anisou)) for x, y in zip(aniso2, pdbfile.atoms[1].anisou): self.assertEqual(x/10000, y) self.assertEqual(len(aniso3), len(pdbfile.atoms[-1].anisou)) for x, y in zip(aniso3, pdbfile.atoms[-1].anisou): self.assertEqual(x/10000, y) pdbfile = read_PDB(self.pdb) check_aniso(pdbfile) output = StringIO() pdbfile.write_pdb(output) output.seek(0) pdbfile2 = read_PDB(output) # Should have no anisou records, since by default they are not written for atom in pdbfile2.atoms: self.assertIs(atom.anisou, None) output = reset_stringio(output) pdbfile.write_pdb(output, renumber=False, write_anisou=True) output.seek(0) # This one should have anisou records pdbfile3 = read_PDB(output) self._compareInputOutputPDBs(pdbfile, pdbfile3) for a1, a2 in zip(pdbfile.atoms, pdbfile3.atoms): if has_numpy(): self.assertEqual(a1.anisou.shape, a2.anisou.shape) else: self.assertEqual(len(a1.anisou), len(a2.anisou)) for x, y in zip(a1.anisou, a2.anisou): self.assertAlmostEqual(x, y, delta=1e-4) self.assertEqual(len(a1.other_locations), len(a2.other_locations)) for key in sorted(a1.other_locations.keys()): oa1 = a1.other_locations[key] oa2 = a2.other_locations[key] if has_numpy(): self.assertEqual(oa1.anisou.shape, oa2.anisou.shape) else: self.assertEqual(len(oa1.anisou), len(oa2.anisou)) for x, y in zip(oa1.anisou, oa2.anisou): self.assertAlmostEqual(x, y, delta=1e-4)
def same_atoms(self, atomlist): """ Determine if two dihedrals are assigned to the same sets of atom types Parameters ---------- atomlist : list 4-element list of atom types to compare against this DihedralParam Returns ------- bool, bool First bool is True if all atoms are the same; False otherwise Second bool is True if atoms are in the same order; False otherwise Notes ----- If this torsion is an improper, the first atom is fixed and the other 3 atoms must be the same (but in any order). If this torsion is a proper, then the torsions must match in either the forward or reverse directions, only. """ if self[0].dihtype == 'improper': # For impropers, the third atom is the central atom and the other 3 # can be in any order if self.atype3 != atomlist[2]: return False, False if (self.atype1 == atomlist[0] and self.atype2 == atomlist[1] and self.atype4 == atomlist[3]): return True, True # Make sure every atom type is unique so every atom type is added to # the set (but we know it is NOT the same order now) set1, set2 = set() , set() for x, y in zip([atomlist[0], atomlist[1], atomlist[3]], [self.atype1, self.atype2, self.atype4]): if x in set1: i = 0 while '%s%d%d' % (x, i, i) in set1: i += 1 set1.add('%s%d%d' % (x, i, i)) else: set1.add(x) if y in set2: i = 0 while '%s%d%d' % (y, i, i) in set2: i += 1 set2.add('%s%d%d' % (y, i, i)) else: set2.add(y) return set1 == set2, False # If we reached here, this is a proper dihedral if self.atype2 == atomlist[1] and self.atype3 == atomlist[2]: same = self.atype1 == atomlist[0] and self.atype4 == atomlist[3] if not same: # Check case when atype2 == atype3 and we're not the same -- # check for reversed order eq = self.atype1 == atomlist[3] and self.atype4 == atomlist[0] return eq, False return same, same if self.atype3 == atomlist[1] and self.atype2 == atomlist[2]: return self.atype1==atomlist[3] and self.atype4==atomlist[0], False return False, False
def cmp_dihedrals(dih1, dih2): self.assertEqual(len(dih1), len(dih2)) for v1, v2 in zip(dih1, dih2): self.assertIs(type(v1), type(v2)) self.assertIs(type(v1.type), type(v2.type)) atoms1 = [v1.atom1, v1.atom2, v1.atom3, v1.atom4] atoms2 = [v2.atom1, v2.atom2, v2.atom3, v2.atom4] for a1, a2 in zip(atoms1, atoms2): cmp_atoms(a1, a2) self.assertEqual(v1.improper, v2.improper) self.assertEqual(v1.ignore_end, v2.ignore_end) if isinstance(v1, DihedralTypeList): self.assertEqual(len(v1.type), len(v2.type)) for vt1, vt2 in zip(v1.type, v2.type): self.assertAlmostEqual(v1.type.phi_k, v2.type.phi_k, places=5) self.assertAlmostEqual(v1.type.per, v2.type.per, places=5) self.assertAlmostEqual(v1.type.phase, v2.type.phase, places=5)
def test_gas_energy_conf_4(self): """ Compare Amber and OpenMM gas phase energies and forces (topology 4) """ parm = AmberParm(get_fn('ethanol_T0.prmtop'), get_fn('ethanol_T0.rst7')) self.assertEqual(parm.combining_rule, 'geometric') system = parm.createSystem() # Default, no cutoff integrator = mm.VerletIntegrator(1.0*u.femtoseconds) sim = app.Simulation(parm.topology, system, integrator, platform=CPU) sim.context.setPositions(parm.positions) energies = energy_decomposition(parm, sim.context) #BOND = 0.0239 ANGLE = 0.0298 DIHED = 0.0093 #VDWAALS = 0.0000 EEL = 6.7526 HBOND = 0.0000 #1-4 VDW = 0.0492 1-4 EEL = -6.0430 RESTRAINT = 0.0000 # Compare OpenMM energies with the Amber energies (above) self.assertAlmostEqual(energies['bond'], 0.0239, places=4) self.assertAlmostEqual(energies['angle'], 0.0298, places=4) self.assertAlmostEqual(energies['dihedral'], 0.0093, places=4) self.assertRelativeEqual(energies['nonbonded'], 0.0000+6.7526+0.0492-6.0430, places=3) # Now test the forces to make sure that they are computed correctly in # the presence of extra points pstate = sim.context.getState(getForces=True) pf = pstate.getForces().value_in_unit(u.kilojoule_per_mole/u.nanometer) # gmx forces: # f[ 0]={ 1.73101e+02, 5.67250e+01, -4.02950e+01} # f[ 1]={-8.13704e+00, -1.79612e+01, 9.88537e+01} # f[ 2]={-2.83120e+01, 6.23352e+00, -5.47393e+00} # f[ 3]={-1.03312e+01, -1.00966e+01, -5.12129e+00} # f[ 4]={-1.69636e+02, 3.34850e+01, -1.73612e+02} # f[ 5]={ 4.19932e+00, -2.58283e+00, 1.29999e+02} # f[ 6]={ 3.02865e+01, -6.68331e+00, -2.99153e+01} # f[ 7]={ 1.00113e+02, -5.22480e+01, 4.80526e+01} # f[ 8]={-9.12828e+01, -6.87157e+00, -2.24877e+01} gf = [ ( 1.73101e+02, 5.67250e+01, -4.02950e+01), (-8.13704e+00, -1.79612e+01, 9.88537e+01), (-2.83120e+01, 6.23352e+00, -5.47393e+00), (-1.03312e+01, -1.00966e+01, -5.12129e+00), (-1.69636e+02, 3.34850e+01, -1.73612e+02), ( 4.19932e+00, -2.58283e+00, 1.29999e+02), ( 3.02865e+01, -6.68331e+00, -2.99153e+01), ( 1.00113e+02, -5.22480e+01, 4.80526e+01), (-9.12828e+01, -6.87157e+00, -2.24877e+01)] for p, s in zip(pf, gf): for x1, x2 in zip(p, s): self.assertAlmostEqual(x1, x2, places=3)
def energy_decomposition_system(structure, system, platform=None, nrg=u.kilocalories_per_mole): """ This function computes the energy contribution for all of the different force groups. Parameters ---------- structure : Structure The Structure with the coordinates for this system system : mm.System The OpenMM System object to get decomposed energies from platform : str The platform to use. Options are None (default), 'CPU', 'Reference', 'CUDA', and 'OpenCL'. None will pick default OpenMM platform for this installation and computer nrg : energy unit, optional The unit to convert all energies into. Default is kcal/mol Returns ------- energies : list of tuple Each entry is a tuple with the name of the force followed by its contribution """ import simtk.openmm as mm # First get all of the old force groups so we can restore them old_groups = [f.getForceGroup() for f in system.getForces()] old_recip_group = [] def _ene(context, grp): st = context.getState(getEnergy=True, groups=1<<grp) return (type(system.getForce(grp)).__name__, st.getPotentialEnergy().value_in_unit(nrg)) try: for i, f in enumerate(system.getForces()): if isinstance(f, mm.NonbondedForce): old_recip_group.append(f.getReciprocalSpaceForceGroup()) f.setReciprocalSpaceForceGroup(i) f.setForceGroup(i) if platform is None: con = mm.Context(system, mm.VerletIntegrator(0.001)) else: con = mm.Context(system, mm.VerletIntegrator(0.001), mm.Platform.getPlatformByName(platform)) con.setPositions(structure.positions) if structure.box is not None: con.setPeriodicBoxVectors(*structure.box_vectors) return list(map(lambda x: _ene(con, x), range(system.getNumForces()))) finally: idx = 0 for grp, force in zip(old_groups, system.getForces()): if isinstance(force, mm.NonbondedForce): force.setReciprocalSpaceForceGroup(old_recip_group[idx]) idx += 1 force.setForceGroup(grp)
def cmp_top_arrays(arr1, arr2): self.assertEqual(len(arr1), len(arr2)) for t1, t2 in zip(arr1, arr2): self.assertIs(type(t1), type(t2)) atoms = [attr for attr in dir(t1) if attr.startswith('atom')] for a in atoms: self._equal_atoms(getattr(t1, a), getattr(t2, a)) if hasattr(t1, 'type'): self.assertEqual(t1.type, t2.type)
def cmp_top_arrays(arr1, arr2): self.assertEqual(len(arr1), len(arr2)) for t1, t2 in zip(arr1, arr2): self.assertIs(type(t1), type(t2)) atoms = [attr for attr in dir(t1) if attr.startswith("atom")] for a in atoms: self._equal_atoms(getattr(t1, a), getattr(t2, a)) if hasattr(t1, "type"): self.assertEqual(t1.type, t2.type)
def get_max_diff(f1, f2): """ Gets the maximum difference between two force vectors """ maxfrc = None assert len(f1) == len(f2), 'vector size mismatch' for v1, v2 in zip(f1, f2): norm = u.norm(v1 - v2) if maxfrc is None: maxfrc = norm else: maxfrc = max(maxfrc, norm) return maxfrc
def test_dyn(self): """ Tests parsing Tinker DYN files """ dyn = tinkerfiles.DynFile(get_fn('nma.dyn')) self.assertEqual(dyn.natom, 2466) for attr in ('accelerations', 'old_accelerations', 'box', 'positions', 'velocities'): self.assertTrue(hasattr(dyn, attr)) for x, y in zip(dyn.positions[10], [-0.1099425448789507, -1.83499212341286, 6.089155631551154]): self.assertAlmostEqual(x, y)
def __init__(self, fname, seq=None): super(XyzFile, self).__init__() if isinstance(fname, string_types): fxyz = genopen(fname, 'r') own_handle_xyz = True else: fxyz = fname own_handle_xyz = False if seq is not None: seqstruct = load_file(seq) # Now parse the file try: natom = int(fxyz.readline().split()[0]) except (ValueError, IndexError): raise TinkerError('Bad XYZ file format; first line') if seq is not None and natom != len(seqstruct.atoms): raise ValueError( 'Sequence file %s # of atoms does not match the # ' 'of atoms in the XYZ file' % seq) words = fxyz.readline().split() if len(words) == 6 and not XyzFile._check_atom_record(words): self.box = [float(w) for w in words] words = fxyz.readline().split() atom = Atom(atomic_number=AtomicNum[element_by_name(words[1])], name=words[1], type=words[5]) atom.xx, atom.xy, atom.xz = [float(w) for w in words[2:5]] residue = Residue('SYS') residue.number = 1 residue._idx = 0 if seq is not None: residue = seqstruct.residues[0] self.add_atom(atom, residue.name, residue.number, residue.chain, residue.insertion_code, residue.segid) bond_ids = [[int(w) for w in words[6:]]] for i, line in enumerate(fxyz): words = line.split() atom = Atom(atomic_number=AtomicNum[element_by_name(words[1])], name=words[1], type=words[5]) atom.xx, atom.xy, atom.xz = [float(w) for w in words[2:5]] if seq is not None: residue = seqstruct.atoms[i + 1].residue self.add_atom(atom, residue.name, residue.number, residue.chain, residue.insertion_code, residue.segid) bond_ids.append([int(w) for w in words[6:]]) # All of the bonds are stored now -- go ahead and make them now for atom, bonds in zip(self.atoms, bond_ids): i = atom.idx + 1 for idx in bonds: if idx > i: self.bonds.append(Bond(atom, self.atoms[idx - 1])) if own_handle_xyz: fxyz.close()
def test_gas_energy_conf_3(self): """ Compare Amber and OpenMM gas phase energies and forces (topology 3) """ parm = AmberParm(get_fn('methanol_T0.prmtop'), get_fn('methanol_T0.rst7')) self.assertEqual(parm.combining_rule, 'geometric') system = parm.createSystem() # Default, no cutoff integrator = mm.VerletIntegrator(1.0 * u.femtoseconds) sim = app.Simulation(parm.topology, system, integrator, platform=CPU) sim.context.setPositions(parm.positions) energies = energy_decomposition(parm, sim.context) #BOND = 0.0224 ANGLE = 0.0469 DIHED = 0.0039 #VDWAALS = 0.0000 EEL = 0.0000 HBOND = 0.0000 #1-4 VDW = 0.0000 1-4 EEL = 3.3789 RESTRAINT = 0.0000 # Compare OpenMM energies with the Amber energies (above) self.assertAlmostEqual(energies['bond'], 0.0224, places=4) self.assertAlmostEqual(energies['angle'], 0.0469, places=4) self.assertAlmostEqual(energies['dihedral'], 0.0039, places=4) self.assertRelativeEqual(energies['nonbonded'], 3.3789, places=3) # Now test the forces to make sure that they are computed correctly in # the presence of extra points pstate = sim.context.getState(getForces=True) pf = pstate.getForces().value_in_unit(u.kilojoule_per_mole / u.nanometer) # gmx forces: # f[ 0]={ 2.19935e+01, 8.60143e+01, 1.77895e+02} # f[ 1]={ 5.25347e+01, 3.46119e+01, -9.73738e+01} # f[ 2]={ 1.76138e+01, -7.13778e+01, -1.08807e+00} # f[ 3]={-3.74994e+01, -5.39602e+01, -6.75679e+01} # f[ 4]={-8.35142e+01, -7.86616e+01, -1.60611e+02} # f[ 5]={ 2.88716e+01, 8.33735e+01, 1.48746e+02} gf = [(2.19935e+01, 8.60143e+01, 1.77895e+02), (5.25347e+01, 3.46119e+01, -9.73738e+01), (1.76138e+01, -7.13778e+01, -1.08807e+00), (-3.74994e+01, -5.39602e+01, -6.75679e+01), (-8.35142e+01, -7.86616e+01, -1.60611e+02), (2.88716e+01, 8.33735e+01, 1.48746e+02)] for p, s in zip(pf, gf): for x1, x2 in zip(p, s): self.assertAlmostEqual(x1, x2, places=3)
def testLoadDataFrameStructureView(self): """ Tests the load_dataframe method on StructureView """ struct = create_random_structure(parametrized=True).view[:10, :] charges = [a.charge for a in struct.atoms] self.assertTrue(not all(x == 0 for x in charges)) df = struct.to_dataframe() # First zero-out all of the charges struct.load_dataframe(dict(charge=[0 for a in struct.atoms])) self.assertTrue(all(a.charge == 0 for a in struct.atoms)) # Now re-load the dataframe to restore the original charges struct.load_dataframe(df) self.assertTrue( all(a.charge == x for a, x in zip(struct.atoms, charges))) # Change the first atomic properties of *everything* now to # make sure that they all get updated df_orig = df.copy() df.loc[0, 'number'] = 1 df.loc[0, 'name'] = 'HAHA' df.loc[0, 'type'] = 'FUNY' df.loc[0, 'atomic_number'] = 92 # uranium df.loc[0, 'charge'] *= 2 df.loc[0, 'mass'] *= 10 df.loc[0, 'nb_idx'] = 10 df.loc[0, 'solvent_radius'] *= 2 df.loc[0, 'screen'] = 0.5 df.loc[0, 'occupancy'] = 0.1 df.loc[0, 'bfactor'] = 0.5 df.loc[0, 'altloc'] = 'X' df.loc[0, 'tree'] = 'BLU' df.loc[0, 'join'] = 1.0 df.loc[0, 'irotat'] = 2.0 df.loc[0, 'rmin'] *= 2 df.loc[0, 'epsilon'] /= 2 struct.load_dataframe(df) atom = struct.atoms[0] self.assertEqual(atom.number, 1) self.assertEqual(atom.name, 'HAHA') self.assertEqual(atom.type, 'FUNY') self.assertEqual(atom.atomic_number, 92) self.assertEqual(atom.charge, charges[0] * 2) self.assertEqual(atom.mass, 10 * df_orig.loc[0, 'mass']) self.assertEqual(atom.nb_idx, 10) self.assertEqual(atom.solvent_radius, 2 * df_orig.loc[0, 'solvent_radius']) self.assertEqual(atom.screen, 0.5) self.assertEqual(atom.occupancy, 0.1) self.assertEqual(atom.bfactor, 0.5) self.assertEqual(atom.altloc, 'X') self.assertEqual(atom.tree, 'BLU') self.assertEqual(atom.join, 1.0) self.assertEqual(atom.irotat, 2.0) self.assertEqual(atom.rmin, 2 * df_orig.loc[0, 'rmin']) self.assertEqual(atom.epsilon, df_orig.loc[0, 'epsilon'] / 2)
def test_reporters_pbc(self): """ Test NetCDF and ASCII restart and trajectory reporters (w/ PBC) """ systemsolv = load_file(get_fn('ildn.solv.top'), xyz=get_fn('ildn.solv.gro')) system = systemsolv.createSystem(nonbondedMethod=app.PME, nonbondedCutoff=8 * u.angstroms) integrator = mm.LangevinIntegrator(300 * u.kelvin, 5.0 / u.picoseconds, 1.0 * u.femtoseconds) sim = app.Simulation(systemsolv.topology, system, integrator, Reference) sim.context.setPositions(systemsolv.positions) sim.reporters.extend([ NetCDFReporter(get_fn('traj.nc', written=True), 1, vels=True, frcs=True), MdcrdReporter(get_fn('traj.mdcrd', written=True), 1), RestartReporter(get_fn('restart.ncrst', written=True), 1, netcdf=True), RestartReporter(get_fn('restart.rst7', written=True), 1), StateDataReporter(get_fn('state.o', written=True), 1, volume=True, density=True, systemMass=1) ]) sim.step(5) for reporter in sim.reporters: reporter.finalize() ntraj = NetCDFTraj.open_old(get_fn('traj.nc', written=True)) atraj = AmberMdcrd(get_fn('traj.mdcrd', written=True), len(systemsolv.atoms), True, mode='r') nrst = NetCDFRestart.open_old(get_fn('restart.ncrst', written=True)) arst = AmberAsciiRestart(get_fn('restart.rst7', written=True), 'r') self.assertEqual(ntraj.frame, 5) self.assertEqual(atraj.frame, 5) self.assertTrue(ntraj.hasvels) self.assertTrue(ntraj.hasfrcs) for i in range(ntraj.frame): for x1, x2 in zip(ntraj.box[i], atraj.box[i]): self.assertAlmostEqual(x1, x2, places=3) self.assertEqual(len(nrst.box), 6) self.assertEqual(len(arst.box), 6) # Make sure the EnergyMinimizerReporter does not fail f = StringIO() rep = EnergyMinimizerReporter(f, volume=True) rep.report(sim) rep.finalize()
def assertAlmostEqualQuantities(self, item1, item2, places=6): try: val1 = item1.value_in_unit(item1.unit) val2 = item2.value_in_unit(item1.unit) except TypeError: raise self.failureException('Incompatible units %s and %s' % (item1.unit, item2.unit)) try: if len(val1) != len(val2): raise self.failureException('collections are different lengths') for x, y in zip(val1, val2): self.assertAlmostEqual(x, y, places=places) except TypeError: self.assertAlmostEqual(val1, val2, places=places)
def test_benzene_cyclohexane(self): """ Test converting binary liquid from Amber prmtop to Gromacs top """ parm = load_file(get_fn('benzene_cyclohexane_10_500.prmtop'), get_fn('benzene_cyclohexane_10_500.inpcrd')) top = gromacs.GromacsTopologyFile.from_structure(parm) self.assertEqual(top.combining_rule, 'lorentz') groname = get_fn('benzene_cyclohexane_10_500.gro', written=True) gromacs.GromacsGroFile.write(parm, groname, precision=8) gro = gromacs.GromacsGroFile.parse(groname) self.assertEqual(len(gro.atoms), len(parm.atoms)) np.testing.assert_allclose(gro.box, parm.box) for a1, a2 in zip(gro.atoms, parm.atoms): self.assertEqual(a1.residue.name, a2.residue.name) self.assertEqual(a1.residue.idx, a2.residue.idx) self.assertEqual(a1.name, a2.name) self.assertAlmostEqual(a1.xx, a2.xx) self.assertAlmostEqual(a1.xy, a2.xy) self.assertAlmostEqual(a1.xz, a2.xz) top.write(get_fn('benzene_cyclohexane_10_500.top', written=True)) saved = GromacsFile(get_saved_fn('benzene_cyclohexane_10_500.top')) written = GromacsFile( get_fn('benzene_cyclohexane_10_500.top', written=True)) self.assertTrue(diff_files(saved, written)) # Check that Gromacs topology is given the correct box information when # generated from a Structure gromacs.GromacsGroFile.write(top, groname, precision=8) gro = gromacs.GromacsGroFile.parse(groname) self.assertEqual(len(gro.atoms), len(parm.atoms)) for a1, a2 in zip(gro.atoms, parm.atoms): self.assertEqual(a1.residue.name, a2.residue.name) self.assertEqual(a1.residue.idx, a2.residue.idx) self.assertEqual(a1.name, a2.name) self.assertAlmostEqual(a1.xx, a2.xx) self.assertAlmostEqual(a1.xy, a2.xy) self.assertAlmostEqual(a1.xz, a2.xz) np.testing.assert_allclose(gro.box, parm.box) np.testing.assert_allclose(top.box, parm.box)
def __str__(self): if len(self.amplitude) == 0: return ('TorsionAngle %r --- %r --- %r --- %r\n' ' No Terms' % (self.atom1, self.atom2, self.atom3, self.atom4)) retstr = 'TorsionAngle %r --- %r --- %r --- %r' % ( self.atom1, self.atom2, self.atom3, self.atom4) seq = range(len(self.amplitude)) for i, amp, phase, per in enumerate( zip(seq, self.amplitude, self.phase, self.periodicity)): retstr += ('\n Term %d\n' ' Amplitude = %.4f\n' ' Phase = %.4f\n' ' Periodicity = %.4f' % (i + 1, amp, phase, per)) return retstr
def test_residue_serialization(self): """ Tests the serialization of Residue """ struct = utils.create_random_structure(parametrized=True) res = struct.residues[0] fobj = BytesIO() pickle.dump(res, fobj) fobj.seek(0) unpickled = pickle.load(fobj) self.assertEqual(len(res.atoms), len(unpickled.atoms)) for a1, a2 in zip(res, unpickled): self._equal_atoms(a1, a2) self.assertIs(a1.residue, res) self.assertIs(a2.residue, unpickled)
def test_gas_energy_conf_2(self): """ Compare Amber and OpenMM gas phase energies and forces (topology 2) """ parm = AmberParm(get_fn('hydrogen-peroxide_T0_2.prmtop'), get_fn('hydrogen-peroxide_T0_2.rst7')) self.assertEqual(parm.combining_rule, 'lorentz') system = parm.createSystem() # Default, no cutoff integrator = mm.VerletIntegrator(1.0 * u.femtoseconds) sim = app.Simulation(parm.topology, system, integrator, platform=CPU) sim.context.setPositions(parm.positions) energies = energy_decomposition(parm, sim.context) #BOND = 0.0319 ANGLE = 2.1690 DIHED = -2.7931 #VDWAALS = 0.0000 EEL = 0.0000 HBOND = 0.0000 #1-4 VDW = 0.0000 1-4 EEL = 0.0000 RESTRAINT = 0.0000 # Compare OpenMM energies with the Amber energies (above) self.assertAlmostEqual(energies['bond'], 0.0319, places=4) self.assertAlmostEqual(energies['angle'], 2.1690, places=4) self.assertAlmostEqual(energies['dihedral'], -2.7931, places=4) self.assertRelativeEqual(energies['nonbonded'], 0.0, places=3) # Now test the forces to make sure that they are computed correctly in # the presence of extra points pstate = sim.context.getState(getForces=True) pf = pstate.getForces().value_in_unit(u.kilojoule_per_mole / u.nanometer) # gmx forces: # f[ 0]={ 3.14357e+02, -5.90363e+02, 2.11410e+02} # f[ 1]={-3.14357e+02, 5.90363e+02, 2.11410e+02} # f[ 2]={ 2.70641e+02, 5.90363e+02, -2.11410e+02} # f[ 3]={-2.70641e+02, -5.90363e+02, -2.11410e+02} gf = [(3.14357e+02, -5.90363e+02, 2.11410e+02), (-3.14357e+02, 5.90363e+02, 2.11410e+02), (2.70641e+02, 5.90363e+02, -2.11410e+02), (-2.70641e+02, -5.90363e+02, -2.11410e+02)] for p, s in zip(pf, gf): for x1, x2 in zip(p, s): self.assertAlmostEqual(x1, x2, places=3)
def test_residue_atom_selection(self): """ Tests combined residue,atom slicing/selections """ sel = pdb1[10:20, :5] # First five atoms of residues 10-19 self.assertEqual(len(sel.atoms), 49) # 1 residue has only 4 atoms c = 0 for res in pdb1.residues[10:20]: for i in range(min(len(res), 5)): self.assertEqual(sel.atoms[c].name, res[i].name) self.assertEqual(sel.atoms[c].xx, res[i].xx) self.assertEqual(sel.atoms[c].xy, res[i].xy) self.assertEqual(sel.atoms[c].xz, res[i].xz) c += 1 sel = pdb1[[0, 2, 3, 5], :2] # First 2 atoms of residues 0, 2, 3, and 5 self.assertEqual(len(sel.atoms), 8) c = 0 for i, res in enumerate([0, 2, 3, 5]): res = pdb1.residues[res] self.assertEqual(sel.atoms[c].name, res[0].name) self.assertEqual(sel.atoms[c].xx, res[0].xx) self.assertEqual(sel.atoms[c].xy, res[0].xy) self.assertEqual(sel.atoms[c].xz, res[0].xz) c += 1 self.assertEqual(sel.atoms[c].name, res[1].name) self.assertEqual(sel.atoms[c].xx, res[1].xx) self.assertEqual(sel.atoms[c].xy, res[1].xy) self.assertEqual(sel.atoms[c].xz, res[1].xz) c += 1 sel = pdb1[8, :] self.assertEqual(len(sel.atoms), len(pdb1.residues[8])) for a1, a2 in zip(sel.atoms, pdb1.residues[8]): self.assertEqual(a1.name, a2.name) self.assertEqual(a1.xx, a2.xx) self.assertEqual(a1.xy, a2.xy) self.assertEqual(a1.xz, a2.xz) self.assertIs(pdb1[8, 4], pdb1.residues[8][4]) sel = pdb1[['ALA', 'GLY'], :] for atom in sel.atoms: self.assertIn(atom.residue.name, ('ALA', 'GLY')) nalagly = sum(r.name in ('ALA', 'GLY') for r in pdb1.residues) natom = sum(len(r) for r in pdb1.residues if r.name in ('ALA', 'GLY')) self.assertEqual(nalagly, len(sel.residues)) self.assertEqual(natom, len(sel.atoms))
def _load_cmap_info(self): """ Loads the CHARMM CMAP types and array """ if not self.has_cmap: return del self.cmaps[:] del self.cmap_types[:] for i in range(self.pointers['CMAP_TYPES']): resolution = self.parm_data['CHARMM_CMAP_RESOLUTION'][i] grid = self.parm_data['CHARMM_CMAP_PARAMETER_%02d' % (i + 1)] cmts = self.parm_comments['CHARMM_CMAP_PARAMETER_%02d' % (i + 1)] self.cmap_types.append( CmapType(resolution, grid, cmts, list=self.cmap_types)) it = iter(self.parm_data['CHARMM_CMAP_INDEX']) for i, j, k, l, m, n in zip(it, it, it, it, it, it): self.cmaps.append( Cmap(self.atoms[i - 1], self.atoms[j - 1], self.atoms[k - 1], self.atoms[l - 1], self.atoms[m - 1], self.cmap_types[n - 1]))
def test_simple(self): """ Tests converting simple Amber system to CHARMM PSF/parameters """ parm = load_file(get_fn('trx.prmtop'), get_fn('trx.inpcrd')) parm.save(get_fn('amber_to_charmm.psf', written=True)) params = charmm.CharmmParameterSet.from_structure(parm) params.write(str=get_fn('amber_to_charmm.str', written=True)) self.assertTrue( diff_files(get_saved_fn('amber_to_charmm.psf'), get_fn('amber_to_charmm.psf', written=True) ) ) self.assertTrue( diff_files(get_saved_fn('amber_to_charmm.str'), get_fn('amber_to_charmm.str', written=True), absolute_error=1e-5, ) ) # Check the PSF file psf = load_file(get_fn('amber_to_charmm.psf', written=True)) psf.load_parameters( charmm.CharmmParameterSet(get_fn('amber_to_charmm.str', written=True)) ) for a1, a2 in zip(psf.atoms, parm.atoms): self.assertEqual(a1.name, a2.name) self.assertEqual(a1.atomic_number, a2.atomic_number) self.assertEqual(a1.mass, a2.mass) self.assertEqual(len(psf.bonds), len(parm.bonds)) self.assertEqual(len(psf.angles), len(parm.angles)) # Get number of unique torsions nnormal = nimp = 0 torsfound = set() for tor in parm.dihedrals: a1, a2, a3, a4 = tor.atom1, tor.atom2, tor.atom3, tor.atom4 if tor.improper: nimp += 1 continue if (a1, a2, a3, a4) in torsfound or (a4, a3, a2, a1) in torsfound: continue torsfound.add((a1, a2, a3, a4)) nnormal += 1 # Make sure that written psf only contains unique torsions. self.assertEqual(nnormal+nimp, len(psf.dihedrals))
def test_residue_atom_selection(self): """ Tests combined residue,atom slicing/selections (view) """ sel = pdb1.view[10:20, :5] # First five atoms of residues 10-19 self.assertIsInstance(sel, pmd.structure.StructureView) self.assertEqual(len(sel.atoms), 49) # 1 residue has only 4 atoms c = 0 for res in pdb1.residues[10:20]: for i in range(min(len(res), 5)): self.assertIs(sel.atoms[c], res[i]) c += 1 sel = pdb1.view[[0, 2, 3, 5], :2] # First 2 atoms of residues 0, 2, 3, and 5 self.assertIsInstance(sel, pmd.structure.StructureView) self.assertEqual(len(sel.atoms), 8) c = 0 for i, res in enumerate([0, 2, 3, 5]): res = pdb1.residues[res] self.assertIs(sel.atoms[c], res[0]) c += 1 self.assertIs(sel.atoms[c], res[1]) c += 1 sel = pdb1.view[8, :] self.assertIsInstance(sel, pmd.structure.StructureView) self.assertEqual(len(sel.atoms), len(pdb1.residues[8])) for a1, a2 in zip(sel.atoms, pdb1.residues[8]): self.assertIs(a1, a2) self.assertIs(pdb1[8, 4], pdb1.residues[8][4]) sel = pdb1.view[['ALA', 'GLY'], :] self.assertIsInstance(sel, pmd.structure.StructureView) for atom in sel.atoms: self.assertIn(atom.residue.name, ('ALA', 'GLY')) self.assertIs(atom.list, pdb1.atoms) nalagly = sum(r.name in ('ALA', 'GLY') for r in pdb1.residues) natom = sum(len(r) for r in pdb1.residues if r.name in ('ALA', 'GLY')) self.assertEqual(nalagly, len(sel.residues)) self.assertEqual(natom, len(sel.atoms))
def test_simple(self): """ Tests converting standard Gromacs system into Amber prmtop """ top = load_file(get_fn(os.path.join('03.AlaGlu', 'topol.top'))) self.assertEqual(top.combining_rule, 'lorentz') parm = amber.AmberParm.from_structure(top) parm.write_parm(get_fn('ala_glu.parm7', written=True)) parm = load_file(get_fn('ala_glu.parm7', written=True)) self.assertIsInstance(parm, amber.AmberParm) self.assertEqual(len(top.atoms), len(parm.atoms)) self.assertEqual(len(top.bonds), len(parm.bonds)) self.assertEqual(len(top.angles), len(parm.angles)) self.assertEqual(len(top.residues), len(parm.residues)) for a1, a2 in zip(top.atoms, parm.atoms): self.assertEqual(a1.name, a2.name) self.assertEqual(a1.type, a2.type) self.assertEqual(a1.atomic_number, a2.atomic_number) self.assertEqual(a1.residue.name, a2.residue.name) self.assertEqual(a1.residue.idx, a2.residue.idx) self.assertAlmostEqual(a1.mass, a2.mass) self.assertIs(type(a1), type(a2)) self.assertAlmostEqual(a1.charge, a2.charge) self.assertEqual(set([a.idx for a in a1.bond_partners]), set([a.idx for a in a2.bond_partners])) self.assertEqual(set([a.idx for a in a1.angle_partners]), set([a.idx for a in a2.angle_partners])) self.assertEqual(set([a.idx for a in a1.dihedral_partners]), set([a.idx for a in a2.dihedral_partners])) # Make sure that assign_nbidx_from_types compresses maximally. First # add a new, equivalent L-J type. Then call assign_nbidx_from_types # again, which should recompress before_nbidx = [a.nb_idx for a in parm.atoms] addLJType(parm, '@1').execute() after_nbidx = [a.nb_idx for a in parm.atoms] self.assertEqual(before_nbidx[1:], after_nbidx[1:]) self.assertEqual(after_nbidx[0], max(before_nbidx) + 1) parm.atoms.assign_nbidx_from_types() # Should recompress self.assertEqual(before_nbidx, [a.nb_idx for a in parm.atoms])
def cmp_type_arrays(arr1, arr2): self.assertEqual(len(arr1), len(arr2)) for x1, x2 in zip(arr1, arr2): self.assertEqual(x1, x2)
def _compare_structures(self, unpickled, structure): self.assertEqual(len(unpickled.residues), len(structure.residues)) for r1, r2 in zip(unpickled.residues, structure.residues): self.assertEqual(len(r1), len(r2)) self.assertEqual(r1.idx, r2.idx) for a1, a2 in zip(r1, r2): self._equal_atoms(a1, a2) def cmp_alists(alist1, alist2): self.assertEqual(len(alist1), len(alist2)) for a1, a2 in zip(alist1, alist2): self._equal_atoms(a1, a2) for a1, a2 in zip(unpickled, structure): self._equal_atoms(a1, a2) self.assertEqual(a1.idx, a2.idx) self.assertEqual(len(a1.bonds), len(a2.bonds)) self.assertEqual(len(a1.angles), len(a2.angles)) self.assertEqual(len(a1.dihedrals), len(a2.dihedrals)) self.assertEqual(len(a1.impropers), len(a2.impropers)) cmp_alists(a1.bond_partners, a2.bond_partners) cmp_alists(a1.angle_partners, a2.angle_partners) cmp_alists(a1.dihedral_partners, a2.dihedral_partners) cmp_alists(a1.tortor_partners, a2.tortor_partners) cmp_alists(a1.exclusion_partners, a2.exclusion_partners) # Check coordinates if structure.get_coordinates() is None: self.assertIs(unpickled.get_coordinates(), None) else: np.testing.assert_equal(structure.get_coordinates(), unpickled.get_coordinates()) # Check unit cell if structure.box is None: self.assertIs(unpickled.box, None) self.assertIs(unpickled.box_vectors, None) else: np.testing.assert_equal(structure.box, unpickled.box) self.assertEqual(structure.box_vectors, unpickled.box_vectors) # Check velocities if structure.velocities is None: self.assertIs(unpickled.velocities, None) else: np.testing.assert_equal(structure.velocities, unpickled.velocities) # Check nrexcl and combining_rule self.assertEqual(structure.nrexcl, unpickled.nrexcl) self.assertEqual(structure.combining_rule, unpickled.combining_rule) # Make sure all of the type arrays are equivalent def cmp_type_arrays(arr1, arr2): self.assertEqual(len(arr1), len(arr2)) for x1, x2 in zip(arr1, arr2): self.assertEqual(x1, x2) cmp_type_arrays(structure.bond_types, unpickled.bond_types) cmp_type_arrays(structure.angle_types, unpickled.angle_types) cmp_type_arrays(structure.dihedral_types, unpickled.dihedral_types) cmp_type_arrays(structure.improper_types, unpickled.improper_types) cmp_type_arrays(structure.urey_bradley_types, unpickled.urey_bradley_types) cmp_type_arrays(structure.rb_torsion_types, unpickled.rb_torsion_types) cmp_type_arrays(structure.cmap_types, unpickled.cmap_types) cmp_type_arrays(structure.trigonal_angle_types, unpickled.trigonal_angle_types) cmp_type_arrays(structure.out_of_plane_bend_types, unpickled.out_of_plane_bend_types) cmp_type_arrays(structure.stretch_bend_types, unpickled.stretch_bend_types) cmp_type_arrays(structure.torsion_torsion_types, unpickled.torsion_torsion_types) cmp_type_arrays(structure.pi_torsion_types, unpickled.pi_torsion_types) cmp_type_arrays(structure.adjust_types, unpickled.adjust_types) # Make sure all of the connectivity arrays are equivalent def cmp_top_arrays(arr1, arr2): self.assertEqual(len(arr1), len(arr2)) for t1, t2 in zip(arr1, arr2): self.assertIs(type(t1), type(t2)) atoms = [attr for attr in dir(t1) if attr.startswith('atom')] for a in atoms: self._equal_atoms(getattr(t1, a), getattr(t2, a)) if hasattr(t1, 'type'): self.assertEqual(t1.type, t2.type) cmp_top_arrays(structure.bonds, unpickled.bonds) cmp_top_arrays(structure.angles, unpickled.angles) cmp_top_arrays(structure.dihedrals, unpickled.dihedrals) cmp_top_arrays(structure.impropers, unpickled.impropers) cmp_top_arrays(structure.urey_bradleys, unpickled.urey_bradleys) cmp_top_arrays(structure.rb_torsions, unpickled.rb_torsions) cmp_top_arrays(structure.cmaps, unpickled.cmaps) cmp_top_arrays(structure.trigonal_angles, unpickled.trigonal_angles) cmp_top_arrays(structure.out_of_plane_bends, unpickled.out_of_plane_bends) cmp_top_arrays(structure.pi_torsions, unpickled.pi_torsions) cmp_top_arrays(structure.stretch_bends, unpickled.stretch_bends) cmp_top_arrays(structure.torsion_torsions, unpickled.torsion_torsions) cmp_top_arrays(structure.chiral_frames, unpickled.chiral_frames) cmp_top_arrays(structure.multipole_frames, unpickled.multipole_frames) cmp_top_arrays(structure.adjusts, unpickled.adjusts) cmp_top_arrays(structure.groups, unpickled.groups)
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
def cmp_alists(alist1, alist2): self.assertEqual(len(alist1), len(alist2)) for a1, a2 in zip(alist1, alist2): self._equal_atoms(a1, a2)