예제 #1
0
def test_multiligand_building(tmpdir):
    """
    Solvates and membranes a system with multiple ligands """
    from vmd import atomsel, molecule
    from Dabble import DabbleBuilder

    # Build the system
    p = str(tmpdir.mkdir("multiligand_build"))
    b = DabbleBuilder(solute_filename=os.path.join(dir, "B2AR_10ALPs.mae"),
                      output_filename=os.path.join(p, "test.mae"),
                      xy_buf=10., wat_buffer=10., overwrite=True, tmp_dir=p)
    b.write()

    # Load the built system
    m2 = molecule.load("mae", os.path.join(p, "test.mae"))
    molecule.set_top(m2)

    # Check the system dimensions are correct
    solsel = atomsel("protein or resname ACE NMA ALP")
    prot_x = max(solsel.get("x")) - min(solsel.get("x"))
    prot_y = max(solsel.get("y")) - min(solsel.get("y"))
    prot_z = max(solsel.get("z")) - min(solsel.get("z"))
    assert(abs(molecule.get_periodic(m2)["a"] - prot_x - 20.0) < 0.1)
    assert(abs(molecule.get_periodic(m2)["b"] - prot_y - 20.0) < 0.1)
    assert(abs(molecule.get_periodic(m2)["c"] - prot_z - 20.0) < 0.1)

    # Check all the alprenolols are there
    assert(len(set(atomsel("resname ALP").get("resid"))) == 10)
예제 #2
0
def save_representative_frames(sample, outdir, msm=None, clusters=None):
    """
    Saves a frame of protein and ligand representing each cluster
    in the sampler in a given directory

    Args:
        sample (Sampler): MSM trajectory object
        outdir (str): Location for saved cluster files
        msm (MarkovStateModel): MSM to use
        clusters (clusters): Cluster stuff
    """
    if msm is None:
        msm = sample.mmsm
    if clusters is None:
        clusters = sample.mclust

    protsel = "(protein or resname ACE NMA) and not same fragment as resname %s" \
              % " ".join(sample.ligands)

    fn = open(os.path.join(outdir, "rmsds"), 'w')

    for cl in msm.mapping_.values():
        print("On cluster: %s" % cl)
        x = visualizers.get_representative_ligand(sample, cl, clusters)
        if x is None: continue
        lg, rms = x
        m, f, l = lg
        print("   Molid: %d\tFrame: %d\tLigand: %d" % (m, f, l))
        fn.write("%s\t%f\n" % (cl, rms))
        atomsel("(%s) or (same fragment as residue %d)" % (protsel, l),
                molid=m,
                frame=f).write("mae", os.path.join(outdir, "%s.mae" % cl))

    fn.close()
예제 #3
0
    def _set_water_names(self):
        """
        Sets the names of water residues and atoms according to the given
        water model. We do it this way instead of with the GraphMatcher because
        waters can have a fake bond
        """
        # Sanity check
        if self.water_model not in self.WATER_NAMES:
            raise DabbleError("Unsupported water model '%s' with forcefield "
                              "'%s'" % (self.water_model, self.forcefield))

        watres = self.WATER_NAMES[self.water_model]
        if watres not in self.matcher.known_res:
            raise DabbleError("Water resname '%s' for model '%s' not defined "
                              "in topology files" % (watres, self.water_model))

        # Set consistent residue and atom names, crystal waters
        # can be named HOH, etc
        residues = set(atomsel("water").residue)

        # If no water, nothing to do
        if not residues:
            return

        watsel = "residue %s" % ' '.join(str(_) for _ in residues)

        atomsel(watsel).resname = self.WATER_NAMES[self.water_model]
        atomsel("%s and noh" % watsel).name = self.WATER_O_NAME
        atomsel("%s and not noh" %
                watsel).name = self.WATER_H_NAMES * len(residues)
예제 #4
0
def general_water(tmpdir, writerclass, forcefield, water_model):
    """
    Tests water generally
    """
    m = molecule.load("pdb", os.path.join(dir, "tip3.pdb"))
    p = str(tmpdir)

    w = writerclass(molid=m,
                    tmp_dir=p,
                    forcefield=forcefield,
                    water_model=water_model)
    w.write(os.path.join(p, "test"))

    if os.path.isfile(os.path.join(p, "test.prmtop")):
        tm = molecule.load("parm7", os.path.join(p, "test.prmtop"), "rst7",
                           os.path.join(p, "test.inpcrd"))
    else:
        tm = molecule.load("psf", os.path.join(p, "test.psf"), "pdb",
                           os.path.join(p, "test.pdb"))

    molecule.set_top(tm)
    watsel = "water or resname TIP3 TP4E TP4 SPC SPCE"
    assert len(set(atomsel(watsel).residue)) == 1
    assert len(set(atomsel(watsel).resid)) == 1

    if water_model == "tip4e":
        assert len(atomsel()) == 4
    else:  # SPC or TIP3
        assert len(atomsel()) == 3
예제 #5
0
    def _set_atom_names(self):
        """
        Sets the atom and residue names for a GROMACS-style force field

        Args:
            molid (int): Molecule ID
        """
        # Rename all residues
        residues = set(atomsel("all", molid=self.molid).residue)
        n_res = len(residues)

        while residues:
            if len(residues) % 500 == 0:
                print("Renaming residues.... %.0f%%  \r" %
                      (100. - 100 * len(residues) / float(n_res)),
                      flush=True)

            residue = residues.pop()
            sel = atomsel("residue %s" % residue)
            resnames, atomnames = self.matcher.get_names(sel,
                                                         print_warning=False)
            if not resnames:
                rgraph = self.matcher.parse_vmd_graph(sel)[0]
                self.matcher.write_dot(rgraph, "rgraph.dot")
                raise ValueError("Unknown residue %s:%d" %
                                 (sel.resname[0], sel.resid[0]))

            self._apply_naming_dictionary(resnames=resnames,
                                          atomnames=atomnames)
            sel.user = 1.0
예제 #6
0
    def _write_solvent(self):
        """
        Writes ions. Renames waters according to the water model and writes
        multiple PDB files to bypass PDB file format issues.

        Returns:
            (list of str): PDB filenames that were written
        """
        # Match up ion names to topology templates
        written = []
        allions = []
        for resname in set(atomsel("numbonds 0").resname):
            allions.extend(self._rename_by_resname(resname, renumber=True))

        # Dump to a temporary PDB file
        if allions:
            _, temp = tempfile.mkstemp(suffix='.pdb',
                                       prefix='amber_ion',
                                       dir=self.tmp_dir)
            os.close(_)
            ionsel = atomsel("residue %s" % ' '.join(str(_) for _ in allions))
            ionsel.write('pdb', temp)
            ionsel.user = 0.0
            written.append(temp)

        # Now write water PDBs, waters are already named
        written.extend(self._write_water_pdbs())

        return written
예제 #7
0
    def _write_unorderedindex_waters(self, residues, molid):
        """
        Renumbers and sorts the specified waters manually. This is much less
        efficient but is necessary in cases where atoms within a water molecule
        are not sequential in index, preventing quick renaming with VMD.
        Identify problem waters, then call this on them. It'll write its own
        psf_wat_* file with just those waters, minimizing inefficiency.

        Args:
            residues (list of int): Problem water molecules
            molid (int): VMD molecule ID to write
        Returns:
            (str): Filename where waters are written
        """
        f, temp = tempfile.mkstemp(suffix='_indexed.pdb',
                                   prefix='psf_wat_',
                                   dir=self.tmp_dir)
        idx = 1
        with os.fdopen(f, 'w') as fileh:
            for ridx, residue in enumerate(residues):
                res = atomsel('residue %d' % residue, molid=molid)

                for i in res.index:
                    a = atomsel('index %d' % i, molid)
                    fileh.write(self.get_pdb_line(a, idx, ridx + 1))
                    idx += 1

            fileh.write('END\n')
        return temp
예제 #8
0
def test_basic_getset(file_3frames):

    m = molecule.load("pdb", file_3frames)
    sel = atomsel(selection="protein", molid=m, frame=1)

    assert sel.frame == 1
    assert sel.molid == m
    assert len(sel.bonds) == 10
    assert str(sel) == "protein"
    assert repr(sel) == "atomsel('protein', molid=%d, frame=%d)" % (m, 1)

    # Default selections
    molecule.set_frame(m, 2)
    molecule.set_top(m)
    sel = atomsel()
    assert repr(sel) == "atomsel('all', molid=%d, frame=-1)" % m

    # Set something without a setter
    with pytest.raises(AttributeError):
        sel.molid = m+1

    # Invalid selection text
    with pytest.raises(ValueError):
        atomsel(selection="cannot be parsed")

    molecule.delete(m)

    # Selection on deleted molecule
    with pytest.raises(ValueError):
        assert sel.frame == 1
    with pytest.raises(ValueError):
        assert sel.molid == m
    with pytest.raises(ValueError):
        assert sel.bonds == []
예제 #9
0
def test_basic_getset(file_3frames):

    m = molecule.load("pdb", file_3frames)
    sel = atomsel(selection="protein", molid=m, frame=1)

    assert sel.frame == 1
    assert sel.molid == m
    assert len(sel.bonds) == 10
    assert str(sel) == "protein"
    assert repr(sel) == "atomsel('protein', molid=%d, frame=%d)" % (m, 1)

    # Default selections
    molecule.set_frame(m, 2)
    molecule.set_top(m)
    sel = atomsel()
    assert repr(sel) == "atomsel('all', molid=%d, frame=-1)" % m

    # Set something without a setter
    with pytest.raises(AttributeError):
        sel.molid = m + 1

    # Invalid selection text
    with pytest.raises(ValueError):
        atomsel(selection="cannot be parsed")

    molecule.delete(m)

    # Selection on deleted molecule
    with pytest.raises(ValueError):
        assert sel.frame == 1
    with pytest.raises(ValueError):
        assert sel.molid == m
    with pytest.raises(ValueError):
        assert sel.bonds == []
