Esempio n. 1
0
    def testComputePBCVectors(self):
        """ Tests computing periodic box vectors """
        deg90 = 90 * degrees
        vecs = computePeriodicBoxVectors(1, 2, 3, deg90, deg90, deg90)
        a, b, c = vecs
        self.assertAlmostEqual(a[0]/nanometers, 1)
        self.assertAlmostEqual(a[1]/nanometers, 0)
        self.assertAlmostEqual(a[2]/nanometers, 0)
        self.assertAlmostEqual(b[0]/nanometers, 0)
        self.assertAlmostEqual(b[1]/nanometers, 2)
        self.assertAlmostEqual(b[2]/nanometers, 0)
        self.assertAlmostEqual(c[0]/nanometers, 0)
        self.assertAlmostEqual(c[1]/nanometers, 0)
        self.assertAlmostEqual(c[2]/nanometers, 3)

        # Make sure round-trip works
        la, lb, lc, al, be, ga = computeLengthsAndAngles(vecs)
        self.assertAlmostEqual(la, 1)
        self.assertAlmostEqual(lb, 2)
        self.assertAlmostEqual(lc, 3)
        self.assertAlmostEqual(al, math.pi / 2)
        self.assertAlmostEqual(be, math.pi / 2)
        self.assertAlmostEqual(ga, math.pi / 2)

        # Now test a truncated octahedron. Can't do a simple round-trip though,
        # due to the reduced form. So test the *second* round-trip, which should
        # yield the same measurements
        vecs = computePeriodicBoxVectors(4.24388485, 4.24388485, 4.24388485,
                109.4712190*degrees, 109.4712190*degrees, 109.4712190*degrees)
        la, lb, lc, al, be, ga = computeLengthsAndAngles(vecs)
        vecs2 = computePeriodicBoxVectors(la, lb, lc, al, be, ga)
        la2, lb2, lc2, al2, be2, ga2 = computeLengthsAndAngles(vecs2)

        # Now make sure that the round-trip worked
        self.assertAlmostEqual(strip_units(la), strip_units(la2))
        self.assertAlmostEqual(strip_units(lb), strip_units(lb2))
        self.assertAlmostEqual(strip_units(lc), strip_units(lc2))
        self.assertAlmostEqual(strip_units(al), strip_units(al2))
        self.assertAlmostEqual(strip_units(be), strip_units(be2))
        self.assertAlmostEqual(strip_units(ga), strip_units(ga2))

        # Check that the vectors are the same
        a1, a2, a3 = vecs
        b1, b2, b3 = vecs2
        for x, y in zip(a1, b1):
            self.assertAlmostEqual(strip_units(x), strip_units(y))
        for x, y in zip(a2, b2):
            self.assertAlmostEqual(strip_units(x), strip_units(y))
        for x, y in zip(a3, b3):
            self.assertAlmostEqual(strip_units(x), strip_units(y))
Esempio n. 2
0
    def writeHeader(topology, file=sys.stdout):
        """Write out the header for a PDB file.

        Parameters
        ----------
        topology : Topology
            The Topology defining the molecular system being written
        file : file=stdout
            A file to write the file to
        """
        print("REMARK   1 CREATED WITH OPENMM %s, %s" % (Platform.getOpenMMVersion(), str(date.today())), file=file)
        vectors = topology.getPeriodicBoxVectors()
        if vectors is not None:
            a, b, c, alpha, beta, gamma = computeLengthsAndAngles(vectors)
            RAD_TO_DEG = 180/math.pi
            print("CRYST1%9.3f%9.3f%9.3f%7.2f%7.2f%7.2f P 1           1 " % (
                    a*10, b*10, c*10, alpha*RAD_TO_DEG, beta*RAD_TO_DEG, gamma*RAD_TO_DEG), file=file)
