By Vikram K. Mulligan, Flatiron Institute (vmulligan@flatironinstitute.org). Documentation written 4 April 2014, and last updated on 26 May 2021.
For information on the sub-modules of the GeneralizedKIC framework, see:
GeneralizedKIC (short for Generalized Kinematic Closure) is a generalization of the existing kinematic closure machinery. The generalized version works with arbitrary backbones, and with loops that go through side-chains, ligands, etc. It has also been implemented with full RosettaScripts support, making it easy to incorporate into more complicated protocols. The RosettaScripts interface gives full control over the inner workings of the algorithm, making it quite a powerful and versatile tool.
Generalized KIC is useful for the following situations:
The above scenarios tend to be sub-problems of more complicated problems, particularly involving heavily cross-linked molecules for which one might wish to sample many conformations.
GeneralizedKIC takes as input a pose that contains a covalently-connected chain of residues (a "loop", where the loop need not be connected solely by conventional backbone connections) to which the algorithm will be applied. The chain of residues need not start out in a sensible conformation, nor need it consist of canonical alpha-amino acids.
GeneralizedKIC will return a pose in which the loop in question has been put in a new, closed conformation (subject to user-specified sampling methods). Only the loop residues (and any "tail" residues specified) will be moved by this mover; all other residues will remain in their starting positions. The FoldTree is disregarded by the GeneralizedKIC mover, and will not be altered by it. (Note: if a pre-selection mover is defined as described in the GeneralizedKIC selector documentation, this mover can alter geometry outside of the loop to be closed, or could alter the FoldTree.)
If no closed solution could be found, GeneralizedKIC will return the original input pose. If a ContingentFilter has been supplied, its value will be set to "false" in this case (and "true" otherwise). By default, GeneralizedKIC will set the mover status to failure if no solution is found, but the user can override this with dont_fail_if_no_solution_found=true.
In general, one must:
These steps are discussed in detail in the next section.
Build or import a structure. GeneralizedKIC cannot add residues or geometry. If one wants to build a new loop, for example, one must add the new loop residues before calling GeneralizedKIC. (In RosettaScripts, the PeptideStubMover is useful for building geometry from scratch or for adding residues to existing geometry.)
Ensure that covalent linkages have been declared. GeneralizedKIC will move atoms about to ensure ideal geometry, but cannot declare new chemical bonds. (In RosettaScripts, the DeclareBond mover lets Rosetta know that certain residues are covalently attached to one another.)
Set the GeneralizedKIC options (number of closure attempts, whether the algorithm should accept the first successful closure or choose from all successful closure attempts, etc.). In RosettaScripts, this is handled inside the block as follows:
<MOVERS>
...
<GeneralizedKIC name="&string" low_memory_mode="(false &bool)" closure_attempts="(100 &int)" stop_if_no_solution="(0 &int)" stop_when_n_solutions_found="(0 &int)" selector="&string" selector_scorefunction="&string" selector_kbt="(1.0 &Real)" contingent_filter="&string" dont_fail_if_no_solution_found="(false &bool)" correct_polymer_dependent_atoms="(false &bool)">
...
</GeneralizedKIC>
...
</MOVERS>
The low_memory_mode option can be used to limit the amount of information about each solution found that is stored, in order to reduce memory consumption. See the note below for more details about the advantages and risks of this non-default mode. The closure_attempts parameter sets the number of times the algorithm will try to close the loop. A setting of 0 means that it will keep trying indefinitely. The stop_when_n_solutions_found option allows the algorithm to stop after finding at least N successful solutions, or, if this is set to 0, to keep going until it has done as many attempts as specified by closure_attempts; in either case a solution is then chosen by the selector. (Note that, because a single attempt returns up to 16 closure solutions, the selector will be applied even if stop_when_n_solutions_found is set to 1, since more than one solution might have been found in the first successful attempt). The selector flag is mandatory, and specifies the way in which a solution is chosen from among the successful solutions. The selector_scorefunction flag allows a separate scorefunction to be used by those selectors that select based on energy or score; this is recommended since score terms based on side-chain packing may produce poor results, since the GeneralizedKIC algorithm does not call the packer. Some selectors also take a temperature value, set by the selector_kbt option. See the GeneralizedKIC selector documentation for more details.Define a series of residues for the GeneralizedKIC closure problem. This must be an unbranched chain of residues with continuous covalent linkages, listed in order from one end of the chain to the other. When the GeneralizedKIC::apply() function is called, a continuous chain of atoms running through the selected residues is automatically chosen. Residues are specified with AddResidue tags within a GeneralizedKIC block. Pivot points must also be indicated explicitly, using the SetPivots tag. Pivots are atoms in the chain of atoms to be closed that are flanked by bonds whose dihedral values will be solved for analytically by the closure algorithm in order to close the loop. Currently, due to hard-coded assumptions in the kinematic closure numerical library, the first pivot must be the second atom in the chain to be closed, and the last pivot must be the second-to-last atom in the chain to be closed. This restriction will be eliminated in a future version of GeneralizedKIC.
Optionally, additional "tail" residues can also be listed. These are residues that are either connected directly to the loop to be closed, or connected indirectly to this loop through other tail residues, and which move with the loop to be closed. The AddTailResidue tag can be used to specify these. Order is not important for the AddTailResidue flag.
<MOVERS>
...
<GeneralizedKIC ...>
<AddResidue res_index="(&int)" />
<AddResidue res_index="(&int)" />
<AddResidue res_index="(&int)" />
...
<AddTailResidue res_index="(&int)" />
<AddTailResidue res_index="(&int)" />
<AddTailResidue res_index="(&int)" />
...
<SetPivots res1="(&int)" atom1="&string" res2="(&int)" atom2="&string" res3="(&int)" atom3="&string" />
...
</GeneralizedKIC>
...
</MOVERS>
For example, if one were closing a loop consisting of residues ALA44, CYS45, LYS46, CYS47, CYS23, ASP22, and PHE21, where CYS47 and CYS23 were linked by a disulfide bond, and where CYS45 were linked to CYS12 by another disulfide such that CYS12 was expected to move with CYS45, one would write:
<MOVERS>
...
<GeneralizedKIC ...>
<AddResidue res_index="4" />
<AddResidue res_index="45" />
<AddResidue res_index="46" />
<AddResidue res_index="47" />
<AddResidue res_index="23" />
<AddResidue res_index="22" />
<AddResidue res_index="21" />
<AddTailResidue res_index="12" />
<SetPivots res1="4" atom1="CA" res2="23" atom2="SG" res3="21" atom3="CA" />
...
</GeneralizedKIC>
...
</MOVERS>
From the above example, we can see that loop segments may run backwards or forwards, or may involve residues that are far apart in linear sequence provided they are covalently linked. Note that while the sequence of residues matter, the overall direction of the loop does not: we could just as happily have added residues in the reverse order (21->22->23->47->46->45->44). In this example, we have arbitrarily chosen CYS23's SG atom as the middle pivot point, though any atom in the chain that is flanked by bonds that can rotate freely could have been chosen.Define one or more GeneralizedKIC perturbers. Each perturber samples conformation space for each closure attempt. See GeneralizedKIC perturbers for details.
Define one or more GeneralizedKIC filters. Filters are applied after each closure attempt, and eliminate solutions that don't meet some criterion. See GeneralizedKIC filters for details.
Set the GeneralizedKICselector. The selector chooses a single solution from the set of solutions found that pass all of the filters. See the documentation on GeneralizedKIC selectors for details, including details on the optional pre-selection mover (a mover applied to all solutions passing filters prior to application of the selector).
That's it! You should be happily closing loops, now.
The kinematic closure algorithm is described in detail in Coutsias et al. (2004). J. Comput. Chem. 25(4):510-28. and in Mandell et al. (2009). Nat. Methods. 6(8)551-2.. Briefly, given a rigid-body transform describing the position and orientation of the residue immediately following a loop relative to a residue immediately preceding a loop, a loop with N degrees of freedom now has N-6 effective degrees of freedom, the remaining 6 degrees of freedom being determined by the condition that the loop be closed. This means that all but 6 degrees of freedom of the loop (e.g. all but 6 chain dihedral angles) may be sampled, perturbed, or set as one sees fit, and the remaining 6 degrees of freedom may be solved for analytically to impose the closure condition. The GeneralizedKIC algorithm does just this, allowing the user to sample all but 6 degrees of freedom of the loop, then solve analytically for the remainining 6 (the dihedral angles flanking 3 pivot atoms) to ensure that the loop is closed. For any given set of values for the other N-6 degrees of freedom, there may be anywhere from 0 to 16 solutions to the system of equations solved by the kinematic closure algorithm.
By default, all solutions found by GenKIC are stored as full poses until one is selected by the selector. Unfortunately, this means that if instructed to store many solutions, GenKIC can exhaust available memory. As of 13 March 2016, a low-memory mode has been added ("low_memory_mode=true"). In this mode, only loop degree-of-freedom values are stored prior to selection. The drawback, however, is it can be risk to use low-memory mode with a preselection mover. Any changes to the pose made by the preselection mover will not be stored, so the preselection mover will have to be re-applied to the selected pose after selection. This costs additional time. In addition, if the preselection mover has any stochastic component to its behaviour, then the second application may not produce identical results to the first. This means that what might have been the lowest-energy pose when the preselection mover was first applied could now be a relatively high-energy pose, for example. For this reason, be judicious in the use of low-memory mode. The preferred course is to stop GenKIC when N solutions have been found to limit memory usage.
This example creates a 10-residue cyclic peptide with a disulfide bond between the N- and C-termini. It then defines a loop starting at residue 3, going backwards to residue 1, through the disulfide to residue 10, and back to residue 5. This loop is closed by kinematic closure, with loop conformations sampled. A bump check filter is applied (AddFilter type="loop_bump_check"), and a solution chosen randomly (selector="random_selector") from the solutions found.
<ROSETTASCRIPTS>
<TASKOPERATIONS>
</TASKOPERATIONS>
<SCOREFXNS>
<ScoreFunction name="tala" weights="talaris2013" symmetric="0" />
</SCOREFXNS>
<FILTERS>
</FILTERS>
<MOVERS>
<PeptideStubMover name="pep_stub" reset="1">
<Append resname="CYD" />
<Append resname="ALA" />
<Append resname="ALA" />
<Append resname="ALA" />
<Append resname="ALA" />
<Append resname="ALA" />
<Append resname="ALA" />
<Append resname="ALA" />
<Append resname="ALA" />
<Append resname="CYD" />
</PeptideStubMover>
<SetTorsion name="tor1">
<Torsion residue="ALL" torsion_name="phi" angle="-64.7"/>
<Torsion residue="ALL" torsion_name="psi" angle="-41.0"/>
<Torsion residue="ALL" torsion_name="omega" angle="180"/>
</SetTorsion>
<SetTorsion name="tor2">
<Torsion residue="pick_atoms" angle="random">
<Atom1 residue="1" atom="N"/>
<Atom2 residue="1" atom="CA"/>
<Atom3 residue="1" atom="CB"/>
<Atom4 residue="1" atom="SG"/>
</Torsion>
<Torsion residue="pick_atoms" angle="random">
<Atom1 residue="10" atom="N"/>
<Atom2 residue="10" atom="CA"/>
<Atom3 residue="10" atom="CB"/>
<Atom4 residue="10" atom="SG"/>
</Torsion>
</SetTorsion>
<DeclareBond name="bond" res1="1" atom1="SG" res2="10" atom2="SG"/>
<GeneralizedKIC name="genkic" closure_attempts="200" stop_when_n_solutions_found="0" selector="random_selector">
<AddResidue res_index="3" />
<AddResidue res_index="2" />
<AddResidue res_index="1" />
<AddResidue res_index="10" />
<AddResidue res_index="9" />
<AddResidue res_index="8" />
<AddResidue res_index="7" />
<AddResidue res_index="6" />
<AddResidue res_index="5" />
<SetPivots res1="3" atom1="CA" res2="1" atom2="SG" res3="5" atom3="CA" />
<CloseBond prioratom_res="10" prioratom="CB" res1="10" atom1="SG" res2="1" atom2="SG" followingatom_res="1" followingatom="CB" bondlength="2.05" angle1="103" angle2="103" randomize_flanking_torsions="true" />
<AddPerturber effect="randomize_alpha_backbone_by_rama">
<AddResidue index="3" />
<AddResidue index="2" />
<AddResidue index="1" />
<AddResidue index="10" />
<AddResidue index="9" />
<AddResidue index="8" />
<AddResidue index="7" />
<AddResidue index="6" />
<AddResidue index="5" />
</AddPerturber>
<AddFilter type="loop_bump_check" />
</GeneralizedKIC>
</MOVERS>
<APPLY_TO_POSE>
</APPLY_TO_POSE>
<PROTOCOLS>
<Add mover="pep_stub"/>
<Add mover="tor1"/>
<Add mover="tor2"/>
<Add mover="bond"/>
<Add mover="genkic"/>
</PROTOCOLS>
</ROSETTASCRIPTS>
GeneralizedKIC cannot handle the following cases:
Autogenerated Tag Syntax Documentation:
The GeneralizedKIC mover allows a user to define a chain of atoms whose conformation is to be sampled or altered subject to the constraint that it remain closed, or that it be closed if it starts out open. The mover has myriad options for controlling sampling and selection of a solution, and can invoke other movers to apply to each closed solution that it finds. It has been written to be fully general, and can operate on chains of atoms that pass through backbones, side-chains, ligands, etc. No assumptions about alpha-amino acid backbones are hard-coded, so GeneralizedKIC should be fully compatible with any non-canonical entity.
References and author information for the GeneralizedKIC mover:
GeneralizedKIC Mover's citation(s): *Bhardwaj G, *Mulligan VK, *Bahl G, Gilmore JM, Harvey PJ, Cheneval O, Buchko GW, Pulavarti SVSRK, Kaas Q, Eletsky A, Huang P-S, Johnsen PS, Greisen P Jr., Rocklin GJ, Song Y, Linsky TW, Watkins A, Rettie SA, Xu X, Carter LP, Bonneau R, Olson JM, Coutsias E, Correnti CE, Szyperski T, Craik DJ, and Baker D. (2016). Accurate de novo design of hyperstable constrained peptides. Nature 538(7625):329-35. doi: 10.1038/nature19791. (*Co-primary authors.)
<GeneralizedKIC name="(&string;)" low_memory_mode="(&bool;)"
correct_polymer_dependent_atoms="(&bool;)"
dont_fail_if_no_solution_found="(&bool;)"
selector="(&genkic_selector_name;)" selector_scorefunction="(&string;)"
selector_kbt="(ℜ)" stop_if_no_solution="(0 &non_negative_integer;)"
closure_attempts="(&non_negative_integer;)"
stop_when_n_solutions_found="(&non_negative_integer;)"
pre_selection_mover="(&string;)" contingent_filter="(&string;)" >
<AddResidue res_index="(&non_negative_integer;)" />
<AddTailResidue res_index="(&non_negative_integer;)" />
<SetPivots res1="(&non_negative_integer;)" atom1="(&string;)"
res2="(&non_negative_integer;)" atom2="(&string;)"
res3="(&non_negative_integer;)" atom3="(&string;)" />
<SampleCisPeptideBond cis_prob="(0.1 ℜ)" >
<AddResidue index="(&non_negative_integer;)" />
</SampleCisPeptideBond>
<CloseBond res1="(&non_negative_integer;)" atom1="(&string;)"
res2="(&non_negative_integer;)" atom2="(&string;)" bondlength="(ℜ)"
angle1="(ℜ)" angle2="(ℜ)"
randomize_flanking_torsions="(&bool;)"
prioratom_res="(&non_negative_integer;)" prioratom="(&string;)"
followingatom_res="(&non_negative_integer;)" followingatom="(&string;)"
torsion="(ℜ)" />
<AddPerturber effect="(&genkic_perturber_name;)"
bin_params_file="(ABBA &string;)"
iterations="(1 &non_negative_integer;)"
must_switch_bins="(false &bool;)" bin="(&string;)"
custom_rama_table="(&string;)" >
<AddResidue index="(&non_negative_integer;)" />
<AddAtoms res1="(&non_negative_integer;)" atom1="(&string;)"
res2="(&non_negative_integer;)" atom2="(&string;)"
res3="(&non_negative_integer;)" atom3="(&string;)"
res4="(&non_negative_integer;)" atom4="(&string;)" />
<AddValue value="(ℜ)" />
</AddPerturber>
<AddFilter type="(&genkic_filter_name;)" residue="(&non_negative_integer;)"
bin_params_file="(ABBA &string;)" bin="(&string;)"
rama_cutoff_energy="(0.3 ℜ)" >
<AddFilterParameterReal name="(&string;)" value="(ℜ)" />
<AddFilterParameterInteger name="(&string;)" value="(&non_negative_integer;)" />
<AddFilterParameterBoolean name="(&string;)" value="(&bool;)" />
<AddFilterParameterString name="(&string;)" value="(&string;)" />
</AddFilter>
<AddAtomPairDistanceFilter res1="(&non_negative_integer;)" atom1="(&string;)"
res2="(&non_negative_integer;)" atom2="(&string;)" distance="(ℜ)"
greater_than="(&bool;)" />
</GeneralizedKIC>
Subtag AddResidue: "AddResidue" sub-tags are used to specify the residues that make up the chain of atoms to be closed, in order of connectivity.
Subtag AddTailResidue: Loops to be closed might have other chains of residues attached to them. By default, GeneralizedKIC fails to respect covalent bonds to any but the end residues in the chain to be closed, and can tear these bonds apart as residues move. Users can optionally specify a list of "tail" residues that are covalently attached to, and move with, the chain of residues to be closed. For example, one might have a series of glycans attached to a serine residue in a protein loop that's being closed with GenKIC. If these residues are specified as tail residues, then they will remain attached to the serine residue even as the loop that contains the serine residue moves.
Subtag SetPivots: Pivots are atoms in the chain of atoms to be closed that are flanked by bonds whose dihedral values will be solved for analytically by the closure algorithm in order to close the loop. Currently, due to hard-coded assumptions in the kinematic closure numerical library, the first pivot must be the second atom in the chain to be closed, and the last pivot must be the second-to-last atom in the chain to be closed.
Subtag SampleCisPeptideBond: A "SampleCisPeptideBond" sub-tag is a shorthand for adding a sample_cis_peptide_bond GeneralizedKICperturber. It tells the GeneralizedKIC mover to sample a cis-peptide bond at a particular residue some subset of the time.
Subtag AddResidue: "AddResidue" sub-sub-tags are used within a "SampleCisPeptideBond" sub-tag to list all of the residues at which cis-peptide bonds should be sampled.
Subtag CloseBond: A "CloseBond" sub-tag is a shorthand for set_bondangle and set_bondlength GeneralizedKICperturbers, as well as an optional pair of randomize_dihedral perturbers for the flanking dihedral angles, and an optional set_torsion perturber. It is intended to be used to set the ideal geometry for an open bond in a loop that GeneralizedKIC should close.
Subtag AddPerturber: The "AddPerturber" sub-tag is used to add and configure GeneralizedKICperturbers. GeneralizedKICperturbers alter the chain to be closed in some way prior to kinematic closure, allowing definition of a desired conformation or conformational sampling. They can only act on the chain to be closed, and have no effect on tail residues or on any other part of the input structure. Perturbers are applied in the order that they are defined. Different perturbers may alter the same degrees of freedom, sequentially.
Subtag AddResidue: The "AddResidue" sub-sub-tag in an "AddPerturber" sub-tag permits a residue to be defined on which the perturber may act. Use multiple "AddResidue" tags to define more than one residue.
Subtag AddAtoms: The "AddAtoms" sub-sub-tag in an "AddPerturber" sub-tag permits one or more atoms to be defined, on which the perturber may act. A particular type of perturber may take a list of one, two, three, or four atoms, depending on what it acts on.
Subtag AddValue: The "AddValue" sub-sub-tag in an "AddPerturber" sub-tag permits a value to be set for those perturbers that take a value. (An example of this is the "set_dihedral" perturber, which takes a value for the dihedral angle to set.) Use multiple "AddValue" tags to specify more than one value.
Subtag AddFilter: An "AddFilter" sub-tag adds a GeneralizedKICfilter, which discards solutions that do not pass certain criteria. Generally, GeneralizedKICfilters are written to be considerably faster than conventional Rosetta filters, since they usually do not act on full poses. They are applied before pre-selection movers.
Subtag AddFilterParameterReal: An "AddFilterParameterReal" sub-sub-tag in an "AddFilter" tag sets a real-valued setting for a filter. For example, the "atom_pair_distance" filter takes a real-valued parameter, called "distance", for the cutoff separation between two atoms used to discard solutions.
Subtag AddFilterParameterInteger: An "AddFilterParameterInteger" sub-sub-tag in an "AddFilter" tag sets an integer setting for a filter. For example, the "atom_pair_distance" filter takes two integer parameters, called "res1" and "res2", for the indices of the two residues containing the two atoms whose separation is to be measured.
Subtag AddFilterParameterBoolean: An "AddFilterParameterBoolean" sub-sub-tag in an "AddFilter" tag sets a Boolean setting for a filter. For example, the "atom_pair_distance" filter has a Boolean parameter called "greater_than" which, when set to "true" selects for interatomic separation greater than a cutoff rather than less than the cutoff.
Subtag AddFilterParameterString: An "AddFilterParameterString" sub-sub-tag in an "AddFilter" tag sets a string setting for a filter. For example, the "atom_pair_distance" filter takes two string parameters, called "atom1" and "atom2", for the names of the two atoms whose separation is to be measured.
Subtag AddAtomPairDistanceFilter: The "AddAtomPairDistanceFilter" sub-tag is a shorthand for adding an "atom_pair_distance" GeneralizedKICFilter. It discards solutions if pairs of atoms are separated by more than a cutoff distance.