예제 #10
0
파일: fileutils.py 프로젝트: drorlab/dabble
def load_solute(filename, tmp_dir):
    """
    Loads a molecule input file, guessing the format from the extension.

    Args:
      filename (str): Filename to load
      tmp_dir (str): Directory to put temporary files in

    Returns:
      (int) VMD molecule ID that was loaded

    Raises:
      ValueError if filetype is currently unsupported
    """
    if len(filename) < 3:
        raise ValueError("Cannot determine filetype of input file '%s'"
                         % filename)
    ext = filename[-3:]
    if ext == 'mae':
        molid = molecule.load('mae', filename)
    elif ext == 'dms':
        molid = molecule.load('dms', filename)
    elif ext == 'pdb':
        # Need to convert to MAE so concatenation will work later
        temp_mae = tempfile.mkstemp(suffix='.mae', prefix='dabble_input',
                                    dir=tmp_dir)[1]
        molid = molecule.load('pdb', filename)
        atomsel('all').write('mae', temp_mae)
        molecule.delete(molid)
        molid = molecule.load('mae', temp_mae)
    else:
        raise ValueError("Filetype '%s' currently unsupported "
                         "for input protein" % ext)
    return molid
예제 #11
0
파일: fileutils.py 프로젝트: drorlab/dabble
def write_ct_blocks(molid, sel, output_filename, tmp_dir):
    """
    Writes a mae format file containing the specified selection.

    Args:
      molid (int): VMD molecule ID to write
      sel (str): the selection to write
      output_filename (str): the file to write to, including .mae extension
      tmp_dir (str): Directory to put files in

    Returns:
      length (int): the number of CT blocks written
    """
    users = sorted(set(atomsel(sel, molid=molid).get('user')))
    filenames = [(tempfile.mkstemp(suffix='.mae',
                                   prefix='dabble_tmp_user',
                                   dir=tmp_dir))[1] for _ in users]
    length = len(users)

    for i, filen in zip(users, filenames):
        tempsel = atomsel('user %f and (%s)' % (i, sel), molid=molid)
        sel2 = atomsel('index ' + \
                       ' '.join([str(s) for s in set(tempsel.get('index'))]),
                       molid=molid)
        sel2.set('user', 0.0)
        sel2.write('mae', filen)

    # Option lets us specify if we should write a pdb/psf or just a mae file
    # Either way it writes a temp mae file, hacky but it works
    concatenate_mae_files(output_filename, input_filenames=filenames)

    # Clean up
    for filename in filenames:
        os.remove(filename) # delete temporary files
    return length
예제 #12
0
 def rmsd_vmd(self,atomselect):
      rmsd_array=[]
      # use frame 0 for the reference
      reference = atomsel(selection=atomselect, molid=self.molID, frame=0)
      reference1 = atomsel(selection=atomselect, molid=self.molID, frame=1)  
      x=reference.rmsd(selection=reference1)
      print (x) 
예제 #13
0
 def get_residue_insert_mem_per_frame(self,frame,membrane,fosfolipid_head_select,protein_select):
     inserted_residues=[]
     protein  = atomsel(selection=protein_select, molid=self.molID, frame=frame) 
     resid_center=protein.centerperresidue()
     resid_z=list(map(lambda x: x, resid_center))     
     membrane  = atomsel(selection=membrane, molid=self.molID, frame=frame)
     #outerleaf
     name_P_down=atomsel(selection=fosfolipid_head_select+" and z<"+str(membrane.center(membrane.mass)[2]) ,molid=self.molID, frame=frame) 
     #inner leaf
     name_P_up=atomsel(selection=fosfolipid_head_select+" and z>"+str(membrane.center(membrane.mass)[2]) ,molid=self.molID, frame=frame)
          
     x_down=np.asarray(name_P_down.x).transpose() 
     y_down=np.asarray(name_P_down.z).transpose()
     p_down = np.polyfit(x_down, y_down, 1)
          
     x_up=np.asarray(name_P_up.x).transpose()  
     y_up=np.asarray(name_P_up.z).transpose()  
     p_up = np.polyfit(x_up, y_up, 1)
     
     for number_resid in range(len(resid_z)):
         x_residue=resid_z[number_resid][0]
         z_down_ajuste = p_down[0]*x_residue + p_down[1]
         z_up_ajuste = p_up[0]*x_residue + p_up[1]
         if resid_z[number_resid][2]<z_up_ajuste and resid_z[number_resid][2]>z_down_ajuste:
                 inserted_residues.append(number_resid)
              
     return inserted_residues
예제 #14
0
 def rmsd_time_references(self,atomselect,references1):
      rmsd_array=[]
      # use frame 0 for the reference
      reference = atomsel(selection=atomselect, molid=self.molID, frame=0)
      reference2 = atomsel(selection=references1, molid=self.molID, frame=0) 
      #compare = atomsel(atomselect)
      #set reference [atomselect $mol "protein" frame 0]
      # the frame being compared 
      #set compare [atomselect $mol "protein"]
      for frame in range(Trajectory.num_frames(self)):
          #protein  = atomsel(selection="protein", molid=molid, frame=frame) 
           # the frame being compared 
          compare = atomsel(selection=atomselect, molid=self.molID, frame=frame) 
          
          compare2 = atomsel(selection=references1, molid=self.molID, frame=frame) 
          #set trans_mat [measure fit $compare $reference]
          trans_mat=atomsel.fit(compare,reference)
          # do the alignment
          #compare.move(trans_mat)
          compare2.move(trans_mat)
          
          #$compare move $trans_mat
          # compute the RMSD
          #set rmsd [measure rmsd $compare $reference]
          rmsd_array.append(atomsel.rmsd(compare2,reference2))
 
      return rmsd_array
예제 #15
0
    def _write_ion_blocks(self):
        """
        Writes a PDB file containing correctly named ions for use by
        psfgen, and instructs psfgen to use it in TCL code.
        """

        # Put our molecule on top to simplify atom selection language
        old_top = molecule.get_top()
        molecule.set_top(self.molid)

        # Select all ions
        allions = []
        for resname in set(atomsel("numbonds 0").resname):
            allions.extend(self._rename_by_resname(resname, renumber=True))

        # Stop if no ions were found
        if not allions:
            return

        # Save ions as pdb
        allsel = atomsel("residue %s" % " ".join(str(_) for _ in allions))
        allsel.resid = range(len(allsel))
        allsel.user = 0.0
        _, temp = tempfile.mkstemp(suffix=".pdb",
                                   prefix="psf_ions_",
                                   dir=self.tmp_dir)
        os.close(_)
        allsel.write("pdb", temp)

        self.psfgen.add_segment(segid="I", pdbfile=temp)
        self.psfgen.read_coords(segid="I", filename=temp)

        molecule.set_top(old_top)
def test_multiligand_building(tmpdir):
    """
    Solvates and membranes a system with multiple ligands """
    from dabble import DabbleBuilder
    p = str(tmpdir)

    # Build the system
    b = DabbleBuilder(solute_filename=os.path.join(dir, "B2AR_10ALPs.mae"),
                      output_filename=os.path.join(p, "test.mae"),
                      xy_buf=10.,
                      wat_buffer=10.,
                      overwrite=True,
                      tmp_dir=p)
    b.write()

    # Load the built system
    m2 = molecule.load("mae", os.path.join(p, "test.mae"))
    molecule.set_top(m2)

    # Check the system dimensions are correct
    solsel = atomsel("protein or resname ACE NMA ALP")
    prot_x = max(solsel.x) - min(solsel.x)
    prot_y = max(solsel.y) - min(solsel.y)
    prot_z = max(solsel.z) - min(solsel.z)
    assert abs(molecule.get_periodic(m2)["a"] - prot_x - 20.0) < 0.1
    assert abs(molecule.get_periodic(m2)["b"] - prot_y - 20.0) < 0.1
    assert abs(molecule.get_periodic(m2)["c"] - prot_z - 20.0) < 0.1

    # Check all the alprenolols are there
    assert len(set(atomsel("resname ALP").resid)) == 10
    assert len(atomsel("resname ALP")) == 420

    molecule.delete(m2)
예제 #17
0
def test_atomsel_update(file_3frames):

    m = molecule.load("pdb", file_3frames)
    atomsel("resid 1", m, frame=2).user = 1.0
    sel = atomsel("user 1.0", molid=m, frame=-1)

    assert sel.frame == -1
    assert sel.index == list(range(10))

    altersel = atomsel("index 9", m, frame=2)
    altersel.user = 0.0
    assert atomsel("index 8 9", m, frame=2).user == approx([1.0, 0.0])
    assert atomsel("index 8 9", m, frame=0).user == approx([0.0, 0.0])

    # Selection should only change if the frame is set to update
    molecule.set_frame(m, 2)
    assert sel.index == list(range(10))
    sel.update()
    assert sel.index == list(range(9))

    # Now put it back to another frame
    sel.frame = 0
    assert sel.frame == 0
    assert sel.index == list(range(9))
    sel.update()
    assert sel.index == []

    molecule.delete(m)