Esempio n. 3
0
    def writeHeader(topology, file=sys.stdout, entry=None, keepIds=False):
        """Write out the header for a PDBx/mmCIF file.

        Parameters
        ----------
        topology : Topology
            The Topology defining the molecular system being written
        file : file=stdout
            A file to write the file to
        entry : str=None
            The entry ID to assign to the CIF file
        keepIds : bool=False
            If True, keep the residue and chain IDs specified in the Topology
            rather than generating new ones.  Warning: It is up to the caller to
            make sure these are valid IDs that satisfy the requirements of the
            PDBx/mmCIF format.  Otherwise, the output file will be invalid.
        """
        if entry is not None:
            print('data_%s' % entry, file=file)
        else:
            print('data_cell', file=file)
        print("# Created with OpenMM %s, %s" %
              (Platform.getOpenMMVersion(), str(date.today())),
              file=file)
        print('#', file=file)
        vectors = topology.getPeriodicBoxVectors()
        if vectors is not None:
            a, b, c, alpha, beta, gamma = computeLengthsAndAngles(vectors)
            RAD_TO_DEG = 180 / math.pi
            print('_cell.length_a     %10.4f' % (a * 10), file=file)
            print('_cell.length_b     %10.4f' % (b * 10), file=file)
            print('_cell.length_c     %10.4f' % (c * 10), file=file)
            print('_cell.angle_alpha  %10.4f' % (alpha * RAD_TO_DEG),
                  file=file)
            print('_cell.angle_beta   %10.4f' % (beta * RAD_TO_DEG), file=file)
            print('_cell.angle_gamma  %10.4f' % (gamma * RAD_TO_DEG),
                  file=file)
            print('#', file=file)

        # Identify bonds that should be listed in the file.

        bonds = []
        for atom1, atom2 in topology.bonds():
            if atom1.residue.name not in PDBFile._standardResidues or atom2.residue.name not in PDBFile._standardResidues:
                bonds.append((atom1, atom2))
            elif atom1.name == 'SG' and atom2.name == 'SG' and atom1.residue.name == 'CYS' and atom2.residue.name == 'CYS':
                bonds.append((atom1, atom2))
        if len(bonds) > 0:

            # Write the bond information.

            print('loop_', file=file)
            print('_struct_conn.id', file=file)
            print('_struct_conn.conn_type_id', file=file)
            print('_struct_conn.ptnr1_label_asym_id', file=file)
            print('_struct_conn.ptnr1_label_comp_id', file=file)
            print('_struct_conn.ptnr1_label_seq_id', file=file)
            print('_struct_conn.ptnr1_label_atom_id', file=file)
            print('_struct_conn.ptnr2_label_asym_id', file=file)
            print('_struct_conn.ptnr2_label_comp_id', file=file)
            print('_struct_conn.ptnr2_label_seq_id', file=file)
            print('_struct_conn.ptnr2_label_atom_id', file=file)
            chainIds = {}
            resIds = {}
            if keepIds:
                for chain in topology.chains():
                    chainIds[chain] = chain.id
                for res in topology.residues():
                    resIds[res] = res.id
            else:
                for (chainIndex, chain) in enumerate(topology.chains()):
                    chainIds[chain] = chr(ord('A') + chainIndex % 26)
                    for (resIndex, res) in enumerate(chain.residues()):
                        resIds[res] = resIndex + 1
            for i, (atom1, atom2) in enumerate(bonds):
                if atom1.residue.name == 'CYS' and atom2.residue.name == 'CYS':
                    bondType = 'disulf'
                else:
                    bondType = 'covale'
                line = "bond%d %s %s %-4s %5s %-4s %s %-4s %5s %-4s"
                print(line %
                      (i + 1, bondType, chainIds[atom1.residue.chain],
                       atom1.residue.name, resIds[atom1.residue], atom1.name,
                       chainIds[atom2.residue.chain], atom2.residue.name,
                       resIds[atom2.residue], atom2.name),
                      file=file)
            print('#', file=file)

        # Write the header for the atom coordinates.

        print('loop_', file=file)
        print('_atom_site.group_PDB', file=file)
        print('_atom_site.id', file=file)
        print('_atom_site.type_symbol', file=file)
        print('_atom_site.label_atom_id', file=file)
        print('_atom_site.label_alt_id', file=file)
        print('_atom_site.label_comp_id', file=file)
        print('_atom_site.label_asym_id', file=file)
        print('_atom_site.label_entity_id', file=file)
        print('_atom_site.label_seq_id', file=file)
        print('_atom_site.pdbx_PDB_ins_code', file=file)
        print('_atom_site.Cartn_x', file=file)
        print('_atom_site.Cartn_y', file=file)
        print('_atom_site.Cartn_z', file=file)
        print('_atom_site.occupancy', file=file)
        print('_atom_site.B_iso_or_equiv', file=file)
        print('_atom_site.Cartn_x_esd', file=file)
        print('_atom_site.Cartn_y_esd', file=file)
        print('_atom_site.Cartn_z_esd', file=file)
        print('_atom_site.occupancy_esd', file=file)
        print('_atom_site.B_iso_or_equiv_esd', file=file)
        print('_atom_site.pdbx_formal_charge', file=file)
        print('_atom_site.auth_seq_id', file=file)
        print('_atom_site.auth_comp_id', file=file)
        print('_atom_site.auth_asym_id', file=file)
        print('_atom_site.auth_atom_id', file=file)
        print('_atom_site.pdbx_PDB_model_num', file=file)
