{ "cells": [ { "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", "< [RosettaCarbohydrates: Modeling and Design](http://nbviewer.jupyter.org/github/RosettaCommons/PyRosetta.notebooks/blob/master/notebooks/13.02-Glycan-Modeling-and-Design.ipynb) | [Contents](toc.ipynb) | [Index](index.ipynb) | [Modeling Membrane Proteins](http://nbviewer.jupyter.org/github/RosettaCommons/PyRosetta.notebooks/blob/master/notebooks/15.00-Modeling-Membrane-Proteins.ipynb) >

\"Open" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# RNA in PyRosetta\n", "Keywords: classify_base_pairs, RNA torsions, RNA score terms, RNA motifs, mutate_position, RNA thread, RNA minimize, RNA_HelixAssembler, RNA fragment assembly, FARFAR protocol, rna_denovo" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## References" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "1. R. Das et al., \"Atomic accuracy in predicting and designing noncanonical RNA structure,\" Nature Methods 7:4, 291-294 (2010).\n", "\n", "\n", "2. A. Watkins et al., \"Blind prediction of noncanonical RNA structure at atomic accuracy,\" Science Advances 4:5 (2018).\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Introduction" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In this lab, we will explore common tasks and approaches for working with RNA using Rosetta. We will be focusing on a simple system that includes a helix capped by a tetraloop for this exercise." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "!pip install pyrosettacolabsetup\n", "import pyrosettacolabsetup; pyrosettacolabsetup.install_pyrosetta()\n", "import pyrosetta; pyrosetta.init()\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from pyrosetta import *\n", "init()" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from pyrosetta.rosetta import *\n", "from pyrosetta.rosetta.core.pose.rna import *\n", "from pyrosetta.rosetta.core.pose import *" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Exploring geometry for RNA ##" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Let's load in this structure with PyRosetta (make sure that you have the PDB file located in your current directory):\n", "\n", "`cd google_drive/MyDrive/student-notebooks/\n", "pose = pose_from_pdb(\"inputs/stem_loop.pdb\")`" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "deletable": false, "nbgrader": { "cell_type": "code", "checksum": "ade0467986e24449fd68226324dcf1c1", "grade": true, "grade_id": "cell-690a147764ad96d7", "locked": false, "points": 0, "schema_version": 3, "solution": true } }, "outputs": [], "source": [ "YOUR-CODE-HERE" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Let's explore the structure in this PDB file. First, use `pose.sequence()` to look at the sequence:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "deletable": false, "nbgrader": { "cell_type": "code", "checksum": "62406b4883cbd9a50eff78f646befd63", "grade": true, "grade_id": "cell-61e3c7efb8ae6b94", "locked": false, "points": 0, "schema_version": 3, "solution": true } }, "outputs": [], "source": [ "# print out the sequence of the pose\n", "YOUR-CODE-HERE" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can see that the pose seems to contain RNA residues. To check this, let's go through the pose residue by residue, checking if each one is RNA." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "for ii in range(pose.size()):\n", " print(pose.residue_type(5).is_RNA())" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "RNA bases interact with each other via **base pairing**, either through the Watson-Crick base pairs that make up standard A-form helices or through non-canonical base pairing interactions. We can use the `classify_base_pairs` function (this lives in `core:pose:rna` which was loaded above) to find and classify all the base pairs in the current pose. Let's take a look." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "base_pairs = classify_base_pairs(pose)\n", "for base_pair in base_pairs:\n", " print(base_pair)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can see that the RNA molecule consists of Watson-Crick base pairs between residues 1-5 and residues 10-14 forming a standard RNA helix. We can also see that residues 6 and 9 form a non-canonical base pair interaction between the sugar and Hoogsteen edges of the respective bases. We can think of this structure as a simple stem-loop, with an idealized A-form helix between residues 1-5 and residues 10-14, and with a tetraloop connecting these chains." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Let's use some of Rosetta's tools for measuring **distances and torsions** to understand the typical geometry of an idealized A-form helix.\n", "\n", "What is the distance between the phosphate atoms of two consecutive residues in one strand of a helix? Check this for a couple pairs of residues." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "P1_xyz = pose.residue(1).xyz(\"P\")\n", "P2_xyz = pose.residue(2).xyz(\"P\")\n", "P3_xyz = pose.residue(3).xyz(\"P\")\n", "print((P1_xyz - P2_xyz).norm())\n", "print((P2_xyz - P3_xyz).norm())" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "RNA nucleotides are quite large compared to amino acids, with many more torsion angles. In the diagram of a nucleotide below, we can see the backbone torsions applicable to RNA: $\\alpha$, $\\beta$, $\\gamma$, $\\delta$, $\\epsilon$, $\\zeta$, and $\\chi$." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from IPython.display import Image\n", "Image('./Media/nucleotide_torsions.png',width='500')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can access the values of these torsions through the pose object. Just like protein torsions can be accessed with functions like `pose.phi(resid)`, RNA torsions can be accessed with analogous functions like `pose.alpha(resid)`.\n", "\n", "**Exercise**: Below, make a function that prints out all the torsions for a given residue. Then, using that function, check the torsions for three different residues in the RNA helix. How similar are torsion angles for different residues in an idealized helix?" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "deletable": false, "nbgrader": { "cell_type": "code", "checksum": "1f2aab69e23c1fc68efd5cee7f06ed0a", "grade": true, "grade_id": "cell-7f8e1ca8cd0481da", "locked": false, "points": 0, "schema_version": 3, "solution": true } }, "outputs": [], "source": [ "YOUR-CODE-HERE" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "deletable": false, "nbgrader": { "cell_type": "code", "checksum": "655ce3e48acdac57626a06862d86363d", "grade": true, "grade_id": "cell-0050cf688492fbb4", "locked": false, "points": 0, "schema_version": 3, "solution": true } }, "outputs": [], "source": [ "YOUR-CODE-HERE" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Scoring RNA poses ##" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Rosetta's energy functions provide a mechanism to score RNA structures, rewarding realistic conformations using a variety of score terms. In this section, we will see how to score RNA poses, and we will use these score terms to better understand our structure.\n", "\n", "To score structures with RNA in Rosetta, it is best to use a high-resolution energy function designed to work with RNA, for instance `stepwise/rna/rna_res_level_energy4.wts`. In fact, the standard high resolution energy function used in Rosetta does not include the score terms that are quite helpful for modeling RNA. To see this, we will evaluate our RNA pose with the `ref2015` score function and `stepwise/rna/rna_res_level_energy4.wts`, comparing the resulting score term values." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "hires_sf = core.scoring.ScoreFunctionFactory.create_score_function(\"ref2015\");" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "hires_sf.show(pose)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Note that `ref2015` does contain some terms that are used for RNA modeling like VDW and hydrogen bonding score terms. What extra terms are included in the RNA high resolution score function?" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "rna_hires_sf = core.scoring.ScoreFunctionFactory.create_score_function(\"stepwise/rna/rna_res_level_energy4.wts\");" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "rna_hires_sf.show(pose)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can see that some new score terms in the high resolution RNA potential, including `rna_torsion`, `suiteness_bonus`, `rna_sugar_close`, and `fa_stack`. We will explore a few of these terms below. To learn about these and other score terms that have been included to more realistically model RNA, check out the papers referenced at the beginning of this notebook." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Analogous to the protein low-resolution potential, an RNA low-resolution potential has been developed to more quickly score RNA structures represented in centroid mode. Lets take a look at the score terms involved." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "rna_lowres_sf = core.scoring.ScoreFunctionFactory.create_score_function(\"rna/denovo/rna_lores_with_rnp_aug.wts\");" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "rna_lowres_sf.show(pose)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can see that when modeling an RNA molecule using centroid positions for nucleotides, we need to separately include terms for base pairing (`rna_base_pair`), base-backbone interactions (`rna_base_backbone`), and so on. " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Returning to the high resolution RNA score function, let us see if we can decompose the energies further to understand which parts of the structure contribute positively and negatively to its energy. First, we can decompose the energies per residue like below." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "rna_hires_sf(pose)\n", "nonzero_scores = pose.energies().residue_total_energies(4).show_nonzero()\n", "print(nonzero_scores)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "A lot of the RNA specific energy terms make more sense when we look at pairs of residues. The energy graph object allows you to explore pairwise energies. The function below uses the energy graph to print out all non-zero scores between residues for a particular score term." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def print_nonzero_pairwise_energies(pose, energy_term, sf):\n", " sf(pose)\n", " energy_graph = pose.energies().energy_graph()\n", " for ii in range(1, pose.size() + 1):\n", " for jj in range(ii + 1, pose.size() + 1):\n", " edge = energy_graph.find_energy_edge(ii, jj)\n", " if (edge != None):\n", " emap = edge.fill_energy_map()\n", " resid1 = str(ii) + \" \" + pose.residue(ii).name1()\n", " resid2 = str(jj) + \" \" + pose.residue(jj).name1()\n", " resid_pair = resid1 + \" \" + resid2\n", " score = emap[ energy_term ]\n", " if score != 0:\n", " print(\"%s: %f\" % (resid_pair, score))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Using the function above, we're going to look at the stacking energies in the high resolution potential." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "print_nonzero_pairwise_energies(pose, core.scoring.ScoreType.fa_stack, rna_hires_sf)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can see that the **stacking energies** are highest for consecutive residues. In the idealized helix, the best stacking energy bonuses are given to stacked purine residues." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now lets take a look at the **torsion energies**. Which energies are the highest? Where are these torsions in the structure?" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "print_nonzero_pairwise_energies(pose, core.scoring.ScoreType.rna_torsion, rna_hires_sf)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "RNA structures are often viewed as being composed of small building blocks called **RNA motifs**. These motifs can be as simple as stacks of base pairs, which we have seen above. Typical motifs also include stereotyped loops, junctions, and tertiary contacts present across many common RNA molecules. Let's take a look to see whether any of these common RNA motifs are present in our simple stem loop structure." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "lowres_potential = core.scoring.rna.RNA_LowResolutionPotential( \"scoring/rna/rna_base_pair_xy.dat\" )\n", "rna_scoring_info = core.scoring.rna.rna_scoring_info_from_pose(pose).rna_filtered_base_base_info()\n", "rna_motifs = core.scoring.rna.get_rna_motifs( pose, lowres_potential, rna_scoring_info)\n", "print(rna_motifs)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can see that our RNA structure includes many stacked Watson-Crick base pair, making the idealized A-form helix. In addition, the loop connecting the strands of the helix in our structure is a stereotyped \"GNRA\" tetraloop, taking a loop conformation that is common across many RNA structures in the PDB." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Manipulating RNA poses ##" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Rosetta allows you to not just explore a given PDB structure, but to manipulate and design structures. In this section, we discuss some basic ways to manipulate RNA structures, and we observe the effects of these manipulations on the structure's energy. For each manipulation, we will make a new copy of the pose to make sure that our changes do not affect the original structure we loaded in." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "One basic manipulation we can make to an RNA structure is to change torsion angles for individual residues. Let's try this out on a residue in the A-form helix, and observe the effect on the rna_torsion score. Did the change we made make the score better or worse?" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "new_pose = Pose()\n", "new_pose.assign(pose)\n", "rna_hires_sf(pose)\n", "torsion_score_before = pose.energies().total_energies()[core.scoring.ScoreType.rna_torsion]\n", "new_pose.set_beta(2, 110)\n", "rna_hires_sf(new_pose)\n", "torsion_score_after = new_pose.energies().total_energies()[core.scoring.ScoreType.rna_torsion]\n", "print(\"%s: %f\" % (\"Torsion score before\", torsion_score_before))\n", "print(\"%s: %f\" % (\"Torsion score after\", torsion_score_after))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "If you want to replace residues in an RNA molecule with their idealized versions, you can use the RNA_IdealCoord class in Rosetta. Below is an example for using that method to first replace a single residue with its idealized version, and then to replace all residues with their idealized versions across the whole pose." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "ideal_pose_one = Pose()\n", "ideal_pose_one.assign(pose)\n", "resid = 2\n", "core.pose.rna.RNA_IdealCoord().apply(ideal_pose_one, resid, core.chemical.rna.PuckerState.ANY_PUCKER, False)\n", "\n", "ideal_pose = Pose()\n", "ideal_pose.assign(pose)\n", "core.pose.rna.RNA_IdealCoord().apply(ideal_pose, False)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Exercise**: Figure out if the total energy of the pose went up or down after replacing one or all of the residues with their idealized versions. What can explain the difference? What about the total torsion energy only - does that go up or down in the pose with idealized residues compared to the original pose?" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "deletable": false, "nbgrader": { "cell_type": "code", "checksum": "63c68b8f6a05ee213fae0de0d59af2c1", "grade": true, "grade_id": "cell-405c334dbcb470b1", "locked": false, "points": 0, "schema_version": 3, "solution": true } }, "outputs": [], "source": [ "YOUR-CODE-HERE" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "deletable": false, "nbgrader": { "cell_type": "code", "checksum": "c1c0425a6051d6e985e3efdcbb06e4af", "grade": true, "grade_id": "cell-8d8090023caba9ad", "locked": false, "points": 0, "schema_version": 3, "solution": true } }, "outputs": [], "source": [ "YOUR-CODE-HERE" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Another common manipulation for an RNA structure is to mutate the nucleotides to different bases. This is a manipulation that is commonly used while modeling one RNA structure using coordinates from another homologous (but not identical) structure. Below we can see how to mutate one residue of our RNA structure to another one." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "mutated_pose = Pose()\n", "mutated_pose.assign(pose)\n", "print(pose.sequence())\n", "rosetta.core.pose.rna.mutate_position(mutated_pose, 1, 'a')\n", "print(mutated_pose.sequence())" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Exercise**: Make a function that mimics the 'rna_thread' Rosetta application, which takes in a pose and a new sequence and replaces all pose residues with the new sequence's residues. Remember to check that the pose's sequence and the new sequence have the same length. \n", "\n", "The pose's current sequence is `cauccgaaaggaug`. Use the function you wrote to make a version that has sequence `cauccuucgggaug` and one that has sequence `aaaaagaaauuuuu`." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "deletable": false, "nbgrader": { "cell_type": "code", "checksum": "77a82bd5b4607066588ecaa20eb923e1", "grade": true, "grade_id": "cell-f1ea3d070c9bd97b", "locked": false, "points": 0, "schema_version": 3, "solution": true } }, "outputs": [], "source": [ "YOUR-CODE-HERE" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "deletable": false, "nbgrader": { "cell_type": "code", "checksum": "f3445e751ac6bc87939c3ed6c2f68bc6", "grade": true, "grade_id": "cell-933a0b69cf8657e5", "locked": false, "points": 0, "schema_version": 3, "solution": true } }, "outputs": [], "source": [ "YOUR-CODE-HERE" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Exercise**: The RNA high resolution potential includes hydrogen bonding terms. CG base pairs have more hydrogen bonds than AU base pairs. Compare the original pose with the pose that has all AU base pairs. What happens to the hydrogen bonding energy in the high resolution potential? " ] }, { "cell_type": "code", "execution_count": null, "metadata": { "deletable": false, "nbgrader": { "cell_type": "code", "checksum": "121ea9e83c7378c206b9fd44437ff429", "grade": true, "grade_id": "cell-905f30b7cab546cd", "locked": false, "points": 0, "schema_version": 3, "solution": true } }, "outputs": [], "source": [ "YOUR-CODE-HERE" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Exercise**: The stacking energies of the GAAA and UUCG tetraloops differ from each other. Which tetraloop provides the most favorable stacking energies overall? Can you figure out which pairs of residues have different stacking energies when the structure has changed (hint: you can base your code here off of the function `print_nonzero_pairwise_energies` above)?" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "deletable": false, "nbgrader": { "cell_type": "code", "checksum": "06b2e5fd4b8b25e7fb84855efed7af1a", "grade": true, "grade_id": "cell-5238d5e4cce441ce", "locked": false, "points": 0, "schema_version": 3, "solution": true } }, "outputs": [], "source": [ "YOUR-CODE-HERE" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "deletable": false, "nbgrader": { "cell_type": "code", "checksum": "51188fbdca819820088a686f676f9717", "grade": true, "grade_id": "cell-5451c79d29dd2993", "locked": false, "points": 0, "schema_version": 3, "solution": true } }, "outputs": [], "source": [ "YOUR-CODE-HERE" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Elements of RNA Structure Prediction" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Many of the same strategies are used when modeling RNA as when modeling proteins. Below, we shall explore some of these procedures specifically applied to RNA molecules to appreciate how they may come together to give a modern structure prediction method." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Generating an ideal A-form Helix" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "On a not wholly unrelated tangent, let us first see how we can quickly generate poses of ideal A-form RNA. You can think of this procedure as analogous to the `pose_from_seq` function used to generate protein poses from primary sequences. Let's use it now to generate a single-strand RNA pose with A-form torsions and the same sequence as the hairpin we've been examining so far.\n", "\n", "```python\n", "assembler = core.import_pose.RNA_HelixAssembler()\n", "assembled_pose = assembler.build_init_pose(pose.sequence(), '')\n", "```\n", "\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "deletable": false, "nbgrader": { "cell_type": "code", "checksum": "3c2e8a202492bd024f5a851be76f8052", "grade": true, "grade_id": "cell-8a96120ce6ea942f", "locked": false, "points": 0, "schema_version": 3, "solution": true } }, "outputs": [], "source": [ "YOUR-CODE-HERE" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Let's get a `PyMOLMover` up and running so we can examine our new pose." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "pmm = PyMOLMover()\n", "pmm.set_PyMOL_model_name('assembled_pose')\n", "pmm.apply(assembled_pose)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "You can also use `RNA_HelixAssmebler` to generate poses that comprise two strands that form an ideal A-form helical stack, like residues 1-5 and 10-14 in the hairpin from above." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "pmm_helix = PyMOLMover()\n", "pmm_helix.set_PyMOL_model_name('helix_pose')\n", "helix_pose = assembler.build_init_pose('ggg','ccc')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Looking in PyMOL, you may be able to appreciate that, true to its name, the `RNA_HelixAssembler` has generated a pose that looks quite helical." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "pmm_helix.apply(helix_pose)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Exercise**: Examine the torsions in several of the residues of `assembled_pose` using the `print_torsions` function you wrote earlier. How do they compare to the torsions from the starting stem loop?" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### RNA Fragments" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Given a library of RNA torsions excised from a published structure, fragment assembly methods will choose an n-mer in the current structure and replace the backbone geometry with the geometry of a corresponding n-mer from the library. Those of you familiar with protein structure prediction methods will recognize this strategy of fragment assembly.\n", "\n", "We will implement a rudimentary version of this protocol for RNA below." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "For the present exercise, we will use the torsions file `inputs/1jj2.torsions`, which comes from the crystal structure of a large ribosomal subunit. This library will be used to initialize a `Mover` specifically designed to perform fragment assembly on RNA molecules, `RNA_FragmentMover`.\n", "```python\n", "fragset = core.import_pose.libraries.RNA_LibraryManager.get_instance().rna_fragment_library(\"inputs/1jj2.torsions\")\n", "atom_level_domain_map = core.pose.toolbox.AtomLevelDomainMap(assembled_pose)\n", "frag_mover = protocols.rna.denovo.movers.RNA_FragmentMover(fragset, atom_level_domain_map, 1, 0)\n", "```\n", "Don't worry too much about the other options that `RNA_FragmentMover` requires at this point, but remember to include them if using this mover outside of this notebook." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "deletable": false, "nbgrader": { "cell_type": "code", "checksum": "5c13a51dfcb635b64d35cef067cfda26", "grade": true, "grade_id": "cell-e28d1be460f75e10", "locked": false, "points": 0, "schema_version": 3, "solution": true } }, "outputs": [], "source": [ "YOUR-CODE-HERE" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Let's practice applying this mover to a `Pose`. To actually make a fragment assembly move, you can call the `random_fragment_insertion` method which requires two arguments:\n", "\n", "1. An input `Pose`\n", "2. The size of the fragment to substitute.\n", "\n", "There is also an `apply()` method that can be called in a similar manner, but it simply calls `random_fragment_insertion()`, so the recommendation is to decrease overhead by calling `random_fragment_insertion()` where possible.\n", "\n", "Let's pratice calling this method below.\n", "```python\n", "practice_pose = Pose()\n", "practice_pose.assign(assembled_pose)\n", "frag_mover.random_fragment_insertion(practice_pose, 3)\n", "pmm.apply(practice_pose)\n", "```\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "deletable": false, "nbgrader": { "cell_type": "code", "checksum": "7012ec08607dd8d0310eaa1015d5d421", "grade": true, "grade_id": "cell-7ebd40e5cc7a1a5c", "locked": false, "points": 0, "schema_version": 3, "solution": true } }, "outputs": [], "source": [ "YOUR-CODE-HERE" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now that we know how to set up a fragment assembly mover in PyRosetta, try the excise below to write a quick folding routine that uses a fragment assembly strategy to try and fold the hairpin sequence. " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Exercise**: Fill in the function below such that `fragment_assembly`\n", "* Accepts an input `Pose`, `RNA_FragmentMover`, fragment size to substitute (`frag_size`), and number of trials (`n_trials`).\n", "* Uses by default the `rna_lowres_sf` energy function from earlier but allows the user to specify a different energy function, if desired\n", "* Performs a fragment substitution and accepts the substitution subject to the Metropolis criterion (assume $kT = 1$)\n", "* Returns the lowest-energy pose found.\n", "\n", "\\* See section 4.1 of these notebooks for a review on Monte Carlo algorithms, if desired. \n", "\n", "Then, apply it to our newly assembled pose using the following recipe:\n", "\n", "1. Run `fragment_assembly` using 3 nucleotide fragments for 400 trials. \n", "2. Then, run `fragment_assembly` using 2 nucleotide fragments for 300 trials.\n", "3. Finally, run `fragment_assembly` using 1 nucleotide fragments for 300 trials." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "deletable": false, "nbgrader": { "cell_type": "code", "checksum": "98d9918c123537289d5837e316b06eb6", "grade": true, "grade_id": "cell-17cc8abff43d174a", "locked": false, "points": 0, "schema_version": 3, "solution": true } }, "outputs": [], "source": [ "import math\n", "import random\n", "\n", "def fragment_assembly(start_pose, frag_mover, frag_size, n_trials, sf=rna_lowres_sf):\n", " curr_pose = Pose()\n", " curr_pose.assign(start_pose)\n", " trial_pose = Pose()\n", " trial_pose.assign(curr_pose)\n", " opt_pose = Pose()\n", " opt_pose.assign(curr_pose)\n", " currE = newE = optE = sf(curr_pose)\n", "YOUR-CODE-HERE\n", " #return curr_pose\n", "\n", "frag_pose = fragment_assembly(assembled_pose, frag_mover, 3, 400)\n", "frag_pose = fragment_assembly(frag_pose, frag_mover, 2, 300)\n", "frag_pose = fragment_assembly(frag_pose, frag_mover, 1, 300)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Examine the fragment assembled `Pose` in PyMOL. Do you recognize any of the motifs from before?\n", "```python\n", "frag_pmm = PyMOLMover()\n", "frag_pmm.set_PyMOL_model_name('frag_pose')\n", "frag_pmm.apply(frag_pose)\n", "```\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "deletable": false, "nbgrader": { "cell_type": "code", "checksum": "4d3b18204bd18ec31aaf61a2cc1da645", "grade": true, "grade_id": "cell-454affa682c5f1d0", "locked": false, "points": 0, "schema_version": 3, "solution": true } }, "outputs": [], "source": [ "YOUR-CODE-HERE" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Minimizing Structures with RNA" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In principle, the standard `MinMover` that has been introduced previously in the context of minimizing purely protein structures can also be used to minimize poses with RNA (as long as the assigned energy function has score terms relevant to RNA and an appropriate `MoveMap` is provided).\n", "\n", "However, as part of the `rna_denovo` protocol, Das and coworkers have developed a subroutine, `RNA_Minimize`, that is specifically geared toward handling minimization of poses with RNA, the use of which is detailed below." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can access the `RNA_Minimize` mover from the `protocols` namespace. The relevant options object, `RNA_MinimizerOptions`, lives in the `import_pose.options` namespace. We will set the maximum number of iterations to 1000, using default values for other options.\n", "```python\n", "rna_min_options = core.import_pose.options.RNA_MinimizerOptions()\n", "rna_min_options.set_max_iter(1000)\n", "rna_minmizer = protocols.rna.denovo.movers.RNA_Minimizer(rna_min_options)\n", "```" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "deletable": false, "nbgrader": { "cell_type": "code", "checksum": "0fb72b85124f4e6f6de4b6b9822ea3b1", "grade": true, "grade_id": "cell-df0b5d2d61c42654", "locked": false, "points": 0, "schema_version": 3, "solution": true } }, "outputs": [], "source": [ "YOUR-CODE-HERE" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Unlike in the case of using `MinMover`, things like an appropriate energy function and `MoveMap` are generated by default by the `RNA_Minimizer` object. By default, `RNA_Minimizer` uses the same high-resolution energy function as above (`stepwise/rna/rna_res_level_energy4.wts`).\n", "\n", "All that remains is to apply it to the relevant pose.\n", "```python\n", "rna_minimizer.apply(frag_pose)\n", "```" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "deletable": false, "nbgrader": { "cell_type": "code", "checksum": "e85b2f4266f3d4cff627e617de18d139", "grade": true, "grade_id": "cell-e80552b2026767ce", "locked": false, "points": 0, "schema_version": 3, "solution": true } }, "outputs": [], "source": [ "YOUR-CODE-HERE" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Let's see what changes minimization has wrought on our structure:\n", "```python\n", "min_pmm = PyMOLMover()\n", "min_pmm.set_PyMOL_model_name('min_pose')\n", "min_pmm.apply(frag_pose)\n", "```" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "deletable": false, "nbgrader": { "cell_type": "code", "checksum": "9fcc794e8aac5bcc7b622dd3b7f5f2bf", "grade": true, "grade_id": "cell-4138129b3ff0e1e2", "locked": false, "points": 0, "schema_version": 3, "solution": true } }, "outputs": [], "source": [ "YOUR-CODE-HERE" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Exercise**: Using the functions described in the first part of the notebook, report on the following with respect to our de novo folded sequence:\n", "1. Which base pairs, if any, were recovered?\n", "2. Which motifs, if any, were recovered?\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "deletable": false, "nbgrader": { "cell_type": "code", "checksum": "6759a733226b0e324bc2bb6827a3ebd8", "grade": true, "grade_id": "cell-d3c9218512f85a39", "locked": false, "points": 0, "schema_version": 3, "solution": true } }, "outputs": [], "source": [ "YOUR-CODE-HERE" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Additional Exercises" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Post-mortem" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Examine our final folded structure and the hairpin from the first part of the tutorial and think about the following questions:\n", "* How well did our brief structure prediction algorithm do at recovering the hairpin we examined at the beginning? \n", "* Which parts were more successfully recovered? Which parts less so? Why might this be? \n", "* What would you do to improve on this method as it stands? Feel free to implement any ideas you have." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### FAR + FAR = FARFAR" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Write a function analogous to the `fragment_assembly` function above that \n", "* Accepts an input `Pose`\n", "* Performs a round of minimization using an `RNA_Minimizer`\n", "* Returns the minimized structure\n", "\n", "Using this new suboutine, craft your own `farfar` ( [Fragment Assembly of RNA with Full Atom Refinement](https://www.rosettacommons.org/docs/latest/application_documentation/rna/rna-denovo)) routine that performs multiple rounds of fragment assembly in a low-resolution potential followed by minimization in a high-resolution energy function. \n", "\n", "Try playing around with the various parameters and see how well you can recover the hairpin starting from just the sequence.\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## RNA Structure Prediction Protocol" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Below we will be running a short RNA de novo modeling run for the stem-loop sequence we have been working with thus far, making use of the **FARFAR protocol** (which you can run with the `rna_denovo` command in Rosetta). As discussed above, the FARFAR protocol involves a mixture of fragment assembly moves and full atom minimization moves. We will generate a small set of structures using FARFAR and compare the energy of the resulting structures to those constructed in the previous exercise. " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "FARFAR builds models for a structure as specified in a FASTA file, making use of any structures of known sub-pieces (for instance, A-form helices for regions known to form stems). In this case, we will provide the helical portion of our structure between residues 1-5 and residues 10-14 as an input to the FARFAR protocol, so that the protocol only has to worry about sampling the loop. In a real modeling scenario, it is often the case that information about the secondary structure of the RNA is known, allowing us to make use of A-form helix rigid bodies to accelerate modeling.\n", "\n", "Let's set up the fasta file and input PDB files to use as options for FARFAR; these files should be in the `inputs/` folder." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "input_pdbs = rosetta.utility.vector1_std_string()\n", "fasta_files = rosetta.utility.vector1_std_string()\n", "input_pdbs.append(\"inputs/stem.pdb\")\n", "fasta_files = rosetta.utility.vector1_std_string()\n", "fasta_files.append(\"inputs/stem_loop.fasta\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We will set up options for `rna_denovo` below, specifying the FASTA file, the input PDBs, the number of structures we would like to generate, and the output file (silent file format)." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "rna_de_novo_setup = core.import_pose.RNA_DeNovoSetup()\n", "rna_de_novo_setup.set_fasta_files(fasta_files)\n", "rna_de_novo_setup.set_minimize_rna(True)\n", "rna_de_novo_setup.set_input_pdbs(input_pdbs)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "rna_de_novo_setup.initialize_from_command_line()" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "rna_de_novo_options = rna_de_novo_setup.options()\n", "rna_de_novo_options.set_nstruct(10)\n", "rna_de_novo_options.set_silent_file(\"outputs/stem_loop.out\")\n", "rna_de_novo_options.set_vall_torsions_file(\"./inputs/1jj2.torsions\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now we will run FARFAR by generating an `RNA_DeNovoProtocol` object and running it with `apply` on a starting pose. This will take a few minutes to run, and will generate 10 structures to the silent file specified above. As the protocol is running, take a look at the output to understand how it works. Note that for each structure generated, the protocol goes through various rounds of fragment assembly with fragments of size 3, 2, and 1, and then runs the RNA minimizer. This is similar to the protocol you made above!" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "rna_de_novo_protocol = rosetta.protocols.rna.denovo.RNA_DeNovoProtocol(rna_de_novo_options, rna_de_novo_setup.rna_params())" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "rna_de_novo_pose = rna_de_novo_setup.pose()\n", "rna_de_novo_protocol.apply(rna_de_novo_pose)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now that we've generated RNA structures with the FARFAR protocol, let's look at the top scoring structures and compare to those that you generated earlier in this module. \n", "\n", "Run the following to get the poses from the silent file that FARFAR wrote to." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "poses = poses_from_silent(\"outputs/stem_loop.out\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Exercise**: Get the best scoring pose generated from FARFAR by iterating through the poses above with a loop (`for pose in poses`...). Make use of the rna_hires_sf that was generated earlier in this notebook to score these structures. Compare the best score with the the score of the `frag_pose` you generated in the previous section. Which is better?" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "deletable": false, "nbgrader": { "cell_type": "code", "checksum": "446c558978ee17285a80e15083e0f81a", "grade": true, "grade_id": "cell-1f6ca941a1ef90b6", "locked": false, "points": 0, "schema_version": 3, "solution": true } }, "outputs": [], "source": [ "YOUR-CODE-HERE" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "deletable": false, "nbgrader": { "cell_type": "code", "checksum": "974cdd0a48dd293127f019c5ef880a89", "grade": true, "grade_id": "cell-c48c7d1410546aef", "locked": false, "points": 0, "schema_version": 3, "solution": true } }, "outputs": [], "source": [ "YOUR-CODE-HERE" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The FARFAR protocol in this section can generate structures with an improved Rosetta score in part because it uses an optimized number of fragment assembly moves for each structure, and in large part because we initialized this run with an idealized A-form helix for the stem portion of our structure. Let's take a look to see what the best pose we generated looks like using the PyMOLMover." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "farfar_pmm = PyMOLMover()\n", "farfar_pmm.set_PyMOL_model_name('farfar_pose')\n", "farfar_pmm.apply(best_pose)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Exercise**: What motifs and features can you see in the best pose for this sequence from our 10 FARFAR models? What features are missing? How might we recover those features?" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Chapter contributors:**\n", "\n", "- Ramya Rangan (Stanford University)\n", "- Matt Adrianowycz (Stanford University)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "< [RosettaCarbohydrates: Modeling and Design](http://nbviewer.jupyter.org/github/RosettaCommons/PyRosetta.notebooks/blob/master/notebooks/13.02-Glycan-Modeling-and-Design.ipynb) | [Contents](toc.ipynb) | [Index](index.ipynb) | [Modeling Membrane Proteins](http://nbviewer.jupyter.org/github/RosettaCommons/PyRosetta.notebooks/blob/master/notebooks/15.00-Modeling-Membrane-Proteins.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.7.1" }, "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": { "height": "470px", "left": "48px", "top": "110px", "width": "267.984px" }, "toc_section_display": true, "toc_window_display": true } }, "nbformat": 4, "nbformat_minor": 4 }