def check_result(format, outdir, solvent=True, lipid=True):
    if format == "prmtop":
        m2 = molecule.load("parm7", os.path.join(outdir, "test.prmtop"),
                           "rst7", os.path.join(outdir, "test.inpcrd"))
    elif format == "psf":
        m2 = molecule.load("psf", os.path.join(outdir, "test.psf"), "pdb",
                           os.path.join(outdir, "test.pdb"))
    # Check by reading .top file, as VMD won't parse it and .gro doesn't
    # have bond information
    elif format == "gro":
        return check_gro(os.path.join(outdir, "test.top"), lipid=lipid)

    elif format == "lammps":
        return check_lammps(os.path.join(outdir, "test.dat"))

    molecule.set_top(m2)

    assert len(set(atomsel("protein").resid)) == 282
    assert len(set(atomsel("resname ACE NMA NME").resid)) == 4
    if solvent:
        assert len(atomsel("water")) == 32106
        assert len(atomsel("same fragment as lipid")) == 12194

    # Check for the corrrect number of alprenolols
    assert len(atomsel("resname ALP")) == 420
    assert len(set(atomsel("resname ALP").resid)) == 10
    assert any(_ in set(atomsel("resname ALP").name) for _ in ["O09", "OX"])
    assert "O1" not in set(atomsel("resname ALP").name)

    # Check coordinates are unique (not zero)
    assert len(atomsel("resname ALP")) == 420
    assert 0.0 not in atomsel("resname ALP").x

    molecule.delete(m2)
예제 #19
0
def write_ct_blocks(molid, sel, output_filename, tmp_dir):
    """
    Writes a mae format file containing the specified selection.

    Args:
      molid (int): VMD molecule ID to write
      sel (str): the selection to write
      output_filename (str): the file to write to, including .mae extension
      tmp_dir (str): Directory to put files in

    Returns:
      length (int): the number of CT blocks written
    """
    users = sorted(set(atomsel(sel, molid=molid).user))
    filenames = [(tempfile.mkstemp(suffix='.mae',
                                   prefix='dabble_tmp_user',
                                   dir=tmp_dir))[1] for _ in users]
    length = len(users)

    for i, filen in zip(users, filenames):
        tempsel = atomsel('user %f and (%s)' % (i, sel), molid=molid)
        sel2 = atomsel('index ' + \
                       ' '.join([str(s) for s in set(tempsel.index)]),
                       molid=molid)
        sel2.user = 0.0
        sel2.write('mae', filen)

    # Option lets us specify if we should write a pdb/psf or just a mae file
    # Either way it writes a temp mae file, hacky but it works
    concatenate_mae_files(output_filename, input_filenames=filenames)

    # Clean up
    for filename in filenames:
        os.remove(filename)  # delete temporary files
    return length
예제 #20
0
파일: builder.py 프로젝트: drorlab/dabble
    def _set_solute_sel(self, molid):
        """
        Gets the list of resids uniquely corresponding to the in the system
        and sets the value of the solute_sel attribute.
        Does this separately by chain since sometimes resids can be the
        same across different chains. This selection can be used to pull out
        the solute once other things are added later.
        This assumes that the solute is the only thing in the system right now.

        Args:
          molid (int) : VMD molecule ID to get the selection from

        Returns:
          (str) : VMD atom selection for these residues
        """
        # Temporary fix for chain W in input file
        if len(atomsel('chain W')):
            print("WARNING: Renaming crystal water chain to X, temporary bugfix")
            atomsel('chain W').set('chain', 'X')
        chains = set(atomsel('all', molid=molid).get('chain'))
        sel = ""
        while len(chains):
            chn = chains.pop() # have to handle first separately because of or
            sel += "(chain %s and resid " % (chn) + \
                   " ".join(["'%d'" % i for i in \
                       set(atomsel('chain %s' % chn, molid=molid).get('resid'))]) + \
                   ")"
            if len(chains):
                sel += " or "

        self.solute_sel = sel
        return sel
예제 #21
0
    def _set_solute_sel(self, molid):
        """
        Gets the list of resids uniquely corresponding to the in the system
        and sets the value of the solute_sel attribute.
        Does this separately by chain since sometimes resids can be the
        same across different chains. This selection can be used to pull out
        the solute once other things are added later.
        This assumes that the solute is the only thing in the system right now.

        Args:
          molid (int) : VMD molecule ID to get the selection from

        Returns:
          (str) : VMD atom selection for these residues
        """
        # Temporary fix for chain W in input file
        if len(atomsel('chain W')):
            print(
                "WARNING: Renaming crystal water chain to X, temporary bugfix")
            atomsel('chain W').set('chain', 'X')
        chains = set(atomsel('all', molid=molid).get('chain'))
        sel = ""
        while len(chains):
            chn = chains.pop()  # have to handle first separately because of or
            sel += "(chain %s and resid " % (chn) + \
                   " ".join(["'%d'" % i for i in \
                       set(atomsel('chain %s' % chn, molid=molid).get('resid'))]) + \
                   ")"
            if len(chains):
                sel += " or "

        self.solute_sel = sel
        return sel
예제 #22
0
    def save_initial_molecule(self, molid, sampled, repindex):
        """
        Saves a single molecule added thing. Names it according to
        the index and the sampled cluster.
        """
        # Write out to the output directory indicating the cluster
        # that was selected in the file name
        outnam = os.path.join(self.outdir,
                              "%d_init_%d.mae" % (repindex, sampled))

        # Since we operate only off stripped prmtops, this should contain
        # the full system minus any dabble additions
        atomsel("all").write("mae", outnam)

        # Start a slurm job that will add additional ligands and dabble
        old_dir = os.getcwd()
        os.chdir(self.config["system"]["rootdir"])
        subprocess.call([
            "sbatch", "--time=2:00:00", "--partition=rondror", "--tasks=2",
            "--cpus-per-task=1", "--mem=8GB",
            "--job-name=%s_dabbler_G%d-%d" %
            (self.config["system"]["jobname"],
             self.config.getint("production", "generation") + 1, repindex),
            "--export=INPUT=%s,CONFIG=%s" %
            (outnam,
             os.path.join(self.config["system"]["rootdir"], "sampler.cfg")),
            "--output=%s" %
            os.path.join(self.outdir, "dabble_%d.log" % repindex),
            "--open-mode=append",
            os.path.join(self.config["system"]["scriptdir"], "ligand_adder.py")
        ])
        os.chdir(old_dir)
예제 #23
0
파일: amber.py 프로젝트: chemlove/dabble
    def _write_ligands(self):
        """
        Writes any remaining user=1.0 residues each to a pdb file. Renumbers
        the residues along the way. Previously this was done with a mol2 file,
        but tleap takes charges from there and we will use a topology library
        file to get the connectivity correct.

        Returns:
            (list of 2-tuple): ilename of each ligand, unit name of ligand
        """

        idx = 1
        pdbs = []

        for residue in set(atomsel("user 1.0").get("residue")):
            temp = tempfile.mkstemp(suffix='.pdb',
                                    prefix='amber_extra',
                                    dir=self.tmp_dir)[1]
            sel = atomsel("residue %d" % residue)
            sel.set('user', 0.0)
            sel.set('resid', idx)
            sel.write("pdb", temp)
            unit = self.matcher.get_unit(sel)
            pdbs.append((temp, unit))
            idx += 1
        return pdbs
예제 #24
0
    def go(self):
        """
        Actually runs
        """
        # Set the user field of actually placed ligand to nonzero
        # this is the prettiest way to do ligand placement, but the user
        # field doesn't save. We temporarily communicate this with zero cooods
        atomsel("all").set("user", 1.0)
        atomsel("same fragment as resname %s and (x=0. and y=0. and z=0.)" %
                self.config["system"]["ligands"].replace(",", " "),
                molid=self.molid).set("user", 0.0)

        # Add ligands and Dabble
        with VmdSilencer(
                output=os.path.join(self.config["system"]["rootdir"],
                                    "systems", str(self.gen +
                                                   1), "generator.log")):
            self.add_ligands_and_dabble()

        # Start the simulation
        self.start_jobs()

        # Check for output files from other adders. If we're all done,
        # increment generation
        for idx in range(1, self.config.getint("model", "samplers") + 1):
            if not os.path.isfile(os.path.join(self.outdir,
                                               "%d.prmtop" % idx)):
                return

        self.config["production"]["generation"] = str(self.gen + 1)
        with open(os.environ.get("CONFIG"), 'w') as configfile:
            self.config.write(configfile)
예제 #25
0
def test_atomsel_update(file_3frames):

    m = molecule.load("pdb", file_3frames)
    atomsel("resid 1", m, frame=2).user = 1.0
    sel = atomsel("user 1.0", molid=m, frame=-1)

    assert sel.frame == -1
    assert sel.index == list(range(10))

    altersel = atomsel("index 9", m, frame=2)
    altersel.user = 0.0
    assert atomsel("index 8 9", m, frame=2).user == approx([1.0, 0.0])
    assert atomsel("index 8 9", m, frame=0).user == approx([0.0, 0.0])

    # Selection should only change if the frame is set to update
    molecule.set_frame(m, 2)
    assert sel.index == list(range(10))
    sel.update()
    assert sel.index == list(range(9))

    # Now put it back to another frame
    sel.frame = 0
    assert sel.frame == 0
    assert sel.index == list(range(9))
    sel.update()
    assert sel.index == []

    molecule.delete(m)