Esempio n. 4
0
    def writeModel(self, positions, unitCellDimensions=None, periodicBoxVectors=None):
        """Write out a model to the DCD file.

        The periodic box can be specified either by the unit cell dimensions
        (for a rectangular box), or the full set of box vectors (for an
        arbitrary triclinic box).  If neither is specified, the box vectors
        specified in the Topology will be used. Regardless of the value
        specified, no dimensions will be written if the Topology does not
        represent a periodic system.

        Parameters
        ----------
        positions : list
            The list of atomic positions to write
        unitCellDimensions : Vec3=None
            The dimensions of the crystallographic unit cell.
        periodicBoxVectors : tuple of Vec3=None
            The vectors defining the periodic box.
        """
        if len(list(self._topology.atoms())) != len(positions):
            raise ValueError('The number of positions must match the number of atoms')
        if is_quantity(positions):
            positions = positions.value_in_unit(nanometers)
        if any(math.isnan(norm(pos)) for pos in positions):
            raise ValueError('Particle position is NaN')
        if any(math.isinf(norm(pos)) for pos in positions):
            raise ValueError('Particle position is infinite')
        file = self._file

        self._modelCount += 1
        if self._interval > 1 and self._firstStep+self._modelCount*self._interval > 1<<31:
            # This will exceed the range of a 32 bit integer.  To avoid crashing or producing a corrupt file,
            # update the header to say the trajectory consisted of a smaller number of larger steps (so the
            # total trajectory length remains correct).
            self._firstStep //= self._interval
            self._dt *= self._interval
            self._interval = 1
            file.seek(0, os.SEEK_SET)
            file.write(struct.pack('<i4c9if', 84, b'C', b'O', b'R', b'D', 0, self._firstStep, self._interval, 0, 0, 0, 0, 0, 0, self._dt))

        # Update the header.

        file.seek(8, os.SEEK_SET)
        file.write(struct.pack('<i', self._modelCount))
        file.seek(20, os.SEEK_SET)
        file.write(struct.pack('<i', self._firstStep+self._modelCount*self._interval))

        # Write the data.

        file.seek(0, os.SEEK_END)
        boxVectors = self._topology.getPeriodicBoxVectors()
        if boxVectors is not None:
            if periodicBoxVectors is not None:
                boxVectors = periodicBoxVectors
            elif unitCellDimensions is not None:
                if is_quantity(unitCellDimensions):
                    unitCellDimensions = unitCellDimensions.value_in_unit(nanometers)
                boxVectors = (Vec3(unitCellDimensions[0], 0, 0), Vec3(0, unitCellDimensions[1], 0), Vec3(0, 0, unitCellDimensions[2]))*nanometers
            (a_length, b_length, c_length, alpha, beta, gamma) = computeLengthsAndAngles(boxVectors)
            a_length = a_length * 10.  # computeLengthsAndAngles returns unitless nanometers, but need angstroms here.
            b_length = b_length * 10.  # computeLengthsAndAngles returns unitless nanometers, but need angstroms here.
            c_length = c_length * 10.  # computeLengthsAndAngles returns unitless nanometers, but need angstroms here.
            angle1 = math.sin(math.pi/2-gamma)
            angle2 = math.sin(math.pi/2-beta)
            angle3 = math.sin(math.pi/2-alpha)
            file.write(struct.pack('<i6di', 48, a_length, angle1, b_length, angle2, angle3, c_length, 48))
        length = struct.pack('<i', 4*len(positions))
        for i in range(3):
            file.write(length)
            data = array.array('f', (10*x[i] for x in positions))
            data.tofile(file)
            file.write(length)
        try:
            file.flush()
        except AttributeError:
            pass