Upload folder using huggingface_hub
Browse files- .gitattributes +22 -10
- .gitignore +5 -0
- LICENSE +21 -0
- README.md +325 -0
- conf/ddG-backrub.xml +114 -0
- conf/ddG-no_backrub_control.xml +108 -0
- conf/fig-overview.png +3 -0
- conf/per_chain_rescore.xml +66 -0
- conf/split_protocol/flex_ddG-backrub_step.xml +108 -0
- conf/split_protocol/flex_ddG-mutation_step.xml +95 -0
- conf/split_protocol/split_commands.txt +32 -0
- config.json +33 -0
- scripts/analyze_flex_ddG.py +344 -0
- scripts/extract_structures.py +262 -0
- scripts/flex_ddg_db3.py +48 -0
- scripts/inputs/1JTG/1JTG_AB.pdb +0 -0
- scripts/inputs/1JTG/chains_to_move.txt +1 -0
- scripts/inputs/1JTG/mutations.mutfile +6 -0
- scripts/inputs/1JTG/mutations.resfile +6 -0
- scripts/inputs/1JTG/nataa_mutations.resfile +6 -0
- scripts/inputs/1JTG/pdb2rosetta.resmap.json +429 -0
- scripts/inputs/1JTG/rosetta2pdb.resmap.json +429 -0
- scripts/per_chain_protocol.py +116 -0
- scripts/reprocess_per_chain.py +253 -0
- scripts/run_example_1.py +121 -0
- scripts/run_example_2_saturation.py +116 -0
.gitattributes
CHANGED
|
@@ -1,35 +1,47 @@
|
|
| 1 |
*.7z filter=lfs diff=lfs merge=lfs -text
|
| 2 |
*.arrow filter=lfs diff=lfs merge=lfs -text
|
| 3 |
*.bin filter=lfs diff=lfs merge=lfs -text
|
|
|
|
| 4 |
*.bz2 filter=lfs diff=lfs merge=lfs -text
|
| 5 |
-
*.ckpt filter=lfs diff=lfs merge=lfs -text
|
| 6 |
*.ftz filter=lfs diff=lfs merge=lfs -text
|
| 7 |
*.gz filter=lfs diff=lfs merge=lfs -text
|
| 8 |
*.h5 filter=lfs diff=lfs merge=lfs -text
|
| 9 |
*.joblib filter=lfs diff=lfs merge=lfs -text
|
| 10 |
*.lfs.* filter=lfs diff=lfs merge=lfs -text
|
| 11 |
-
*.mlmodel filter=lfs diff=lfs merge=lfs -text
|
| 12 |
*.model filter=lfs diff=lfs merge=lfs -text
|
| 13 |
*.msgpack filter=lfs diff=lfs merge=lfs -text
|
| 14 |
-
*.npy filter=lfs diff=lfs merge=lfs -text
|
| 15 |
-
*.npz filter=lfs diff=lfs merge=lfs -text
|
| 16 |
*.onnx filter=lfs diff=lfs merge=lfs -text
|
| 17 |
*.ot filter=lfs diff=lfs merge=lfs -text
|
| 18 |
*.parquet filter=lfs diff=lfs merge=lfs -text
|
| 19 |
*.pb filter=lfs diff=lfs merge=lfs -text
|
| 20 |
-
*.pickle filter=lfs diff=lfs merge=lfs -text
|
| 21 |
-
*.pkl filter=lfs diff=lfs merge=lfs -text
|
| 22 |
*.pt filter=lfs diff=lfs merge=lfs -text
|
| 23 |
*.pth filter=lfs diff=lfs merge=lfs -text
|
| 24 |
*.rar filter=lfs diff=lfs merge=lfs -text
|
| 25 |
-
*.safetensors filter=lfs diff=lfs merge=lfs -text
|
| 26 |
saved_model/**/* filter=lfs diff=lfs merge=lfs -text
|
| 27 |
*.tar.* filter=lfs diff=lfs merge=lfs -text
|
| 28 |
-
*.tar filter=lfs diff=lfs merge=lfs -text
|
| 29 |
*.tflite filter=lfs diff=lfs merge=lfs -text
|
| 30 |
*.tgz filter=lfs diff=lfs merge=lfs -text
|
| 31 |
-
*.wasm filter=lfs diff=lfs merge=lfs -text
|
| 32 |
*.xz filter=lfs diff=lfs merge=lfs -text
|
| 33 |
*.zip filter=lfs diff=lfs merge=lfs -text
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 34 |
*.zst filter=lfs diff=lfs merge=lfs -text
|
| 35 |
-
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
|
|
|
| 1 |
*.7z filter=lfs diff=lfs merge=lfs -text
|
| 2 |
*.arrow filter=lfs diff=lfs merge=lfs -text
|
| 3 |
*.bin filter=lfs diff=lfs merge=lfs -text
|
| 4 |
+
*.bin.* filter=lfs diff=lfs merge=lfs -text
|
| 5 |
*.bz2 filter=lfs diff=lfs merge=lfs -text
|
|
|
|
| 6 |
*.ftz filter=lfs diff=lfs merge=lfs -text
|
| 7 |
*.gz filter=lfs diff=lfs merge=lfs -text
|
| 8 |
*.h5 filter=lfs diff=lfs merge=lfs -text
|
| 9 |
*.joblib filter=lfs diff=lfs merge=lfs -text
|
| 10 |
*.lfs.* filter=lfs diff=lfs merge=lfs -text
|
|
|
|
| 11 |
*.model filter=lfs diff=lfs merge=lfs -text
|
| 12 |
*.msgpack filter=lfs diff=lfs merge=lfs -text
|
|
|
|
|
|
|
| 13 |
*.onnx filter=lfs diff=lfs merge=lfs -text
|
| 14 |
*.ot filter=lfs diff=lfs merge=lfs -text
|
| 15 |
*.parquet filter=lfs diff=lfs merge=lfs -text
|
| 16 |
*.pb filter=lfs diff=lfs merge=lfs -text
|
|
|
|
|
|
|
| 17 |
*.pt filter=lfs diff=lfs merge=lfs -text
|
| 18 |
*.pth filter=lfs diff=lfs merge=lfs -text
|
| 19 |
*.rar filter=lfs diff=lfs merge=lfs -text
|
|
|
|
| 20 |
saved_model/**/* filter=lfs diff=lfs merge=lfs -text
|
| 21 |
*.tar.* filter=lfs diff=lfs merge=lfs -text
|
|
|
|
| 22 |
*.tflite filter=lfs diff=lfs merge=lfs -text
|
| 23 |
*.tgz filter=lfs diff=lfs merge=lfs -text
|
|
|
|
| 24 |
*.xz filter=lfs diff=lfs merge=lfs -text
|
| 25 |
*.zip filter=lfs diff=lfs merge=lfs -text
|
| 26 |
+
*.zstandard filter=lfs diff=lfs merge=lfs -text
|
| 27 |
+
*.tfevents* filter=lfs diff=lfs merge=lfs -text
|
| 28 |
+
*.db* filter=lfs diff=lfs merge=lfs -text
|
| 29 |
+
*.ark* filter=lfs diff=lfs merge=lfs -text
|
| 30 |
+
**/*ckpt*data* filter=lfs diff=lfs merge=lfs -text
|
| 31 |
+
**/*ckpt*.meta filter=lfs diff=lfs merge=lfs -text
|
| 32 |
+
**/*ckpt*.index filter=lfs diff=lfs merge=lfs -text
|
| 33 |
+
*.safetensors filter=lfs diff=lfs merge=lfs -text
|
| 34 |
+
*.ckpt filter=lfs diff=lfs merge=lfs -text
|
| 35 |
+
*.gguf* filter=lfs diff=lfs merge=lfs -text
|
| 36 |
+
*.ggml filter=lfs diff=lfs merge=lfs -text
|
| 37 |
+
*.llamafile* filter=lfs diff=lfs merge=lfs -text
|
| 38 |
+
*.pt2 filter=lfs diff=lfs merge=lfs -text
|
| 39 |
+
*.mlmodel filter=lfs diff=lfs merge=lfs -text
|
| 40 |
+
*.npy filter=lfs diff=lfs merge=lfs -text
|
| 41 |
+
*.npz filter=lfs diff=lfs merge=lfs -text
|
| 42 |
+
*.pickle filter=lfs diff=lfs merge=lfs -text
|
| 43 |
+
*.pkl filter=lfs diff=lfs merge=lfs -text
|
| 44 |
+
*.tar filter=lfs diff=lfs merge=lfs -text
|
| 45 |
+
*.wasm filter=lfs diff=lfs merge=lfs -text
|
| 46 |
*.zst filter=lfs diff=lfs merge=lfs -text
|
| 47 |
+
*tfevents* filter=lfs diff=lfs merge=lfs -textconf/fig-overview.png filter=lfs diff=lfs merge=lfs -text
|
.gitignore
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
output
|
| 2 |
+
output_saturation
|
| 3 |
+
analysis_output
|
| 4 |
+
questions
|
| 5 |
+
ddG-backrub-per_chain.xml
|
LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
MIT License
|
| 2 |
+
|
| 3 |
+
Copyright (c) 2018 Kyle Barlow
|
| 4 |
+
|
| 5 |
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
| 6 |
+
of this software and associated documentation files (the "Software"), to deal
|
| 7 |
+
in the Software without restriction, including without limitation the rights
|
| 8 |
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
| 9 |
+
copies of the Software, and to permit persons to whom the Software is
|
| 10 |
+
furnished to do so, subject to the following conditions:
|
| 11 |
+
|
| 12 |
+
The above copyright notice and this permission notice shall be included in all
|
| 13 |
+
copies or substantial portions of the Software.
|
| 14 |
+
|
| 15 |
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
| 16 |
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
| 17 |
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
| 18 |
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
| 19 |
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
| 20 |
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
| 21 |
+
SOFTWARE.
|
README.md
ADDED
|
@@ -0,0 +1,325 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
license: mit
|
| 3 |
+
language:
|
| 4 |
+
- en
|
| 5 |
+
- zh
|
| 6 |
+
tags:
|
| 7 |
+
- OneScience
|
| 8 |
+
- life-science
|
| 9 |
+
- protein
|
| 10 |
+
- binding-affinity
|
| 11 |
+
- mutation
|
| 12 |
+
- Rosetta
|
| 13 |
+
frameworks: Other
|
| 14 |
+
---
|
| 15 |
+
|
| 16 |
+
<p align="center">
|
| 17 |
+
<strong>
|
| 18 |
+
<span style="font-size: 30px;">Flex ddG</span>
|
| 19 |
+
</strong>
|
| 20 |
+
</p>
|
| 21 |
+
|
| 22 |
+
# Model Introduction
|
| 23 |
+
|
| 24 |
+
Flex ddG is a Rosetta-based workflow for predicting the effects of mutations at protein-protein interfaces and estimating changes in binding free energy before and after mutation (interface ΔΔG). It uses the Rosetta Backrub protocol to sample local backbone conformations, then performs side-chain repacking, structural minimization, and interface energy calculations for the wild type and mutant to assess how mutations affect protein binding affinity.
|
| 25 |
+
|
| 26 |
+
Paper:
|
| 27 |
+
|
| 28 |
+
> **Flex ddG: Rosetta Ensemble-Based Estimation of Changes in Protein–Protein Binding Affinity upon Mutation**
|
| 29 |
+
> https://doi.org/10.1021/acs.jpcb.7b11367
|
| 30 |
+
|
| 31 |
+
# Model Description
|
| 32 |
+
|
| 33 |
+
Flex ddG is not a model that relies on neural network weights; it is a computational workflow based on the Rosetta energy function and conformational sampling. Inputs typically include a protein complex PDB file, interface chain information, and a Rosetta resfile describing the mutations. The workflow uses Backrub sampling to generate an ensemble of conformations, optimizes and calculates interface energies for the wild type and mutant separately, and ultimately produces ΔΔG.
|
| 34 |
+
|
| 35 |
+
# Use Cases
|
| 36 |
+
|
| 37 |
+
| Use case | Description |
|
| 38 |
+
| --- | --- |
|
| 39 |
+
| Protein-protein interface mutation effect prediction | Predict changes in binding free energy ΔΔG caused by mutations |
|
| 40 |
+
| Interface hotspot residue analysis | Evaluate the effects of mutations at specific sites on binding stability |
|
| 41 |
+
| Single-site saturation mutagenesis scan | Generate all 20 standard amino acid substitutions at a target site and calculate ΔΔG for each |
|
| 42 |
+
| Protein engineering and interface optimization | Help screen for mutations that may enhance or weaken protein interactions |
|
| 43 |
+
|
| 44 |
+
# Usage
|
| 45 |
+
|
| 46 |
+
## 1. Using OneCode
|
| 47 |
+
|
| 48 |
+
Experience intelligent one-click AI4S programming in the OneCode online environment:
|
| 49 |
+
|
| 50 |
+
[Try intelligent one-click AI4S programming](https://web-2069360198568017922-iaaj.ksai.scnet.cn:58043/home)
|
| 51 |
+
|
| 52 |
+
## 2. Manual Installation and Usage
|
| 53 |
+
|
| 54 |
+
**Hardware Requirements**
|
| 55 |
+
|
| 56 |
+
- The core computations in Flex ddG are performed by Rosetta CPU programs; the standard workflow does not require a GPU/DCU.
|
| 57 |
+
- The official Python scripts use `multiprocessing` to launch multiple Rosetta instances concurrently. Each Rosetta instance requires approximately 2 GB of memory, so set the concurrency level according to the number of CPU cores and the node's available memory.
|
| 58 |
+
|
| 59 |
+
### Set Up the Runtime Environment
|
| 60 |
+
|
| 61 |
+
#### DCU Environment
|
| 62 |
+
|
| 63 |
+
```bash
|
| 64 |
+
# Activate DTK and CONDA first
|
| 65 |
+
conda create -n onescience311 python=3.11 -y
|
| 66 |
+
conda activate onescience311
|
| 67 |
+
|
| 68 |
+
# Install with uv support
|
| 69 |
+
pip install onescience[bio] \
|
| 70 |
+
-i http://mirrors.onescience.ai:3141/pypi/simple/ \
|
| 71 |
+
--trusted-host mirrors.onescience.ai
|
| 72 |
+
```
|
| 73 |
+
|
| 74 |
+
#### Environment Notes
|
| 75 |
+
|
| 76 |
+
- The core dependency of Flex ddG is **Rosetta**. The main workflow requires the `rosetta_scripts` executable built by Rosetta.
|
| 77 |
+
|
| 78 |
+
|
| 79 |
+
### Install Rosetta
|
| 80 |
+
|
| 81 |
+
Flex ddG does not require neural network model weights or additional large datasets, but Rosetta must be installed separately.
|
| 82 |
+
|
| 83 |
+
#### 1) Install Rosetta
|
| 84 |
+
|
| 85 |
+
Rosetta must be licensed, downloaded, and installed separately according to the official RosettaCommons instructions:
|
| 86 |
+
|
| 87 |
+
```text
|
| 88 |
+
https://www.rosettacommons.org/software
|
| 89 |
+
```
|
| 90 |
+
|
| 91 |
+
The Rosetta license is independent of the MIT License for the Flex ddG tutorial repository. Academic and non-commercial users can apply for a non-commercial license; commercial use requires a separate license.
|
| 92 |
+
|
| 93 |
+
After installation, make sure that at least the following files exist:
|
| 94 |
+
|
| 95 |
+
```text
|
| 96 |
+
/path/to/rosetta/source/bin/rosetta_scripts
|
| 97 |
+
/path/to/rosetta/source/bin/score_jd2
|
| 98 |
+
```
|
| 99 |
+
|
| 100 |
+
#### 2) Configure the Rosetta Paths
|
| 101 |
+
|
| 102 |
+
Before running the workflow, update the following line in `scripts/run_example_1.py` and `scripts/run_example_2_saturation.py`:
|
| 103 |
+
|
| 104 |
+
```python
|
| 105 |
+
rosetta_scripts_path = os.path.expanduser("~/rosetta/source/bin/rosetta_scripts")
|
| 106 |
+
```
|
| 107 |
+
|
| 108 |
+
To run `scripts/extract_structures.py`, also update `score_jd2_path` in the script to the actual path of the Rosetta `score_jd2` executable.
|
| 109 |
+
|
| 110 |
+
## 3. Quick Start
|
| 111 |
+
|
| 112 |
+
### Download the Model Package
|
| 113 |
+
|
| 114 |
+
```bash
|
| 115 |
+
hf download OneScience-Group/flex_ddG --local-dir ./flex_ddG
|
| 116 |
+
cd flex_ddG
|
| 117 |
+
```
|
| 118 |
+
|
| 119 |
+
- Flex ddG **additionally depends on Rosetta**. Rosetta is not included in this model repository; first apply for a license and install Rosetta as described in "Install Rosetta", then configure `rosetta_scripts_path`.
|
| 120 |
+
- To extract PDB structures from `struct.db3`, you also need to configure the path to Rosetta's `score_jd2` executable.
|
| 121 |
+
- The default parameters in this document are intended only for quick functional verification and do not represent parameters for production scientific calculations.
|
| 122 |
+
|
| 123 |
+
### Quick Verification
|
| 124 |
+
|
| 125 |
+
First, verify that the Rosetta executable is available:
|
| 126 |
+
|
| 127 |
+
```bash
|
| 128 |
+
/path/to/rosetta/source/bin/rosetta_scripts -help
|
| 129 |
+
```
|
| 130 |
+
|
| 131 |
+
Run the official example:
|
| 132 |
+
|
| 133 |
+
```bash
|
| 134 |
+
python scripts/run_example_1.py
|
| 135 |
+
```
|
| 136 |
+
|
| 137 |
+
On success, the following directory will be generated:
|
| 138 |
+
|
| 139 |
+
```text
|
| 140 |
+
output/
|
| 141 |
+
```
|
| 142 |
+
|
| 143 |
+
# Example Data
|
| 144 |
+
|
| 145 |
+
The official example directory is:
|
| 146 |
+
|
| 147 |
+
```text
|
| 148 |
+
scripts/inputs/
|
| 149 |
+
└── 1JTG/
|
| 150 |
+
├── 1JTG_AB.pdb
|
| 151 |
+
├── chains_to_move.txt
|
| 152 |
+
├── nataa_mutations.resfile
|
| 153 |
+
├── mutations.resfile
|
| 154 |
+
├── mutations.mutfile
|
| 155 |
+
├── pdb2rosetta.resmap.json
|
| 156 |
+
└── rosetta2pdb.resmap.json
|
| 157 |
+
```
|
| 158 |
+
|
| 159 |
+
The files are:
|
| 160 |
+
|
| 161 |
+
| File | Description |
|
| 162 |
+
| --- | --- |
|
| 163 |
+
| `1JTG_AB.pdb` | Protein complex structure |
|
| 164 |
+
| `chains_to_move.txt` | Defines the chain that moves as one side of the interface during calculations |
|
| 165 |
+
| `nataa_mutations.resfile` | The mutation resfile used by Flex ddG |
|
| 166 |
+
| `mutations.resfile` | Example mutation configuration |
|
| 167 |
+
| `mutations.mutfile` | Example mutation information |
|
| 168 |
+
|
| 169 |
+
The resfile used by Flex ddG must begin with `NATAA`. The official scripts explicitly state that it should not be replaced with `NATRO`, as this changes the repacking behavior of residues near the mutant and introduces bias into ΔΔG.
|
| 170 |
+
|
| 171 |
+
For your own tasks, you typically need at least:
|
| 172 |
+
|
| 173 |
+
```text
|
| 174 |
+
Complex PDB
|
| 175 |
+
+ Interface chain information
|
| 176 |
+
+ A resfile describing the mutations
|
| 177 |
+
```
|
| 178 |
+
# Inference Examples
|
| 179 |
+
## Flex ddG Calculation for Specified Mutations
|
| 180 |
+
Make sure that the Rosetta path in `scripts/run_example_1.py` is configured correctly:
|
| 181 |
+
|
| 182 |
+
```python
|
| 183 |
+
rosetta_scripts_path = "/path/to/rosetta/source/bin/rosetta_scripts"
|
| 184 |
+
```
|
| 185 |
+
|
| 186 |
+
Run:
|
| 187 |
+
|
| 188 |
+
```bash
|
| 189 |
+
python scripts/run_example_1.py
|
| 190 |
+
```
|
| 191 |
+
|
| 192 |
+
The script reads the complex structure, `chains_to_move.txt`, and `nataa_mutations.resfile` from `scripts/inputs/`, then calls `conf/ddG-backrub.xml` to run Flex ddG.
|
| 193 |
+
|
| 194 |
+
Key parameters:
|
| 195 |
+
|
| 196 |
+
| Parameter | Default | Common production setting/meaning |
|
| 197 |
+
| --- | ---: | --- |
|
| 198 |
+
| `nstruct` | 3 | Typically about 35 or more independent replicates in production |
|
| 199 |
+
| `number_backrub_trials` | 10 | 35000 is commonly used in the official benchmark |
|
| 200 |
+
| `max_minimization_iter` | 5 | Standard value: 5000 |
|
| 201 |
+
| `abs_score_convergence_thresh` | 200.0 | Standard value: 1.0 |
|
| 202 |
+
| `backrub_trajectory_stride` | 5 | Controls the interval between Backrub trajectory checkpoints |
|
| 203 |
+
|
| 204 |
+
The small parameter values in this document are intended to shorten runtime and should not be used directly for production ΔΔG calculations.
|
| 205 |
+
|
| 206 |
+
## Single-Site Saturation Mutagenesis
|
| 207 |
+
|
| 208 |
+
Run:
|
| 209 |
+
|
| 210 |
+
```bash
|
| 211 |
+
python scripts/run_example_2_saturation.py
|
| 212 |
+
```
|
| 213 |
+
|
| 214 |
+
The script sequentially generates a resfile for each of the 20 standard amino acid substitutions at the specified residue and runs Flex ddG.
|
| 215 |
+
|
| 216 |
+
Configure the target site in the script:
|
| 217 |
+
|
| 218 |
+
```python
|
| 219 |
+
residue_to_mutate = ('B', 49, '')
|
| 220 |
+
```
|
| 221 |
+
|
| 222 |
+
The format is:
|
| 223 |
+
|
| 224 |
+
```text
|
| 225 |
+
(chain ID, PDB residue number, insertion code)
|
| 226 |
+
```
|
| 227 |
+
|
| 228 |
+
Results are saved in:
|
| 229 |
+
|
| 230 |
+
```text
|
| 231 |
+
output_saturation/
|
| 232 |
+
```
|
| 233 |
+
|
| 234 |
+
## Parallel Execution Recommendations
|
| 235 |
+
|
| 236 |
+
The official scripts use the following defaults:
|
| 237 |
+
|
| 238 |
+
```python
|
| 239 |
+
use_multiprocessing = True
|
| 240 |
+
max_cpus = 2
|
| 241 |
+
```
|
| 242 |
+
|
| 243 |
+
During actual execution, adjust `max_cpus` according to the allocated number of CPU cores and the node's available memory. Each Rosetta instance uses CPU and memory independently, so setting it to all available cores unconditionally is not recommended.
|
| 244 |
+
|
| 245 |
+
# Result Analysis
|
| 246 |
+
|
| 247 |
+
After Example 1 is complete:
|
| 248 |
+
|
| 249 |
+
```bash
|
| 250 |
+
python scripts/analyze_flex_ddG.py output
|
| 251 |
+
```
|
| 252 |
+
|
| 253 |
+
For saturation mutagenesis results:
|
| 254 |
+
|
| 255 |
+
```bash
|
| 256 |
+
python scripts/analyze_flex_ddG.py output_saturation
|
| 257 |
+
```
|
| 258 |
+
|
| 259 |
+
The analysis script outputs:
|
| 260 |
+
|
| 261 |
+
```text
|
| 262 |
+
wt_dG
|
| 263 |
+
mut_dG
|
| 264 |
+
ΔΔG
|
| 265 |
+
```
|
| 266 |
+
|
| 267 |
+
The results are written to:
|
| 268 |
+
|
| 269 |
+
```text
|
| 270 |
+
analysis_output/
|
| 271 |
+
```
|
| 272 |
+
|
| 273 |
+
the CSV files in this directory. It also provides reweighted mutant ΔΔG values using the GAM model fitted in the original Flex ddG paper.
|
| 274 |
+
|
| 275 |
+
To extract structures after Backrub, wild-type minimization, or mutant minimization:
|
| 276 |
+
|
| 277 |
+
```bash
|
| 278 |
+
python scripts/extract_structures.py output
|
| 279 |
+
```
|
| 280 |
+
|
| 281 |
+
The script looks for `struct.db3` and calls Rosetta `score_jd2` to export PDB files.
|
| 282 |
+
|
| 283 |
+
# Output Description
|
| 284 |
+
|
| 285 |
+
After running `scripts/run_example_1.py`, the main results are located at:
|
| 286 |
+
|
| 287 |
+
```text
|
| 288 |
+
output/
|
| 289 |
+
└── <case>/
|
| 290 |
+
└── <replicate>/
|
| 291 |
+
├── rosetta.out
|
| 292 |
+
├── ddG.db3
|
| 293 |
+
└── struct.db3
|
| 294 |
+
```
|
| 295 |
+
|
| 296 |
+
The files are:
|
| 297 |
+
|
| 298 |
+
| File | Description |
|
| 299 |
+
| --- | --- |
|
| 300 |
+
| `rosetta.out` | Rosetta run log |
|
| 301 |
+
| `ddG.db3` | Database of Flex ddG energy and trajectory results |
|
| 302 |
+
| `struct.db3` | Database of structures generated by Rosetta |
|
| 303 |
+
| `analysis_output/*.csv` | Summary of ΔΔG results generated by `scripts/analyze_flex_ddG.py` |
|
| 304 |
+
|
| 305 |
+
The analysis script reads the Backrub trajectory stride from the `ddG.db3` generated by each run, so you usually do not need to modify the analysis script manually. If the database does not contain a stride, use:
|
| 306 |
+
|
| 307 |
+
```bash
|
| 308 |
+
python scripts/analyze_flex_ddG.py output --stride N
|
| 309 |
+
```
|
| 310 |
+
to override it.
|
| 311 |
+
|
| 312 |
+
# Official OneScience Information
|
| 313 |
+
|
| 314 |
+
| Platform | Main OneScience repository | Skills repository |
|
| 315 |
+
| --- | --- | --- |
|
| 316 |
+
| Gitee | https://gitee.com/onescience-ai/onescience | https://gitee.com/onescience-ai/oneskills |
|
| 317 |
+
| GitHub | https://github.com/onescience-ai/OneScience | https://github.com/onescience-ai/oneskills |
|
| 318 |
+
|
| 319 |
+
# Citation and License
|
| 320 |
+
|
| 321 |
+
- Original Flex ddG paper: [Flex ddG: Rosetta Ensemble-Based Estimation of Changes in Protein–Protein Binding Affinity upon Mutation](https://doi.org/10.1021/acs.jpcb.7b11367).
|
| 322 |
+
- Flex ddG uses the Rosetta Backrub conformational sampling method. Related paper: [Backrub-Like Backbone Simulation Recapitulates Natural Protein Conformational Variability and Improves Mutant Side-Chain Prediction](https://doi.org/10.1016/j.jmb.2008.05.023).
|
| 323 |
+
- The official flex_ddG_tutorial source code is released under the MIT License; see `LICENSE` in the repository root.
|
| 324 |
+
- **Rosetta is not covered by the MIT License of the Flex ddG tutorial repository.** Rosetta is distributed under a separate software license; academic and non-commercial users can apply for a non-commercial license, while commercial use requires a separate commercial license.
|
| 325 |
+
- For research use, we recommend citing the relevant Flex ddG, Backrub, and Rosetta publications, and adding citations as required by the relevant OneScience project.
|
conf/ddG-backrub.xml
ADDED
|
@@ -0,0 +1,114 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<ROSETTASCRIPTS>
|
| 2 |
+
<SCOREFXNS>
|
| 3 |
+
<ScoreFunction name="fa_talaris2014" weights="talaris2014"/>
|
| 4 |
+
<ScoreFunction name="fa_talaris2014_cst" weights="talaris2014">
|
| 5 |
+
<Reweight scoretype="atom_pair_constraint" weight="1.0"/>
|
| 6 |
+
<Set fa_max_dis="9.0"/>
|
| 7 |
+
</ScoreFunction>
|
| 8 |
+
</SCOREFXNS>
|
| 9 |
+
|
| 10 |
+
<!-- ### Only required input file (other than PDB) - mutation resfile ### -->
|
| 11 |
+
<!-- #### All residues must be set to be NATAA packable at top of resfile ### -->
|
| 12 |
+
<TASKOPERATIONS>
|
| 13 |
+
<ReadResfile name="res_mutate" filename="%%mutate_resfile_relpath%%"/>
|
| 14 |
+
</TASKOPERATIONS>
|
| 15 |
+
|
| 16 |
+
<RESIDUE_SELECTORS>
|
| 17 |
+
<Task name="resselector" fixed="0" packable="0" designable="1" task_operations="res_mutate"/>
|
| 18 |
+
<Neighborhood name="bubble" selector="resselector" distance="8.0"/>
|
| 19 |
+
<PrimarySequenceNeighborhood name="bubble_adjacent" selector="bubble" lower="1" upper="1"/>
|
| 20 |
+
<StoredResidueSubset name="restore_neighbor_shell" subset_name="neighbor_shell"/>
|
| 21 |
+
<Not name="everythingelse" selector="restore_neighbor_shell"/>
|
| 22 |
+
</RESIDUE_SELECTORS>
|
| 23 |
+
<TASKOPERATIONS>
|
| 24 |
+
<OperateOnResidueSubset name="repackonly" selector="restore_neighbor_shell">
|
| 25 |
+
<RestrictToRepackingRLT/>
|
| 26 |
+
</OperateOnResidueSubset>
|
| 27 |
+
<OperateOnResidueSubset name="norepack" selector="everythingelse">
|
| 28 |
+
<PreventRepackingRLT/>
|
| 29 |
+
</OperateOnResidueSubset>
|
| 30 |
+
<UseMultiCoolAnnealer name="multicool" states="6"/>
|
| 31 |
+
<ExtraChiCutoff name="extrachizero" extrachi_cutoff="0"/>
|
| 32 |
+
<InitializeFromCommandline name="commandline_init"/>
|
| 33 |
+
<RestrictToRepacking name="restrict_to_repacking"/>
|
| 34 |
+
</TASKOPERATIONS>
|
| 35 |
+
|
| 36 |
+
<FILTERS>
|
| 37 |
+
</FILTERS>
|
| 38 |
+
|
| 39 |
+
<MOVERS>
|
| 40 |
+
<StoreResidueSubset name="neighbor_shell_storer" subset_name="neighbor_shell" residue_selector="bubble_adjacent" />
|
| 41 |
+
|
| 42 |
+
<AddConstraintsToCurrentConformationMover name="addcst" use_distance_cst="1" coord_dev="0.5" min_seq_sep="0" max_distance="9" CA_only="1" bound_width="0.0" cst_weight="0.0"/>
|
| 43 |
+
<ClearConstraintsMover name="clearcst"/>
|
| 44 |
+
<MinMover name="minimize" scorefxn="fa_talaris2014_cst" chi="1" bb="1" type="lbfgs_armijo_nonmonotone" tolerance="0.000001" max_iter="%%max_minimization_iter%%" abs_score_convergence_threshold="%%abs_score_convergence_thresh%%"/>
|
| 45 |
+
|
| 46 |
+
<PackRotamersMover name="repack" scorefxn="fa_talaris2014" task_operations="commandline_init,repackonly,norepack,multicool"/>
|
| 47 |
+
<PackRotamersMover name="mutate" scorefxn="fa_talaris2014" task_operations="commandline_init,res_mutate,norepack,multicool"/>
|
| 48 |
+
|
| 49 |
+
<ReportToDB name="dbreport" batch_description="interface_ddG" database_name="ddG.db3">
|
| 50 |
+
<ScoreTypeFeatures/>
|
| 51 |
+
<ScoreFunctionFeatures scorefxn="fa_talaris2014"/>
|
| 52 |
+
<StructureScoresFeatures scorefxn="fa_talaris2014"/>
|
| 53 |
+
</ReportToDB>
|
| 54 |
+
|
| 55 |
+
<ReportToDB name="structreport" batch_description="interface_ddG_struct" database_name="struct.db3">
|
| 56 |
+
<PoseConformationFeatures/>
|
| 57 |
+
<PdbDataFeatures/>
|
| 58 |
+
<JobDataFeatures/>
|
| 59 |
+
<ResidueFeatures/>
|
| 60 |
+
<PoseCommentsFeatures/>
|
| 61 |
+
<ProteinResidueConformationFeatures/>
|
| 62 |
+
<ResidueConformationFeatures/>
|
| 63 |
+
</ReportToDB>
|
| 64 |
+
|
| 65 |
+
<SavePoseMover name="save_wt_bound_pose" restore_pose="0" reference_name="wt_bound_pose"/>
|
| 66 |
+
<SavePoseMover name="save_backrub_pose" restore_pose="0" reference_name="backrubpdb"/>
|
| 67 |
+
<SavePoseMover name="restore_backrub_pose" restore_pose="1" reference_name="backrubpdb"/>
|
| 68 |
+
|
| 69 |
+
<InterfaceDdGMover name="int_ddG_mover" wt_ref_savepose_mover="save_wt_bound_pose" chain_name="%%chainstomove%%" db_reporter="dbreport" scorefxn="fa_talaris2014"/>
|
| 70 |
+
|
| 71 |
+
<ScoreMover name="apply_score" scorefxn="fa_talaris2014_cst" verbose="0"/>
|
| 72 |
+
|
| 73 |
+
<!-- This ParsedProtocol allows the ddG calculation to take place multiple times along the backrub trajectory, if desired -->
|
| 74 |
+
<ParsedProtocol name="finish_ddg_post_backrub">
|
| 75 |
+
<Add mover_name="save_backrub_pose"/>
|
| 76 |
+
<Add mover_name="structreport"/>
|
| 77 |
+
|
| 78 |
+
<Add mover_name="repack"/>
|
| 79 |
+
|
| 80 |
+
<Add mover_name="addcst"/>
|
| 81 |
+
<Add mover_name="minimize"/>
|
| 82 |
+
<Add mover_name="clearcst"/>
|
| 83 |
+
|
| 84 |
+
<Add mover_name="save_wt_bound_pose"/>
|
| 85 |
+
<Add mover_name="structreport"/>
|
| 86 |
+
<Add mover_name="restore_backrub_pose"/>
|
| 87 |
+
|
| 88 |
+
<Add mover_name="mutate"/>
|
| 89 |
+
|
| 90 |
+
<Add mover_name="addcst"/>
|
| 91 |
+
<Add mover_name="minimize"/>
|
| 92 |
+
<Add mover_name="clearcst"/>
|
| 93 |
+
<Add mover_name="structreport"/>
|
| 94 |
+
|
| 95 |
+
<Add mover_name="int_ddG_mover"/>
|
| 96 |
+
</ParsedProtocol>
|
| 97 |
+
|
| 98 |
+
<BackrubProtocol name="backrub" mc_kt="1.2" ntrials="%%number_backrub_trials%%" pivot_residue_selector="restore_neighbor_shell" task_operations="restrict_to_repacking,commandline_init,extrachizero" recover_low="0" trajectory_stride="%%backrub_trajectory_stride%%" trajectory_apply_mover="finish_ddg_post_backrub"/>
|
| 99 |
+
|
| 100 |
+
</MOVERS>
|
| 101 |
+
<APPLY_TO_POSE>
|
| 102 |
+
</APPLY_TO_POSE>
|
| 103 |
+
<PROTOCOLS>
|
| 104 |
+
<Add mover_name="addcst"/>
|
| 105 |
+
<Add mover_name="apply_score"/> <!-- Necessary to initialize neighbor graph -->
|
| 106 |
+
<Add mover_name="neighbor_shell_storer"/>
|
| 107 |
+
|
| 108 |
+
<Add mover_name="minimize"/>
|
| 109 |
+
<Add mover_name="clearcst"/>
|
| 110 |
+
|
| 111 |
+
<Add mover_name="backrub"/>
|
| 112 |
+
</PROTOCOLS>
|
| 113 |
+
<OUTPUT />
|
| 114 |
+
</ROSETTASCRIPTS>
|
conf/ddG-no_backrub_control.xml
ADDED
|
@@ -0,0 +1,108 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<ROSETTASCRIPTS>
|
| 2 |
+
<SCOREFXNS>
|
| 3 |
+
<ScoreFunction name="fa_talaris2014" weights="talaris2014"/>
|
| 4 |
+
<ScoreFunction name="fa_talaris2014_cst" weights="talaris2014">
|
| 5 |
+
<Reweight scoretype="atom_pair_constraint" weight="1.0"/>
|
| 6 |
+
<Set fa_max_dis="9.0"/>
|
| 7 |
+
</ScoreFunction>
|
| 8 |
+
</SCOREFXNS>
|
| 9 |
+
|
| 10 |
+
<!-- ### Only required input file (other than PDB) - mutation resfile ### -->
|
| 11 |
+
<!-- #### All residues must be set to be NATAA packable at top of resfile ### -->
|
| 12 |
+
<TASKOPERATIONS>
|
| 13 |
+
<ReadResfile name="res_mutate" filename="%%mutate_resfile_relpath%%"/>
|
| 14 |
+
</TASKOPERATIONS>
|
| 15 |
+
|
| 16 |
+
<RESIDUE_SELECTORS>
|
| 17 |
+
<Task name="resselector" fixed="0" packable="0" designable="1" task_operations="res_mutate"/>
|
| 18 |
+
<Neighborhood name="bubble" selector="resselector" distance="8.0"/>
|
| 19 |
+
<PrimarySequenceNeighborhood name="bubble_adjacent" selector="bubble" lower="1" upper="1"/>
|
| 20 |
+
<StoredResidueSubset name="restore_neighbor_shell" subset_name="neighbor_shell"/>
|
| 21 |
+
<Not name="everythingelse" selector="restore_neighbor_shell"/>
|
| 22 |
+
</RESIDUE_SELECTORS>
|
| 23 |
+
<TASKOPERATIONS>
|
| 24 |
+
<OperateOnResidueSubset name="repackonly" selector="restore_neighbor_shell">
|
| 25 |
+
<RestrictToRepackingRLT/>
|
| 26 |
+
</OperateOnResidueSubset>
|
| 27 |
+
<OperateOnResidueSubset name="norepack" selector="everythingelse">
|
| 28 |
+
<PreventRepackingRLT/>
|
| 29 |
+
</OperateOnResidueSubset>
|
| 30 |
+
<UseMultiCoolAnnealer name="multicool" states="6"/>
|
| 31 |
+
<ExtraChiCutoff name="extrachizero" extrachi_cutoff="0"/>
|
| 32 |
+
<InitializeFromCommandline name="commandline_init"/>
|
| 33 |
+
<RestrictToRepacking name="restrict_to_repacking"/>
|
| 34 |
+
</TASKOPERATIONS>
|
| 35 |
+
|
| 36 |
+
<FILTERS>
|
| 37 |
+
</FILTERS>
|
| 38 |
+
|
| 39 |
+
<MOVERS>
|
| 40 |
+
<StoreResidueSubset name="neighbor_shell_storer" subset_name="neighbor_shell" residue_selector="bubble_adjacent" />
|
| 41 |
+
|
| 42 |
+
<AddConstraintsToCurrentConformationMover name="addcst" use_distance_cst="1" coord_dev="0.5" min_seq_sep="0" max_distance="9" CA_only="1" bound_width="0.0" cst_weight="0.0"/>
|
| 43 |
+
<ClearConstraintsMover name="clearcst"/>
|
| 44 |
+
<MinMover name="minimize" scorefxn="fa_talaris2014_cst" chi="1" bb="1" type="lbfgs_armijo_nonmonotone" tolerance="0.000001" max_iter="%%max_minimization_iter%%" abs_score_convergence_threshold="%%abs_score_convergence_thresh%%"/>
|
| 45 |
+
|
| 46 |
+
<PackRotamersMover name="repack" scorefxn="fa_talaris2014" task_operations="commandline_init,repackonly,norepack,multicool"/>
|
| 47 |
+
<PackRotamersMover name="mutate" scorefxn="fa_talaris2014" task_operations="commandline_init,res_mutate,norepack,multicool"/>
|
| 48 |
+
|
| 49 |
+
<ReportToDB name="dbreport" batch_description="interface_ddG" database_name="ddG.db3">
|
| 50 |
+
<ScoreTypeFeatures/>
|
| 51 |
+
<ScoreFunctionFeatures scorefxn="fa_talaris2014"/>
|
| 52 |
+
<StructureScoresFeatures scorefxn="fa_talaris2014"/>
|
| 53 |
+
</ReportToDB>
|
| 54 |
+
|
| 55 |
+
<ReportToDB name="structreport" batch_description="interface_ddG_struct" database_name="struct.db3">
|
| 56 |
+
<PoseConformationFeatures/>
|
| 57 |
+
<PdbDataFeatures/>
|
| 58 |
+
<JobDataFeatures/>
|
| 59 |
+
<ResidueFeatures/>
|
| 60 |
+
<PoseCommentsFeatures/>
|
| 61 |
+
<ProteinResidueConformationFeatures/>
|
| 62 |
+
<ResidueConformationFeatures/>
|
| 63 |
+
</ReportToDB>
|
| 64 |
+
|
| 65 |
+
<SavePoseMover name="save_wt_bound_pose" restore_pose="0" reference_name="wt_bound_pose"/>
|
| 66 |
+
<SavePoseMover name="save_backrub_pose" restore_pose="0" reference_name="backrubpdb"/>
|
| 67 |
+
<SavePoseMover name="restore_backrub_pose" restore_pose="1" reference_name="backrubpdb"/>
|
| 68 |
+
|
| 69 |
+
<InterfaceDdGMover name="int_ddG_mover" wt_ref_savepose_mover="save_wt_bound_pose" chain_name="%%chainstomove%%" db_reporter="dbreport" scorefxn="fa_talaris2014"/>
|
| 70 |
+
|
| 71 |
+
<ScoreMover name="apply_score" scorefxn="fa_talaris2014_cst" verbose="0"/>
|
| 72 |
+
|
| 73 |
+
</MOVERS>
|
| 74 |
+
<APPLY_TO_POSE>
|
| 75 |
+
</APPLY_TO_POSE>
|
| 76 |
+
<PROTOCOLS>
|
| 77 |
+
<Add mover_name="addcst"/>
|
| 78 |
+
<Add mover_name="apply_score"/> <!-- Necessary to initialize neighbor graph -->
|
| 79 |
+
<Add mover_name="neighbor_shell_storer"/>
|
| 80 |
+
|
| 81 |
+
<Add mover_name="minimize"/>
|
| 82 |
+
<Add mover_name="clearcst"/>
|
| 83 |
+
|
| 84 |
+
<Add mover_name="save_backrub_pose"/>
|
| 85 |
+
<Add mover_name="structreport"/>
|
| 86 |
+
|
| 87 |
+
<Add mover_name="repack"/>
|
| 88 |
+
|
| 89 |
+
<Add mover_name="addcst"/>
|
| 90 |
+
<Add mover_name="minimize"/>
|
| 91 |
+
<Add mover_name="clearcst"/>
|
| 92 |
+
|
| 93 |
+
<Add mover_name="save_wt_bound_pose"/>
|
| 94 |
+
<Add mover_name="structreport"/>
|
| 95 |
+
<Add mover_name="restore_backrub_pose"/>
|
| 96 |
+
|
| 97 |
+
<Add mover_name="mutate"/>
|
| 98 |
+
|
| 99 |
+
<Add mover_name="addcst"/>
|
| 100 |
+
<Add mover_name="minimize"/>
|
| 101 |
+
<Add mover_name="clearcst"/>
|
| 102 |
+
<Add mover_name="structreport"/>
|
| 103 |
+
|
| 104 |
+
<Add mover_name="int_ddG_mover"/>
|
| 105 |
+
|
| 106 |
+
</PROTOCOLS>
|
| 107 |
+
<OUTPUT />
|
| 108 |
+
</ROSETTASCRIPTS>
|
conf/fig-overview.png
ADDED
|
Git LFS Details
|
conf/per_chain_rescore.xml
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<ROSETTASCRIPTS>
|
| 2 |
+
<!--
|
| 3 |
+
Reprocess an EXISTING flex ddG run to recover per-chain intramolecular energies.
|
| 4 |
+
|
| 5 |
+
No re-sampling is needed: struct.db3 already holds the coordinates of every backrub,
|
| 6 |
+
wild type minimized, and mutant minimized pose. This protocol reads those poses back in,
|
| 7 |
+
isolates one chain at a time, and reports the isolated chain's total score.
|
| 8 |
+
|
| 9 |
+
Isolating the chain matters. A Chain residue selector alone is not enough, because
|
| 10 |
+
struct.db3 stores the *bound* poses, so a selector-scoped metric still picks up cross-chain
|
| 11 |
+
pair energies (roughly half the interface energy leaks into each chain). Deleting the other
|
| 12 |
+
chains reproduces the separated, unrelaxed unbound state exactly, because intra-chain
|
| 13 |
+
energy is invariant under the rigid-body translation InterfaceDdGMover uses to unbind.
|
| 14 |
+
|
| 15 |
+
Chain selectors below are for a two chain A/B complex. Add one Chain selector, one
|
| 16 |
+
DeleteRegionMover, one ReportToDB and one restore/delete/report triple per extra chain.
|
| 17 |
+
|
| 18 |
+
Usage (run once per struct.db3, from the directory containing it):
|
| 19 |
+
|
| 20 |
+
rosetta_scripts -inout:dbms:database_name struct.db3 -in:use_database \
|
| 21 |
+
-parser:protocol per_chain_rescore.xml \
|
| 22 |
+
-restore_talaris_behavior -in:file:fullatom -out:nooutput
|
| 23 |
+
|
| 24 |
+
Then read per_chain.db3 with reprocess_per_chain.py.
|
| 25 |
+
-->
|
| 26 |
+
<SCOREFXNS>
|
| 27 |
+
<ScoreFunction name="fa_talaris2014" weights="talaris2014"/>
|
| 28 |
+
</SCOREFXNS>
|
| 29 |
+
|
| 30 |
+
<RESIDUE_SELECTORS>
|
| 31 |
+
<Chain name="chain_A" chains="A"/>
|
| 32 |
+
<Chain name="chain_B" chains="B"/>
|
| 33 |
+
<Not name="not_chain_A" selector="chain_A"/>
|
| 34 |
+
<Not name="not_chain_B" selector="chain_B"/>
|
| 35 |
+
</RESIDUE_SELECTORS>
|
| 36 |
+
|
| 37 |
+
<MOVERS>
|
| 38 |
+
<SavePoseMover name="save_full" reference_name="full_pose" restore_pose="0"/>
|
| 39 |
+
<SavePoseMover name="restore_full" reference_name="full_pose" restore_pose="1"/>
|
| 40 |
+
|
| 41 |
+
<DeleteRegionMover name="isolate_chain_A" residue_selector="not_chain_A"/>
|
| 42 |
+
<DeleteRegionMover name="isolate_chain_B" residue_selector="not_chain_B"/>
|
| 43 |
+
|
| 44 |
+
<ReportToDB name="chain_A_report" batch_description="per_chain" database_name="per_chain.db3">
|
| 45 |
+
<ScoreTypeFeatures/>
|
| 46 |
+
<ScoreFunctionFeatures scorefxn="fa_talaris2014"/>
|
| 47 |
+
<StructureScoresFeatures scorefxn="fa_talaris2014"/>
|
| 48 |
+
</ReportToDB>
|
| 49 |
+
<ReportToDB name="chain_B_report" batch_description="per_chain" database_name="per_chain.db3">
|
| 50 |
+
<ScoreTypeFeatures/>
|
| 51 |
+
<ScoreFunctionFeatures scorefxn="fa_talaris2014"/>
|
| 52 |
+
<StructureScoresFeatures scorefxn="fa_talaris2014"/>
|
| 53 |
+
</ReportToDB>
|
| 54 |
+
</MOVERS>
|
| 55 |
+
|
| 56 |
+
<PROTOCOLS>
|
| 57 |
+
<Add mover_name="save_full"/>
|
| 58 |
+
<Add mover_name="isolate_chain_A"/>
|
| 59 |
+
<Add mover_name="chain_A_report"/>
|
| 60 |
+
|
| 61 |
+
<Add mover_name="restore_full"/>
|
| 62 |
+
<Add mover_name="isolate_chain_B"/>
|
| 63 |
+
<Add mover_name="chain_B_report"/>
|
| 64 |
+
</PROTOCOLS>
|
| 65 |
+
<OUTPUT />
|
| 66 |
+
</ROSETTASCRIPTS>
|
conf/split_protocol/flex_ddG-backrub_step.xml
ADDED
|
@@ -0,0 +1,108 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<ROSETTASCRIPTS>
|
| 2 |
+
<SCOREFXNS>
|
| 3 |
+
<ScoreFunction name="fa_fxn" weights="talaris2014">
|
| 4 |
+
</ScoreFunction>
|
| 5 |
+
<ScoreFunction name="fa_fxn_cst" weights="talaris2014">
|
| 6 |
+
<Reweight scoretype="atom_pair_constraint" weight="1.0"/>
|
| 7 |
+
<Set fa_max_dis="9.0"/>
|
| 8 |
+
</ScoreFunction>
|
| 9 |
+
</SCOREFXNS>
|
| 10 |
+
|
| 11 |
+
<!-- ### Only required input - mutation resfile ### -->
|
| 12 |
+
<!-- #### All residues must be set to be NATAA packable at top of resfile ### -->
|
| 13 |
+
<TASKOPERATIONS>
|
| 14 |
+
<ReadResfile name="res_mutate" filename="%%mutate_resfile_relpath%%"/>
|
| 15 |
+
</TASKOPERATIONS>
|
| 16 |
+
|
| 17 |
+
<RESIDUE_SELECTORS>
|
| 18 |
+
<Task name="resselector" fixed="0" packable="0" designable="1" task_operations="res_mutate"/>
|
| 19 |
+
<Neighborhood name="bubble" selector="resselector" distance="%%neighbor_distance%%" include_focus_in_subset="true"/>
|
| 20 |
+
<PrimarySequenceNeighborhood name="bubble_adjacent" selector="bubble" lower="1" upper="1"/>
|
| 21 |
+
<StoredResidueSubset name="restore_neighbor_shell" subset_name="neighbor_shell"/>
|
| 22 |
+
<Not name="everythingelse" selector="restore_neighbor_shell"/>
|
| 23 |
+
</RESIDUE_SELECTORS>
|
| 24 |
+
<TASKOPERATIONS>
|
| 25 |
+
<OperateOnResidueSubset name="repackonly" selector="restore_neighbor_shell">
|
| 26 |
+
<RestrictToRepackingRLT/>
|
| 27 |
+
</OperateOnResidueSubset>
|
| 28 |
+
<OperateOnResidueSubset name="norepack" selector="everythingelse">
|
| 29 |
+
<PreventRepackingRLT/>
|
| 30 |
+
</OperateOnResidueSubset>
|
| 31 |
+
<UseMultiCoolAnnealer name="multicool" states="6"/>
|
| 32 |
+
<ExtraChiCutoff name="extrachizero" extrachi_cutoff="0"/>
|
| 33 |
+
<InitializeFromCommandline name="commandline_init"/>
|
| 34 |
+
<RestrictToRepacking name="restrict_to_repacking"/>
|
| 35 |
+
</TASKOPERATIONS>
|
| 36 |
+
|
| 37 |
+
<FILTERS>
|
| 38 |
+
</FILTERS>
|
| 39 |
+
|
| 40 |
+
<MOVERS>
|
| 41 |
+
<StoreResidueSubset name="neighbor_shell_storer" subset_name="neighbor_shell" residue_selector="bubble_adjacent" />
|
| 42 |
+
|
| 43 |
+
<AddConstraintsToCurrentConformationMover name="addcst" use_distance_cst="1" coord_dev="0.5" min_seq_sep="0" max_distance="9" CA_only="1" bound_width="0.0" cst_weight="0.0"/>
|
| 44 |
+
<ClearConstraintsMover name="clearcst"/>
|
| 45 |
+
<MinMover name="minimize" scorefxn="fa_fxn_cst" chi="1" bb="1" type="lbfgs_armijo_nonmonotone" tolerance="%%min_tolerance%%" max_iter="%%min_max_iter%%" abs_score_convergence_threshold="%%min_abs_score_convergence_threshold%%"/>
|
| 46 |
+
|
| 47 |
+
<PackRotamersMover name="repack" scorefxn="fa_fxn" task_operations="commandline_init,repackonly,norepack,multicool"/>
|
| 48 |
+
|
| 49 |
+
<SavePoseMover name="input_struct_spm" reference_name="input_struct"/>
|
| 50 |
+
<SavePoseMover name="input_struct_lpm" restore_pose="1" reference_name="input_struct"/>
|
| 51 |
+
<SavePoseMover name="min_input_struct_spm" reference_name="min_input_struct"/>
|
| 52 |
+
<SavePoseMover name="min_input_struct_lpm" restore_pose="1" reference_name="min_input_struct"/>
|
| 53 |
+
|
| 54 |
+
<ReportToDB name="structreport" batch_description="interface_ddG_struct" database_name="struct.db3">
|
| 55 |
+
<PoseConformationFeatures/>
|
| 56 |
+
<PdbDataFeatures/>
|
| 57 |
+
<JobDataFeatures/>
|
| 58 |
+
<ResidueFeatures/>
|
| 59 |
+
<PoseCommentsFeatures/>
|
| 60 |
+
<ProteinResidueConformationFeatures/>
|
| 61 |
+
<ResidueConformationFeatures/>
|
| 62 |
+
<RotamerFeatures/>
|
| 63 |
+
<ResidueBurialFeatures/>
|
| 64 |
+
<ProteinRMSDFeatures reference_name="min_input_struct"/>
|
| 65 |
+
</ReportToDB>
|
| 66 |
+
|
| 67 |
+
<ScoreMover name="apply_score" scorefxn="fa_fxn_cst" verbose="0"/>
|
| 68 |
+
|
| 69 |
+
<PDBTrajectoryRecorder name="dump_wt_minimized" stride="1" filename="wt_minimized.pdb"/>
|
| 70 |
+
|
| 71 |
+
<ParsedProtocol name="finish_wt_post_backrub">
|
| 72 |
+
<Add mover_name="structreport"/>
|
| 73 |
+
|
| 74 |
+
<Add mover_name="repack"/>
|
| 75 |
+
|
| 76 |
+
<Add mover_name="addcst"/>
|
| 77 |
+
<Add mover_name="minimize"/>
|
| 78 |
+
<Add mover_name="clearcst"/>
|
| 79 |
+
|
| 80 |
+
<Add mover_name="structreport"/>
|
| 81 |
+
<Add mover_name="dump_wt_minimized"/>
|
| 82 |
+
</ParsedProtocol>
|
| 83 |
+
|
| 84 |
+
<BackrubProtocol name="backrub" mc_kt="%%backrub_kt%%" ntrials="%%backrub_trials%%" pivot_residue_selector="restore_neighbor_shell" task_operations="restrict_to_repacking,commandline_init,extrachizero" recover_low="0" trajectory_stride="%%backrub_stride%%" trajectory_apply_mover="finish_wt_post_backrub" trajectory="1" scorefxn="fa_fxn"/>
|
| 85 |
+
|
| 86 |
+
</MOVERS>
|
| 87 |
+
<APPLY_TO_POSE>
|
| 88 |
+
</APPLY_TO_POSE>
|
| 89 |
+
<PROTOCOLS>
|
| 90 |
+
<Add mover_name="input_struct_spm"/>
|
| 91 |
+
<Add mover_name="addcst"/>
|
| 92 |
+
<Add mover_name="apply_score"/> <!-- Necessary to initialize neighbor graph -->
|
| 93 |
+
<Add mover_name="neighbor_shell_storer"/>
|
| 94 |
+
|
| 95 |
+
<Add mover_name="minimize"/>
|
| 96 |
+
|
| 97 |
+
<Add mover_name="clearcst"/>
|
| 98 |
+
<Add mover_name="min_input_struct_spm"/>
|
| 99 |
+
|
| 100 |
+
<Add mover_name="input_struct_lpm"/>
|
| 101 |
+
<Add mover_name="structreport"/>
|
| 102 |
+
<Add mover_name="min_input_struct_lpm"/>
|
| 103 |
+
<Add mover_name="structreport"/>
|
| 104 |
+
|
| 105 |
+
<Add mover_name="backrub"/>
|
| 106 |
+
</PROTOCOLS>
|
| 107 |
+
<OUTPUT />
|
| 108 |
+
</ROSETTASCRIPTS>
|
conf/split_protocol/flex_ddG-mutation_step.xml
ADDED
|
@@ -0,0 +1,95 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<ROSETTASCRIPTS>
|
| 2 |
+
<SCOREFXNS>
|
| 3 |
+
<ScoreFunction name="fa_fxn" weights="talaris2014"/>
|
| 4 |
+
<ScoreFunction name="fa_fxn_cst" weights="talaris2014">
|
| 5 |
+
<Reweight scoretype="atom_pair_constraint" weight="1.0"/>
|
| 6 |
+
<Set fa_max_dis="9.0"/>
|
| 7 |
+
</ScoreFunction>
|
| 8 |
+
</SCOREFXNS>
|
| 9 |
+
|
| 10 |
+
<TASKOPERATIONS>
|
| 11 |
+
<ReadResfile name="res_mutate" filename="%%mutate_resfile_relpath%%"/>
|
| 12 |
+
</TASKOPERATIONS>
|
| 13 |
+
|
| 14 |
+
<RESIDUE_SELECTORS>
|
| 15 |
+
<Task name="resselector" fixed="0" packable="0" designable="1" task_operations="res_mutate"/>
|
| 16 |
+
<Neighborhood name="bubble_helper" selector="resselector" distance="%%neighbor_distance%%" include_focus_in_subset="true"/>
|
| 17 |
+
<NativeSelector name="bubble" residue_selector="bubble_helper" />
|
| 18 |
+
<PrimarySequenceNeighborhood name="bubble_adjacent" selector="bubble" lower="1" upper="1"/>
|
| 19 |
+
<StoredResidueSubset name="restore_neighbor_shell" subset_name="neighbor_shell"/>
|
| 20 |
+
<Not name="everythingelse" selector="restore_neighbor_shell"/>
|
| 21 |
+
</RESIDUE_SELECTORS>
|
| 22 |
+
<TASKOPERATIONS>
|
| 23 |
+
<OperateOnResidueSubset name="repackonly" selector="restore_neighbor_shell">
|
| 24 |
+
<RestrictToRepackingRLT/>
|
| 25 |
+
</OperateOnResidueSubset>
|
| 26 |
+
<OperateOnResidueSubset name="norepack" selector="everythingelse">
|
| 27 |
+
<PreventRepackingRLT/>
|
| 28 |
+
</OperateOnResidueSubset>
|
| 29 |
+
<UseMultiCoolAnnealer name="multicool" states="6"/>
|
| 30 |
+
<ExtraChiCutoff name="extrachizero" extrachi_cutoff="0"/>
|
| 31 |
+
<InitializeFromCommandline name="commandline_init"/>
|
| 32 |
+
<RestrictToRepacking name="restrict_to_repacking"/>
|
| 33 |
+
</TASKOPERATIONS>
|
| 34 |
+
|
| 35 |
+
<MOVERS>
|
| 36 |
+
<AddConstraintsToCurrentConformationMover name="addcst" use_distance_cst="1" coord_dev="0.5" min_seq_sep="0" max_distance="9" CA_only="1" bound_width="0.0" cst_weight="0.0"/>
|
| 37 |
+
<ClearConstraintsMover name="clearcst"/>
|
| 38 |
+
<MinMover name="minimize" scorefxn="fa_fxn_cst" chi="1" bb="1" type="lbfgs_armijo_nonmonotone" tolerance="%%min_tolerance%%" max_iter="%%min_max_iter%%" abs_score_convergence_threshold="%%min_abs_score_convergence_threshold%%"/>
|
| 39 |
+
|
| 40 |
+
<PackRotamersMover name="mutate" scorefxn="fa_fxn" task_operations="commandline_init,res_mutate,norepack,multicool"/>
|
| 41 |
+
|
| 42 |
+
<ReportToDB name="dbreport" batch_description="interface_ddG" database_name="ddG.db3">
|
| 43 |
+
<ResidueFeatures/>
|
| 44 |
+
<ScoreTypeFeatures/>
|
| 45 |
+
<ScoreFunctionFeatures scorefxn="fa_fxn"/>
|
| 46 |
+
<StructureScoresFeatures scorefxn="fa_fxn"/>
|
| 47 |
+
<HBondFeatures scorefxn="fa_fxn"/>
|
| 48 |
+
<InterfaceFeatures scorefxn="fa_fxn" pack_together="false"/>
|
| 49 |
+
</ReportToDB>
|
| 50 |
+
|
| 51 |
+
<ReportToDB name="structreport" batch_description="interface_ddG_struct" database_name="struct.db3">
|
| 52 |
+
<PoseConformationFeatures/>
|
| 53 |
+
<PdbDataFeatures/>
|
| 54 |
+
<JobDataFeatures/>
|
| 55 |
+
<ResidueFeatures/>
|
| 56 |
+
<PoseCommentsFeatures/>
|
| 57 |
+
<ProteinResidueConformationFeatures/>
|
| 58 |
+
<ResidueConformationFeatures/>
|
| 59 |
+
<RotamerFeatures/>
|
| 60 |
+
<ResidueBurialFeatures/>
|
| 61 |
+
</ReportToDB>
|
| 62 |
+
|
| 63 |
+
<SavePoseMover name="save_wt_bound_pose" restore_pose="0" reference_name="wt_bound_pose"/>
|
| 64 |
+
<LoadPDB name="load_backrub_pdb" filename="%%backrub_pdb_path%%"/>
|
| 65 |
+
|
| 66 |
+
<InterfaceDdGMover name="int_ddG_mover" wt_ref_savepose_mover="save_wt_bound_pose" chain_name="%%chainstomove%%" db_reporter="dbreport" scorefxn="fa_fxn"/>
|
| 67 |
+
|
| 68 |
+
<ScoreMover name="apply_score" scorefxn="fa_fxn_cst" verbose="0"/>
|
| 69 |
+
<StoreResidueSubset name="neighbor_shell_storer" subset_name="neighbor_shell" residue_selector="bubble_adjacent" />
|
| 70 |
+
|
| 71 |
+
</MOVERS>
|
| 72 |
+
<APPLY_TO_POSE>
|
| 73 |
+
</APPLY_TO_POSE>
|
| 74 |
+
<PROTOCOLS>
|
| 75 |
+
<Add mover_name="save_wt_bound_pose"/>
|
| 76 |
+
|
| 77 |
+
<Add mover_name="load_backrub_pdb"/>
|
| 78 |
+
<Add mover_name="neighbor_shell_storer"/>
|
| 79 |
+
|
| 80 |
+
<Add mover_name="addcst"/>
|
| 81 |
+
<Add mover_name="apply_score"/>
|
| 82 |
+
<Add mover_name="clearcst"/>
|
| 83 |
+
<Add mover_name="mutate"/>
|
| 84 |
+
|
| 85 |
+
<Add mover_name="addcst"/>
|
| 86 |
+
<Add mover_name="minimize"/>
|
| 87 |
+
<Add mover_name="clearcst"/>
|
| 88 |
+
<Add mover_name="structreport"/>
|
| 89 |
+
|
| 90 |
+
<Add mover_name="int_ddG_mover"/>
|
| 91 |
+
|
| 92 |
+
<Add mover_name="dbreport"/>
|
| 93 |
+
</PROTOCOLS>
|
| 94 |
+
<OUTPUT />
|
| 95 |
+
</ROSETTASCRIPTS>
|
conf/split_protocol/split_commands.txt
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
Backrub step command line example:
|
| 2 |
+
|
| 3 |
+
rosetta_scripts.linuxgccrelease
|
| 4 |
+
-parser:protocol flex_ddG-backrub_step.xml
|
| 5 |
+
-s wt_pdb_path # Starting WT crystal structure
|
| 6 |
+
-in:file:fullatom
|
| 7 |
+
-parser:script_vars
|
| 8 |
+
mutate_resfile_relpath=%s # Path to a resfile specifying mutant positions. Can be any set of mutations (only the positions matter), as mutations are made in the next step. Positions need to be known now to pick backrub region.
|
| 9 |
+
backrub_kt=1.2
|
| 10 |
+
backrub_trials=36000
|
| 11 |
+
backrub_stride=12000
|
| 12 |
+
neighbor_distance=12.0
|
| 13 |
+
sc_sample_rotwells_unif=0
|
| 14 |
+
min_tolerance=0.000001
|
| 15 |
+
min_max_iter=5000
|
| 16 |
+
min_abs_score_convergence_threshold=1.0
|
| 17 |
+
|
| 18 |
+
Mutation step command line example:
|
| 19 |
+
|
| 20 |
+
rosetta_scripts.linuxgccrelease
|
| 21 |
+
-parser:protocol flex_ddG-mutation_step.xml
|
| 22 |
+
-s wt_minimized_pdb_path # Path to the WT minimized PDB structure from the first script, needed to score ddG calculation
|
| 23 |
+
-native # Path to the starting WT crystal structure, needed so that same neighbor residue bubble is selected
|
| 24 |
+
-in:file:fullatom
|
| 25 |
+
-parser:script_vars
|
| 26 |
+
chainstomove=%s
|
| 27 |
+
mutate_resfile_relpath=%s # Path to resfile specifying mutations
|
| 28 |
+
min_tolerance=0.000001
|
| 29 |
+
min_max_iter=5000
|
| 30 |
+
neighbor_distance=12.0
|
| 31 |
+
min_abs_score_convergence_threshold=1.0
|
| 32 |
+
backrub_pdb_path=%s # Path to backrub PDB output from earlier step, mutations will be applied to this model
|
config.json
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"project": "flex_ddG_tutorial",
|
| 3 |
+
"purpose": "Directory layout metadata only. This file is not used by the runtime scripts.",
|
| 4 |
+
"layout": {
|
| 5 |
+
"conf": {
|
| 6 |
+
"description": "Rosetta XML protocols and related protocol configuration files.",
|
| 7 |
+
"paths": [
|
| 8 |
+
"conf/ddG-backrub.xml",
|
| 9 |
+
"conf/ddG-no_backrub_control.xml",
|
| 10 |
+
"conf/per_chain_rescore.xml",
|
| 11 |
+
"conf/split_protocol/",
|
| 12 |
+
"conf/fig-overview.png"
|
| 13 |
+
]
|
| 14 |
+
},
|
| 15 |
+
"scripts": {
|
| 16 |
+
"description": "Python entry points, helper modules, and bundled example input data.",
|
| 17 |
+
"paths": [
|
| 18 |
+
"scripts/run_example_1.py",
|
| 19 |
+
"scripts/run_example_2_saturation.py",
|
| 20 |
+
"scripts/analyze_flex_ddG.py",
|
| 21 |
+
"scripts/extract_structures.py",
|
| 22 |
+
"scripts/inputs/"
|
| 23 |
+
]
|
| 24 |
+
},
|
| 25 |
+
"root": {
|
| 26 |
+
"description": "Top-level documentation, license, and static overview assets.",
|
| 27 |
+
"paths": [
|
| 28 |
+
"README.md",
|
| 29 |
+
"LICENSE"
|
| 30 |
+
]
|
| 31 |
+
}
|
| 32 |
+
}
|
| 33 |
+
}
|
scripts/analyze_flex_ddG.py
ADDED
|
@@ -0,0 +1,344 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/usr/bin/python3
|
| 2 |
+
|
| 3 |
+
import sys
|
| 4 |
+
import os
|
| 5 |
+
import sqlite3
|
| 6 |
+
import shutil
|
| 7 |
+
import tempfile
|
| 8 |
+
from pprint import pprint
|
| 9 |
+
import pandas as pd
|
| 10 |
+
import numpy as np
|
| 11 |
+
import re
|
| 12 |
+
import argparse
|
| 13 |
+
import datetime
|
| 14 |
+
import sys
|
| 15 |
+
import collections
|
| 16 |
+
import threading
|
| 17 |
+
|
| 18 |
+
import flex_ddg_db3
|
| 19 |
+
|
| 20 |
+
rosetta_output_file_name = 'rosetta.out'
|
| 21 |
+
output_database_name = 'ddG.db3'
|
| 22 |
+
script_output_folder = 'analysis_output'
|
| 23 |
+
|
| 24 |
+
# Only a fallback. The stride each run actually used is read back out of its own ddG.db3, so
|
| 25 |
+
# runs with different strides analyze correctly and nothing here needs editing to match a run.
|
| 26 |
+
# This value is used only when the database does not record it, and a warning is printed.
|
| 27 |
+
default_trajectory_stride = 5
|
| 28 |
+
|
| 29 |
+
zemu_gam_params = {
|
| 30 |
+
'fa_sol' : (6.940, -6.722),
|
| 31 |
+
'hbond_sc' : (1.902, -1.999),
|
| 32 |
+
'hbond_bb_sc' : (0.063, 0.452),
|
| 33 |
+
'fa_rep' : (1.659, -0.836),
|
| 34 |
+
'fa_elec' : (0.697, -0.122),
|
| 35 |
+
'hbond_lr_bb' : (2.738, -1.179),
|
| 36 |
+
'fa_atr' : (2.313, -1.649),
|
| 37 |
+
}
|
| 38 |
+
|
| 39 |
+
def gam_function(x, score_term = None ):
|
| 40 |
+
return -1.0 * np.exp( zemu_gam_params[score_term][0] ) + 2.0 * np.exp( zemu_gam_params[score_term][0] ) / ( 1.0 + np.exp( -1.0 * x * np.exp( zemu_gam_params[score_term][1] ) ) )
|
| 41 |
+
|
| 42 |
+
def apply_zemu_gam(scores):
|
| 43 |
+
new_columns = list(scores.columns)
|
| 44 |
+
new_columns.remove('total_score')
|
| 45 |
+
scores = scores.copy()[ new_columns ]
|
| 46 |
+
for score_term in zemu_gam_params:
|
| 47 |
+
assert( score_term in scores.columns )
|
| 48 |
+
scores[score_term] = scores[score_term].apply( gam_function, score_term = score_term )
|
| 49 |
+
scores[ 'total_score' ] = scores[ list(zemu_gam_params.keys()) ].sum( axis = 1 )
|
| 50 |
+
scores[ 'score_function_name' ] = scores[ 'score_function_name' ] + '-gam'
|
| 51 |
+
return scores
|
| 52 |
+
|
| 53 |
+
def rosetta_output_succeeded( potential_struct_dir ):
|
| 54 |
+
path_to_rosetta_output = os.path.join( potential_struct_dir, rosetta_output_file_name )
|
| 55 |
+
if not os.path.isfile(path_to_rosetta_output):
|
| 56 |
+
return False
|
| 57 |
+
|
| 58 |
+
db3_file = os.path.join( potential_struct_dir, output_database_name )
|
| 59 |
+
if not os.path.isfile( db3_file ):
|
| 60 |
+
return False
|
| 61 |
+
|
| 62 |
+
success_line_found = False
|
| 63 |
+
no_more_batches_line_found = False
|
| 64 |
+
with open( path_to_rosetta_output, 'r' ) as f:
|
| 65 |
+
for line in f:
|
| 66 |
+
if line.startswith( 'protocols.jd2.JobDistributor' ) and 'reported success in' in line:
|
| 67 |
+
success_line_found = True
|
| 68 |
+
if line.startswith( 'protocols.jd2.JobDistributor' ) and 'no more batches to process' in line:
|
| 69 |
+
no_more_batches_line_found = True
|
| 70 |
+
|
| 71 |
+
return no_more_batches_line_found and success_line_found
|
| 72 |
+
|
| 73 |
+
def find_finished_jobs( output_folder ):
|
| 74 |
+
return_dict = {}
|
| 75 |
+
job_dirs = [ os.path.abspath(os.path.join(output_folder, d)) for d in os.listdir(output_folder) if os.path.isdir( os.path.join(output_folder, d) )]
|
| 76 |
+
for job_dir in job_dirs:
|
| 77 |
+
completed_struct_dirs = []
|
| 78 |
+
for potential_struct_dir in sorted([ os.path.abspath(os.path.join(job_dir, d)) for d in os.listdir(job_dir) if os.path.isdir( os.path.join(job_dir, d) )]):
|
| 79 |
+
if rosetta_output_succeeded( potential_struct_dir ):
|
| 80 |
+
completed_struct_dirs.append( potential_struct_dir )
|
| 81 |
+
return_dict[job_dir] = completed_struct_dirs
|
| 82 |
+
|
| 83 |
+
return return_dict
|
| 84 |
+
|
| 85 |
+
def get_scores_from_db3_file(db3_file, struct_number, case_name, trajectory_stride):
|
| 86 |
+
conn = sqlite3.connect(db3_file)
|
| 87 |
+
conn.row_factory = sqlite3.Row
|
| 88 |
+
c = conn.cursor()
|
| 89 |
+
|
| 90 |
+
num_batches = c.execute('SELECT max(batch_id) from batches').fetchone()[0]
|
| 91 |
+
|
| 92 |
+
scores = pd.read_sql_query('''
|
| 93 |
+
SELECT batches.name, structure_scores.struct_id, score_types.score_type_name, structure_scores.score_value, score_function_method_options.score_function_name from structure_scores
|
| 94 |
+
INNER JOIN batches ON batches.batch_id=structure_scores.batch_id
|
| 95 |
+
INNER JOIN score_function_method_options ON score_function_method_options.batch_id=batches.batch_id
|
| 96 |
+
INNER JOIN score_types ON score_types.batch_id=structure_scores.batch_id AND score_types.score_type_id=structure_scores.score_type_id
|
| 97 |
+
''', conn)
|
| 98 |
+
|
| 99 |
+
def renumber_struct_id( struct_id ):
|
| 100 |
+
return trajectory_stride * ( 1 + (int(struct_id-1) // num_batches) )
|
| 101 |
+
|
| 102 |
+
scores['struct_id'] = scores['struct_id'].apply( renumber_struct_id )
|
| 103 |
+
scores['name'] = scores['name'].apply( lambda x: x[:-9] if x.endswith('_dbreport') else x )
|
| 104 |
+
scores = scores.pivot_table( index = ['name', 'struct_id', 'score_function_name'], columns = 'score_type_name', values = 'score_value' ).reset_index()
|
| 105 |
+
scores.rename( columns = {
|
| 106 |
+
'name' : 'state',
|
| 107 |
+
'struct_id' : 'backrub_steps',
|
| 108 |
+
}, inplace=True)
|
| 109 |
+
scores['struct_num'] = struct_number
|
| 110 |
+
scores['case_name'] = case_name
|
| 111 |
+
|
| 112 |
+
conn.close()
|
| 113 |
+
|
| 114 |
+
return scores
|
| 115 |
+
|
| 116 |
+
def get_per_chain_scores_from_db3_file(db3_file, struct_number, case_name, trajectory_stride):
|
| 117 |
+
'''Read the per-chain intramolecular energies written by the per-chain protocol variant
|
| 118 |
+
(see per_chain_protocol.py). Returns None if the run did not report them.
|
| 119 |
+
|
| 120 |
+
Only the unbound states are meaningful here: the chains are 1000 A apart, so there are no
|
| 121 |
+
cross-chain pair energies and each value is exactly that chain's intramolecular energy. On
|
| 122 |
+
the bound states the value additionally carries roughly half the interface energy, because
|
| 123 |
+
Rosetta splits each two-body term between its two residues.
|
| 124 |
+
|
| 125 |
+
Note that chain IDs come back lowercased, because Rosetta lowercases database table names.
|
| 126 |
+
Chain "A" appears here as "a". per_chain_protocol.py refuses to set up a run whose chain IDs
|
| 127 |
+
differ only by case, so this stays unambiguous.
|
| 128 |
+
'''
|
| 129 |
+
conn = sqlite3.connect(db3_file)
|
| 130 |
+
conn.row_factory = sqlite3.Row
|
| 131 |
+
c = conn.cursor()
|
| 132 |
+
|
| 133 |
+
chain_tables = [ row[0] for row in c.execute(
|
| 134 |
+
"SELECT name FROM sqlite_master WHERE type='table' AND name LIKE 'chain\\_%\\_energy' ESCAPE '\\'"
|
| 135 |
+
).fetchall() ]
|
| 136 |
+
if len(chain_tables) == 0:
|
| 137 |
+
conn.close()
|
| 138 |
+
return None
|
| 139 |
+
|
| 140 |
+
num_batches = c.execute('SELECT max(batch_id) from batches').fetchone()[0]
|
| 141 |
+
|
| 142 |
+
dfs = []
|
| 143 |
+
for table in chain_tables:
|
| 144 |
+
chain = table[len('chain_'):-len('_energy')]
|
| 145 |
+
df = pd.read_sql_query('''
|
| 146 |
+
SELECT batches.name, %s.struct_id, %s.total_energy from %s
|
| 147 |
+
INNER JOIN structures ON structures.struct_id=%s.struct_id
|
| 148 |
+
INNER JOIN batches ON batches.batch_id=structures.batch_id
|
| 149 |
+
''' % (table, table, table, table), conn)
|
| 150 |
+
df['chain'] = chain
|
| 151 |
+
dfs.append(df)
|
| 152 |
+
conn.close()
|
| 153 |
+
|
| 154 |
+
scores = pd.concat( dfs )
|
| 155 |
+
scores['struct_id'] = scores['struct_id'].apply(
|
| 156 |
+
lambda struct_id: trajectory_stride * ( 1 + (int(struct_id-1) // num_batches) ) )
|
| 157 |
+
scores['name'] = scores['name'].apply( lambda x: x[:-9] if x.endswith('_dbreport') else x )
|
| 158 |
+
scores.rename( columns = {
|
| 159 |
+
'name' : 'state',
|
| 160 |
+
'struct_id' : 'backrub_steps',
|
| 161 |
+
'total_energy' : 'intra_energy',
|
| 162 |
+
}, inplace=True)
|
| 163 |
+
scores['struct_num'] = struct_number
|
| 164 |
+
scores['case_name'] = case_name
|
| 165 |
+
|
| 166 |
+
return scores
|
| 167 |
+
|
| 168 |
+
def calc_per_chain_ddg( scores ):
|
| 169 |
+
'''Per-chain intramolecular ddG, read off the unbound states and averaged over nstruct.'''
|
| 170 |
+
unbound = scores.loc[ scores['state'].isin(['unbound_wt', 'unbound_mut']) ].copy()
|
| 171 |
+
if len(unbound) == 0:
|
| 172 |
+
return None
|
| 173 |
+
|
| 174 |
+
wide = unbound.pivot_table(
|
| 175 |
+
index = ['case_name', 'chain', 'backrub_steps', 'struct_num'],
|
| 176 |
+
columns = 'state', values = 'intra_energy' ).reset_index()
|
| 177 |
+
if 'unbound_wt' not in wide.columns or 'unbound_mut' not in wide.columns:
|
| 178 |
+
return None
|
| 179 |
+
wide['ddG'] = wide['unbound_mut'] - wide['unbound_wt']
|
| 180 |
+
|
| 181 |
+
summary = wide.groupby( ['case_name', 'chain', 'backrub_steps'] ).agg(
|
| 182 |
+
nstruct = ('ddG', 'size'),
|
| 183 |
+
wt_intra = ('unbound_wt', 'mean'),
|
| 184 |
+
mut_intra = ('unbound_mut', 'mean'),
|
| 185 |
+
ddG = ('ddG', 'mean'),
|
| 186 |
+
ddG_sd = ('ddG', 'std'),
|
| 187 |
+
).reset_index()
|
| 188 |
+
summary['ddG_sem'] = summary['ddG_sd'] / np.sqrt( summary['nstruct'] )
|
| 189 |
+
return summary.round(decimals=5)
|
| 190 |
+
|
| 191 |
+
def resolve_trajectory_stride( db3_file, stride_override = None ):
|
| 192 |
+
'''Stride to label this database's checkpoints with, preferring what the run recorded.'''
|
| 193 |
+
if stride_override is not None:
|
| 194 |
+
return stride_override
|
| 195 |
+
|
| 196 |
+
stride = flex_ddg_db3.trajectory_stride_from_db3( db3_file )
|
| 197 |
+
if stride is not None:
|
| 198 |
+
return stride
|
| 199 |
+
|
| 200 |
+
print( 'WARNING: %s does not record backrub_trajectory_stride; assuming %d.' % (
|
| 201 |
+
db3_file, default_trajectory_stride ) )
|
| 202 |
+
print( ' If the run used a different stride, pass --stride to label the' )
|
| 203 |
+
print( ' checkpoints correctly. This affects labels only, not any energy.' )
|
| 204 |
+
return default_trajectory_stride
|
| 205 |
+
|
| 206 |
+
def process_finished_struct( output_path, case_name, stride_override = None ):
|
| 207 |
+
db3_file = os.path.join( output_path, output_database_name )
|
| 208 |
+
assert( os.path.isfile( db3_file ) )
|
| 209 |
+
struct_number = int( os.path.basename(output_path) )
|
| 210 |
+
trajectory_stride = resolve_trajectory_stride( db3_file, stride_override )
|
| 211 |
+
scores_df = get_scores_from_db3_file( db3_file, struct_number, case_name, trajectory_stride )
|
| 212 |
+
per_chain_df = get_per_chain_scores_from_db3_file( db3_file, struct_number, case_name, trajectory_stride )
|
| 213 |
+
|
| 214 |
+
return scores_df, per_chain_df
|
| 215 |
+
|
| 216 |
+
def calc_ddg( scores ):
|
| 217 |
+
total_structs = np.max( scores['struct_num'] )
|
| 218 |
+
|
| 219 |
+
nstructs_to_analyze = set([total_structs])
|
| 220 |
+
for x in range(10, total_structs):
|
| 221 |
+
if x % 10 == 0:
|
| 222 |
+
nstructs_to_analyze.add(x)
|
| 223 |
+
nstructs_to_analyze = sorted(nstructs_to_analyze)
|
| 224 |
+
|
| 225 |
+
all_ddg_scores = []
|
| 226 |
+
for nstructs in nstructs_to_analyze:
|
| 227 |
+
ddg_scores = scores.loc[ ((scores['state'] == 'unbound_mut') | (scores['state'] == 'bound_wt')) & (scores['struct_num'] <= nstructs) ].copy()
|
| 228 |
+
for column in ddg_scores.columns:
|
| 229 |
+
if column not in ['state', 'case_name', 'backrub_steps', 'struct_num', 'score_function_name']:
|
| 230 |
+
ddg_scores.loc[:,column] *= -1.0
|
| 231 |
+
ddg_scores = pd.concat( [ ddg_scores, scores.loc[ ((scores['state'] == 'unbound_wt') | (scores['state'] == 'bound_mut')) & (scores['struct_num'] <= nstructs) ].copy() ] )
|
| 232 |
+
ddg_scores = ddg_scores.groupby( ['case_name', 'backrub_steps', 'struct_num', 'score_function_name'] ).sum( numeric_only = True ).reset_index()
|
| 233 |
+
|
| 234 |
+
if nstructs == total_structs:
|
| 235 |
+
struct_scores = ddg_scores.copy()
|
| 236 |
+
|
| 237 |
+
ddg_scores = ddg_scores.groupby( ['case_name', 'backrub_steps', 'score_function_name'] ).mean( numeric_only = True ).round(decimals=5).reset_index()
|
| 238 |
+
new_columns = list(ddg_scores.columns.values)
|
| 239 |
+
new_columns.remove( 'struct_num' )
|
| 240 |
+
ddg_scores = ddg_scores[new_columns]
|
| 241 |
+
ddg_scores[ 'scored_state' ] = 'ddG'
|
| 242 |
+
ddg_scores[ 'nstruct' ] = nstructs
|
| 243 |
+
all_ddg_scores.append(ddg_scores)
|
| 244 |
+
|
| 245 |
+
return (pd.concat(all_ddg_scores), struct_scores)
|
| 246 |
+
|
| 247 |
+
def calc_dgs( scores ):
|
| 248 |
+
l = []
|
| 249 |
+
|
| 250 |
+
total_structs = np.max( scores['struct_num'] )
|
| 251 |
+
|
| 252 |
+
nstructs_to_analyze = set([total_structs])
|
| 253 |
+
for x in range(10, total_structs):
|
| 254 |
+
if x % 10 == 0:
|
| 255 |
+
nstructs_to_analyze.add(x)
|
| 256 |
+
nstructs_to_analyze = sorted(nstructs_to_analyze)
|
| 257 |
+
|
| 258 |
+
for state in ['mut', 'wt']:
|
| 259 |
+
for nstructs in nstructs_to_analyze:
|
| 260 |
+
dg_scores = scores.loc[ (scores['state'].str.endswith(state)) & (scores['state'].str.startswith('unbound')) & (scores['struct_num'] <= nstructs) ].copy()
|
| 261 |
+
for column in dg_scores.columns:
|
| 262 |
+
if column not in ['state', 'case_name', 'backrub_steps', 'struct_num', 'score_function_name']:
|
| 263 |
+
dg_scores.loc[:,column] *= -1.0
|
| 264 |
+
dg_scores = pd.concat( [ dg_scores, scores.loc[ (scores['state'].str.endswith(state)) & (scores['state'].str.startswith('bound')) & (scores['struct_num'] <= nstructs) ].copy() ] )
|
| 265 |
+
dg_scores = dg_scores.groupby( ['case_name', 'backrub_steps', 'struct_num', 'score_function_name'] ).sum( numeric_only = True ).reset_index()
|
| 266 |
+
dg_scores = dg_scores.groupby( ['case_name', 'backrub_steps', 'score_function_name'] ).mean( numeric_only = True ).round(decimals=5).reset_index()
|
| 267 |
+
new_columns = list(dg_scores.columns.values)
|
| 268 |
+
new_columns.remove( 'struct_num' )
|
| 269 |
+
dg_scores = dg_scores[new_columns]
|
| 270 |
+
dg_scores[ 'scored_state' ] = state + '_dG'
|
| 271 |
+
dg_scores[ 'nstruct' ] = nstructs
|
| 272 |
+
l.append( dg_scores )
|
| 273 |
+
return l
|
| 274 |
+
|
| 275 |
+
def analyze_output_folder( output_folder, stride_override = None ):
|
| 276 |
+
# Pass in an outer output folder. Subdirectories are considered different mutation cases, with subdirectories of different structures.
|
| 277 |
+
finished_jobs = find_finished_jobs( output_folder )
|
| 278 |
+
if len(finished_jobs) == 0:
|
| 279 |
+
print( 'No finished jobs found' )
|
| 280 |
+
return
|
| 281 |
+
|
| 282 |
+
ddg_scores_dfs = []
|
| 283 |
+
struct_scores_dfs = []
|
| 284 |
+
per_chain_dfs = []
|
| 285 |
+
for finished_job, finished_structs in finished_jobs.items():
|
| 286 |
+
inner_scores_list = []
|
| 287 |
+
inner_per_chain_list = []
|
| 288 |
+
for finished_struct in finished_structs:
|
| 289 |
+
inner_scores, inner_per_chain = process_finished_struct( finished_struct, os.path.basename(finished_job), stride_override )
|
| 290 |
+
inner_scores_list.append( inner_scores )
|
| 291 |
+
if inner_per_chain is not None:
|
| 292 |
+
inner_per_chain_list.append( inner_per_chain )
|
| 293 |
+
scores = pd.concat( inner_scores_list )
|
| 294 |
+
if len(inner_per_chain_list) > 0:
|
| 295 |
+
per_chain_summary = calc_per_chain_ddg( pd.concat( inner_per_chain_list ) )
|
| 296 |
+
if per_chain_summary is not None:
|
| 297 |
+
per_chain_dfs.append( per_chain_summary )
|
| 298 |
+
ddg_scores, struct_scores = calc_ddg( scores )
|
| 299 |
+
struct_scores_dfs.append( struct_scores )
|
| 300 |
+
ddg_scores_dfs.append( ddg_scores )
|
| 301 |
+
ddg_scores_dfs.append( apply_zemu_gam(ddg_scores) )
|
| 302 |
+
ddg_scores_dfs.extend( calc_dgs( scores ) )
|
| 303 |
+
|
| 304 |
+
if not os.path.isdir(script_output_folder):
|
| 305 |
+
os.makedirs(script_output_folder)
|
| 306 |
+
basename = os.path.basename(output_folder)
|
| 307 |
+
|
| 308 |
+
pd.concat( struct_scores_dfs ).to_csv( os.path.join(script_output_folder, basename + '-struct_scores_results.csv' ) )
|
| 309 |
+
|
| 310 |
+
df = pd.concat( ddg_scores_dfs )
|
| 311 |
+
df.to_csv( os.path.join(script_output_folder, basename + '-results.csv') )
|
| 312 |
+
|
| 313 |
+
display_columns = ['backrub_steps', 'case_name', 'nstruct', 'score_function_name', 'scored_state', 'total_score']
|
| 314 |
+
for score_type in ['mut_dG', 'wt_dG', 'ddG']:
|
| 315 |
+
print( score_type )
|
| 316 |
+
print( df.loc[ df['scored_state'] == score_type ][display_columns].head( n = 20 ) )
|
| 317 |
+
print( '' )
|
| 318 |
+
|
| 319 |
+
if len(per_chain_dfs) > 0:
|
| 320 |
+
per_chain = pd.concat( per_chain_dfs )
|
| 321 |
+
per_chain.to_csv( os.path.join(script_output_folder, basename + '-per_chain_results.csv'), index = False )
|
| 322 |
+
print( 'per-chain intramolecular ddG (from the unbound states)' )
|
| 323 |
+
print( per_chain.head( n = 40 ).to_string(index = False) )
|
| 324 |
+
print( '' )
|
| 325 |
+
print( 'NOTE: this is the intramolecular strain difference in the *bound* backbone' )
|
| 326 |
+
print( ' conformation, not a folding ddG -- the unbound state is never relaxed.' )
|
| 327 |
+
print( ' A chain you did not mutate should come out at ~0 +/- ddG_sem; if it does' )
|
| 328 |
+
print( ' not, nstruct is too low to average out the whole-pose minimization noise.' )
|
| 329 |
+
print( '' )
|
| 330 |
+
|
| 331 |
+
if __name__ == '__main__':
|
| 332 |
+
parser = argparse.ArgumentParser(
|
| 333 |
+
description = 'Analyze one or more flex ddG output folders (e.g. "output").' )
|
| 334 |
+
parser.add_argument( 'output_folders', nargs = '+', help = 'flex ddG output folder(s)' )
|
| 335 |
+
parser.add_argument( '--stride', type = int, default = None,
|
| 336 |
+
help = 'override backrub_trajectory_stride instead of reading it from'
|
| 337 |
+
' each ddG.db3. Affects checkpoint labels only, not any energy.' )
|
| 338 |
+
parsed_args = parser.parse_args()
|
| 339 |
+
|
| 340 |
+
for folder_to_analyze in parsed_args.output_folders:
|
| 341 |
+
if os.path.isdir( folder_to_analyze ):
|
| 342 |
+
analyze_output_folder( folder_to_analyze, parsed_args.stride )
|
| 343 |
+
else:
|
| 344 |
+
print( 'ERROR: %s is not a valid directory' % folder_to_analyze )
|
scripts/extract_structures.py
ADDED
|
@@ -0,0 +1,262 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/usr/bin/env python3
|
| 2 |
+
|
| 3 |
+
import os
|
| 4 |
+
import sys
|
| 5 |
+
import argparse
|
| 6 |
+
import functools
|
| 7 |
+
import subprocess
|
| 8 |
+
import re
|
| 9 |
+
import shutil
|
| 10 |
+
import datetime
|
| 11 |
+
import math
|
| 12 |
+
import collections
|
| 13 |
+
import threading
|
| 14 |
+
|
| 15 |
+
import flex_ddg_db3
|
| 16 |
+
|
| 17 |
+
use_multiprocessing = False
|
| 18 |
+
if use_multiprocessing:
|
| 19 |
+
import multiprocessing
|
| 20 |
+
|
| 21 |
+
# The Reporter class is useful for printing output for tasks which will take a long time
|
| 22 |
+
# Really, you should just use tqdm now, but I used this before I knew about tqdm and it removes a dependency
|
| 23 |
+
|
| 24 |
+
# Time in seconds function
|
| 25 |
+
# Converts datetime timedelta object to number of seconds
|
| 26 |
+
def ts(td):
|
| 27 |
+
return (td.microseconds + (td.seconds + td.days * 24 * 3600) * 1e6) / 1e6
|
| 28 |
+
|
| 29 |
+
def mean(l):
|
| 30 |
+
# Not using numpy mean to avoid dependency
|
| 31 |
+
return float( sum(l) ) / float( len(l) )
|
| 32 |
+
|
| 33 |
+
class Reporter:
|
| 34 |
+
def __init__( self, task, entries = 'files', print_output = True, eol_char = '\r' ):
|
| 35 |
+
self._lock = threading.Lock()
|
| 36 |
+
self.print_output = print_output
|
| 37 |
+
self.start = datetime.datetime.now()
|
| 38 |
+
self.entries = entries
|
| 39 |
+
self.lastreport = self.start
|
| 40 |
+
self.task = task
|
| 41 |
+
self.report_interval = datetime.timedelta( seconds = 1 ) # Interval to print progress
|
| 42 |
+
self.n = 0
|
| 43 |
+
self.completion_time = None
|
| 44 |
+
if self.print_output:
|
| 45 |
+
print('\nStarting ' + task)
|
| 46 |
+
self.total_count = None # Total tasks to be processed
|
| 47 |
+
self.maximum_output_string_length = 0
|
| 48 |
+
self.rolling_est_total_time = collections.deque( maxlen = 50 )
|
| 49 |
+
self.kv_callback_results = {}
|
| 50 |
+
self.list_results = []
|
| 51 |
+
self.eol_char = eol_char
|
| 52 |
+
|
| 53 |
+
def set_total_count(self, x):
|
| 54 |
+
self.total_count = x
|
| 55 |
+
self.rolling_est_total_time = collections.deque( maxlen = max(1, int( .05 * x )) )
|
| 56 |
+
|
| 57 |
+
def decrement_total_count(self):
|
| 58 |
+
if self.total_count:
|
| 59 |
+
self.total_count -= 1
|
| 60 |
+
|
| 61 |
+
def report(self, n):
|
| 62 |
+
with self._lock:
|
| 63 |
+
self.n = n
|
| 64 |
+
time_now = datetime.datetime.now()
|
| 65 |
+
if self.print_output and self.lastreport < (time_now - self.report_interval):
|
| 66 |
+
self.lastreport = time_now
|
| 67 |
+
if self.total_count:
|
| 68 |
+
percent_done = float(self.n) / float(self.total_count)
|
| 69 |
+
est_total_time_seconds = ts(time_now - self.start) * (1.0 / percent_done)
|
| 70 |
+
self.rolling_est_total_time.append( est_total_time_seconds )
|
| 71 |
+
est_total_time = datetime.timedelta( seconds = mean(self.rolling_est_total_time) )
|
| 72 |
+
time_remaining = est_total_time - (time_now - self.start)
|
| 73 |
+
eta = time_now + time_remaining
|
| 74 |
+
time_remaining_str = 'ETA: %s Est. time remaining: ' % eta.strftime("%Y-%m-%d %H:%M:%S")
|
| 75 |
+
|
| 76 |
+
time_remaining_str += str( datetime.timedelta( seconds = int(ts(time_remaining)) ) )
|
| 77 |
+
|
| 78 |
+
output_string = " Processed: %d %s (%.1f%%) %s" % (n, self.entries, percent_done*100.0, time_remaining_str)
|
| 79 |
+
else:
|
| 80 |
+
output_string = " Processed: %d %s" % (n, self.entries)
|
| 81 |
+
|
| 82 |
+
output_string += self.eol_char
|
| 83 |
+
|
| 84 |
+
if len(output_string) > self.maximum_output_string_length:
|
| 85 |
+
self.maximum_output_string_length = len(output_string)
|
| 86 |
+
elif len(output_string) < self.maximum_output_string_length:
|
| 87 |
+
output_string = output_string.ljust(self.maximum_output_string_length)
|
| 88 |
+
sys.stdout.write( output_string )
|
| 89 |
+
sys.stdout.flush()
|
| 90 |
+
|
| 91 |
+
def increment_report(self):
|
| 92 |
+
self.report(self.n + 1)
|
| 93 |
+
|
| 94 |
+
def increment_report_callback(self, cb_value):
|
| 95 |
+
self.increment_report()
|
| 96 |
+
|
| 97 |
+
def increment_report_keyval_callback(self, kv_pair):
|
| 98 |
+
key, value = kv_pair
|
| 99 |
+
self.kv_callback_results[key] = value
|
| 100 |
+
self.increment_report()
|
| 101 |
+
|
| 102 |
+
def increment_report_list_callback(self, new_list_items):
|
| 103 |
+
self.list_results.extend(new_list_items)
|
| 104 |
+
self.increment_report()
|
| 105 |
+
|
| 106 |
+
def decrement_report(self):
|
| 107 |
+
self.report(self.n - 1)
|
| 108 |
+
|
| 109 |
+
def add_to_report(self, x):
|
| 110 |
+
self.report(self.n + x)
|
| 111 |
+
|
| 112 |
+
def done(self):
|
| 113 |
+
self.completion_time = datetime.datetime.now()
|
| 114 |
+
if self.print_output:
|
| 115 |
+
print('Done %s, processed %d %s, took %s\n' % (self.task, self.n, self.entries, self.completion_time-self.start))
|
| 116 |
+
|
| 117 |
+
def elapsed_time(self):
|
| 118 |
+
if self.completion_time:
|
| 119 |
+
return self.completion_time - self.start
|
| 120 |
+
else:
|
| 121 |
+
return datetime.datetime.now() - self.start
|
| 122 |
+
|
| 123 |
+
|
| 124 |
+
struct_db3_file = 'struct.db3'
|
| 125 |
+
|
| 126 |
+
# Extraction uses the score_jd2 binary, not rosetta_scripts. It is built alongside
|
| 127 |
+
# rosetta_scripts by the standard Rosetta build, but is a separate executable.
|
| 128 |
+
#score_jd2_path = os.path.expanduser( '~/rosetta/source/bin/score_jd2' )
|
| 129 |
+
score_jd2_path = os.path.expanduser(
|
| 130 |
+
"/public/home/scnb9biwet/jiangqq/flex_ddG_tutorial-master/software/rosetta3.9/main/source/bin/score_jd2.default.linuxgccrelease"
|
| 131 |
+
)
|
| 132 |
+
# Only a fallback. Extracted structures are named by how many backrub steps produced them, so
|
| 133 |
+
# the stride each run used is read back out of its own struct.db3. This value is used only when
|
| 134 |
+
# the database does not record it, and a warning is printed.
|
| 135 |
+
default_trajectory_stride = 5
|
| 136 |
+
|
| 137 |
+
def resolve_trajectory_stride( struct_db, stride_override = None ):
|
| 138 |
+
'''Stride to name this database's extracted PDBs with, preferring what the run recorded.'''
|
| 139 |
+
if stride_override is not None:
|
| 140 |
+
return stride_override
|
| 141 |
+
|
| 142 |
+
stride = flex_ddg_db3.trajectory_stride_from_db3( struct_db )
|
| 143 |
+
if stride is not None:
|
| 144 |
+
return stride
|
| 145 |
+
|
| 146 |
+
print( 'WARNING: %s does not record backrub_trajectory_stride; assuming %d.' % (
|
| 147 |
+
struct_db, default_trajectory_stride ) )
|
| 148 |
+
print( ' If the run used a different stride, pass --stride, or the extracted PDBs' )
|
| 149 |
+
print( ' will be named with the wrong backrub step counts.' )
|
| 150 |
+
return default_trajectory_stride
|
| 151 |
+
|
| 152 |
+
def recursive_find_struct_dbs( input_dir ):
|
| 153 |
+
return_list = []
|
| 154 |
+
|
| 155 |
+
for path in [os.path.join(input_dir, x) for x in os.listdir( input_dir )]:
|
| 156 |
+
if os.path.isdir( path ):
|
| 157 |
+
return_list.extend( recursive_find_struct_dbs( path ) )
|
| 158 |
+
elif os.path.isfile( path ) and os.path.basename( path ) == struct_db3_file:
|
| 159 |
+
return_list.append( path )
|
| 160 |
+
|
| 161 |
+
return return_list
|
| 162 |
+
|
| 163 |
+
def extract_structures( struct_db, rename_function = None ):
|
| 164 |
+
args = [
|
| 165 |
+
os.path.abspath( score_jd2_path ),
|
| 166 |
+
'-inout:dbms:database_name', struct_db3_file,
|
| 167 |
+
'-in:use_database',
|
| 168 |
+
'-out:pdb',
|
| 169 |
+
]
|
| 170 |
+
|
| 171 |
+
working_directory = os.path.dirname( struct_db )
|
| 172 |
+
rosetta_outfile_path = os.path.join(working_directory, 'structure_output.txt' )
|
| 173 |
+
if not use_multiprocessing:
|
| 174 |
+
print(rosetta_outfile_path)
|
| 175 |
+
rosetta_outfile = open( rosetta_outfile_path, 'w')
|
| 176 |
+
if not use_multiprocessing:
|
| 177 |
+
print( ' '.join( args ) )
|
| 178 |
+
# No shell: joining the arguments into a string breaks as soon as a path contains a space.
|
| 179 |
+
rosetta_process = subprocess.Popen(
|
| 180 |
+
args,
|
| 181 |
+
stdout=rosetta_outfile, stderr=subprocess.STDOUT, close_fds = True, cwd = working_directory,
|
| 182 |
+
)
|
| 183 |
+
return_code = rosetta_process.wait()
|
| 184 |
+
rosetta_outfile.close()
|
| 185 |
+
|
| 186 |
+
if return_code == 0:
|
| 187 |
+
os.remove( rosetta_outfile_path )
|
| 188 |
+
else:
|
| 189 |
+
print( 'ERROR: score_jd2 failed on %s (exit %d) -- see %s' % (
|
| 190 |
+
struct_db, return_code, rosetta_outfile_path ) )
|
| 191 |
+
return return_code
|
| 192 |
+
|
| 193 |
+
if rename_function != None:
|
| 194 |
+
for path in [ os.path.join( working_directory, x ) for x in os.listdir( working_directory ) ]:
|
| 195 |
+
m = re.match( r'(\d+)_0001\.pdb$', os.path.basename(path) )
|
| 196 |
+
if m:
|
| 197 |
+
dest_path = os.path.join( working_directory, rename_function( int(m.group(1)) ) )
|
| 198 |
+
shutil.move( path, dest_path )
|
| 199 |
+
|
| 200 |
+
return return_code
|
| 201 |
+
|
| 202 |
+
def flex_ddG_rename(struct_id, trajectory_stride):
|
| 203 |
+
steps = [
|
| 204 |
+
'backrub',
|
| 205 |
+
'wt',
|
| 206 |
+
'mut',
|
| 207 |
+
]
|
| 208 |
+
|
| 209 |
+
return '%s_%05d.pdb' % ( steps[ (struct_id-1) % len(steps) ], (((struct_id-1) // len(steps)) + 1) * trajectory_stride )
|
| 210 |
+
|
| 211 |
+
def main( input_dir, stride_override = None ):
|
| 212 |
+
struct_dbs = recursive_find_struct_dbs( input_dir )
|
| 213 |
+
print( 'Found {:d} structure database files to extract'.format( len(struct_dbs) ) )
|
| 214 |
+
|
| 215 |
+
if use_multiprocessing:
|
| 216 |
+
pool = multiprocessing.Pool()
|
| 217 |
+
r = Reporter('extracting structure database files', entries = '.db3 files')
|
| 218 |
+
r.set_total_count( len(struct_dbs) )
|
| 219 |
+
|
| 220 |
+
for struct_db in struct_dbs:
|
| 221 |
+
# Each database is named using the stride its own run was launched with.
|
| 222 |
+
# functools.partial rather than a lambda, so that this stays picklable for the
|
| 223 |
+
# multiprocessing path below.
|
| 224 |
+
stride = resolve_trajectory_stride( struct_db, stride_override )
|
| 225 |
+
rename_function = functools.partial( flex_ddG_rename, trajectory_stride = stride )
|
| 226 |
+
if use_multiprocessing:
|
| 227 |
+
pool.apply_async(
|
| 228 |
+
extract_structures,
|
| 229 |
+
args = (struct_db,),
|
| 230 |
+
kwds = {'rename_function' : rename_function},
|
| 231 |
+
callback = r.increment_report_callback
|
| 232 |
+
)
|
| 233 |
+
else:
|
| 234 |
+
r.increment_report_callback(
|
| 235 |
+
extract_structures( struct_db, rename_function = rename_function )
|
| 236 |
+
)
|
| 237 |
+
|
| 238 |
+
if use_multiprocessing:
|
| 239 |
+
pool.close()
|
| 240 |
+
pool.join()
|
| 241 |
+
r.done()
|
| 242 |
+
|
| 243 |
+
if __name__ == '__main__':
|
| 244 |
+
parser = argparse.ArgumentParser(
|
| 245 |
+
description = 'Extract PDBs from the struct.db3 files under a flex ddG output folder.' )
|
| 246 |
+
parser.add_argument( 'output_folders', nargs = '+', help = 'flex ddG output folder(s)' )
|
| 247 |
+
parser.add_argument( '--stride', type = int, default = None,
|
| 248 |
+
help = 'override backrub_trajectory_stride instead of reading it from'
|
| 249 |
+
' each struct.db3. Affects extracted PDB names only.' )
|
| 250 |
+
parsed_args = parser.parse_args()
|
| 251 |
+
|
| 252 |
+
if not os.path.isfile( score_jd2_path ):
|
| 253 |
+
print( 'ERROR: "score_jd2_path" variable must be set to the location of the "score_jd2" binary executable' )
|
| 254 |
+
print( 'This file might look something like: "score_jd2.linuxgccrelease"' )
|
| 255 |
+
print( 'Note that this is a different executable from the "rosetta_scripts" binary used to run flex ddG' )
|
| 256 |
+
raise Exception( 'score_jd2 missing' )
|
| 257 |
+
|
| 258 |
+
for x in parsed_args.output_folders:
|
| 259 |
+
if os.path.isdir(x):
|
| 260 |
+
main( x, parsed_args.stride )
|
| 261 |
+
else:
|
| 262 |
+
print( 'ERROR: %s is not a valid directory' % x )
|
scripts/flex_ddg_db3.py
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/usr/bin/env python3
|
| 2 |
+
|
| 3 |
+
'''Small helpers shared by analyze_flex_ddG.py and extract_structures.py.
|
| 4 |
+
|
| 5 |
+
Standard library only, so that extract_structures.py keeps running without numpy or pandas.
|
| 6 |
+
'''
|
| 7 |
+
|
| 8 |
+
import re
|
| 9 |
+
import sqlite3
|
| 10 |
+
|
| 11 |
+
# Rosetta records the full option list it was invoked with in the "protocols" table of every
|
| 12 |
+
# features database it writes, so the stride a run actually used can be read back out of the
|
| 13 |
+
# output instead of being remembered and re-typed by hand.
|
| 14 |
+
_stride_re = re.compile( r'backrub_trajectory_stride[= ]+(\d+)' )
|
| 15 |
+
|
| 16 |
+
def trajectory_stride_from_db3( db3_file ):
|
| 17 |
+
'''The backrub_trajectory_stride the run in db3_file was launched with.
|
| 18 |
+
|
| 19 |
+
Returns None if it cannot be determined, which happens for databases written by Rosetta
|
| 20 |
+
versions that predate the protocols table, or if the stride was left at the XML default
|
| 21 |
+
instead of being passed on the command line. Callers should fall back to a default and say
|
| 22 |
+
so, because the stride does not affect any energy -- it only labels the checkpoints, so a
|
| 23 |
+
wrong value silently mislabels every row (and misnames every extracted PDB) rather than
|
| 24 |
+
causing a visible failure.
|
| 25 |
+
'''
|
| 26 |
+
try:
|
| 27 |
+
conn = sqlite3.connect( 'file:%s?mode=ro' % db3_file, uri = True )
|
| 28 |
+
except sqlite3.Error:
|
| 29 |
+
return None
|
| 30 |
+
|
| 31 |
+
try:
|
| 32 |
+
try:
|
| 33 |
+
rows = conn.execute( 'SELECT specified_options, command_line FROM protocols' ).fetchall()
|
| 34 |
+
except sqlite3.Error:
|
| 35 |
+
return None
|
| 36 |
+
|
| 37 |
+
strides = set()
|
| 38 |
+
for row in rows:
|
| 39 |
+
for field in row:
|
| 40 |
+
if field:
|
| 41 |
+
strides.update( int(m) for m in _stride_re.findall( field ) )
|
| 42 |
+
finally:
|
| 43 |
+
conn.close()
|
| 44 |
+
|
| 45 |
+
# More than one distinct value means the database mixes runs; we cannot label it correctly.
|
| 46 |
+
if len( strides ) == 1:
|
| 47 |
+
return strides.pop()
|
| 48 |
+
return None
|
scripts/inputs/1JTG/1JTG_AB.pdb
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
scripts/inputs/1JTG/chains_to_move.txt
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
B
|
scripts/inputs/1JTG/mutations.mutfile
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
total 4
|
| 2 |
+
4
|
| 3 |
+
N 351 K
|
| 4 |
+
D 397 K
|
| 5 |
+
D 425 K
|
| 6 |
+
V 427 K
|
scripts/inputs/1JTG/mutations.resfile
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
NATRO
|
| 2 |
+
start
|
| 3 |
+
135 B PIKAA K
|
| 4 |
+
163 B PIKAA K
|
| 5 |
+
165 B PIKAA K
|
| 6 |
+
89 B PIKAA K
|
scripts/inputs/1JTG/nataa_mutations.resfile
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
NATAA
|
| 2 |
+
start
|
| 3 |
+
135 B PIKAA K
|
| 4 |
+
163 B PIKAA K
|
| 5 |
+
165 B PIKAA K
|
| 6 |
+
89 B PIKAA K
|
scripts/inputs/1JTG/pdb2rosetta.resmap.json
ADDED
|
@@ -0,0 +1,429 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"A 26 ": 1,
|
| 3 |
+
"A 27 ": 2,
|
| 4 |
+
"A 28 ": 3,
|
| 5 |
+
"A 29 ": 4,
|
| 6 |
+
"A 30 ": 5,
|
| 7 |
+
"A 31 ": 6,
|
| 8 |
+
"A 32 ": 7,
|
| 9 |
+
"A 33 ": 8,
|
| 10 |
+
"A 34 ": 9,
|
| 11 |
+
"A 35 ": 10,
|
| 12 |
+
"A 36 ": 11,
|
| 13 |
+
"A 37 ": 12,
|
| 14 |
+
"A 38 ": 13,
|
| 15 |
+
"A 39 ": 14,
|
| 16 |
+
"A 40 ": 15,
|
| 17 |
+
"A 41 ": 16,
|
| 18 |
+
"A 42 ": 17,
|
| 19 |
+
"A 43 ": 18,
|
| 20 |
+
"A 44 ": 19,
|
| 21 |
+
"A 45 ": 20,
|
| 22 |
+
"A 46 ": 21,
|
| 23 |
+
"A 47 ": 22,
|
| 24 |
+
"A 48 ": 23,
|
| 25 |
+
"A 49 ": 24,
|
| 26 |
+
"A 50 ": 25,
|
| 27 |
+
"A 51 ": 26,
|
| 28 |
+
"A 52 ": 27,
|
| 29 |
+
"A 53 ": 28,
|
| 30 |
+
"A 54 ": 29,
|
| 31 |
+
"A 55 ": 30,
|
| 32 |
+
"A 56 ": 31,
|
| 33 |
+
"A 57 ": 32,
|
| 34 |
+
"A 58 ": 33,
|
| 35 |
+
"A 59 ": 34,
|
| 36 |
+
"A 60 ": 35,
|
| 37 |
+
"A 61 ": 36,
|
| 38 |
+
"A 62 ": 37,
|
| 39 |
+
"A 63 ": 38,
|
| 40 |
+
"A 64 ": 39,
|
| 41 |
+
"A 65 ": 40,
|
| 42 |
+
"A 66 ": 41,
|
| 43 |
+
"A 67 ": 42,
|
| 44 |
+
"A 68 ": 43,
|
| 45 |
+
"A 69 ": 44,
|
| 46 |
+
"A 70 ": 45,
|
| 47 |
+
"A 71 ": 46,
|
| 48 |
+
"A 72 ": 47,
|
| 49 |
+
"A 73 ": 48,
|
| 50 |
+
"A 74 ": 49,
|
| 51 |
+
"A 75 ": 50,
|
| 52 |
+
"A 76 ": 51,
|
| 53 |
+
"A 77 ": 52,
|
| 54 |
+
"A 78 ": 53,
|
| 55 |
+
"A 79 ": 54,
|
| 56 |
+
"A 80 ": 55,
|
| 57 |
+
"A 81 ": 56,
|
| 58 |
+
"A 82 ": 57,
|
| 59 |
+
"A 83 ": 58,
|
| 60 |
+
"A 84 ": 59,
|
| 61 |
+
"A 85 ": 60,
|
| 62 |
+
"A 86 ": 61,
|
| 63 |
+
"A 87 ": 62,
|
| 64 |
+
"A 88 ": 63,
|
| 65 |
+
"A 89 ": 64,
|
| 66 |
+
"A 90 ": 65,
|
| 67 |
+
"A 91 ": 66,
|
| 68 |
+
"A 92 ": 67,
|
| 69 |
+
"A 93 ": 68,
|
| 70 |
+
"A 94 ": 69,
|
| 71 |
+
"A 95 ": 70,
|
| 72 |
+
"A 96 ": 71,
|
| 73 |
+
"A 97 ": 72,
|
| 74 |
+
"A 98 ": 73,
|
| 75 |
+
"A 99 ": 74,
|
| 76 |
+
"A 100 ": 75,
|
| 77 |
+
"A 101 ": 76,
|
| 78 |
+
"A 102 ": 77,
|
| 79 |
+
"A 103 ": 78,
|
| 80 |
+
"A 104 ": 79,
|
| 81 |
+
"A 105 ": 80,
|
| 82 |
+
"A 106 ": 81,
|
| 83 |
+
"A 107 ": 82,
|
| 84 |
+
"A 108 ": 83,
|
| 85 |
+
"A 109 ": 84,
|
| 86 |
+
"A 110 ": 85,
|
| 87 |
+
"A 111 ": 86,
|
| 88 |
+
"A 112 ": 87,
|
| 89 |
+
"A 113 ": 88,
|
| 90 |
+
"A 114 ": 89,
|
| 91 |
+
"A 115 ": 90,
|
| 92 |
+
"A 116 ": 91,
|
| 93 |
+
"A 117 ": 92,
|
| 94 |
+
"A 118 ": 93,
|
| 95 |
+
"A 119 ": 94,
|
| 96 |
+
"A 120 ": 95,
|
| 97 |
+
"A 121 ": 96,
|
| 98 |
+
"A 122 ": 97,
|
| 99 |
+
"A 123 ": 98,
|
| 100 |
+
"A 124 ": 99,
|
| 101 |
+
"A 125 ": 100,
|
| 102 |
+
"A 126 ": 101,
|
| 103 |
+
"A 127 ": 102,
|
| 104 |
+
"A 128 ": 103,
|
| 105 |
+
"A 129 ": 104,
|
| 106 |
+
"A 130 ": 105,
|
| 107 |
+
"A 131 ": 106,
|
| 108 |
+
"A 132 ": 107,
|
| 109 |
+
"A 133 ": 108,
|
| 110 |
+
"A 134 ": 109,
|
| 111 |
+
"A 135 ": 110,
|
| 112 |
+
"A 136 ": 111,
|
| 113 |
+
"A 137 ": 112,
|
| 114 |
+
"A 138 ": 113,
|
| 115 |
+
"A 139 ": 114,
|
| 116 |
+
"A 140 ": 115,
|
| 117 |
+
"A 141 ": 116,
|
| 118 |
+
"A 142 ": 117,
|
| 119 |
+
"A 143 ": 118,
|
| 120 |
+
"A 144 ": 119,
|
| 121 |
+
"A 145 ": 120,
|
| 122 |
+
"A 146 ": 121,
|
| 123 |
+
"A 147 ": 122,
|
| 124 |
+
"A 148 ": 123,
|
| 125 |
+
"A 149 ": 124,
|
| 126 |
+
"A 150 ": 125,
|
| 127 |
+
"A 151 ": 126,
|
| 128 |
+
"A 152 ": 127,
|
| 129 |
+
"A 153 ": 128,
|
| 130 |
+
"A 154 ": 129,
|
| 131 |
+
"A 155 ": 130,
|
| 132 |
+
"A 156 ": 131,
|
| 133 |
+
"A 157 ": 132,
|
| 134 |
+
"A 158 ": 133,
|
| 135 |
+
"A 159 ": 134,
|
| 136 |
+
"A 160 ": 135,
|
| 137 |
+
"A 161 ": 136,
|
| 138 |
+
"A 162 ": 137,
|
| 139 |
+
"A 163 ": 138,
|
| 140 |
+
"A 164 ": 139,
|
| 141 |
+
"A 165 ": 140,
|
| 142 |
+
"A 166 ": 141,
|
| 143 |
+
"A 167 ": 142,
|
| 144 |
+
"A 168 ": 143,
|
| 145 |
+
"A 169 ": 144,
|
| 146 |
+
"A 170 ": 145,
|
| 147 |
+
"A 171 ": 146,
|
| 148 |
+
"A 172 ": 147,
|
| 149 |
+
"A 173 ": 148,
|
| 150 |
+
"A 174 ": 149,
|
| 151 |
+
"A 175 ": 150,
|
| 152 |
+
"A 176 ": 151,
|
| 153 |
+
"A 177 ": 152,
|
| 154 |
+
"A 178 ": 153,
|
| 155 |
+
"A 179 ": 154,
|
| 156 |
+
"A 180 ": 155,
|
| 157 |
+
"A 181 ": 156,
|
| 158 |
+
"A 182 ": 157,
|
| 159 |
+
"A 183 ": 158,
|
| 160 |
+
"A 184 ": 159,
|
| 161 |
+
"A 185 ": 160,
|
| 162 |
+
"A 186 ": 161,
|
| 163 |
+
"A 187 ": 162,
|
| 164 |
+
"A 188 ": 163,
|
| 165 |
+
"A 189 ": 164,
|
| 166 |
+
"A 190 ": 165,
|
| 167 |
+
"A 191 ": 166,
|
| 168 |
+
"A 192 ": 167,
|
| 169 |
+
"A 193 ": 168,
|
| 170 |
+
"A 194 ": 169,
|
| 171 |
+
"A 195 ": 170,
|
| 172 |
+
"A 196 ": 171,
|
| 173 |
+
"A 197 ": 172,
|
| 174 |
+
"A 198 ": 173,
|
| 175 |
+
"A 199 ": 174,
|
| 176 |
+
"A 200 ": 175,
|
| 177 |
+
"A 201 ": 176,
|
| 178 |
+
"A 202 ": 177,
|
| 179 |
+
"A 203 ": 178,
|
| 180 |
+
"A 204 ": 179,
|
| 181 |
+
"A 205 ": 180,
|
| 182 |
+
"A 206 ": 181,
|
| 183 |
+
"A 207 ": 182,
|
| 184 |
+
"A 208 ": 183,
|
| 185 |
+
"A 209 ": 184,
|
| 186 |
+
"A 210 ": 185,
|
| 187 |
+
"A 211 ": 186,
|
| 188 |
+
"A 212 ": 187,
|
| 189 |
+
"A 213 ": 188,
|
| 190 |
+
"A 215 ": 189,
|
| 191 |
+
"A 216 ": 190,
|
| 192 |
+
"A 217 ": 191,
|
| 193 |
+
"A 218 ": 192,
|
| 194 |
+
"A 219 ": 193,
|
| 195 |
+
"A 220 ": 194,
|
| 196 |
+
"A 221 ": 195,
|
| 197 |
+
"A 222 ": 196,
|
| 198 |
+
"A 223 ": 197,
|
| 199 |
+
"A 224 ": 198,
|
| 200 |
+
"A 225 ": 199,
|
| 201 |
+
"A 226 ": 200,
|
| 202 |
+
"A 227 ": 201,
|
| 203 |
+
"A 228 ": 202,
|
| 204 |
+
"A 229 ": 203,
|
| 205 |
+
"A 230 ": 204,
|
| 206 |
+
"A 231 ": 205,
|
| 207 |
+
"A 232 ": 206,
|
| 208 |
+
"A 233 ": 207,
|
| 209 |
+
"A 234 ": 208,
|
| 210 |
+
"A 235 ": 209,
|
| 211 |
+
"A 236 ": 210,
|
| 212 |
+
"A 237 ": 211,
|
| 213 |
+
"A 238 ": 212,
|
| 214 |
+
"A 239 ": 213,
|
| 215 |
+
"A 240 ": 214,
|
| 216 |
+
"A 241 ": 215,
|
| 217 |
+
"A 242 ": 216,
|
| 218 |
+
"A 243 ": 217,
|
| 219 |
+
"A 244 ": 218,
|
| 220 |
+
"A 245 ": 219,
|
| 221 |
+
"A 246 ": 220,
|
| 222 |
+
"A 247 ": 221,
|
| 223 |
+
"A 248 ": 222,
|
| 224 |
+
"A 249 ": 223,
|
| 225 |
+
"A 250 ": 224,
|
| 226 |
+
"A 251 ": 225,
|
| 227 |
+
"A 252 ": 226,
|
| 228 |
+
"A 253 ": 227,
|
| 229 |
+
"A 254 ": 228,
|
| 230 |
+
"A 255 ": 229,
|
| 231 |
+
"A 256 ": 230,
|
| 232 |
+
"A 257 ": 231,
|
| 233 |
+
"A 258 ": 232,
|
| 234 |
+
"A 259 ": 233,
|
| 235 |
+
"A 260 ": 234,
|
| 236 |
+
"A 261 ": 235,
|
| 237 |
+
"A 262 ": 236,
|
| 238 |
+
"A 263 ": 237,
|
| 239 |
+
"A 264 ": 238,
|
| 240 |
+
"A 265 ": 239,
|
| 241 |
+
"A 266 ": 240,
|
| 242 |
+
"A 267 ": 241,
|
| 243 |
+
"A 268 ": 242,
|
| 244 |
+
"A 269 ": 243,
|
| 245 |
+
"A 270 ": 244,
|
| 246 |
+
"A 271 ": 245,
|
| 247 |
+
"A 272 ": 246,
|
| 248 |
+
"A 273 ": 247,
|
| 249 |
+
"A 274 ": 248,
|
| 250 |
+
"A 275 ": 249,
|
| 251 |
+
"A 276 ": 250,
|
| 252 |
+
"A 277 ": 251,
|
| 253 |
+
"A 278 ": 252,
|
| 254 |
+
"A 279 ": 253,
|
| 255 |
+
"A 280 ": 254,
|
| 256 |
+
"A 281 ": 255,
|
| 257 |
+
"A 282 ": 256,
|
| 258 |
+
"A 283 ": 257,
|
| 259 |
+
"A 284 ": 258,
|
| 260 |
+
"A 285 ": 259,
|
| 261 |
+
"A 286 ": 260,
|
| 262 |
+
"A 287 ": 261,
|
| 263 |
+
"A 288 ": 262,
|
| 264 |
+
"B 1 ": 263,
|
| 265 |
+
"B 2 ": 264,
|
| 266 |
+
"B 3 ": 265,
|
| 267 |
+
"B 4 ": 266,
|
| 268 |
+
"B 5 ": 267,
|
| 269 |
+
"B 6 ": 268,
|
| 270 |
+
"B 7 ": 269,
|
| 271 |
+
"B 8 ": 270,
|
| 272 |
+
"B 9 ": 271,
|
| 273 |
+
"B 10 ": 272,
|
| 274 |
+
"B 11 ": 273,
|
| 275 |
+
"B 12 ": 274,
|
| 276 |
+
"B 13 ": 275,
|
| 277 |
+
"B 14 ": 276,
|
| 278 |
+
"B 15 ": 277,
|
| 279 |
+
"B 16 ": 278,
|
| 280 |
+
"B 17 ": 279,
|
| 281 |
+
"B 18 ": 280,
|
| 282 |
+
"B 19 ": 281,
|
| 283 |
+
"B 20 ": 282,
|
| 284 |
+
"B 21 ": 283,
|
| 285 |
+
"B 22 ": 284,
|
| 286 |
+
"B 23 ": 285,
|
| 287 |
+
"B 24 ": 286,
|
| 288 |
+
"B 25 ": 287,
|
| 289 |
+
"B 26 ": 288,
|
| 290 |
+
"B 27 ": 289,
|
| 291 |
+
"B 28 ": 290,
|
| 292 |
+
"B 29 ": 291,
|
| 293 |
+
"B 30 ": 292,
|
| 294 |
+
"B 31 ": 293,
|
| 295 |
+
"B 32 ": 294,
|
| 296 |
+
"B 33 ": 295,
|
| 297 |
+
"B 34 ": 296,
|
| 298 |
+
"B 35 ": 297,
|
| 299 |
+
"B 36 ": 298,
|
| 300 |
+
"B 37 ": 299,
|
| 301 |
+
"B 38 ": 300,
|
| 302 |
+
"B 39 ": 301,
|
| 303 |
+
"B 40 ": 302,
|
| 304 |
+
"B 41 ": 303,
|
| 305 |
+
"B 42 ": 304,
|
| 306 |
+
"B 43 ": 305,
|
| 307 |
+
"B 44 ": 306,
|
| 308 |
+
"B 45 ": 307,
|
| 309 |
+
"B 46 ": 308,
|
| 310 |
+
"B 47 ": 309,
|
| 311 |
+
"B 48 ": 310,
|
| 312 |
+
"B 49 ": 311,
|
| 313 |
+
"B 50 ": 312,
|
| 314 |
+
"B 51 ": 313,
|
| 315 |
+
"B 52 ": 314,
|
| 316 |
+
"B 53 ": 315,
|
| 317 |
+
"B 54 ": 316,
|
| 318 |
+
"B 55 ": 317,
|
| 319 |
+
"B 56 ": 318,
|
| 320 |
+
"B 57 ": 319,
|
| 321 |
+
"B 58 ": 320,
|
| 322 |
+
"B 59 ": 321,
|
| 323 |
+
"B 60 ": 322,
|
| 324 |
+
"B 61 ": 323,
|
| 325 |
+
"B 62 ": 324,
|
| 326 |
+
"B 63 ": 325,
|
| 327 |
+
"B 64 ": 326,
|
| 328 |
+
"B 65 ": 327,
|
| 329 |
+
"B 66 ": 328,
|
| 330 |
+
"B 67 ": 329,
|
| 331 |
+
"B 68 ": 330,
|
| 332 |
+
"B 69 ": 331,
|
| 333 |
+
"B 70 ": 332,
|
| 334 |
+
"B 71 ": 333,
|
| 335 |
+
"B 72 ": 334,
|
| 336 |
+
"B 73 ": 335,
|
| 337 |
+
"B 74 ": 336,
|
| 338 |
+
"B 75 ": 337,
|
| 339 |
+
"B 76 ": 338,
|
| 340 |
+
"B 77 ": 339,
|
| 341 |
+
"B 78 ": 340,
|
| 342 |
+
"B 79 ": 341,
|
| 343 |
+
"B 80 ": 342,
|
| 344 |
+
"B 81 ": 343,
|
| 345 |
+
"B 82 ": 344,
|
| 346 |
+
"B 83 ": 345,
|
| 347 |
+
"B 84 ": 346,
|
| 348 |
+
"B 85 ": 347,
|
| 349 |
+
"B 86 ": 348,
|
| 350 |
+
"B 87 ": 349,
|
| 351 |
+
"B 88 ": 350,
|
| 352 |
+
"B 89 ": 351,
|
| 353 |
+
"B 90 ": 352,
|
| 354 |
+
"B 91 ": 353,
|
| 355 |
+
"B 92 ": 354,
|
| 356 |
+
"B 93 ": 355,
|
| 357 |
+
"B 94 ": 356,
|
| 358 |
+
"B 95 ": 357,
|
| 359 |
+
"B 96 ": 358,
|
| 360 |
+
"B 97 ": 359,
|
| 361 |
+
"B 98 ": 360,
|
| 362 |
+
"B 99 ": 361,
|
| 363 |
+
"B 100 ": 362,
|
| 364 |
+
"B 101 ": 363,
|
| 365 |
+
"B 102 ": 364,
|
| 366 |
+
"B 103 ": 365,
|
| 367 |
+
"B 104 ": 366,
|
| 368 |
+
"B 105 ": 367,
|
| 369 |
+
"B 106 ": 368,
|
| 370 |
+
"B 107 ": 369,
|
| 371 |
+
"B 108 ": 370,
|
| 372 |
+
"B 109 ": 371,
|
| 373 |
+
"B 110 ": 372,
|
| 374 |
+
"B 111 ": 373,
|
| 375 |
+
"B 112 ": 374,
|
| 376 |
+
"B 113 ": 375,
|
| 377 |
+
"B 114 ": 376,
|
| 378 |
+
"B 115 ": 377,
|
| 379 |
+
"B 116 ": 378,
|
| 380 |
+
"B 117 ": 379,
|
| 381 |
+
"B 118 ": 380,
|
| 382 |
+
"B 119 ": 381,
|
| 383 |
+
"B 120 ": 382,
|
| 384 |
+
"B 121 ": 383,
|
| 385 |
+
"B 122 ": 384,
|
| 386 |
+
"B 123 ": 385,
|
| 387 |
+
"B 124 ": 386,
|
| 388 |
+
"B 125 ": 387,
|
| 389 |
+
"B 126 ": 388,
|
| 390 |
+
"B 127 ": 389,
|
| 391 |
+
"B 128 ": 390,
|
| 392 |
+
"B 129 ": 391,
|
| 393 |
+
"B 130 ": 392,
|
| 394 |
+
"B 131 ": 393,
|
| 395 |
+
"B 132 ": 394,
|
| 396 |
+
"B 133 ": 395,
|
| 397 |
+
"B 134 ": 396,
|
| 398 |
+
"B 135 ": 397,
|
| 399 |
+
"B 136 ": 398,
|
| 400 |
+
"B 137 ": 399,
|
| 401 |
+
"B 138 ": 400,
|
| 402 |
+
"B 139 ": 401,
|
| 403 |
+
"B 140 ": 402,
|
| 404 |
+
"B 141 ": 403,
|
| 405 |
+
"B 142 ": 404,
|
| 406 |
+
"B 143 ": 405,
|
| 407 |
+
"B 144 ": 406,
|
| 408 |
+
"B 145 ": 407,
|
| 409 |
+
"B 146 ": 408,
|
| 410 |
+
"B 147 ": 409,
|
| 411 |
+
"B 148 ": 410,
|
| 412 |
+
"B 149 ": 411,
|
| 413 |
+
"B 150 ": 412,
|
| 414 |
+
"B 151 ": 413,
|
| 415 |
+
"B 152 ": 414,
|
| 416 |
+
"B 153 ": 415,
|
| 417 |
+
"B 154 ": 416,
|
| 418 |
+
"B 155 ": 417,
|
| 419 |
+
"B 156 ": 418,
|
| 420 |
+
"B 157 ": 419,
|
| 421 |
+
"B 158 ": 420,
|
| 422 |
+
"B 159 ": 421,
|
| 423 |
+
"B 160 ": 422,
|
| 424 |
+
"B 161 ": 423,
|
| 425 |
+
"B 162 ": 424,
|
| 426 |
+
"B 163 ": 425,
|
| 427 |
+
"B 164 ": 426,
|
| 428 |
+
"B 165 ": 427
|
| 429 |
+
}
|
scripts/inputs/1JTG/rosetta2pdb.resmap.json
ADDED
|
@@ -0,0 +1,429 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"1": "A 26 ",
|
| 3 |
+
"2": "A 27 ",
|
| 4 |
+
"3": "A 28 ",
|
| 5 |
+
"4": "A 29 ",
|
| 6 |
+
"5": "A 30 ",
|
| 7 |
+
"6": "A 31 ",
|
| 8 |
+
"7": "A 32 ",
|
| 9 |
+
"8": "A 33 ",
|
| 10 |
+
"9": "A 34 ",
|
| 11 |
+
"10": "A 35 ",
|
| 12 |
+
"11": "A 36 ",
|
| 13 |
+
"12": "A 37 ",
|
| 14 |
+
"13": "A 38 ",
|
| 15 |
+
"14": "A 39 ",
|
| 16 |
+
"15": "A 40 ",
|
| 17 |
+
"16": "A 41 ",
|
| 18 |
+
"17": "A 42 ",
|
| 19 |
+
"18": "A 43 ",
|
| 20 |
+
"19": "A 44 ",
|
| 21 |
+
"20": "A 45 ",
|
| 22 |
+
"21": "A 46 ",
|
| 23 |
+
"22": "A 47 ",
|
| 24 |
+
"23": "A 48 ",
|
| 25 |
+
"24": "A 49 ",
|
| 26 |
+
"25": "A 50 ",
|
| 27 |
+
"26": "A 51 ",
|
| 28 |
+
"27": "A 52 ",
|
| 29 |
+
"28": "A 53 ",
|
| 30 |
+
"29": "A 54 ",
|
| 31 |
+
"30": "A 55 ",
|
| 32 |
+
"31": "A 56 ",
|
| 33 |
+
"32": "A 57 ",
|
| 34 |
+
"33": "A 58 ",
|
| 35 |
+
"34": "A 59 ",
|
| 36 |
+
"35": "A 60 ",
|
| 37 |
+
"36": "A 61 ",
|
| 38 |
+
"37": "A 62 ",
|
| 39 |
+
"38": "A 63 ",
|
| 40 |
+
"39": "A 64 ",
|
| 41 |
+
"40": "A 65 ",
|
| 42 |
+
"41": "A 66 ",
|
| 43 |
+
"42": "A 67 ",
|
| 44 |
+
"43": "A 68 ",
|
| 45 |
+
"44": "A 69 ",
|
| 46 |
+
"45": "A 70 ",
|
| 47 |
+
"46": "A 71 ",
|
| 48 |
+
"47": "A 72 ",
|
| 49 |
+
"48": "A 73 ",
|
| 50 |
+
"49": "A 74 ",
|
| 51 |
+
"50": "A 75 ",
|
| 52 |
+
"51": "A 76 ",
|
| 53 |
+
"52": "A 77 ",
|
| 54 |
+
"53": "A 78 ",
|
| 55 |
+
"54": "A 79 ",
|
| 56 |
+
"55": "A 80 ",
|
| 57 |
+
"56": "A 81 ",
|
| 58 |
+
"57": "A 82 ",
|
| 59 |
+
"58": "A 83 ",
|
| 60 |
+
"59": "A 84 ",
|
| 61 |
+
"60": "A 85 ",
|
| 62 |
+
"61": "A 86 ",
|
| 63 |
+
"62": "A 87 ",
|
| 64 |
+
"63": "A 88 ",
|
| 65 |
+
"64": "A 89 ",
|
| 66 |
+
"65": "A 90 ",
|
| 67 |
+
"66": "A 91 ",
|
| 68 |
+
"67": "A 92 ",
|
| 69 |
+
"68": "A 93 ",
|
| 70 |
+
"69": "A 94 ",
|
| 71 |
+
"70": "A 95 ",
|
| 72 |
+
"71": "A 96 ",
|
| 73 |
+
"72": "A 97 ",
|
| 74 |
+
"73": "A 98 ",
|
| 75 |
+
"74": "A 99 ",
|
| 76 |
+
"75": "A 100 ",
|
| 77 |
+
"76": "A 101 ",
|
| 78 |
+
"77": "A 102 ",
|
| 79 |
+
"78": "A 103 ",
|
| 80 |
+
"79": "A 104 ",
|
| 81 |
+
"80": "A 105 ",
|
| 82 |
+
"81": "A 106 ",
|
| 83 |
+
"82": "A 107 ",
|
| 84 |
+
"83": "A 108 ",
|
| 85 |
+
"84": "A 109 ",
|
| 86 |
+
"85": "A 110 ",
|
| 87 |
+
"86": "A 111 ",
|
| 88 |
+
"87": "A 112 ",
|
| 89 |
+
"88": "A 113 ",
|
| 90 |
+
"89": "A 114 ",
|
| 91 |
+
"90": "A 115 ",
|
| 92 |
+
"91": "A 116 ",
|
| 93 |
+
"92": "A 117 ",
|
| 94 |
+
"93": "A 118 ",
|
| 95 |
+
"94": "A 119 ",
|
| 96 |
+
"95": "A 120 ",
|
| 97 |
+
"96": "A 121 ",
|
| 98 |
+
"97": "A 122 ",
|
| 99 |
+
"98": "A 123 ",
|
| 100 |
+
"99": "A 124 ",
|
| 101 |
+
"100": "A 125 ",
|
| 102 |
+
"101": "A 126 ",
|
| 103 |
+
"102": "A 127 ",
|
| 104 |
+
"103": "A 128 ",
|
| 105 |
+
"104": "A 129 ",
|
| 106 |
+
"105": "A 130 ",
|
| 107 |
+
"106": "A 131 ",
|
| 108 |
+
"107": "A 132 ",
|
| 109 |
+
"108": "A 133 ",
|
| 110 |
+
"109": "A 134 ",
|
| 111 |
+
"110": "A 135 ",
|
| 112 |
+
"111": "A 136 ",
|
| 113 |
+
"112": "A 137 ",
|
| 114 |
+
"113": "A 138 ",
|
| 115 |
+
"114": "A 139 ",
|
| 116 |
+
"115": "A 140 ",
|
| 117 |
+
"116": "A 141 ",
|
| 118 |
+
"117": "A 142 ",
|
| 119 |
+
"118": "A 143 ",
|
| 120 |
+
"119": "A 144 ",
|
| 121 |
+
"120": "A 145 ",
|
| 122 |
+
"121": "A 146 ",
|
| 123 |
+
"122": "A 147 ",
|
| 124 |
+
"123": "A 148 ",
|
| 125 |
+
"124": "A 149 ",
|
| 126 |
+
"125": "A 150 ",
|
| 127 |
+
"126": "A 151 ",
|
| 128 |
+
"127": "A 152 ",
|
| 129 |
+
"128": "A 153 ",
|
| 130 |
+
"129": "A 154 ",
|
| 131 |
+
"130": "A 155 ",
|
| 132 |
+
"131": "A 156 ",
|
| 133 |
+
"132": "A 157 ",
|
| 134 |
+
"133": "A 158 ",
|
| 135 |
+
"134": "A 159 ",
|
| 136 |
+
"135": "A 160 ",
|
| 137 |
+
"136": "A 161 ",
|
| 138 |
+
"137": "A 162 ",
|
| 139 |
+
"138": "A 163 ",
|
| 140 |
+
"139": "A 164 ",
|
| 141 |
+
"140": "A 165 ",
|
| 142 |
+
"141": "A 166 ",
|
| 143 |
+
"142": "A 167 ",
|
| 144 |
+
"143": "A 168 ",
|
| 145 |
+
"144": "A 169 ",
|
| 146 |
+
"145": "A 170 ",
|
| 147 |
+
"146": "A 171 ",
|
| 148 |
+
"147": "A 172 ",
|
| 149 |
+
"148": "A 173 ",
|
| 150 |
+
"149": "A 174 ",
|
| 151 |
+
"150": "A 175 ",
|
| 152 |
+
"151": "A 176 ",
|
| 153 |
+
"152": "A 177 ",
|
| 154 |
+
"153": "A 178 ",
|
| 155 |
+
"154": "A 179 ",
|
| 156 |
+
"155": "A 180 ",
|
| 157 |
+
"156": "A 181 ",
|
| 158 |
+
"157": "A 182 ",
|
| 159 |
+
"158": "A 183 ",
|
| 160 |
+
"159": "A 184 ",
|
| 161 |
+
"160": "A 185 ",
|
| 162 |
+
"161": "A 186 ",
|
| 163 |
+
"162": "A 187 ",
|
| 164 |
+
"163": "A 188 ",
|
| 165 |
+
"164": "A 189 ",
|
| 166 |
+
"165": "A 190 ",
|
| 167 |
+
"166": "A 191 ",
|
| 168 |
+
"167": "A 192 ",
|
| 169 |
+
"168": "A 193 ",
|
| 170 |
+
"169": "A 194 ",
|
| 171 |
+
"170": "A 195 ",
|
| 172 |
+
"171": "A 196 ",
|
| 173 |
+
"172": "A 197 ",
|
| 174 |
+
"173": "A 198 ",
|
| 175 |
+
"174": "A 199 ",
|
| 176 |
+
"175": "A 200 ",
|
| 177 |
+
"176": "A 201 ",
|
| 178 |
+
"177": "A 202 ",
|
| 179 |
+
"178": "A 203 ",
|
| 180 |
+
"179": "A 204 ",
|
| 181 |
+
"180": "A 205 ",
|
| 182 |
+
"181": "A 206 ",
|
| 183 |
+
"182": "A 207 ",
|
| 184 |
+
"183": "A 208 ",
|
| 185 |
+
"184": "A 209 ",
|
| 186 |
+
"185": "A 210 ",
|
| 187 |
+
"186": "A 211 ",
|
| 188 |
+
"187": "A 212 ",
|
| 189 |
+
"188": "A 213 ",
|
| 190 |
+
"189": "A 215 ",
|
| 191 |
+
"190": "A 216 ",
|
| 192 |
+
"191": "A 217 ",
|
| 193 |
+
"192": "A 218 ",
|
| 194 |
+
"193": "A 219 ",
|
| 195 |
+
"194": "A 220 ",
|
| 196 |
+
"195": "A 221 ",
|
| 197 |
+
"196": "A 222 ",
|
| 198 |
+
"197": "A 223 ",
|
| 199 |
+
"198": "A 224 ",
|
| 200 |
+
"199": "A 225 ",
|
| 201 |
+
"200": "A 226 ",
|
| 202 |
+
"201": "A 227 ",
|
| 203 |
+
"202": "A 228 ",
|
| 204 |
+
"203": "A 229 ",
|
| 205 |
+
"204": "A 230 ",
|
| 206 |
+
"205": "A 231 ",
|
| 207 |
+
"206": "A 232 ",
|
| 208 |
+
"207": "A 233 ",
|
| 209 |
+
"208": "A 234 ",
|
| 210 |
+
"209": "A 235 ",
|
| 211 |
+
"210": "A 236 ",
|
| 212 |
+
"211": "A 237 ",
|
| 213 |
+
"212": "A 238 ",
|
| 214 |
+
"213": "A 239 ",
|
| 215 |
+
"214": "A 240 ",
|
| 216 |
+
"215": "A 241 ",
|
| 217 |
+
"216": "A 242 ",
|
| 218 |
+
"217": "A 243 ",
|
| 219 |
+
"218": "A 244 ",
|
| 220 |
+
"219": "A 245 ",
|
| 221 |
+
"220": "A 246 ",
|
| 222 |
+
"221": "A 247 ",
|
| 223 |
+
"222": "A 248 ",
|
| 224 |
+
"223": "A 249 ",
|
| 225 |
+
"224": "A 250 ",
|
| 226 |
+
"225": "A 251 ",
|
| 227 |
+
"226": "A 252 ",
|
| 228 |
+
"227": "A 253 ",
|
| 229 |
+
"228": "A 254 ",
|
| 230 |
+
"229": "A 255 ",
|
| 231 |
+
"230": "A 256 ",
|
| 232 |
+
"231": "A 257 ",
|
| 233 |
+
"232": "A 258 ",
|
| 234 |
+
"233": "A 259 ",
|
| 235 |
+
"234": "A 260 ",
|
| 236 |
+
"235": "A 261 ",
|
| 237 |
+
"236": "A 262 ",
|
| 238 |
+
"237": "A 263 ",
|
| 239 |
+
"238": "A 264 ",
|
| 240 |
+
"239": "A 265 ",
|
| 241 |
+
"240": "A 266 ",
|
| 242 |
+
"241": "A 267 ",
|
| 243 |
+
"242": "A 268 ",
|
| 244 |
+
"243": "A 269 ",
|
| 245 |
+
"244": "A 270 ",
|
| 246 |
+
"245": "A 271 ",
|
| 247 |
+
"246": "A 272 ",
|
| 248 |
+
"247": "A 273 ",
|
| 249 |
+
"248": "A 274 ",
|
| 250 |
+
"249": "A 275 ",
|
| 251 |
+
"250": "A 276 ",
|
| 252 |
+
"251": "A 277 ",
|
| 253 |
+
"252": "A 278 ",
|
| 254 |
+
"253": "A 279 ",
|
| 255 |
+
"254": "A 280 ",
|
| 256 |
+
"255": "A 281 ",
|
| 257 |
+
"256": "A 282 ",
|
| 258 |
+
"257": "A 283 ",
|
| 259 |
+
"258": "A 284 ",
|
| 260 |
+
"259": "A 285 ",
|
| 261 |
+
"260": "A 286 ",
|
| 262 |
+
"261": "A 287 ",
|
| 263 |
+
"262": "A 288 ",
|
| 264 |
+
"263": "B 1 ",
|
| 265 |
+
"264": "B 2 ",
|
| 266 |
+
"265": "B 3 ",
|
| 267 |
+
"266": "B 4 ",
|
| 268 |
+
"267": "B 5 ",
|
| 269 |
+
"268": "B 6 ",
|
| 270 |
+
"269": "B 7 ",
|
| 271 |
+
"270": "B 8 ",
|
| 272 |
+
"271": "B 9 ",
|
| 273 |
+
"272": "B 10 ",
|
| 274 |
+
"273": "B 11 ",
|
| 275 |
+
"274": "B 12 ",
|
| 276 |
+
"275": "B 13 ",
|
| 277 |
+
"276": "B 14 ",
|
| 278 |
+
"277": "B 15 ",
|
| 279 |
+
"278": "B 16 ",
|
| 280 |
+
"279": "B 17 ",
|
| 281 |
+
"280": "B 18 ",
|
| 282 |
+
"281": "B 19 ",
|
| 283 |
+
"282": "B 20 ",
|
| 284 |
+
"283": "B 21 ",
|
| 285 |
+
"284": "B 22 ",
|
| 286 |
+
"285": "B 23 ",
|
| 287 |
+
"286": "B 24 ",
|
| 288 |
+
"287": "B 25 ",
|
| 289 |
+
"288": "B 26 ",
|
| 290 |
+
"289": "B 27 ",
|
| 291 |
+
"290": "B 28 ",
|
| 292 |
+
"291": "B 29 ",
|
| 293 |
+
"292": "B 30 ",
|
| 294 |
+
"293": "B 31 ",
|
| 295 |
+
"294": "B 32 ",
|
| 296 |
+
"295": "B 33 ",
|
| 297 |
+
"296": "B 34 ",
|
| 298 |
+
"297": "B 35 ",
|
| 299 |
+
"298": "B 36 ",
|
| 300 |
+
"299": "B 37 ",
|
| 301 |
+
"300": "B 38 ",
|
| 302 |
+
"301": "B 39 ",
|
| 303 |
+
"302": "B 40 ",
|
| 304 |
+
"303": "B 41 ",
|
| 305 |
+
"304": "B 42 ",
|
| 306 |
+
"305": "B 43 ",
|
| 307 |
+
"306": "B 44 ",
|
| 308 |
+
"307": "B 45 ",
|
| 309 |
+
"308": "B 46 ",
|
| 310 |
+
"309": "B 47 ",
|
| 311 |
+
"310": "B 48 ",
|
| 312 |
+
"311": "B 49 ",
|
| 313 |
+
"312": "B 50 ",
|
| 314 |
+
"313": "B 51 ",
|
| 315 |
+
"314": "B 52 ",
|
| 316 |
+
"315": "B 53 ",
|
| 317 |
+
"316": "B 54 ",
|
| 318 |
+
"317": "B 55 ",
|
| 319 |
+
"318": "B 56 ",
|
| 320 |
+
"319": "B 57 ",
|
| 321 |
+
"320": "B 58 ",
|
| 322 |
+
"321": "B 59 ",
|
| 323 |
+
"322": "B 60 ",
|
| 324 |
+
"323": "B 61 ",
|
| 325 |
+
"324": "B 62 ",
|
| 326 |
+
"325": "B 63 ",
|
| 327 |
+
"326": "B 64 ",
|
| 328 |
+
"327": "B 65 ",
|
| 329 |
+
"328": "B 66 ",
|
| 330 |
+
"329": "B 67 ",
|
| 331 |
+
"330": "B 68 ",
|
| 332 |
+
"331": "B 69 ",
|
| 333 |
+
"332": "B 70 ",
|
| 334 |
+
"333": "B 71 ",
|
| 335 |
+
"334": "B 72 ",
|
| 336 |
+
"335": "B 73 ",
|
| 337 |
+
"336": "B 74 ",
|
| 338 |
+
"337": "B 75 ",
|
| 339 |
+
"338": "B 76 ",
|
| 340 |
+
"339": "B 77 ",
|
| 341 |
+
"340": "B 78 ",
|
| 342 |
+
"341": "B 79 ",
|
| 343 |
+
"342": "B 80 ",
|
| 344 |
+
"343": "B 81 ",
|
| 345 |
+
"344": "B 82 ",
|
| 346 |
+
"345": "B 83 ",
|
| 347 |
+
"346": "B 84 ",
|
| 348 |
+
"347": "B 85 ",
|
| 349 |
+
"348": "B 86 ",
|
| 350 |
+
"349": "B 87 ",
|
| 351 |
+
"350": "B 88 ",
|
| 352 |
+
"351": "B 89 ",
|
| 353 |
+
"352": "B 90 ",
|
| 354 |
+
"353": "B 91 ",
|
| 355 |
+
"354": "B 92 ",
|
| 356 |
+
"355": "B 93 ",
|
| 357 |
+
"356": "B 94 ",
|
| 358 |
+
"357": "B 95 ",
|
| 359 |
+
"358": "B 96 ",
|
| 360 |
+
"359": "B 97 ",
|
| 361 |
+
"360": "B 98 ",
|
| 362 |
+
"361": "B 99 ",
|
| 363 |
+
"362": "B 100 ",
|
| 364 |
+
"363": "B 101 ",
|
| 365 |
+
"364": "B 102 ",
|
| 366 |
+
"365": "B 103 ",
|
| 367 |
+
"366": "B 104 ",
|
| 368 |
+
"367": "B 105 ",
|
| 369 |
+
"368": "B 106 ",
|
| 370 |
+
"369": "B 107 ",
|
| 371 |
+
"370": "B 108 ",
|
| 372 |
+
"371": "B 109 ",
|
| 373 |
+
"372": "B 110 ",
|
| 374 |
+
"373": "B 111 ",
|
| 375 |
+
"374": "B 112 ",
|
| 376 |
+
"375": "B 113 ",
|
| 377 |
+
"376": "B 114 ",
|
| 378 |
+
"377": "B 115 ",
|
| 379 |
+
"378": "B 116 ",
|
| 380 |
+
"379": "B 117 ",
|
| 381 |
+
"380": "B 118 ",
|
| 382 |
+
"381": "B 119 ",
|
| 383 |
+
"382": "B 120 ",
|
| 384 |
+
"383": "B 121 ",
|
| 385 |
+
"384": "B 122 ",
|
| 386 |
+
"385": "B 123 ",
|
| 387 |
+
"386": "B 124 ",
|
| 388 |
+
"387": "B 125 ",
|
| 389 |
+
"388": "B 126 ",
|
| 390 |
+
"389": "B 127 ",
|
| 391 |
+
"390": "B 128 ",
|
| 392 |
+
"391": "B 129 ",
|
| 393 |
+
"392": "B 130 ",
|
| 394 |
+
"393": "B 131 ",
|
| 395 |
+
"394": "B 132 ",
|
| 396 |
+
"395": "B 133 ",
|
| 397 |
+
"396": "B 134 ",
|
| 398 |
+
"397": "B 135 ",
|
| 399 |
+
"398": "B 136 ",
|
| 400 |
+
"399": "B 137 ",
|
| 401 |
+
"400": "B 138 ",
|
| 402 |
+
"401": "B 139 ",
|
| 403 |
+
"402": "B 140 ",
|
| 404 |
+
"403": "B 141 ",
|
| 405 |
+
"404": "B 142 ",
|
| 406 |
+
"405": "B 143 ",
|
| 407 |
+
"406": "B 144 ",
|
| 408 |
+
"407": "B 145 ",
|
| 409 |
+
"408": "B 146 ",
|
| 410 |
+
"409": "B 147 ",
|
| 411 |
+
"410": "B 148 ",
|
| 412 |
+
"411": "B 149 ",
|
| 413 |
+
"412": "B 150 ",
|
| 414 |
+
"413": "B 151 ",
|
| 415 |
+
"414": "B 152 ",
|
| 416 |
+
"415": "B 153 ",
|
| 417 |
+
"416": "B 154 ",
|
| 418 |
+
"417": "B 155 ",
|
| 419 |
+
"418": "B 156 ",
|
| 420 |
+
"419": "B 157 ",
|
| 421 |
+
"420": "B 158 ",
|
| 422 |
+
"421": "B 159 ",
|
| 423 |
+
"422": "B 160 ",
|
| 424 |
+
"423": "B 161 ",
|
| 425 |
+
"424": "B 162 ",
|
| 426 |
+
"425": "B 163 ",
|
| 427 |
+
"426": "B 164 ",
|
| 428 |
+
"427": "B 165 "
|
| 429 |
+
}
|
scripts/per_chain_protocol.py
ADDED
|
@@ -0,0 +1,116 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/usr/bin/env python3
|
| 2 |
+
"""
|
| 3 |
+
Generate a copy of ddG-backrub.xml that additionally reports per-chain energies.
|
| 4 |
+
|
| 5 |
+
Why
|
| 6 |
+
---
|
| 7 |
+
The `unbound_wt` / `unbound_mut` totals in ddG.db3 are whole-pose scores. InterfaceDdGMover
|
| 8 |
+
builds the unbound state by rigid-body translating the moving chain(s) 1000 A apart, without
|
| 9 |
+
repacking or re-minimizing, and every chain stays in the pose
|
| 10 |
+
(protocols/features/InterfaceDdGMover.cc::unbind). So
|
| 11 |
+
|
| 12 |
+
unbound_X_total = sum over chains of intra(chain) for X in {wt, mut}
|
| 13 |
+
|
| 14 |
+
and `unbound_mut - unbound_wt` is the summed intramolecular ddG of *every* chain, including
|
| 15 |
+
the ones that were never mutated. Those only differ between the wild type and mutant branches
|
| 16 |
+
because the whole pose is re-minimized independently in each, so they contribute artifact.
|
| 17 |
+
|
| 18 |
+
What this adds
|
| 19 |
+
--------------
|
| 20 |
+
A `TotalEnergyMetric` per chain, reported into ddG.db3 by the same ReportToDB mover that
|
| 21 |
+
InterfaceDdGMover already applies to all four states. This is *reporting only* -- it adds no
|
| 22 |
+
sampling, consumes no random numbers, and leaves ddG_bind bit-identical (verified against the
|
| 23 |
+
unmodified protocol with -constant_seed).
|
| 24 |
+
|
| 25 |
+
Reading the result
|
| 26 |
+
------------------
|
| 27 |
+
On the **unbound** states the chains are 1000 A apart, so there are no cross-chain pair
|
| 28 |
+
energies and the reported value is exactly that chain's intramolecular energy. That is the
|
| 29 |
+
number to use:
|
| 30 |
+
|
| 31 |
+
per-chain ddG(chain X) = intra_mut(X) - intra_wt(X)
|
| 32 |
+
|
| 33 |
+
On the **bound** states the value is intra(chain) + roughly half the interface energy, because
|
| 34 |
+
Rosetta's residue_total_energies splits each two-body term between its two residues. Those rows
|
| 35 |
+
are useful as a cross-check (they sum to the pose total) but should not be read as per-chain
|
| 36 |
+
stability numbers.
|
| 37 |
+
|
| 38 |
+
Caveat this does NOT fix
|
| 39 |
+
------------------------
|
| 40 |
+
The unbound state is still never relaxed. This gives you the intramolecular strain difference
|
| 41 |
+
*in the bound backbone conformation*, not a folding ddG of the free monomer. For that you want
|
| 42 |
+
a dedicated monomer protocol (e.g. cartesian_ddg) run on the isolated chain.
|
| 43 |
+
"""
|
| 44 |
+
|
| 45 |
+
import os
|
| 46 |
+
|
| 47 |
+
|
| 48 |
+
def chains_in_pdb(pdb_path):
|
| 49 |
+
"""Chain IDs in the order they first appear in the PDB."""
|
| 50 |
+
chains = []
|
| 51 |
+
with open(pdb_path) as f:
|
| 52 |
+
for line in f:
|
| 53 |
+
if line.startswith(('ATOM', 'HETATM')):
|
| 54 |
+
chain = line[21]
|
| 55 |
+
if chain not in chains:
|
| 56 |
+
chains.append(chain)
|
| 57 |
+
return chains
|
| 58 |
+
|
| 59 |
+
|
| 60 |
+
def write_per_chain_protocol(base_xml_path, chains, out_path, scorefxn='fa_talaris2014'):
|
| 61 |
+
"""Write a copy of base_xml_path with a per-chain TotalEnergyMetric for each chain.
|
| 62 |
+
|
| 63 |
+
Each chain gets its own database table (chain_<X>_energy) with a single `total_energy`
|
| 64 |
+
column. Separate tables rather than one table with prefixed columns is deliberate: as of
|
| 65 |
+
Rosetta 2022.45, SimpleMetricFeatures builds schema column names as `custom_type + name`
|
| 66 |
+
but builds the INSERT as `custom_type + "_" + name`, so any non-empty custom_type produces
|
| 67 |
+
"table simple_metrics has no column named ..." at report time.
|
| 68 |
+
"""
|
| 69 |
+
if not chains:
|
| 70 |
+
raise ValueError('No chains given')
|
| 71 |
+
|
| 72 |
+
# Rosetta lowercases table names, so chains differing only in case would collide.
|
| 73 |
+
lowered = [c.lower() for c in chains]
|
| 74 |
+
if len(set(lowered)) != len(lowered):
|
| 75 |
+
raise ValueError('Chain IDs differ only by case, which collides in table names: %s' % chains)
|
| 76 |
+
|
| 77 |
+
xml = open(base_xml_path).read()
|
| 78 |
+
|
| 79 |
+
def substitute(text, anchor, addition):
|
| 80 |
+
if anchor not in text:
|
| 81 |
+
raise ValueError('Could not find anchor in %s:\n %s' % (base_xml_path, anchor))
|
| 82 |
+
return text.replace(anchor, anchor + addition, 1)
|
| 83 |
+
|
| 84 |
+
selectors = ''.join(
|
| 85 |
+
'\n <Chain name="chain_%s" chains="%s"/>' % (c, c) for c in chains)
|
| 86 |
+
xml = substitute(
|
| 87 |
+
xml, ' <StoredResidueSubset name="restore_neighbor_shell" subset_name="neighbor_shell"/>',
|
| 88 |
+
selectors)
|
| 89 |
+
|
| 90 |
+
metrics = '\n'.join(
|
| 91 |
+
' <TotalEnergyMetric name="chain_%s_energy" residue_selector="chain_%s" scorefxn="%s"/>'
|
| 92 |
+
% (c, c, scorefxn) for c in chains)
|
| 93 |
+
anchor = ' <FILTERS>'
|
| 94 |
+
if anchor not in xml:
|
| 95 |
+
raise ValueError('Could not find FILTERS block in %s' % base_xml_path)
|
| 96 |
+
xml = xml.replace(anchor, ' <SIMPLE_METRICS>\n%s\n </SIMPLE_METRICS>\n\n%s' % (metrics, anchor), 1)
|
| 97 |
+
|
| 98 |
+
reporters = ''.join(
|
| 99 |
+
'\n <SimpleMetricFeatures metrics="chain_%s_energy" table_name="chain_%s_energy"/>'
|
| 100 |
+
% (c, c) for c in chains)
|
| 101 |
+
xml = substitute(
|
| 102 |
+
xml, ' <StructureScoresFeatures scorefxn="%s"/>' % scorefxn, reporters)
|
| 103 |
+
|
| 104 |
+
with open(out_path, 'w') as f:
|
| 105 |
+
f.write(xml)
|
| 106 |
+
return out_path
|
| 107 |
+
|
| 108 |
+
|
| 109 |
+
if __name__ == '__main__':
|
| 110 |
+
import sys
|
| 111 |
+
if len(sys.argv) != 4:
|
| 112 |
+
sys.exit('usage: per_chain_protocol.py <base.xml> <input.pdb> <out.xml>')
|
| 113 |
+
base_xml, pdb, out = sys.argv[1:4]
|
| 114 |
+
found = chains_in_pdb(pdb)
|
| 115 |
+
write_per_chain_protocol(base_xml, found, out)
|
| 116 |
+
print('Wrote %s with per-chain metrics for chains: %s' % (out, ', '.join(found)))
|
scripts/reprocess_per_chain.py
ADDED
|
@@ -0,0 +1,253 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/usr/bin/env python3
|
| 2 |
+
"""
|
| 3 |
+
Recover per-chain intramolecular energies from an EXISTING flex ddG run.
|
| 4 |
+
|
| 5 |
+
No re-sampling is required. The backrub trajectory is the expensive part and you already ran
|
| 6 |
+
it: struct.db3 holds the coordinates of every backrub, wild type minimized and mutant minimized
|
| 7 |
+
pose. This script reads those poses back into Rosetta, isolates one chain at a time, rescores,
|
| 8 |
+
and reports per-chain ddG. Verified to reproduce the in-protocol per-chain metric (see
|
| 9 |
+
per_chain_protocol.py) to nine decimal places.
|
| 10 |
+
|
| 11 |
+
Why the chains have to be physically isolated rather than just selected: struct.db3 stores the
|
| 12 |
+
*bound* poses. A Chain residue selector scoped over a bound pose still picks up cross-chain pair
|
| 13 |
+
energies, because Rosetta's residue_total_energies splits each two-body term between its two
|
| 14 |
+
residues, so roughly half the interface energy leaks into each chain. Deleting the other chains
|
| 15 |
+
reproduces the separated unbound state exactly, since intra-chain energy is invariant under the
|
| 16 |
+
rigid-body translation InterfaceDdGMover uses to unbind.
|
| 17 |
+
|
| 18 |
+
What this does and does not give you
|
| 19 |
+
------------------------------------
|
| 20 |
+
It gives you the intramolecular energy difference between the mutant and wild type in the
|
| 21 |
+
*bound* backbone conformation, per chain. That is a strain term. It is NOT a folding ddG of the
|
| 22 |
+
free monomer: the unbound state is never relaxed here, in this script or in flex ddG itself. For
|
| 23 |
+
a true monomer stability ddG use a dedicated protocol such as cartesian_ddg on the isolated chain.
|
| 24 |
+
|
| 25 |
+
Built-in control: a chain you did not mutate should come out at 0 within its SEM. If it does not,
|
| 26 |
+
nstruct is too low to average out the whole-pose minimization noise, and the mutated chain's
|
| 27 |
+
number is not trustworthy either.
|
| 28 |
+
|
| 29 |
+
Usage
|
| 30 |
+
-----
|
| 31 |
+
python3 reprocess_per_chain.py <output_folder> [--stride N] [--chains A,B] [--csv out.csv]
|
| 32 |
+
|
| 33 |
+
The backrub_trajectory_stride is read back out of each struct.db3, so --stride is only needed
|
| 34 |
+
for databases that do not record it. It affects the checkpoint labels, not any energy.
|
| 35 |
+
"""
|
| 36 |
+
|
| 37 |
+
import argparse
|
| 38 |
+
import glob
|
| 39 |
+
import os
|
| 40 |
+
import re
|
| 41 |
+
import sqlite3
|
| 42 |
+
import subprocess
|
| 43 |
+
import sys
|
| 44 |
+
|
| 45 |
+
import numpy as np
|
| 46 |
+
import pandas as pd
|
| 47 |
+
|
| 48 |
+
import flex_ddg_db3
|
| 49 |
+
|
| 50 |
+
rosetta_scripts_path = os.path.expanduser('~/rosetta/source/bin/rosetta_scripts')
|
| 51 |
+
|
| 52 |
+
# Must match the score function the original run used.
|
| 53 |
+
rosetta_flags = [
|
| 54 |
+
'-restore_talaris_behavior',
|
| 55 |
+
'-in:file:fullatom',
|
| 56 |
+
'-out:nooutput',
|
| 57 |
+
]
|
| 58 |
+
|
| 59 |
+
struct_db3_name = 'struct.db3'
|
| 60 |
+
per_chain_db3_name = 'per_chain.db3'
|
| 61 |
+
|
| 62 |
+
# flex ddG writes three poses per checkpoint, in this order.
|
| 63 |
+
pose_order = ['backrub', 'wt', 'mut']
|
| 64 |
+
|
| 65 |
+
|
| 66 |
+
def chains_in_struct_db3(struct_db3):
|
| 67 |
+
conn = sqlite3.connect(struct_db3)
|
| 68 |
+
try:
|
| 69 |
+
chains = [row[0] for row in conn.execute(
|
| 70 |
+
'SELECT DISTINCT chain_id FROM residue_pdb_identification ORDER BY chain_id')]
|
| 71 |
+
finally:
|
| 72 |
+
conn.close()
|
| 73 |
+
return [c for c in chains if c and c.strip()]
|
| 74 |
+
|
| 75 |
+
|
| 76 |
+
def write_rescore_protocol(chains, out_path, scorefxn='fa_talaris2014'):
|
| 77 |
+
"""Emit a RosettaScripts protocol that isolates and rescores each chain in turn."""
|
| 78 |
+
lowered = [c.lower() for c in chains]
|
| 79 |
+
if len(set(lowered)) != len(lowered):
|
| 80 |
+
raise ValueError('Chain IDs differ only by case, which collides in batch names: %s' % chains)
|
| 81 |
+
|
| 82 |
+
selectors = '\n'.join(
|
| 83 |
+
' <Chain name="chain_%s" chains="%s"/>\n'
|
| 84 |
+
' <Not name="not_chain_%s" selector="chain_%s"/>' % (c, c, c, c) for c in chains)
|
| 85 |
+
|
| 86 |
+
movers = '\n'.join(
|
| 87 |
+
' <DeleteRegionMover name="isolate_chain_%s" residue_selector="not_chain_%s"/>\n'
|
| 88 |
+
' <ReportToDB name="chain_%s_report" batch_description="per_chain" database_name="%s">\n'
|
| 89 |
+
' <ScoreTypeFeatures/>\n'
|
| 90 |
+
' <ScoreFunctionFeatures scorefxn="%s"/>\n'
|
| 91 |
+
' <StructureScoresFeatures scorefxn="%s"/>\n'
|
| 92 |
+
' </ReportToDB>' % (c, c, c, per_chain_db3_name, scorefxn, scorefxn) for c in chains)
|
| 93 |
+
|
| 94 |
+
steps = [' <Add mover_name="save_full"/>']
|
| 95 |
+
for i, c in enumerate(chains):
|
| 96 |
+
if i > 0:
|
| 97 |
+
steps.append(' <Add mover_name="restore_full"/>')
|
| 98 |
+
steps.append(' <Add mover_name="isolate_chain_%s"/>' % c)
|
| 99 |
+
steps.append(' <Add mover_name="chain_%s_report"/>' % c)
|
| 100 |
+
|
| 101 |
+
xml = '''<ROSETTASCRIPTS>
|
| 102 |
+
<SCOREFXNS>
|
| 103 |
+
<ScoreFunction name="%s" weights="talaris2014"/>
|
| 104 |
+
</SCOREFXNS>
|
| 105 |
+
|
| 106 |
+
<RESIDUE_SELECTORS>
|
| 107 |
+
%s
|
| 108 |
+
</RESIDUE_SELECTORS>
|
| 109 |
+
|
| 110 |
+
<MOVERS>
|
| 111 |
+
<SavePoseMover name="save_full" reference_name="full_pose" restore_pose="0"/>
|
| 112 |
+
<SavePoseMover name="restore_full" reference_name="full_pose" restore_pose="1"/>
|
| 113 |
+
%s
|
| 114 |
+
</MOVERS>
|
| 115 |
+
|
| 116 |
+
<PROTOCOLS>
|
| 117 |
+
%s
|
| 118 |
+
</PROTOCOLS>
|
| 119 |
+
<OUTPUT />
|
| 120 |
+
</ROSETTASCRIPTS>
|
| 121 |
+
''' % (scorefxn, selectors, movers, '\n'.join(steps))
|
| 122 |
+
|
| 123 |
+
with open(out_path, 'w') as f:
|
| 124 |
+
f.write(xml)
|
| 125 |
+
return out_path
|
| 126 |
+
|
| 127 |
+
|
| 128 |
+
def rescore_one(struct_db3, protocol_path):
|
| 129 |
+
"""Run the isolate-and-rescore protocol on one struct.db3, writing per_chain.db3 beside it."""
|
| 130 |
+
working_dir = os.path.dirname(os.path.abspath(struct_db3))
|
| 131 |
+
out_db3 = os.path.join(working_dir, per_chain_db3_name)
|
| 132 |
+
if os.path.isfile(out_db3):
|
| 133 |
+
os.remove(out_db3)
|
| 134 |
+
|
| 135 |
+
args = [
|
| 136 |
+
os.path.abspath(rosetta_scripts_path),
|
| 137 |
+
'-inout:dbms:database_name', struct_db3_name,
|
| 138 |
+
'-in:use_database',
|
| 139 |
+
'-parser:protocol', os.path.abspath(protocol_path),
|
| 140 |
+
] + rosetta_flags
|
| 141 |
+
|
| 142 |
+
log_path = os.path.join(working_dir, 'per_chain_rescore.log')
|
| 143 |
+
with open(log_path, 'w') as log:
|
| 144 |
+
proc = subprocess.Popen(args, stdout=log, stderr=subprocess.STDOUT, cwd=working_dir)
|
| 145 |
+
returncode = proc.wait()
|
| 146 |
+
|
| 147 |
+
if returncode != 0 or not os.path.isfile(out_db3):
|
| 148 |
+
raise RuntimeError('Rescoring failed for %s -- see %s' % (struct_db3, log_path))
|
| 149 |
+
return out_db3
|
| 150 |
+
|
| 151 |
+
|
| 152 |
+
def read_per_chain_db3(per_chain_db3, struct_number, case_name, stride):
|
| 153 |
+
conn = sqlite3.connect(per_chain_db3)
|
| 154 |
+
df = pd.read_sql_query('''
|
| 155 |
+
SELECT batches.name AS batch, structures.tag AS tag, structure_scores.score_value AS energy
|
| 156 |
+
FROM structure_scores
|
| 157 |
+
INNER JOIN structures ON structures.struct_id=structure_scores.struct_id
|
| 158 |
+
INNER JOIN batches ON batches.batch_id=structure_scores.batch_id
|
| 159 |
+
INNER JOIN score_types ON score_types.batch_id=structure_scores.batch_id
|
| 160 |
+
AND score_types.score_type_id=structure_scores.score_type_id
|
| 161 |
+
WHERE score_types.score_type_name="total_score"
|
| 162 |
+
''', conn)
|
| 163 |
+
conn.close()
|
| 164 |
+
|
| 165 |
+
# batch name is "chain_<X>_report"; tag is "<original struct.db3 struct_id>_0001"
|
| 166 |
+
df['chain'] = df['batch'].apply(lambda b: b[len('chain_'):-len('_report')])
|
| 167 |
+
original_id = df['tag'].apply(lambda t: int(re.match(r'(\d+)', t).group(1)))
|
| 168 |
+
df['pose'] = original_id.apply(lambda i: pose_order[(i - 1) % len(pose_order)])
|
| 169 |
+
df['backrub_steps'] = original_id.apply(lambda i: stride * (((i - 1) // len(pose_order)) + 1))
|
| 170 |
+
df['struct_num'] = struct_number
|
| 171 |
+
df['case_name'] = case_name
|
| 172 |
+
return df[['case_name', 'struct_num', 'backrub_steps', 'chain', 'pose', 'energy']]
|
| 173 |
+
|
| 174 |
+
|
| 175 |
+
def main():
|
| 176 |
+
parser = argparse.ArgumentParser(description=__doc__,
|
| 177 |
+
formatter_class=argparse.RawDescriptionHelpFormatter)
|
| 178 |
+
parser.add_argument('output_folder', help='flex ddG output folder (e.g. "output")')
|
| 179 |
+
parser.add_argument('--stride', type=int, default=None,
|
| 180 |
+
help='override backrub_trajectory_stride instead of reading it from each '
|
| 181 |
+
'struct.db3. Affects checkpoint labels only, not any energy.')
|
| 182 |
+
parser.add_argument('--chains', default=None,
|
| 183 |
+
help='comma-separated chains (default: auto-detect from struct.db3)')
|
| 184 |
+
parser.add_argument('--csv', default=None, help='write the full per-structure table here')
|
| 185 |
+
parser.add_argument('--reuse', action='store_true',
|
| 186 |
+
help='skip Rosetta where per_chain.db3 already exists')
|
| 187 |
+
args = parser.parse_args()
|
| 188 |
+
|
| 189 |
+
if not os.path.isfile(rosetta_scripts_path):
|
| 190 |
+
sys.exit('ERROR: set rosetta_scripts_path to your compiled rosetta_scripts binary')
|
| 191 |
+
|
| 192 |
+
struct_db3s = sorted(glob.glob(os.path.join(args.output_folder, '*', '*', struct_db3_name)))
|
| 193 |
+
if not struct_db3s:
|
| 194 |
+
sys.exit('ERROR: no %s found under %s' % (struct_db3_name, args.output_folder))
|
| 195 |
+
print('Found %d %s files' % (len(struct_db3s), struct_db3_name))
|
| 196 |
+
|
| 197 |
+
chains = args.chains.split(',') if args.chains else chains_in_struct_db3(struct_db3s[0])
|
| 198 |
+
print('Chains: %s' % ', '.join(chains))
|
| 199 |
+
|
| 200 |
+
protocol_path = os.path.join(args.output_folder, 'per_chain_rescore.generated.xml')
|
| 201 |
+
write_rescore_protocol(chains, protocol_path)
|
| 202 |
+
print('Wrote protocol %s\n' % protocol_path)
|
| 203 |
+
|
| 204 |
+
frames = []
|
| 205 |
+
for i, struct_db3 in enumerate(struct_db3s, start=1):
|
| 206 |
+
struct_dir = os.path.dirname(struct_db3)
|
| 207 |
+
case_name = os.path.basename(os.path.dirname(struct_dir))
|
| 208 |
+
struct_number = os.path.basename(struct_dir)
|
| 209 |
+
out_db3 = os.path.join(struct_dir, per_chain_db3_name)
|
| 210 |
+
|
| 211 |
+
if args.reuse and os.path.isfile(out_db3):
|
| 212 |
+
print(' [%d/%d] %s (reusing)' % (i, len(struct_db3s), struct_dir))
|
| 213 |
+
else:
|
| 214 |
+
print(' [%d/%d] %s' % (i, len(struct_db3s), struct_dir))
|
| 215 |
+
out_db3 = rescore_one(struct_db3, protocol_path)
|
| 216 |
+
|
| 217 |
+
stride = args.stride
|
| 218 |
+
if stride is None:
|
| 219 |
+
stride = flex_ddg_db3.trajectory_stride_from_db3(struct_db3)
|
| 220 |
+
if stride is None:
|
| 221 |
+
stride = 5
|
| 222 |
+
print(' WARNING: %s does not record backrub_trajectory_stride; assuming %d. '
|
| 223 |
+
'Pass --stride to label the checkpoints correctly.' % (struct_db3, stride))
|
| 224 |
+
|
| 225 |
+
frames.append(read_per_chain_db3(out_db3, struct_number, case_name, stride))
|
| 226 |
+
|
| 227 |
+
per_structure = pd.concat(frames)
|
| 228 |
+
wide = per_structure[per_structure['pose'].isin(['wt', 'mut'])].pivot_table(
|
| 229 |
+
index=['case_name', 'chain', 'backrub_steps', 'struct_num'],
|
| 230 |
+
columns='pose', values='energy').reset_index()
|
| 231 |
+
wide['ddG'] = wide['mut'] - wide['wt']
|
| 232 |
+
|
| 233 |
+
if args.csv:
|
| 234 |
+
wide.to_csv(args.csv, index=False)
|
| 235 |
+
print('\nWrote %s' % args.csv)
|
| 236 |
+
|
| 237 |
+
summary = wide.groupby(['case_name', 'chain', 'backrub_steps']).agg(
|
| 238 |
+
nstruct=('ddG', 'size'),
|
| 239 |
+
wt_intra=('wt', 'mean'),
|
| 240 |
+
mut_intra=('mut', 'mean'),
|
| 241 |
+
ddG=('ddG', 'mean'),
|
| 242 |
+
ddG_sd=('ddG', 'std'),
|
| 243 |
+
).reset_index()
|
| 244 |
+
summary['ddG_sem'] = summary['ddG_sd'] / np.sqrt(summary['nstruct'])
|
| 245 |
+
|
| 246 |
+
print('\n=== per-chain intramolecular ddG ===')
|
| 247 |
+
print(summary.round(4).to_string(index=False))
|
| 248 |
+
print('\nA chain you did NOT mutate should read ~0 within ddG_sem.')
|
| 249 |
+
print('This is bound-conformation strain, not a folding ddG (see the module docstring).')
|
| 250 |
+
|
| 251 |
+
|
| 252 |
+
if __name__ == '__main__':
|
| 253 |
+
main()
|
scripts/run_example_1.py
ADDED
|
@@ -0,0 +1,121 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/usr/bin/python
|
| 2 |
+
|
| 3 |
+
from __future__ import print_function
|
| 4 |
+
|
| 5 |
+
import socket
|
| 6 |
+
import sys
|
| 7 |
+
import os
|
| 8 |
+
import subprocess
|
| 9 |
+
|
| 10 |
+
script_dir = os.path.dirname(os.path.abspath(__file__))
|
| 11 |
+
project_root = os.path.dirname(script_dir)
|
| 12 |
+
conf_dir = os.path.join(project_root, 'conf')
|
| 13 |
+
inputs_dir = os.path.join(script_dir, 'inputs')
|
| 14 |
+
|
| 15 |
+
use_multiprocessing = True
|
| 16 |
+
if use_multiprocessing:
|
| 17 |
+
import multiprocessing
|
| 18 |
+
max_cpus = 2 # We might want to not run on the full number of cores, as Rosetta take about 2 Gb of memory per instance
|
| 19 |
+
|
| 20 |
+
###################################################################################################################################################################
|
| 21 |
+
# Important: The variables below are set to values that will make the run complete faster (as a tutorial example), but will not give scientifically valid results.
|
| 22 |
+
# Please change them to the "normal" default values before a real run.
|
| 23 |
+
###################################################################################################################################################################
|
| 24 |
+
|
| 25 |
+
#rosetta_scripts_path = os.path.expanduser("~/rosetta/source/bin/rosetta_scripts")
|
| 26 |
+
rosetta_scripts_path = os.path.expanduser(
|
| 27 |
+
"/public/home/scnb9biwet/jiangqq/flex_ddG_tutorial-master/software/rosetta3.9/main/source/bin/rosetta_scripts.default.linuxgccrelease"
|
| 28 |
+
)
|
| 29 |
+
nstruct = 3 # Normally 35
|
| 30 |
+
max_minimization_iter = 5 # Normally 5000
|
| 31 |
+
abs_score_convergence_thresh = 200.0 # Normally 1.0
|
| 32 |
+
number_backrub_trials = 10 # Normally 35000
|
| 33 |
+
backrub_trajectory_stride = 5 # Can be whatever you want, if you would like to see results from earlier time points in the backrub trajectory. 7000 is a reasonable number, to give you three checkpoints for a 35000 step run, but you could also set it to 35000 for quickest run time (as the final minimization and packing steps will only need to be run one time).
|
| 34 |
+
path_to_script = os.path.join(conf_dir, 'ddG-backrub.xml')
|
| 35 |
+
|
| 36 |
+
# Additionally report the intramolecular energy of each individual chain into ddG.db3.
|
| 37 |
+
# This is reporting only: it adds no sampling, consumes no random numbers, and leaves the
|
| 38 |
+
# binding ddG bit-identical. Read the per-chain numbers off the *unbound* states, where the
|
| 39 |
+
# chains are 1000 A apart and the value is exactly that chain's intramolecular energy.
|
| 40 |
+
# See per_chain_protocol.py for the full explanation and caveats.
|
| 41 |
+
report_per_chain_energies = False
|
| 42 |
+
|
| 43 |
+
if not os.path.isfile(rosetta_scripts_path):
|
| 44 |
+
print('ERROR: "rosetta_scripts_path" variable must be set to the location of the "rosetta_scripts" binary executable')
|
| 45 |
+
print('This file might look something like: "rosetta_scripts.linuxgccrelease"')
|
| 46 |
+
raise Exception('Rosetta scripts missing')
|
| 47 |
+
|
| 48 |
+
def protocol_for( input_pdb_path ):
|
| 49 |
+
"""Return the XML to run, generating the per-chain reporting variant if requested."""
|
| 50 |
+
if not report_per_chain_energies:
|
| 51 |
+
return os.path.abspath(path_to_script)
|
| 52 |
+
|
| 53 |
+
import per_chain_protocol
|
| 54 |
+
chains = per_chain_protocol.chains_in_pdb( input_pdb_path )
|
| 55 |
+
derived = os.path.abspath( os.path.splitext(path_to_script)[0] + '-per_chain.xml' )
|
| 56 |
+
per_chain_protocol.write_per_chain_protocol( path_to_script, chains, derived )
|
| 57 |
+
return derived
|
| 58 |
+
|
| 59 |
+
def run_flex_ddg( name, input_path, input_pdb_path, chains_to_move, nstruct_i ):
|
| 60 |
+
output_directory = os.path.join( project_root, 'output', os.path.join( name, '%02d' % nstruct_i ) )
|
| 61 |
+
if not os.path.isdir(output_directory):
|
| 62 |
+
os.makedirs(output_directory)
|
| 63 |
+
|
| 64 |
+
flex_ddg_args = [
|
| 65 |
+
os.path.abspath(rosetta_scripts_path),
|
| 66 |
+
"-s %s" % os.path.abspath(input_pdb_path),
|
| 67 |
+
'-parser:protocol', protocol_for( input_pdb_path ),
|
| 68 |
+
'-parser:script_vars',
|
| 69 |
+
'chainstomove=' + chains_to_move,
|
| 70 |
+
'mutate_resfile_relpath=' + os.path.abspath( os.path.join( input_path, 'nataa_mutations.resfile' ) ),
|
| 71 |
+
'number_backrub_trials=%d' % number_backrub_trials,
|
| 72 |
+
'max_minimization_iter=%d' % max_minimization_iter,
|
| 73 |
+
'abs_score_convergence_thresh=%.1f' % abs_score_convergence_thresh,
|
| 74 |
+
'backrub_trajectory_stride=%d' % backrub_trajectory_stride ,
|
| 75 |
+
'-restore_talaris_behavior',
|
| 76 |
+
'-in:file:fullatom',
|
| 77 |
+
'-ignore_unrecognized_res',
|
| 78 |
+
'-ignore_zero_occupancy false',
|
| 79 |
+
'-ex1',
|
| 80 |
+
'-ex2',
|
| 81 |
+
]
|
| 82 |
+
|
| 83 |
+
log_path = os.path.join(output_directory, 'rosetta.out')
|
| 84 |
+
|
| 85 |
+
print( 'Running Rosetta with args:' )
|
| 86 |
+
print( ' '.join(flex_ddg_args) )
|
| 87 |
+
print( 'Output logged to:', os.path.abspath(log_path) )
|
| 88 |
+
print()
|
| 89 |
+
|
| 90 |
+
outfile = open(log_path, 'w')
|
| 91 |
+
process = subprocess.Popen(flex_ddg_args, stdout=outfile, stderr=subprocess.STDOUT, close_fds = True, cwd = output_directory)
|
| 92 |
+
returncode = process.wait()
|
| 93 |
+
outfile.close()
|
| 94 |
+
|
| 95 |
+
if __name__ == '__main__':
|
| 96 |
+
cases = []
|
| 97 |
+
for nstruct_i in range(1, nstruct + 1 ):
|
| 98 |
+
for case_name in os.listdir(inputs_dir):
|
| 99 |
+
case_path = os.path.join( inputs_dir, case_name )
|
| 100 |
+
for f in os.listdir(case_path):
|
| 101 |
+
if f.endswith('.pdb'):
|
| 102 |
+
input_pdb_path = os.path.join( case_path, f )
|
| 103 |
+
break
|
| 104 |
+
|
| 105 |
+
with open( os.path.join( case_path, 'chains_to_move.txt' ), 'r' ) as f:
|
| 106 |
+
chains_to_move = f.readlines()[0].strip()
|
| 107 |
+
|
| 108 |
+
cases.append( (case_name, case_path, input_pdb_path, chains_to_move, nstruct_i) )
|
| 109 |
+
|
| 110 |
+
if use_multiprocessing:
|
| 111 |
+
pool = multiprocessing.Pool( processes = min(max_cpus, multiprocessing.cpu_count()) )
|
| 112 |
+
|
| 113 |
+
for args in cases:
|
| 114 |
+
if use_multiprocessing:
|
| 115 |
+
pool.apply_async( run_flex_ddg, args = args )
|
| 116 |
+
else:
|
| 117 |
+
run_flex_ddg( *args )
|
| 118 |
+
|
| 119 |
+
if use_multiprocessing:
|
| 120 |
+
pool.close()
|
| 121 |
+
pool.join()
|
scripts/run_example_2_saturation.py
ADDED
|
@@ -0,0 +1,116 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/usr/bin/python
|
| 2 |
+
|
| 3 |
+
from __future__ import print_function
|
| 4 |
+
|
| 5 |
+
import socket
|
| 6 |
+
import sys
|
| 7 |
+
import os
|
| 8 |
+
import subprocess
|
| 9 |
+
|
| 10 |
+
script_dir = os.path.dirname(os.path.abspath(__file__))
|
| 11 |
+
project_root = os.path.dirname(script_dir)
|
| 12 |
+
conf_dir = os.path.join(project_root, 'conf')
|
| 13 |
+
inputs_dir = os.path.join(script_dir, 'inputs')
|
| 14 |
+
|
| 15 |
+
use_multiprocessing = True
|
| 16 |
+
if use_multiprocessing:
|
| 17 |
+
import multiprocessing
|
| 18 |
+
max_cpus = 2 # We might want to not run on the full number of cores, as Rosetta take about 2 Gb of memory per instance
|
| 19 |
+
|
| 20 |
+
###################################################################################################################################################################
|
| 21 |
+
# Important: The variables below are set to values that will make the run complete faster (as a tutorial example), but will not give scientifically valid results.
|
| 22 |
+
# Please change them to the "normal" default values before a real run.
|
| 23 |
+
###################################################################################################################################################################
|
| 24 |
+
|
| 25 |
+
#rosetta_scripts_path = os.path.expanduser("~/rosetta/source/bin/rosetta_scripts")
|
| 26 |
+
rosetta_scripts_path = os.path.expanduser(
|
| 27 |
+
"/public/home/scnb9biwet/jiangqq/flex_ddG_tutorial-master/software/rosetta3.9/main/source/bin/rosetta_scripts.default.linuxgccrelease"
|
| 28 |
+
)
|
| 29 |
+
nstruct = 3 # Normally 35
|
| 30 |
+
max_minimization_iter = 5 # Normally 5000
|
| 31 |
+
abs_score_convergence_thresh = 200.0 # Normally 1.0
|
| 32 |
+
number_backrub_trials = 10 # Normally 35000
|
| 33 |
+
backrub_trajectory_stride = 5 # Can be whatever you want, if you would like to see results from earlier time points in the backrub trajectory. 7000 is a reasonable number, to give you three checkpoints for a 35000 step run, but you could also set it to 35000 for quickest run time (as the final minimization and packing steps will only need to be run one time).
|
| 34 |
+
path_to_script = os.path.join(conf_dir, 'ddG-backrub.xml')
|
| 35 |
+
residue_to_mutate = ('B', 49, '') # Residue position to perfrom saturation mutatagenesis. Format: (Chain, PDB residue number, insertion code).
|
| 36 |
+
|
| 37 |
+
if not os.path.isfile(rosetta_scripts_path):
|
| 38 |
+
print('ERROR: "rosetta_scripts_path" variable must be set to the location of the "rosetta_scripts" binary executable')
|
| 39 |
+
print('This file might look something like: "rosetta_scripts.linuxgccrelease"')
|
| 40 |
+
raise Exception('Rosetta scripts missing')
|
| 41 |
+
|
| 42 |
+
def run_flex_ddg_saturation( name, input_path, input_pdb_path, chains_to_move, mut_aa, nstruct_i ):
|
| 43 |
+
output_directory = os.path.join( project_root, 'output_saturation', os.path.join( '%s_%s' % (name, mut_aa), '%02d' % nstruct_i ) )
|
| 44 |
+
if not os.path.isdir(output_directory):
|
| 45 |
+
os.makedirs(output_directory)
|
| 46 |
+
|
| 47 |
+
mutation_chain, mutation_resi, mutation_icode = residue_to_mutate
|
| 48 |
+
resfile_path = os.path.join( output_directory, 'mutate_%s%d%s_to_%s.resfile' % (mutation_chain, mutation_resi, mutation_icode, mut_aa) )
|
| 49 |
+
with open( resfile_path, 'w') as f:
|
| 50 |
+
# Header must be NATAA, not NATRO. This resfile is used both to pick the mutated
|
| 51 |
+
# position and as the task operation for the mutant PackRotamersMover. With NATRO,
|
| 52 |
+
# the mutant branch freezes the 8 A neighbor shell while the wild type branch
|
| 53 |
+
# repacks it, which biases every ddG upwards by several REU (a self-mutation to the
|
| 54 |
+
# native amino acid comes out at +6 instead of 0).
|
| 55 |
+
f.write( 'NATAA\nstart\n%d%s %s PIKAA %s\n' % (mutation_resi, mutation_icode, mutation_chain, mut_aa) )
|
| 56 |
+
|
| 57 |
+
flex_ddg_args = [
|
| 58 |
+
os.path.abspath(rosetta_scripts_path),
|
| 59 |
+
"-s %s" % os.path.abspath(input_pdb_path),
|
| 60 |
+
'-parser:protocol', os.path.abspath(path_to_script),
|
| 61 |
+
'-parser:script_vars',
|
| 62 |
+
'chainstomove=' + chains_to_move,
|
| 63 |
+
'mutate_resfile_relpath=' + os.path.abspath( resfile_path ),
|
| 64 |
+
'number_backrub_trials=%d' % number_backrub_trials,
|
| 65 |
+
'max_minimization_iter=%d' % max_minimization_iter,
|
| 66 |
+
'abs_score_convergence_thresh=%.1f' % abs_score_convergence_thresh,
|
| 67 |
+
'backrub_trajectory_stride=%d' % backrub_trajectory_stride ,
|
| 68 |
+
'-restore_talaris_behavior',
|
| 69 |
+
'-in:file:fullatom',
|
| 70 |
+
'-ignore_unrecognized_res',
|
| 71 |
+
'-ignore_zero_occupancy false',
|
| 72 |
+
'-ex1',
|
| 73 |
+
'-ex2',
|
| 74 |
+
]
|
| 75 |
+
|
| 76 |
+
log_path = os.path.join(output_directory, 'rosetta.out')
|
| 77 |
+
|
| 78 |
+
print( 'Running Rosetta with args:' )
|
| 79 |
+
print( ' '.join(flex_ddg_args) )
|
| 80 |
+
print( 'Output logged to:', os.path.abspath(log_path) )
|
| 81 |
+
print()
|
| 82 |
+
|
| 83 |
+
outfile = open(log_path, 'w')
|
| 84 |
+
process = subprocess.Popen(flex_ddg_args, stdout=outfile, stderr=subprocess.STDOUT, close_fds = True, cwd = output_directory)
|
| 85 |
+
returncode = process.wait()
|
| 86 |
+
outfile.close()
|
| 87 |
+
|
| 88 |
+
if __name__ == '__main__':
|
| 89 |
+
mutation_chain, mutation_resi, mutation_icode = residue_to_mutate
|
| 90 |
+
cases = []
|
| 91 |
+
for nstruct_i in range(1, nstruct + 1 ):
|
| 92 |
+
for case_name in os.listdir(inputs_dir):
|
| 93 |
+
case_path = os.path.join( inputs_dir, case_name )
|
| 94 |
+
for f in os.listdir(case_path):
|
| 95 |
+
if f.endswith('.pdb'):
|
| 96 |
+
input_pdb_path = os.path.join( case_path, f )
|
| 97 |
+
break
|
| 98 |
+
|
| 99 |
+
with open( os.path.join( case_path, 'chains_to_move.txt' ), 'r' ) as f:
|
| 100 |
+
chains_to_move = f.readlines()[0].strip()
|
| 101 |
+
|
| 102 |
+
for mut_aa in 'ACDEFGHIKLMNPQRSTVWY':
|
| 103 |
+
cases.append( ('%s_%s%d%s' % (case_name, mutation_chain, mutation_resi, mutation_icode), case_path, input_pdb_path, chains_to_move, mut_aa, nstruct_i) )
|
| 104 |
+
|
| 105 |
+
if use_multiprocessing:
|
| 106 |
+
pool = multiprocessing.Pool( processes = min(max_cpus, multiprocessing.cpu_count()) )
|
| 107 |
+
|
| 108 |
+
for args in cases:
|
| 109 |
+
if use_multiprocessing:
|
| 110 |
+
pool.apply_async( run_flex_ddg_saturation, args = args )
|
| 111 |
+
else:
|
| 112 |
+
run_flex_ddg_saturation( *args )
|
| 113 |
+
|
| 114 |
+
if use_multiprocessing:
|
| 115 |
+
pool.close()
|
| 116 |
+
pool.join()
|