예제 #26
0
def test_atomsel_fit_move(file_3nob):

    m1 = molecule.load("mae", file_3nob)
    m2 = molecule.load("mae", file_3nob)

    sel1 = atomsel("protein", m1)
    sel2 = atomsel("protein", m2)

    # Move one selection over
    assert sel1.x[0] == approx(sel2.x[0])
    sel1.moveby((1.0, 0.0, 0.0))
    assert sel1.x[0] == approx(sel2.x[0] + 1.0)
    sel1.moveby([1.0, 0.0, 0.0])
    assert sel1.x[0] == approx(sel2.x[0] + 2.0)
    assert sel1.y[0] == approx(sel2.y[0])
    assert sel1.z[0] == approx(sel2.z[0])

    # Fit, no weights
    fit1 = sel1.fit(sel2)
    assert fit1[0] == approx(1.0, abs=1e-5)

    # Fit, with weights
    fit0 = sel1.fit(selection=sel2, weight=[0.0] + [1.0]*(len(sel2)-1))
    assert fit0 == approx((1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0,
                           1.0, 0.0, -2.0, 0.0, 0.0, 1.0))

    # Test selection invertible
    fit2 = np.reshape(sel2.fit(sel1), (4,4))
    assert np.linalg.inv(fit2) == approx(np.reshape(fit1, (4,4)))

    # Move
    sel1.move(fit1)
    assert sel1.x[0] == sel2.x[0]

    # Move with a numpy array - all zeros nans the array?
    sel1.move(np.zeros((16,)))
    assert sel1.y == approx(sel1.x, nan_ok=True)
    assert sel1.y != approx(sel1.x, nan_ok=False)

    # Operations on empty selection
    isel = atomsel("resname NOPE", m1)
    with pytest.raises(ValueError):
        isel.moveby((1., 2., 3.))

    with pytest.raises(ValueError):
        isel.move(fit1)

    with pytest.raises(ValueError):
        isel.fit(isel)

    molecule.delete(m1)
    with pytest.raises(ValueError):
        sel1.fit(sel2)

    molecule.delete(m2)
    with pytest.raises(ValueError):
        sel1.moveby((1,2,3))
    with pytest.raises(ValueError):
        sel2.move(fit1)
예제 #27
0
def test_atomsel_fit_move(file_3nob):

    m1 = molecule.load("mae", file_3nob)
    m2 = molecule.load("mae", file_3nob)

    sel1 = atomsel("protein", m1)
    sel2 = atomsel("protein", m2)

    # Move one selection over
    assert sel1.x[0] == approx(sel2.x[0])
    sel1.moveby((1.0, 0.0, 0.0))
    assert sel1.x[0] == approx(sel2.x[0] + 1.0)
    sel1.moveby([1.0, 0.0, 0.0])
    assert sel1.x[0] == approx(sel2.x[0] + 2.0)
    assert sel1.y[0] == approx(sel2.y[0])
    assert sel1.z[0] == approx(sel2.z[0])

    # Fit, no weights
    fit1 = sel1.fit(sel2)
    assert fit1[0] == approx(1.0, abs=1e-5)

    # Fit, with weights
    fit0 = sel1.fit(selection=sel2, weight=[0.0] + [1.0] * (len(sel2) - 1))
    assert fit0 == approx((1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0,
                           1.0, 0.0, -2.0, 0.0, 0.0, 1.0))

    # Test selection invertible
    fit2 = np.reshape(sel2.fit(sel1), (4, 4))
    assert np.linalg.inv(fit2) == approx(np.reshape(fit1, (4, 4)))

    # Move
    sel1.move(fit1)
    assert sel1.x[0] == sel2.x[0]

    # Move with a numpy array - all zeros nans the array?
    sel1.move(np.zeros((16, )))
    assert sel1.y == approx(sel1.x, nan_ok=True)
    assert sel1.y != approx(sel1.x, nan_ok=False)

    # Operations on empty selection
    isel = atomsel("resname NOPE", m1)
    with pytest.raises(ValueError):
        isel.moveby((1., 2., 3.))

    with pytest.raises(ValueError):
        isel.move(fit1)

    with pytest.raises(ValueError):
        isel.fit(isel)

    molecule.delete(m1)
    with pytest.raises(ValueError):
        sel1.fit(sel2)

    molecule.delete(m2)
    with pytest.raises(ValueError):
        sel1.moveby((1, 2, 3))
    with pytest.raises(ValueError):
        sel2.move(fit1)
예제 #28
0
 def porcentaje_contact_radio_gyrations(self,atomselect1,atomselect2):
     for frame in range(Trajectory.num_frames(self)):
         #protein  = atomsel(selection="protein", molid=molid, frame=frame) 
         sel1 = atomsel(selection=atomselect1, molid=self.molID, frame=frame) 
         sel2 =atomsel(selection=atomselect2, molid=self.molID, frame=frame)
         sel1_z = np.array((sel1.center(sel1.mass)[2]))
         sel2_z= np.array((sel2.center(sel2.mass)[2]))
         distance_mass_weight.append(np.linalg.norm(sel2_z-sel1_z))
예제 #29
0
파일: amber.py 프로젝트: chemlove/dabble
    def _write_protein(self):
        """
        Writes the protein chain to a pdb file. Writes each fragment to a
        separate file. This is somewhat inelegant but necessary in order to
        have disulfide bonds between different fragments have sane residue
        numbering in leap.

        Returns:
            list of (str, str) Name of pdb files written, and UNIT sequence
                inside
        """
        pdbinfos = []
        psel = atomsel("user 1.0 and resname %s" %
                       " ".join(self.matcher._acids))

        # Start the protein numbering from 1, as it's lost in the prmtop anyway.
        # Make resids increase across chains/fragments too, so that bond section
        # for covalent modifications is simple.
        fragres = 1
        for i, frag in enumerate(sorted(set(psel.get("fragment")))):
            temp = tempfile.mkstemp(suffix='_prot.pdb',
                                    prefix='amber_prot_',
                                    dir=self.tmp_dir)[1]

            # Now write out all the resides to a pdb file
            resseq = []
            with open(temp, 'w') as fileh:
                idx = 1
                # Grab resids again since they may have updated
                # Check for multiple residues with the same resid (insertion codes)
                for resid in sorted(set(atomsel("fragment '%s'" \
                                                % frag).get("resid"))):
                    selstr = "fragment '%s' and resid '%d' " \
                             "and user 1.0" % (frag, resid)
                    for residue in sorted(set(atomsel(selstr).get("residue"))):
                        sel = atomsel("residue %d" % residue)
                        sel.set('resid', fragres)
                        sel.set('segname', str(i))
                        sel.set('user', 0.0)
                        idx = self._write_residue(sel,
                                                  fileh,
                                                  idx,
                                                  hetatm=False)
                        resseq.append(sel.get("resname")[0])
                        fragres += 1
                fileh.write("END\n")
                fileh.close()

            # Insert line breaks every 100 AA to avoid buffer overflow in tleap
            seqstring = ""
            for i, res in enumerate(resseq):
                seqstring += " %s" % res
                if i % 100 == 0:
                    seqstring += "\n"
            pdbinfos.append((temp, seqstring))

        return pdbinfos
예제 #30
0
파일: builder.py 프로젝트: drorlab/dabble
    def _trim_water(self, molid):
        """
        Removes water residues in the +- Z direction in the system. Used
        to chop off extra waters from the protein that are past a certain cutoff
        distance. Changes are apparent on next write.

        Args:
          molid (int): VMD molecule id to use

        Returns:
          int Number of atoms deleted

        Raises:
          ValueError if water buffer is None
        """

        if not self.opts.get('wat_buffer'):
            raise ValueError("Water buffer undefined")

        # Remove waters in the Z direction
        # Check if we are trimming to absolute size and set z buf if so
        total = 0
        zcoord = atomsel(self.solute_sel).get('z')
        total = _remove_residues('(not (%s) and not (%s)) and noh and z > %f' % \
                                 (self.solute_sel, self.opts['lipid_sel'],
                                  self._zmax), molid=molid)
        total += _remove_residues('(not (%s) and not (%s)) and noh and z < %f' %
                                  (self.solute_sel, self.opts['lipid_sel'],
                                   self._zmin), molid=molid)

        # Trim in the XY direction if it's a pure water system
        # lipid trimming is done in trim_xy_residues and takes into account
        # lipid center, etc.
        if self.water_only:
            xcoord = atomsel(self.solute_sel).get('x')
            buf = (self.size[0] - max(xcoord) + min(xcoord))/2.
            total += _remove_residues('(not (%s)) and noh and x > %f' %
                                      (self.solute_sel,
                                       max(xcoord) + buf),
                                       molid=molid)
            total += _remove_residues('(not (%s)) and noh and x < %f' %
                                      (self.solute_sel,
                                       min(xcoord) - buf),
                                      molid=molid)

            ycoord = atomsel(self.solute_sel).get('y')
            buf = (self.size[1] - max(ycoord) + min(ycoord))/2.
            total += _remove_residues('(not (%s)) and noh and y > %f' %
                                      (self.solute_sel,
                                       max(ycoord) + buf),
                                      molid=molid)
            total += _remove_residues('(not (%s)) and noh and y < %f' %
                                      (self.solute_sel,
                                       min(ycoord) - buf),
                                      molid=molid)

        return total
