You are here

constrain 2 proteins in protein-protein docking

2 posts / 0 new
Last post
constrain 2 proteins in protein-protein docking
#1

We want to dock 2 proteins (red and green) to see how they dimerize. Each crystal structure has 2 parts that are not connected to one another  (The receptor at the top and the SKP part below do not have any linkers to make the 2 parts become one chain) They just interact with some electrostatic interactions. This makes the receptor and SKP apart from each other for all docking outputs. From the literature review, we could not reject the SKP part on docking because it has some effect on receptor conformation.  How can we constrain this docking problem, since we know some of the interacting residues? 

PS. I have tried to get the receptor and SKP on the same chain but the structure was broken. I have also tried to specify the relative chain partners as "AC_BD" (set both SKP parts to be rigid, and receptors to be flexible), but it did not work. 

Category: 
Post Situation: 
Wed, 2020-08-12 08:38
PatC

Why specifically did "AC_BD" fail? Is everything on the same segment (`segi` in PyMOL)?

Constraints for Rosetta are documented here: https://www.rosettacommons.org/docs/latest/rosetta_basics/file_types/constraint-file

They are technically "restraints" not constraints as they are penalties as opposed to keeping things absolutely fixed. If you want something fixed in an AMBER style "constraint", you need to play with movemaps or packers.

For pyrosetta there are three ways to specify constraints:

From file

setup = pyrosetta.rosetta.protocols.constraint_movers.ConstraintSetMover()
setup.constraint_file(constraint_file)
setup.apply(pose)

From a set of constraints.

# constraints require atomID, which are a bit clunky to select so here's a function to select them.
def get_AtomID(chain:str, resi:int, atomname:str) -> pyrosetta.rosetta.core.id.AtomID:
    r = pose.pdb_info().pdb2pose(res=resi, chain=chain)
    assert r != 0, f'{resi}:{chain} is absent'
    residue = pose.residue(r)
    return pyrosetta.rosetta.core.id.AtomID(atomno_in=residue.atom_index(atomname), rsd_in=r)


HarmonicFunc = pyrosetta.rosetta.core.scoring.func.HarmonicFunc
# see pyrosetta.rosetta.core.scoring.func for the others!

# first lets make a list...
cons = []

# Specify the atoms you want...
cons.append( pyrosetta.rosetta.core.scoring.constraints.AtomPairConstraint(get_AtomID('A', 1901, 'O'),
                                                                    get_AtomID('A', 2201, 'N6'),
                                                                    HarmonicFunc(x0_in=3.1, sd_in=0.2))

cons.append( ...
...

# lets make the list into a vector
cl = pyrosetta.rosetta.utility.vector1_std_shared_ptr_const_core_scoring_constraints_Constraint_t()
cl.extend(cons)

# lets make the vector into a constraint set
cs = pyrosetta.rosetta.core.scoring.constraints.ConstraintSet()
cs.add_constraints(cl)


setup = pyrosetta.rosetta.protocols.constraint_movers.ConstraintSetMover()
setup.constraint_set(cs)
setup.apply(pose)

From a generator and a residue selector

resi_A = pyrosetta.rosetta.core.select.residue_selector.ResidueIndexSelector()
resi_A.set_index(str(posi_A))

resi_B = pyrosetta.rosetta.core.select.residue_selector.ResidueIndexSelector()
resi_B.set_index(str(posi_B))

# see https://www.rosettacommons.org/docs/latest/scripting_documentation/RosettaScripts/Movers/movers_pages/constraint_generators/AtomPairConstraintGenerator
# the residue selector can have multiple residues making a web of constraints!
constraint = pyrosetta.rosetta.protocols.constraint_generator.AtomPairConstraintGenerator()
constraint.set_residue_selector(resi_A)
constraint.set_secondary_selector(resi_B) #optional, see docs
constraint.set_ca_only(True)
constraint.set_use_harmonic_function(True)
constraint.set_max_distance(2.0)
constraint.set_sd(0.5)

add_csts = pyrosetta.rosetta.protocols.constraint_generator.AddConstraints()
add_csts.add_generator(constraint)
add_csts.apply(pose)

Add weights

A constraint is added to a pose, but the weight of a constraint is in a scorefunction. This is true for the binaries and scripts, where the weight has to be specified.

scorefxn = pyrosetta.create_score_function(name) # name = ref2015 etc.
# alternatively: scorefxn = pyrosetta.get_fa_scorefxn()
stm = pyrosetta.rosetta.core.scoring.ScoreTypeManager()
scorefxn.set_weight(stm.score_type_from_name("atom_pair_constraint"), 10)
       

Centroid

One thing to note is that the scorefunction for the centroid mode also needs the weights, but the centroid residues have a beta carbon only as a sidechain. So changes may be required. Docking protocols go through a centroid mode.

Sat, 2020-08-15 08:17
matteoferla