{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "Before you turn this problem in, make sure everything runs as expected. First, **restart the kernel** (in the menubar, select Kernel$\\rightarrow$Restart) and then **run all cells** (in the menubar, select Cell$\\rightarrow$Run All).\n", "\n", "Make sure you fill in any place that says `YOUR CODE HERE` or \"YOUR ANSWER HERE\", as well as your name and collaborators below:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "NAME = \"\"\n", "COLLABORATORS = \"\"" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "---" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "*This notebook contains material from [PyRosetta](https://RosettaCommons.github.io/PyRosetta.notebooks);\n", "content is available [on Github](https://github.com/RosettaCommons/PyRosetta.notebooks.git).*" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "< [`GALigandDock` Protocol with `pyrosetta.distributed` Using the `beta_cart.wts` Scorefunction](http://nbviewer.jupyter.org/github/RosettaCommons/PyRosetta.notebooks/blob/master/notebooks/08.02-Ligand-Docking-pyrosetta.distributed.ipynb) | [Contents](toc.ipynb) | [Index](index.ipynb) | [Working With Density](http://nbviewer.jupyter.org/github/RosettaCommons/PyRosetta.notebooks/blob/master/notebooks/11.00-Working-With-Density.ipynb) >

\"Open" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Working With Symmetry\n", "Keywords: symmetry, asymmetric, SetupForSymmetryMover, virtual\n", "\n", "## Overview\n", "Symmetry is an important concept to learn when working with biomolecules. When a protein is crystalized, it is in the precense of its symmetrical neighbors - which can be important if testing particular protocols or using crystal density for refinement or full structure building.\n", "\n", "Symmetry can also be useful for designing symmetrical structures or large repeating meta-proteins like protein cages. \n", "\n", "### Symmetry In Rosetta\n", "So why do we care if our protein is symmetrical or not when it comes to Rosetta? Each residue and atom that is loaded into Rosetta takes time to both load, and time to score. Since scoring can happen thousands of times - even in a short protocol, anything we can do to speed this up becomes important. The most expensive operation in Rosetta is minimization, and by using symmetry - we can reduce the minimization time exponentially by minimizing a single copy instead of ALL copies. We will get into the details about how this works below.\n", "\n", "When we use symmetry in Rosetta - we are basically telling rosetta that the symmetrical partners are 'special', however, the total number of residues is now ALL residues, including symmetrical partners. Upon setting up symmety in Rosetta, Rosetta will replace the `Conformation` within the pose with a **Symmetrical** version, called the `SymmetricConformation`. If you know anything about classes, this `SymmetricConformation` is derived from the actual `Conformation` object, but contains extra information about the pose and some functions are replaced. \n", "\n", "### Symmetric Scoring and Moving\n", "Ok, so now lets assume that we have our symmetric pose. Now what? Well, the symmetric copies are all tied to their real counterparts. Once you move a chain, residue, or atom by packing or minimization, the symmetric copies of that residue are all moved in the same way. \n", "\n", "Cool. But what about scoring? Scoring works very similarly - instead of scoring each and every residue in our pose, Rosetta will score just our assymetric unit, and multiply that out to the number of symmetric copies we have. Intelligently, Rosetta will also figure out the symmetric interfaces that arise from the interactions of our assymetric unit to the symmetric copies and score them appropriately.\n", "\n", "### Symmetry-aware movers\n", "Most of our common movers are symmetry-aware. At one point there were different symmetric and non-symmetric versions of particular code, such as MinMover and PackRotamersMover. Now though, Rosetta will automatically use the pose to figure out what needs to be done. You should seek original documentation (and contact the author if not explicit) to make sure that an uncommon protocol you are using is symmetry-aware.\n", "\n", "## Documentation\n", "More information on RosettaSymmetry can be found in the following places:\n", "- https://www.rosettacommons.org/docs/latest/rosetta_basics/structural_concepts/symmetry\n", "- https://www.rosettacommons.org/demos/latest/tutorials/Symmetry/Symmetry\n", "- https://www.rosettacommons.org/docs/latest/application_documentation/utilities/make-symmdef-file\n", "- https://www.rosettacommons.org/docs/latest/scripting_documentation/RosettaScripts/Movers/movers_pages/SetupForSymmetryMover\n", "- https://www.rosettacommons.org/docs/latest/scripting_documentation/RosettaScripts/Movers/movers_pages/ExtractAsymmetricUnitMover\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Notebook setup\n", "import sys\n", "if 'google.colab' in sys.modules:\n", " !pip install pyrosettacolabsetup\n", " import pyrosettacolabsetup\n", " pyrosettacolabsetup.setup()\n", " print (\"Notebook is set for PyRosetta use in Colab. Have fun!\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Here, we will use a few specific options. The first three options make Rosetta a bit more robust to input structures. The `-load_PDB_components` cannot be used with glycans, unfortunately, and our structure has a few very important glycans. Finally, we load a bunch of glycan-specific options, which we will cover in the next tutorial." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from pyrosetta import *\n", "from pyrosetta.rosetta import *\n", "from pyrosetta.teaching import *\n", "import os\n", "\n", "init('-ignore_unrecognized_res -load_PDB_components false -ignore_zero_occupancy false @inputs/glycan_flags')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Creating a SymDef file\n", "\n", "Here, we will start with how to create a basic symdef file for cyrstal symmetry. Note that there are ways to do this without a symdef file, but these do not currently work for glycan structures, which we will be using here. \n", "\n", "The `make_symdef_file.pl` file is within Rosetta3. To use it, you will need to download and licence Rosetta3. The code is in the `Rosetta/main/src/apps/public` directory. In the interest of reducing code drift, this file is NOT included in the tutorial directory as we may then have version drift. \n", "\n", "If you have done this, we can use the following command to create the symdef file. Here, the radius of symmetrical partners is 12A, which is certainly fairly large, but produces a very well represented crystal." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "pdb = \"inputs/1jnd.pdb\"\n", "base_cmd = f'cd inputs && make_symmdef_file.pl -r 12 -m CRYST -p {pdb}.pdb > {pdb}_crys.symm && cd -'\n", "print(base_cmd)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Use this base command and the `os.system(cmd)` function to run the code or use the provided symdef file. " ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "os.system('cp inputs/1jnd_crys.symm .')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Take a look at the symmetrized structure in pymol (`inputs/1jnd_symm.pdb`). What would happen if we increased the radius to 24 instead of 12?" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Setup a Symmetrized Pose\n", "\n", "Here, we will run a basic Rosetta protocol with symmetry. There are much more complicated things you can do with symmetry, but for now, we just want to symmetrically pack the protein. Please see the docs for more on symmetry. The full Rosetta C++ tutorial for symmetry is a great place to go from here: - https://www.rosettacommons.org/demos/latest/tutorials/Symmetry/Symmetry \n", "\n", "Lets first create a pose, and then use the `SetupForSymmetryMover` on the pose. Note this is an unrefined input structure. This is so that minmover will actually do something. A pareto-optimal refined structure can be found in the inputs as `1jnd_refined.pdb.gz`" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "p = pose_from_pdb('inputs/1jnd.pdb')\n", "original = p.clone()" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "p.total_residue()" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "type(p.conformation())" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "symmetrize = rosetta.protocols.symmetry.SetupForSymmetryMover(\"1jnd_crys.symm\")\n", "symmetrize.apply(p)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "print(p.total_residue())\n", "print(type(p.conformation()))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "How many symmetric copies do we have in our pose?\n", "How do the scores compare for our original pose and our symmetrized version?" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now lets use some of the functionality to understand how this all works. We can use the `SymetricInfo` object that is part of the `SymmetricConformation` to get at some info. Lets take a look at all residues and find the assymetric unit residues and equivalent residues for the rest." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "print(\"AssymUnit? equivalent_res\")\n", "sym_info = p.conformation().Symmetry_Info()\n", "for i in range(1, p.size()+1):\n", " print(i, sym_info.bb_is_independent(i), sym_info.bb_follows(i))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Which residues are our original pose residues? Note that the final residues are called `Virtual` residues. Virtual residues are not scored. They have coordinates, and can move, but simply result in a score of zero. They are useful in some contexts to hide a part of the pose from the scoring machinery, and there are movers that can change residues to and from virtual. In this case, they are used for the FoldTree - in order to allow refinement of the full crystal environment. They allow relative movement of each subunit relative to each other. There are two virtual residues for each subunit" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "print(p.residue(3654))" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "print(\"Total Subunits:\", (3654-18)/404)\n", "print(\"Total Subunits:\", sym_info.subunits())" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "score = get_score_function()\n", "print(score(original))\n", "print(score(p))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Running Protocols with Symmetry\n", "\n", "Now, lets try running a minimization with symmetry on. " ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "mm = MoveMap()\n", "mm.set_bb(True)\n", "mm.set_chi(True)\n", "minmover = rosetta.protocols.minimization_packing.MinMover()\n", "minmover.score_function(score)\n", "minmover.set_movemap(mm)\n", "minmover.apply(p)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "score(p)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "How does our pose look? For being such a large pose, how was the speed of minimization? \n", "\n", "How does this compare to our refined pose? Try to copy a subunit to a new object in PyMol. Then use the align command to align it to our assymetric unit. What is the RMSD?" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now lets pack with our symmetric structure. " ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from rosetta.core.pack.task import *\n", "from rosetta.core.pack.task.operation import *\n", "\n", "packer = PackRotamersMover()\n", "tf = rosetta.core.pack.task.TaskFactory()\n", "\n", "tf.push_back(RestrictToRepacking())\n", "tf.push_back(IncludeCurrent())\n", "packer.task_factory(tf)\n", "\n", "p = original.clone()\n", "symmetrize.apply(p)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "packer.apply(p)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "print(\"packed\", score(p))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Conclusions\n", "\n", "Symmetry is a useful tool in the Rosetta Library. There are also selectors and movers that you may find useful, such as the `AsymmetricUnitSelector` in `rosetta.core.select.residue_selectors` and the `ExtractAsymmetricUnitMover`, which will give you back just the single subunit, without any asymetric partners, and the `ExtractAsymmetricPoseMover`, which will remove 'symmetry' information and give you back a pose with all the subunits. The later of these can be found by importing `rosetta.protocols.symmetry`.\n", "\n", "Note that not ALL protocols will respect symmetry - so please check the original documentation to see if symmetry is supported. If you are unsure, please email the developer." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Chapter contributors:**\n", "\n", "- Jared Adolf-Bryfogle (Scripps; Institute for Protein Innovation)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "< [`GALigandDock` Protocol with `pyrosetta.distributed` Using the `beta_cart.wts` Scorefunction](http://nbviewer.jupyter.org/github/RosettaCommons/PyRosetta.notebooks/blob/master/notebooks/08.02-Ligand-Docking-pyrosetta.distributed.ipynb) | [Contents](toc.ipynb) | [Index](index.ipynb) | [Working With Density](http://nbviewer.jupyter.org/github/RosettaCommons/PyRosetta.notebooks/blob/master/notebooks/11.00-Working-With-Density.ipynb) >

\"Open" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.6.0" }, "toc": { "base_numbering": 1, "nav_menu": {}, "number_sections": true, "sideBar": true, "skip_h1_title": false, "title_cell": "Table of Contents", "title_sidebar": "Contents", "toc_cell": false, "toc_position": {}, "toc_section_display": true, "toc_window_display": false } }, "nbformat": 4, "nbformat_minor": 1 }