예제 #31
0
    def get_disulfide(self, selection, molid):
        """
        Checks if the selection corresponds to a cysteine in a disulfide bond.
        Sets the patch line appropriately and matches atom names using
        a subgraph match to the normal cysteine residue

        Args:
            selection (VMD atomsel): Selection to check
            molid (int): VMD molecule ID to look for other CYS in

        Returns:
            resnames (dict int -> str) Residue name translation dictionary
            atomnames (dict int -> str) Atom name translation dictionary
            conect (int) Residue this one is connected to
       """
        rgraph, _ = self.parse_vmd_graph(selection)

        # Sanity check
        if not self.known_res.get("CYX"):
            raise ValueError("CYX undefined. Check forcefields!")

        # Check for the 3 join atoms corresponding to the disulfide bonds
        externs = self.get_extraresidue_atoms(selection)
        if len(externs) != 3:
            return (None, None, None)

        # With the AMBER format, the CYX residue should be a subgraph of this
        # residue as the only difference is the _join bond
        graph = self.known_res.get("CYX")
        matcher = isomorphism.GraphMatcher(rgraph, graph, \
                                           node_match=self._check_atom_match)
        if matcher.subgraph_is_isomorphic():
            match = next(matcher.match())
        else:
            return (None, None, None)

        # Generate naming dictionaries to return
        nammatch = dict((i, graph.node[match[i]].get("atomname")) \
                        for i in match.keys() if \
                        graph.node[match[i]].get("residue") == "self")
        resmatch = dict((i, graph.node[match[i]].get("resname")) \
                        for i in match.keys() if \
                        graph.node[match[i]].get("residue") == "self")

        # Now we know it's a cysteine in a disulfide bond
        # Identify which resid and fragment corresponds to the other cysteine
        partners = [n for n in externs if \
                    atomsel("index %d" % n,
                            molid=molid).get("element")[0] == "S"]
        if not partners:
            raise ValueError("3 bonded Cys %d isn't a valid disulfide!"
                             % selection.get('resid')[0])
        osel = atomsel("index %d" % partners[0], molid=molid)
        conect = osel.get("residue")[0]

        return (resmatch, nammatch, conect)
예제 #32
0
    def get_disulfide(self, selection, molid):
        """
        Checks if the selection corresponds to a cysteine in a disulfide bond.
        Sets the patch line appropriately and matches atom names using
        a subgraph match to the normal cysteine residue

        Args:
            selection (VMD atomsel): Selection to check
            molid (int): VMD molecule ID to look for other CYS in

        Returns:
            resnames (dict int -> str) Residue name translation dictionary
            atomnames (dict int -> str) Atom name translation dictionary
            conect (int) Residue this one is connected to
       """
        rgraph, _ = self.parse_vmd_graph(selection)

        # Sanity check
        if not self.known_res.get("CYX"):
            raise DabbleError("CYX undefined. Check forcefields!")

        # Check for the 3 join atoms corresponding to the disulfide bonds
        externs = self.get_extraresidue_atoms(selection)
        if len(externs) != 3:
            return (None, None, None)

        # With the AMBER format, the CYX residue should be a subgraph of this
        # residue as the only difference is the _join bond
        graph = self.known_res.get("CYX")
        matcher = isomorphism.GraphMatcher(rgraph, graph, \
                                           node_match=self._check_atom_match)
        if matcher.subgraph_is_isomorphic():
            match = next(matcher.match())
        else:
            return (None, None, None)

        # Generate naming dictionaries to return
        nammatch = dict((i, graph.node[match[i]].get("atomname")) \
                        for i in match.keys() if \
                        graph.node[match[i]].get("residue") == "self")
        resmatch = dict((i, graph.node[match[i]].get("resname")) \
                        for i in match.keys() if \
                        graph.node[match[i]].get("residue") == "self")

        # Now we know it's a cysteine in a disulfide bond
        # Identify which resid and fragment corresponds to the other cysteine
        partners = [n for n in externs if \
                    atomsel("index %d" % n,
                            molid=molid).get("element")[0] == "S"]
        if not partners:
            raise DabbleError("3 bonded Cys %d isn't a valid disulfide!" %
                              selection.get('resid')[0])
        osel = atomsel("index %d" % partners[0], molid=molid)
        conect = osel.get("residue")[0]

        return (resmatch, nammatch, conect)
예제 #33
0
def test_load_mae(file_rho):
    from vmd import molecule, atomsel
    assert callable(atomsel)

    molecule.load('mae', file_rho)
    chrg = set(atomsel().get('charge'))
    assert chrg == set([0.0, 1.0, -1.0])

    ins = set(atomsel().get('insertion'))
    assert set(_.strip() for _ in ins) == set(['', 'A'])
예제 #34
0
def test_load_mae():
    from vmd import molecule, atomsel
    assert callable(atomsel)

    molecule.load('mae', os.path.join(dir, "rho_test.mae"))
    chrg = set(atomsel().get('charge'))
    assert chrg == set([0.0, 1.0, -1.0])

    ins = set(atomsel().get('insertion'))
    assert ins == set([' ', 'A'])
예제 #35
0
def test_load_mae(file_rho):
    from vmd import molecule, atomsel
    assert callable(atomsel)

    molecule.load('mae', file_rho)
    chrg = set(atomsel().get('charge'))
    assert chrg == set([0.0, 1.0, -1.0])

    ins = set(atomsel().get('insertion'))
    assert set(_.strip() for _ in ins) == set(['', 'A'])
예제 #36
0
def test_multiple_insertion_codes(tmpdir):
    from dabble.param import CharmmWriter

    # Generate the file
    p = str(tmpdir)
    molid = molecule.load("mae", os.path.join(dir, "3PTB_1lig_prepped.mae"))
    w = CharmmWriter(molid=molid,
                     tmp_dir=p,
                     forcefield="charmm",
                     hmr=False,
                     override_defaults=False)
    w.write(os.path.join(p, "test"))

    # Load the output file and start checking it
    m2 = molecule.load("psf", os.path.join(p, "test.psf"), "pdb",
                       os.path.join(p, "test.pdb"))
    molecule.set_top(m2)

    # Check the entire protein is there and connected
    assert len(atomsel("protein or resname ACE NMA NME")) == 3229
    assert len(set(atomsel("protein or resname ACE NMA NME").fragment)) == 1

    # Check the calcium ion is present
    assert atomsel("element Ca").resname == ["CAL"]

    # Check residues with insertion codes
    assert set(atomsel("resid 184").resname) == set(["GLY", "TYR"])
    assert set(atomsel("resid 188").resname) == set(["GLY", "LYS"])
    assert set(atomsel("resid 221").resname) == set(["ALA", "GLN"])
    assert set(atomsel("resid 245").resname) == set(["ASN", "NMA"])
    assert set(atomsel("all").insertion) == set([" ", "A"])

    # Check the ligand is there
    assert len(atomsel("resname BAMI")) == 18
예제 #37
0
    def _rename_atoms_amber(self):
        """
        Matches up atom names with those in the provided topologies and
        sets the atom and residue names correctly in the built molecule.
        Handles all non-lipid atoms. Sets the user field of all atoms to 1.0
        to track which things have been written.

        Returns:
            (set of tuples (int,int)): Residue #s of disulfide or otherwise
                noncanonically linked residues

        Raises:
            ValueError if a residue definition could not be found
        """

        self._set_water_names()
        nonlips = set(
            atomsel("not (water or %s)" % self.lipid_sel,
                    molid=self.molid).residue)
        n_res = len(nonlips)
        conect = set()  # Atom indices bound to noncanonical residues
        while nonlips:
            if len(nonlips) % 500 == 0:
                print("Renaming residues.... %.0f%%  \r" %
                      (100. - 100 * len(nonlips) / float(n_res)),
                      flush=True)

            residue = nonlips.pop()
            sel = atomsel("residue %s" % residue)
            resnames, atomnames = self.matcher.get_names(sel,
                                                         print_warning=False)

            # Check if it's a linkage to another amino acid
            if not resnames:
                resnames, atomnames, other = self.matcher.get_linkage(
                    sel, self.molid)
                if not resnames:
                    rgraph = self.matcher.parse_vmd_graph(sel)[0]
                    self.matcher.write_dot(rgraph, "rgraph.dot")
                    raise DabbleError(
                        "ERROR: Could not find a residue definition "
                        "for %s:%s" % (sel.resname[0], sel.resid[0]))

                print(
                    "\tBonded residue: %s:%d -> %s" %
                    (sel.resname[0], sel.resid[0], list(resnames.values())[0]))
                conect.add(other)

            # Do the renaming
            self._apply_naming_dictionary(resnames=resnames,
                                          atomnames=atomnames)

        atomsel('all').user = 1.0
        print("\n", flush=True)
        return conect
예제 #38
0
def test_atomsel_minmax_center(file_3frames):

    m = molecule.load("pdb", file_3frames)
    sel = atomsel(selection="protein", molid=m, frame=1)
    alasel = atomsel("resname ALA", molid=m)

    # Minmax without radii
    assert sel.minmax() == (approx(
        (2.497, 0.724, -0.890)), approx((6.009, 4.623, 2.131)))

    # Minmax with radii
    sel.radius = 10.0
    assert sel.minmax(radii=True) == (approx(
        (2.497 - 10., 0.724 - 10.,
         -0.890 - 10.)), approx((6.009 + 10., 4.623 + 10., 2.131 + 10.)))

    assert sel.center(weight=None) == approx((4.040, 2.801, 0.492), rel=1e-3)
    assert sel.center(weight=[0.] * 9 + [1.]) == atomsel("index 9", m).center()

    # Wrong number of weights
    with pytest.raises(TypeError):
        sel.center(weight=3.0)
    with pytest.raises(ValueError):
        sel.center([3., 2.])

    sel = atomsel("all")
    assert sel.centerperresidue() == [
        approx((4.040, 2.801, 0.492), rel=1e-3),
        approx((7.260, 3.987, 0.000), rel=1e-3)
    ]
    assert sel.centerperresidue(weight=None)[0] == alasel.centerperresidue()[0]

    # Centerperresidue with weights
    with pytest.raises(TypeError):
        sel.centerperresidue(weight=[True] * len(sel))
    with pytest.raises(TypeError):
        sel.centerperresidue(3)
    with pytest.raises(ValueError):
        sel.centerperresidue([1.0, 2.0])

    weights = [1.0] * 10 + [0.0] * 6
    assert sel.centerperresidue(weight=weights)[0] == approx(alasel.center(),
                                                             rel=1e-3)
    assert all([math.isnan(x) for x in sel.centerperresidue(weights)[1]])
    molecule.delete(m)

    # Operations on deleted molecule
    with pytest.raises(ValueError):
        sel.minmax(radii=False)
    with pytest.raises(ValueError):
        sel.centerrperres()
    with pytest.raises(ValueError):
        sel.center()
예제 #39
0
def test_atomsel_minmax_center(file_3frames):

    m = molecule.load("pdb", file_3frames)
    sel = atomsel(selection="protein", molid=m, frame=1)
    alasel = atomsel("resname ALA", molid=m)

    # Minmax without radii
    assert sel.minmax() == (approx((2.497, 0.724, -0.890)),
                            approx((6.009, 4.623, 2.131)))


    # Minmax with radii
    sel.radius  = 10.0
    assert sel.minmax(radii=True) == (approx((2.497-10., 0.724-10., -0.890-10.)),
                                      approx((6.009+10., 4.623+10., 2.131+10.)))

    assert sel.center(weight=None) == approx((4.040, 2.801, 0.492), rel=1e-3)
    assert sel.center(weight=[0.]*9+ [1.]) == atomsel("index 9", m).center()

    # Wrong number of weights
    with pytest.raises(TypeError):
        sel.center(weight=3.0)
    with pytest.raises(ValueError):
        sel.center([3.,2.])


    sel = atomsel("all")
    assert sel.centerperresidue() == [approx((4.040, 2.801, 0.492), rel=1e-3),
                                      approx((7.260, 3.987, 0.000), rel=1e-3)]
    assert sel.centerperresidue(weight=None)[0] == alasel.centerperresidue()[0]


    # Centerperresidue with weights
    with pytest.raises(TypeError):
        sel.centerperresidue(weight=[True]*len(sel))
    with pytest.raises(TypeError):
        sel.centerperresidue(3)
    with pytest.raises(ValueError):
        sel.centerperresidue([1.0,2.0])

    weights = [1.0]*10 + [0.0]*6
    assert sel.centerperresidue(weight=weights)[0] == approx(alasel.center(),
                                                             rel=1e-3)
    assert all([math.isnan(x) for x in sel.centerperresidue(weights)[1]])
    molecule.delete(m)

    # Operations on deleted molecule
    with pytest.raises(ValueError):
        sel.minmax(radii=False)
    with pytest.raises(ValueError):
        sel.centerrperres()
    with pytest.raises(ValueError):
        sel.center()
예제 #40
0
    def _trim_water(self, molid):
        """
        Removes water residues in the +- Z direction in the system. Used
        to chop off extra waters from the protein that are past a certain cutoff
        distance. Changes are apparent on next write.

        Args:
          molid (int): VMD molecule id to use

        Returns:
          int Number of atoms deleted

        Raises:
          ValueError if water buffer is None
        """

        if not self.opts.get('wat_buffer'):
            raise ValueError("Water buffer undefined")

        # Remove waters in the Z direction
        # Check if we are trimming to absolute size and set z buf if so
        total = 0
        total = _remove_residues('(not (%s) and not (%s)) and noh and z > %f' % \
                                 (self.solute_sel, self.opts['lipid_sel'],
                                  self._zmax), molid=molid)
        total += _remove_residues(
            '(not (%s) and not (%s)) and noh and z < %f' %
            (self.solute_sel, self.opts['lipid_sel'], self._zmin),
            molid=molid)

        # Trim in the XY direction if it's a pure water system
        # lipid trimming is done in trim_xy_residues and takes into account
        # lipid center, etc.
        if self.water_only:
            xcoord = atomsel(self.solute_sel).get('x')
            buf = (self.size[0] - max(xcoord) + min(xcoord)) / 2.
            total += _remove_residues('(not (%s)) and noh and x > %f' %
                                      (self.solute_sel, max(xcoord) + buf),
                                      molid=molid)
            total += _remove_residues('(not (%s)) and noh and x < %f' %
                                      (self.solute_sel, min(xcoord) - buf),
                                      molid=molid)

            ycoord = atomsel(self.solute_sel).get('y')
            buf = (self.size[1] - max(ycoord) + min(ycoord)) / 2.
            total += _remove_residues('(not (%s)) and noh and y > %f' %
                                      (self.solute_sel, max(ycoord) + buf),
                                      molid=molid)
            total += _remove_residues('(not (%s)) and noh and y < %f' %
                                      (self.solute_sel, min(ycoord) - buf),
                                      molid=molid)

        return total
예제 #41
0
    def add_ligands_and_dabble(self):
        """
        Adds remaining ligands to file.
        Saves all molecules to a temporary file and invokes the Dabble
        Builder API. Names them according to the replicate id.

        Args:
            molid (int): Molecule ID to save
        """

        # Add remaining ligands
        for _ in range(self.config.getint("system", "num_ligands") -
                       1):  # First already set
            self._greedily_add_ligand()

        # Print out resampler info, for easy backtracking
        print("SAMPLER %d.psf: Clusters: %s" %
              (self.repindex, self.sampled_clusters))
        sys.stdout.flush()

        # Write temporary file with correct ligand positions
        filen = os.path.join(self.outdir, "%d_inp.mae" % self.repindex)
        atomsel("all", self.molid).write('mae', filen)

        with TemporaryDirectory(dir=os.environ.get("SCRATCH"),
                                prefix="dabble") as tdir:
            if len(self.dabbleopts.get("topologies", "").strip()):
                topos = self.dabbleopts["topologies"].split(',')
            else:
                topos = None
            if len(self.dabbleopts.get("parameters", "").strip()):
                params = self.dabbleopts["parameters"].split(',')
            else:
                params = None
            builder = DabbleBuilder(
                solute_filename=filen,
                output_filename=os.path.join(self.outdir,
                                             "%d.prmtop" % self.repindex),
                user_x=float(self.dabbleopts["dimensions"].split(',')[0]),
                user_y=float(self.dabbleopts["dimensions"].split(',')[1]),
                user_z=float(self.dabbleopts["dimensions"].split(',')[2]),
                membrane_system=self.dabbleopts.get("solvent", "DEFAULT"),
                forcefield=self.dabbleopts["forcefield"],
                extra_topos=topos,
                extra_params=params,
                exclude_sel=self.dabbleopts.get("excludesel"),
                hmassrepartition=self.config.getboolean("production",
                                                        "hmr",
                                                        fallback=True),
                overwrite=True,
                tmp_dir=tdir)
            builder.write()
예제 #42
0
파일: charmm.py 프로젝트: drorlab/dabble
def check_atom_names(molid):
    """
    Checks that there are no spaces in atom names. If spaces are
    found, they are removed and a warning is printed
    """

    names = set(atomsel(molid=molid).get('name'))
    for name in names:
        if ' ' in name:
            print("\nWARNING: Found space character in name '%s'\n"
                  "         Incompatible with charmm formats, removing it"
                  % name)
            atomsel("name '%s'", molid=molid).set('name', name.replace(' ', ''))
예제 #43
0
파일: test_lsd.py 프로젝트: drorlab/dabble
def test_amber_params(tmpdir):
    """
    Tests writing a ligand with amber parameters
    """
    from Dabble.param import AmberWriter

    # Parameterize with amber parameters
    p = str(tmpdir.mkdir("multiligand_rename"))
    molid = molecule.load("mae", os.path.join(dir, "07HT2B_WT.mae"))
    w = AmberWriter(molid, tmp_dir=p, forcefield="amber", hmr=False,
                    extra_topos=[os.path.join(dir,"lsd.lib")],
                    extra_params=[os.path.join(dir, "lsd.frcmod")],
                    override_defaults=False)
    w.write(os.path.join(p, "test"))

    # Check output is correct
    m2 = molecule.load("parm7", os.path.join(p, "test.prmtop"),
                       "rst7", os.path.join(p, "test.inpcrd"))
    molecule.set_top(m2)

    # Check the system is correctly built
    assert(len(set(atomsel("protein or resname ACE NMA").get("resid"))) == 298)
    assert(len(atomsel("water")) == 186)
    assert(len(atomsel("ion")) == 0)

    # Check the LSD and CHL (cholesterol) are present
    assert(len(atomsel("resname LSD")) == 50)
    assert(len(atomsel("resname CHL")) == 74)

    # Check the partial charges are set
    # Here the LSD library has partial charges of 0 except +0.6 on the N2
    assert(len(set(atomsel("resname LSD").get("charge"))) == 2)
    assert(abs(atomsel("resname LSD and name N2").get("charge")[0] - 0.6) < 0.01)
    assert(abs(set(atomsel("resname LSD and not name N2").get("charge")).pop()) < 0.01)
예제 #44
0
파일: builder.py 프로젝트: drorlab/dabble
    def _remove_xy_lipids(self, molid):
        """
        Removes residues in the +-XY direction in the system. Used to chop off
        lipids that are protruding outside of the box dimensions.

        Args:
          molid (int): VMD molecule id to use

        Returns:
          (int) number of atoms deleted

        Raises:
          ValueError if the 'lipid' only contains hydrogens
        """

        # Select residues that are outside the box
        half_x_size = self.size[0] / 2.0
        half_y_size = self.size[1] / 2.0
        box_sel_str = 'abs(x) > %f or abs(y) > %f' % (half_x_size, half_y_size)

        # Identify lipids that have some part outside of the box
        suspicious_lipid_residues = list(set(atomsel('(%s) and (%s)' % \
               (self.opts['lipid_sel'], box_sel_str), molid=molid).get('residue')))
        bad_lipids = []

        # Delete lipids whose center is too far out of the box, keep others
        for i in suspicious_lipid_residues:
            lipid_center = atomsel('noh and residue %s' % str(i),
                                   molid=molid).center()
            # Sanity check
            if not len(lipid_center):
                raise ValueError("No heavy atoms found in suspicious residue %s"
                                 "Check your input file." % str(i))

            if abs(lipid_center[0]) > half_x_size or \
               abs(lipid_center[1]) > half_y_size:
                bad_lipids.append(i)
        lipid_headgroup_sel = 'residue ' + ' '.join([str(l) for l in bad_lipids])

        # Do the deletion
        removal_sel_str = '(%s) or not (%s)' % (lipid_headgroup_sel,
                                                self.opts['lipid_sel'])
        total = _remove_residues('noh and (%s) and (%s) and not (%s)' %
                                 (box_sel_str,
                                  removal_sel_str,
                                  self.solute_sel),
                                 molid=molid)
        return total
예제 #45
0
파일: builder.py 프로젝트: drorlab/dabble
def _convert_water_molecule_to_ion(molid, atom_id, element):
    """
    Converts a water molecule to an ion, deleting the hydgrogens and
    placing the ion where the water oxygen was

    Args:
      molid (int): VMD molecule to operate on
      atom_id (int): Atom index of water oxygen to change to ion
      element (str in Na, K, Cl): Ion to apply

    Raises:
      ValueError: if invalid element specified
      ValueError: if atom id is not of an oxygen water
    """

    if element not in ['Na', 'K', 'Cl']:
        raise ValueError("Ion must be Na, K, or Cl. Was '%s'" % element)

    element_received = atomsel('index %d' % atom_id).get('element')[0]
    if element_received is not 'O':
        raise ValueError("Received non-water oxygen to convert, id %d element %s"
                         % (atom_id, element_received))

    molutils.set_ion(molid, atom_id, element)
    _remove_atoms('element H and same residue as index %d' % atom_id, molid)
예제 #46
0
파일: molutils.py 프로젝트: drorlab/dabble
def set_ion(molid, atom_id, element):
    """
    Sets an atom to be the desired ion

    Args:
      molid (int): VMD molecule to operate on
      atom_id (int): Atom index to change to ion
      element (str in Na, K, Cl): Ion to apply

    Raises:
      ValueError if the index to change is not present
    """

    sel = atomsel('index %d' % atom_id, molid=molid)
    if len(sel) == 0:
        raise ValueError("Index %d does not exist" % atom_id)

    resname = dict(Na='SOD', K='POT', Cl='CLA')[element]
    name = dict(Na='NA', K='K', Cl='CL')[element]
    attype = dict(Na='NA', K='K', Cl='CL')[element]
    charge = dict(Na=1, K=1, Cl=-1)[element]
    sel.set('element', element)
    sel.set('name', name)
    sel.set('type', attype)
    sel.set('resname', resname)
    sel.set('chain', 'N')
    sel.set('segid', 'ION')
    sel.set('charge', charge)
예제 #47
0
파일: builder.py 프로젝트: drorlab/dabble
def _find_convertible_water_molecule(molid, # pylint: disable=invalid-name
                                     water_sel='resname TIP3',
                                     min_ion_dist=5.0):
    """
    Finds a water molecule that can be converted to an ion

    Args:
      molid (int): VMD molid to look at
      water_sel (str): VMD atom selection for water
      min_ion_dist (float): Minimum distance between ionds

    Returns:
      (int) Atom index of a water oxygen that is convertible

    Raises:
      ValueError if no convertible water molecules are found
    """

    inclusion_sel = 'beta 1 and noh and (%s)' % water_sel
    exclusion_sel = 'beta 1 and not (%s)' % water_sel
    sel = atomsel('(%s) and not pbwithin %f of (%s)' \
                  % (inclusion_sel, min_ion_dist, exclusion_sel), molid)
    if len(sel) == 0:
        raise ValueError("No convertible water molecules found in %s" % sel)

    return sel.get('index')[random.randint(0, len(sel))]
예제 #48
0
파일: charmm.py 프로젝트: drorlab/dabble
    def _check_psf_output(self):
        """
        Scans the output psf from psfgen for atoms where the coordinate
        could not be set, indicating an unmatched atom. This checek is necessary
        because sometimes psfgen will run with no errors or warnings but will
        have unmatched atoms that are all at (0,0,0).
        """

        # Check file was written at all
        if not os.path.isfile('%s.pdb'% self.psf_name):
            print("\nERROR: psf file failed to write.\n"
                  "       Please see log above.\n")
            quit(1)

        # Open the pdb file in VMD and check for atoms with no occupancy
        fileh = molecule.load('pdb', '%s.pdb' % self.psf_name)
        errors = atomsel("occupancy=-1", molid=fileh)

        # Print out error messages
        if len(errors):
            print("\nERROR: Couldn't find the following atoms.")
            for i in range(len(errors)):
                print("  %s%s:%s" % (errors.get("resname")[i], errors.get("resid")[i],
                                     errors.get("name")[i]))

            print("Check if they are present in the original structure.\n"
                  "If they are, check dabble name translation or file a "
                  "bug report to Robin.\n")
            quit(1)
        else:
            print("\nChecked output pdb/psf has all atoms present "
                  "and correct.\n")
예제 #49
0
파일: builder.py 프로젝트: drorlab/dabble
    def add_molecule(self, filename, desc):
        """
        Adds a molecule file to the system.

        Args:
          filename (str): File to load
          desc (str): Type of molecule: solute, solvent, etc

        Returns:
          True if the molecule was successfully added
        """

        molid = fileutils.load_solute(filename, tmp_dir=self.tmp_dir)
        self.molids[desc] = molid
        atomsel('all', molid=molid).set('beta', 1)
        return True
예제 #50
0
def test_write(tmpdir, file_3frames):

    m = molecule.load("pdb", struct_file=file_3frames)
    tmpdir = str(tmpdir)

    # Deprecated arguments
    with pytest.warns(DeprecationWarning):
        molecule.write(m, "psf", beg=0, end=1,
                       filename=os.path.join(tmpdir, "deprecated.psf"))

    # Write with stride
    molecule.write(molid=m, filetype="pdb", first=0, stride=2,
                   filename=os.path.join(tmpdir, "2frames.pdb"))
    m2 = molecule.load("pdb", os.path.join(tmpdir, "2frames.pdb"))
    assert molecule.numframes(m2) == 2

    # Write a selection
    sel = atomsel("resname ALA", molid=m)
    molecule.write(m, "mae", selection=sel, first=0, last=0,
                   filename=os.path.join(tmpdir, "ala.mae"))
    m3 = molecule.load("mae", os.path.join(tmpdir, "ala.mae"))
    assert molecule.numframes(m3) == 1
    assert set(atomsel(molid=m3).resname) == set(["ALA"])

    # Write an invalid selection on a different molid
    sel2 = atomsel("resname ALA", molid=m3)
    with pytest.raises(ValueError):
        molecule.write(m, "mae", os.path.join(tmpdir, "badsel.mae"),
                       selection=sel2)

    # Write a nonexistent atom selection
    with pytest.raises(TypeError):
        molecule.write(m, "mae", os.path.join(tmpdir, "badsel.mae"),
                       selection=None)

    # Write zero frames
    with pytest.raises(ValueError):
        molecule.write(first=20, last=21, molid=m, filetype="psf",
                       filename=os.path.join(tmpdir, "zeroframes.psf"))

    # Write to an invalid file name (in this case, a directory)
    with pytest.raises(ValueError):
        molecule.write(m, "pdb", filename=os.path.join(tmpdir, "."))

    molecule.delete(m)
    molecule.delete(m2)
    molecule.delete(m3)
예제 #51
0
파일: charmm.py 프로젝트: drorlab/dabble
def get_bonded_atoms(molid, index):
    """
    Returns the element of all atoms bonded to the current atom.

    Args:
       molid (int): VMD molecule ID to consider
       index (int): Atom index to look at bonded atoms

    Returns:
      (list of str) elements of atoms bound to the current atom
    """

    asel = atomsel('index %d' % index, molid=molid)
    bound = []
    for atom in asel.bonds[0]:
        bound.append(atomsel('index %d' % atom).get('element')[0])
    return bound
예제 #52
0
파일: molutils.py 프로젝트: drorlab/dabble
def center_system(molid, tmp_dir, center_z=False):
    """
    Centers an entire system in the XY-plane, and optionally in the Z
    dimension. Needs to save and reload the file in case the current
    positions need to be concatenated to produce a new file.

    Args:
      molid (int): VMD molecule id to center
      tmp_dir (str): Directory to create temp file in
      center_z (bool): Whether or not to center along the Z axis as well

    Returns:
      (int) : VMD molecule id of centered system
    """
    # pylint: disable=invalid-name
    x, y, z = atomsel('all', molid=molid).center()

    if center_z is True:
        atomsel('all', molid=molid).moveby((-x, -y, -z))
    else:
        atomsel('all', molid=molid).moveby((-x, -y, 0))

    # Save and reload the solute to record atom positions
    temp_mae = tempfile.mkstemp(suffix='.mae',
                                prefix='dabble_centered',
                                dir=tmp_dir)[1]
    atomsel('all', molid=molid).write('mae', temp_mae)
    molecule.delete(molid)
    new_id = molecule.load('mae', temp_mae)
    return new_id
예제 #53
0
def test_atomsel_sasa(file_3frames):

    m1 = molecule.load("pdb", file_3frames)
    m2 = molecule.load("pdb", file_3frames)
    s1 = atomsel("resname ALA", m1)
    s2 = atomsel("all", m2)

    # Invalid radius
    with pytest.raises(ValueError):
        s1.sasa(srad=-2.0)

    assert s1.sasa(srad=0.0) == approx(93.86288452)

    # Invalid samples
    with pytest.raises(ValueError):
        s1.sasa(srad=1.0, samples=0)
    with pytest.raises(ValueError):
        s1.sasa(srad=1.0, samples=-10)

    # Points object invalid
    with pytest.raises(TypeError):
        s1.sasa(srad=1.0, points=[])

    with pytest.raises(TypeError):
        s1.sasa(srad=1.0, points=(3,3))

    # Test correct calculation
    assert s1.sasa(srad=1.0) == approx(176.46739)
    assert s2.sasa(1.0, restrict=s1) == approx(142.44455)
    assert s1.sasa(0.5) == approx(s1.sasa(0.5, restrict=s1))

    # Using points object
    _, points = s1.sasa(0.5, points=True, samples=1)
    assert len(points) == 3 # Samples is an upper bound
    assert points[0] == approx((3.99603, 3.19342, 3.62426), rel=1e-3)

    # Test on deleted molecule
    molecule.delete(m1)
    with pytest.raises(ValueError):
        s1.sasa(srad=5.0)

    with pytest.raises(ValueError):
        s2.sasa(1.0, restrict=s1)

    molecule.delete(m2)
예제 #54
0
def test_compare_mol():
    from vmd import atomsel, molecule
    from Dabble.param import CharmmMatcher

    molid = molecule.load("mae", dir+"lsd_prot.mae")
    g = CharmmMatcher([dir+"lsd_prot_trunc.str", dir+"masses.rtf"])
    (resdict, mdict) = g.get_names(atomsel("all", molid=molid))
    assert(mdict=={0: 'C13', 1: 'N20', 2: 'C12', 3: 'C11', 4: 'C15', 5: 'C7', 6: 'C3', 7: 'C8', 8: 'N1', 9: 'C1', 10: 'C4', 11: 'C5', 12: 'C2', 13: 'C6', 14: 'C9', 15: 'C10', 16: 'C14', 17: 'C16', 18: 'O1', 19: 'N3', 20: 'C17', 21: 'C18', 22: 'C19', 23: 'C20', 24: 'H131', 25: 'H132', 26: 'H121', 27: 'H122', 28: 'H123', 29: 'H11', 30: 'H151', 31: 'H8', 32: 'H4', 33: 'H5', 34: 'H2', 35: 'H10', 36: 'H14', 37: 'H171', 38: 'H172', 39: 'H181', 40: 'H182', 41: 'H183', 42: 'H191', 43: 'H192', 44: 'H201', 45: 'H202', 46: 'H203', 47: 'H152', 48: 'HN1', 49: 'HN2'})
    assert("LSD"==resdict)
예제 #55
0
def test_atomsel_selection(file_3nob):

    m = molecule.load("mae", file_3nob)

    with pytest.raises(ValueError):
        atomsel("resname NMA or isala")

    selection.add_macro(name="isala", selection="resname ALA")
    s1 = atomsel("resname NMA or isala")
    assert len(s1) == 46

    # TODO: Calling add_macro twice makes 2 entries???

    selection.add_macro(name="isala", selection="resname NMA")
    s1.update()
    assert len(s1) == 6

    selection.del_macro(name="isala")
    molecule.delete(m)
예제 #56
0
def test_patches():
    from vmd import atomsel, molecule
    from Dabble.param import CharmmMatcher

    molid = molecule.load("mae", dir+"phosphoserine.mae")
    g = CharmmMatcher([dir+"phosphoserine.str"])
    (name, patch, mdict) = g.get_patches(atomsel("resname SEP", molid=molid))
    assert(name == "SER")
    assert(patch == "PSEP")
    assert(mdict=={5: '-C', 16: 'N', 17: 'CA', 18: 'CB', 19: 'OG', 20: 'C', 21: 'O', 22: 'P', 23: 'O1P', 24: 'O2P', 25: 'OT', 26: 'HN', 27: 'HA', 28: 'HB1', 29: 'HB2', 30: '+N'})
예제 #57
0
def test_evaltcl(file_rho):
    from vmd import evaltcl, atomsel, molecule

    molid = int(evaltcl("mol new"))
    assert molecule.get_top() == molid
    assert evaltcl("mol addfile %s type mae waitfor all" % file_rho)
    assert "molecule%d" % molid in evaltcl("mol list")

    with pytest.raises(ValueError):
        evaltcl("atomsel all")

    assert evaltcl("set all_atoms [atomselect %s \" all \" frame %s]"
                   % (molid, 0))  == "atomselect0"
    assert set(evaltcl("$all_atoms get chain").split()) == \
           set(atomsel("all").chain)
    assert set(evaltcl("$all_atoms get name").split()) == \
           set(atomsel("all").name)

    with pytest.raises(ValueError):
        evaltcl("$all_atoms get invalid")
예제 #58
0
파일: charmm.py 프로젝트: drorlab/dabble
    def _write_unorderedindex_waters(self, residues, molid):
        """
        Renumbers and sorts the specified waters manually. This is much less
        efficient but is necessary in cases where atoms within a water molecule
        are not sequential in index, preventing quick renaming with VMD.
        Identify problem waters, then call this on them. It'll write its own
        psf_wat_* file with just those waters, minimizing inefficiency.

        Args:
            residues (list of int): Problem water molecules
            molid (int): VMD molecule ID to write
        Returns:
            (int) Number of waters written
        """
        temp = tempfile.mkstemp(suffix='_indexed.pdb', prefix='psf_wat_',
                                dir=self.tmp_dir)[1]
        fileh = open(temp, 'w')

        idx = 1
        for ridx, residue in enumerate(residues):
            res = atomsel('residue %d' % residue, molid=molid)

            for i in res.get('index'):
                a = atomsel('index %d' % i, molid) # pylint: disable=invalid-name
                entry = ('%-6s%5d %-5s%-4s%c%4d    %8.3f%8.3f%8.3f%6.2f%6.2f'
                         '     %-4s%2s\n' % ('ATOM', idx, a.get('name')[0],
                                             a.get('resname')[0],
                                             a.get('chain')[0],
                                             ridx+1,
                                             a.get('x')[0],
                                             a.get('y')[0],
                                             a.get('z')[0],
                                             0.0, 0.0, a.get('segname')[0],
                                             a.get('element')[0]))
                idx += 1
                fileh.write(entry)

        fileh.write('END\n')
        fileh.close()
        return idx
예제 #59
0
def test_multiligand_parameterizing(tmpdir):
    """
    Checks the parameterization of a system with multiple ligands
    """
    from vmd import atomsel, molecule
    from Dabble.param import CharmmWriter

    # Parameterize the multiple ligand system with charmm parameters
    p = str(tmpdir.mkdir("multiligand_parameterize"))
    molid = molecule.load("mae", os.path.join(dir, "test_multiligand_correct.mae"))
    w = CharmmWriter(tmp_dir=p, molid=molid, lipid_sel="lipid",
                     extra_topos=[os.path.join(dir, "alprenolol.rtf")])
    w.write(os.path.join(p, "test"))

    # Load the created file
    m2 = molecule.load("psf", os.path.join(p, "test.psf"))
    molecule.set_top(m2)

    # Check the system is intact
    assert(len(set(atomsel("protein").get("resid"))) == 282)
    assert(len(set(atomsel("resname ACE NMA").get("resid"))) == 4)
    assert(len(atomsel("water")) == 32106)
    assert(len(atomsel("lipid")) == 12194)

    # Check for the correct number of alprenolols
    assert(len(atomsel("resname ALP")) == 420)
    assert(set(atomsel("resname ALP").get("resid")) == set(range(1,11)))
예제 #60
0
def test_hmr_param(tmpdir):
    """
    Tests phosphorylations on Ser
    Also checks HMR
    """
    from Dabble.param import AmberWriter
    from vmd import atomsel, molecule

    # Build the system with HMR
    p = str(tmpdir.mkdir("hmr_param"))
    molid = molecule.load("mae", os.path.join(dir, "rho_test.mae"))
    w = AmberWriter(tmp_dir=p, molid=molid, hmr=True,
                    extra_topos=[], extra_params=[])
    w.write(os.path.join(p, "test"))

    # Load the built system for checking
    # Use psf so we can check HMR was done correctly
    m2 = molecule.load("psf", os.path.join(p, "test.psf"))
    m3 = molecule.load("parm7", os.path.join(p, "test.prmtop"))

    # Check the protein is there with correct capping groups
    assert len(atomsel("protein", m2)) == 299
    assert len(atomsel("protein", m3)) == 299
    assert len(set(atomsel("resname ACE NMA", m2).get("resid"))) == 2
    assert len(set(atomsel("resname ACE NMA", m3).get("resid"))) == 2

    # Check for 3 phosphoserines and no regular serines
    molecule.set_top(m2)
    assert atomsel("resname SER").get("name").count("P") == 3
    assert not atomsel("resname SER and not same residue as name P")

    # Check for one phosphothreonine
    assert len(set(atomsel("resname THR").get("resid"))) == 3
    assert len(atomsel("resname THR and name P")) == 1

    # Check HMR was done correctly
    minmasspre = min(atomsel("all", m2).get("mass"))
    minmasspost = min(atomsel("all", m3).get("mass"))
    assert abs(minmasspre - 1.008) < 0.0001
    assert abs(minmasspost - 1.008) > 0.0001