anzhi2710gmailcom commited on
Commit
d766458
·
verified ·
1 Parent(s): 40f2e20

Upload folder using huggingface_hub

Browse files
This view is limited to 50 files because it contains too many changes.   See raw diff
Files changed (50) hide show
  1. .gitattributes +28 -9
  2. .gitignore +171 -0
  3. .gitmodules +4 -0
  4. CODE_OF_CONDUCT.md +127 -0
  5. CONTRIBUTING.md +61 -0
  6. LICENSE +201 -0
  7. README.md +520 -0
  8. conf/examples/5o45.cif +0 -0
  9. conf/examples/PDL1_quick_start.yaml +16 -0
  10. conf/examples/msa/PDL1/0/non_pairing.a3m +0 -0
  11. conf/examples/msa/PDL1/0/pairing.a3m +0 -0
  12. configuration.json +39 -0
  13. model/PXDesignBench/.gitignore +168 -0
  14. model/PXDesignBench/CODE_OF_CONDUCT.md +127 -0
  15. model/PXDesignBench/CONTRIBUTING.md +61 -0
  16. model/PXDesignBench/ColabDesign/.github/workflows/python-publish.yml +39 -0
  17. model/PXDesignBench/ColabDesign/.gitignore +2 -0
  18. model/PXDesignBench/ColabDesign/LICENSE.txt +8 -0
  19. model/PXDesignBench/ColabDesign/MANIFEST.in +4 -0
  20. model/PXDesignBench/ColabDesign/README.md +29 -0
  21. model/PXDesignBench/ColabDesign/af/LICENSE.txt +8 -0
  22. model/PXDesignBench/ColabDesign/af/README.md +336 -0
  23. model/PXDesignBench/ColabDesign/af/contrib/README.md +1 -0
  24. model/PXDesignBench/ColabDesign/af/design.ipynb +452 -0
  25. model/PXDesignBench/ColabDesign/af/examples/AF2Rank.ipynb +0 -0
  26. model/PXDesignBench/ColabDesign/af/examples/RSO.ipynb +1297 -0
  27. model/PXDesignBench/ColabDesign/af/examples/af2cycler.ipynb +741 -0
  28. model/PXDesignBench/ColabDesign/af/examples/af_cyc_design.ipynb +320 -0
  29. model/PXDesignBench/ColabDesign/af/examples/af_pseudo_diffusion.ipynb +266 -0
  30. model/PXDesignBench/ColabDesign/af/examples/af_pseudo_diffusion_dgram.ipynb +376 -0
  31. model/PXDesignBench/ColabDesign/af/examples/af_pseudo_diffusion_recycle.ipynb +329 -0
  32. model/PXDesignBench/ColabDesign/af/examples/af_relax_design.ipynb +400 -0
  33. model/PXDesignBench/ColabDesign/af/examples/af_single_sequential.ipynb +164 -0
  34. model/PXDesignBench/ColabDesign/af/examples/afdesign_hotspot_test.ipynb +247 -0
  35. model/PXDesignBench/ColabDesign/af/examples/binder_hallucination.ipynb +42 -0
  36. model/PXDesignBench/ColabDesign/af/examples/disulfide_design.ipynb +348 -0
  37. model/PXDesignBench/ColabDesign/af/examples/hallucination.ipynb +193 -0
  38. model/PXDesignBench/ColabDesign/af/examples/hallucination_custom_loss.ipynb +260 -0
  39. model/PXDesignBench/ColabDesign/af/examples/partial_hallucination_rewire.ipynb +161 -0
  40. model/PXDesignBench/ColabDesign/af/examples/peptide_binder_design.ipynb +319 -0
  41. model/PXDesignBench/ColabDesign/af/examples/use_esm_1b_bias.ipynb +329 -0
  42. model/PXDesignBench/ColabDesign/af_design_tutorial.ipynb +43 -0
  43. model/PXDesignBench/ColabDesign/colabdesign/__init__.py +16 -0
  44. model/PXDesignBench/ColabDesign/colabdesign/af/README.md +6 -0
  45. model/PXDesignBench/ColabDesign/colabdesign/af/__init__.py +13 -0
  46. model/PXDesignBench/ColabDesign/colabdesign/af/alphafold/__init__.py +14 -0
  47. model/PXDesignBench/ColabDesign/colabdesign/af/alphafold/common/__init__.py +14 -0
  48. model/PXDesignBench/ColabDesign/colabdesign/af/alphafold/common/confidence.py +169 -0
  49. model/PXDesignBench/ColabDesign/colabdesign/af/alphafold/common/protein.py +229 -0
  50. model/PXDesignBench/ColabDesign/colabdesign/af/alphafold/common/residue_constants.py +911 -0
.gitattributes CHANGED
@@ -1,35 +1,54 @@
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 -text
48
+ weight/release_data/ccd_cache/components.v20240608.cif filter=lfs diff=lfs merge=lfs -text
49
+ model/PXDesignBench/pxdbench/metrics/TMalign filter=lfs diff=lfs merge=lfs -text
50
+ model/Protenix-pxd/Protenix_Technical_Report.pdf filter=lfs diff=lfs merge=lfs -text
51
+ model/Protenix-pxd/assets/constraint_metrics.png filter=lfs diff=lfs merge=lfs -text
52
+ model/Protenix-pxd/assets/mini_performance.png filter=lfs diff=lfs merge=lfs -text
53
+ model/Protenix-pxd/assets/protenix_predictions.gif filter=lfs diff=lfs merge=lfs -text
54
+ model/Protenix-pxd/assets/v0.5.0_metrics.png filter=lfs diff=lfs merge=lfs -text
.gitignore ADDED
@@ -0,0 +1,171 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Byte-compiled / optimized / DLL files
2
+ *__pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+
6
+ # C extensions
7
+ *.so
8
+ *.o
9
+ *.obj
10
+ *.d
11
+ # ninjia relate
12
+ *ninja*
13
+ lock
14
+ # Distribution / packaging
15
+ .Python
16
+ .vscode
17
+ build/
18
+ develop-eggs/
19
+ dist/
20
+ downloads/
21
+ eggs/
22
+ .eggs/
23
+ lib/
24
+ lib64/
25
+ parts/
26
+ sdist/
27
+ var/
28
+ wheels/
29
+ share/python-wheels/
30
+ *.egg-info/
31
+ .installed.cfg
32
+ *.egg
33
+ MANIFEST
34
+
35
+ # PyInstaller
36
+ # Usually these files are written by a python script from a template
37
+ # before PyInstaller builds the exe, so as to inject date/other infos into it.
38
+ *.manifest
39
+ *.spec
40
+
41
+ # Installer logs
42
+ pip-log.txt
43
+ pip-delete-this-directory.txt
44
+
45
+ # Unit test / coverage reports
46
+ .tox/
47
+ .nox/
48
+ .coverage
49
+ .coverage.*
50
+ .cache
51
+ *.cover
52
+ *.py,cover
53
+ .hypothesis/
54
+ .pytest_cache/
55
+
56
+ # Translations
57
+ *.mo
58
+ *.pot
59
+
60
+ # Django stuff:
61
+ *.log
62
+ local_settings.py
63
+ db.sqlite3
64
+ db.sqlite3-journal
65
+
66
+ # Flask stuff:
67
+ instance/
68
+ .webassets-cache
69
+
70
+ # Scrapy stuff:
71
+ .scrapy
72
+
73
+ # Sphinx documentation
74
+ docs/_build/
75
+
76
+ # PyBuilder
77
+ .pybuilder/
78
+ target/
79
+
80
+ # Jupyter Notebook
81
+ .ipynb_checkpoints
82
+
83
+ # IPython
84
+ profile_default/
85
+ ipython_config.py
86
+
87
+ # data cache and checkpoints
88
+ data_cache/
89
+ checkpoints/
90
+
91
+ # pyenv
92
+ # For a library or package, you might want to ignore these files since the code is
93
+ # intended to run in multiple environments; otherwise, check them in:
94
+ # .python-version
95
+
96
+ # pipenv
97
+ # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
98
+ # However, in case of collaboration, if having platform-specific dependencies or dependencies
99
+ # having no cross-platform support, pipenv may install dependencies that don't work, or not
100
+ # install all needed dependencies.
101
+ #Pipfile.lock
102
+
103
+ # poetry
104
+ # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
105
+ # This is especially recommended for binary packages to ensure reproducibility, and is more
106
+ # commonly ignored for libraries.
107
+ # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
108
+ #poetry.lock
109
+
110
+ # pdm
111
+ # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
112
+ #pdm.lock
113
+ # pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
114
+ # in version control.
115
+ # https://pdm.fming.dev/#use-with-ide
116
+ .pdm.toml
117
+
118
+ # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
119
+ __pypackages__/
120
+
121
+ # Celery stuff
122
+ celerybeat-schedule
123
+ celerybeat.pid
124
+
125
+ # SageMath parsed files
126
+ *.sage.py
127
+
128
+ # Environments
129
+ .env
130
+ .venv
131
+ env/
132
+ venv/
133
+ ENV/
134
+ env.bak/
135
+ venv.bak/
136
+
137
+ # Spyder project settings
138
+ .spyderproject
139
+ .spyproject
140
+
141
+ # Rope project settings
142
+ .ropeproject
143
+
144
+ # mkdocs documentation
145
+ /site
146
+
147
+ # mypy
148
+ .mypy_cache/
149
+ .dmypy.json
150
+ dmypy.json
151
+
152
+ # Pyre type checker
153
+ .pyre/
154
+
155
+ # pytype static type analyzer
156
+ .pytype/
157
+
158
+ # Cython debug symbols
159
+ cython_debug/
160
+
161
+ # PyCharm
162
+ # JetBrains specific template is maintained in a separate JetBrains.gitignore that can
163
+ # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
164
+ # and can be added to the global gitignore or merged into this file. For a more nuclear
165
+ # option (not recommended) you can uncomment the following to ignore the entire idea folder.
166
+ #.idea/
167
+
168
+ wandb/
169
+ output*/
170
+ release_data/
171
+ tool_weights/
.gitmodules ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ [submodule "eval_design"]
2
+ path = eval_design
3
+ url = https://github.com/bytedance/PXDesignBench.git
4
+ branch = master
CODE_OF_CONDUCT.md ADDED
@@ -0,0 +1,127 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Contributor Covenant Code of Conduct
2
+
3
+ ## Our Pledge
4
+
5
+ We as members, contributors, and leaders pledge to make participation in our
6
+ community a harassment-free experience for everyone, regardless of age, body
7
+ size, visible or invisible disability, ethnicity, sex characteristics, gender
8
+ identity and expression, level of experience, education, socio-economic status,
9
+ nationality, personal appearance, race, religion, or sexual identity
10
+ and orientation.
11
+
12
+ We pledge to act and interact in ways that contribute to an open, welcoming,
13
+ diverse, inclusive, and healthy community.
14
+
15
+ ## Our Standards
16
+
17
+ Examples of behavior that contributes to a positive environment for our
18
+ community include:
19
+
20
+ * Demonstrating empathy and kindness toward other people
21
+ * Being respectful of differing opinions, viewpoints, and experiences
22
+ * Giving and gracefully accepting constructive feedback
23
+ * Accepting responsibility and apologizing to those affected by our mistakes,
24
+ and learning from the experience
25
+ * Focusing on what is best not just for us as individuals, but for the
26
+ overall community
27
+
28
+ Examples of unacceptable behavior include:
29
+
30
+ * The use of sexualized language or imagery, and sexual attention or
31
+ advances of any kind
32
+ * Trolling, insulting or derogatory comments, and personal or political attacks
33
+ * Public or private harassment
34
+ * Publishing others' private information, such as a physical or email
35
+ address, without their explicit permission
36
+ * Other conduct which could reasonably be considered inappropriate in a
37
+ professional setting
38
+
39
+ ## Enforcement Responsibilities
40
+
41
+ Community leaders are responsible for clarifying and enforcing our standards of
42
+ acceptable behavior and will take appropriate and fair corrective action in
43
+ response to any behavior that they deem inappropriate, threatening, offensive,
44
+ or harmful.
45
+
46
+ Community leaders have the right and responsibility to remove, edit, or reject
47
+ comments, commits, code, wiki edits, issues, and other contributions that are
48
+ not aligned to this Code of Conduct, and will communicate reasons for moderation
49
+ decisions when appropriate.
50
+
51
+ ## Scope
52
+
53
+ This Code of Conduct applies within all community spaces, and also applies when
54
+ an individual is officially representing the community in public spaces.
55
+ Examples of representing our community include using an official e-mail address,
56
+ posting via an official social media account, or acting as an appointed
57
+ representative at an online or offline event.
58
+
59
+ ## Enforcement
60
+
61
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be
62
+ reported to the community leaders responsible for enforcement.
63
+ All complaints will be reviewed and investigated promptly and fairly.
64
+
65
+ All community leaders are obligated to respect the privacy and security of the
66
+ reporter of any incident.
67
+
68
+ ## Enforcement Guidelines
69
+
70
+ Community leaders will follow these Community Impact Guidelines in determining
71
+ the consequences for any action they deem in violation of this Code of Conduct:
72
+
73
+ ### 1. Correction
74
+
75
+ **Community Impact**: Use of inappropriate language or other behavior deemed
76
+ unprofessional or unwelcome in the community.
77
+
78
+ **Consequence**: A private, written warning from community leaders, providing
79
+ clarity around the nature of the violation and an explanation of why the
80
+ behavior was inappropriate. A public apology may be requested.
81
+
82
+ ### 2. Warning
83
+
84
+ **Community Impact**: A violation through a single incident or series
85
+ of actions.
86
+
87
+ **Consequence**: A warning with consequences for continued behavior. No
88
+ interaction with the people involved, including unsolicited interaction with
89
+ those enforcing the Code of Conduct, for a specified period of time. This
90
+ includes avoiding interactions in community spaces as well as external channels
91
+ like social media. Violating these terms may lead to a temporary or
92
+ permanent ban.
93
+
94
+ ### 3. Temporary Ban
95
+
96
+ **Community Impact**: A serious violation of community standards, including
97
+ sustained inappropriate behavior.
98
+
99
+ **Consequence**: A temporary ban from any sort of interaction or public
100
+ communication with the community for a specified period of time. No public or
101
+ private interaction with the people involved, including unsolicited interaction
102
+ with those enforcing the Code of Conduct, is allowed during this period.
103
+ Violating these terms may lead to a permanent ban.
104
+
105
+ ### 4. Permanent Ban
106
+
107
+ **Community Impact**: Demonstrating a pattern of violation of community
108
+ standards, including sustained inappropriate behavior, harassment of an
109
+ individual, or aggression toward or disparagement of classes of individuals.
110
+
111
+ **Consequence**: A permanent ban from any sort of public interaction within
112
+ the community.
113
+
114
+ ## Attribution
115
+
116
+ This Code of Conduct is adapted from the [Contributor Covenant][homepage],
117
+ version 2.0, available at
118
+ https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
119
+
120
+ Community Impact Guidelines were inspired by [Mozilla's code of conduct
121
+ enforcement ladder](https://github.com/mozilla/diversity).
122
+
123
+ [homepage]: https://www.contributor-covenant.org
124
+
125
+ For answers to common questions about this code of conduct, see the FAQ at
126
+ https://www.contributor-covenant.org/faq. Translations are available at
127
+ https://www.contributor-covenant.org/translations.
CONTRIBUTING.md ADDED
@@ -0,0 +1,61 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Contributing
2
+
3
+ Thank you for investing your time in contributing to <NAME> project!
4
+
5
+ Read our [Code of Coduct](./CODE_OF_CONDUCT.md) to keep our community approachable and respectable.
6
+
7
+ This guide details how to use issues and pull requests to improve <NAME> project.
8
+
9
+ ## General Guidelines
10
+
11
+ ### Pull Requests
12
+
13
+ Make sure to keep Pull Requests small and functional to make them easier to review, understand, and look up in commit history. This repository uses "Squash and Commit" to keep our history clean and make it easier to revert changes based on PR.
14
+
15
+ Adding the appropriate documentation, unit tests and e2e tests as part of a feature is the responsibility of the feature owner, whether it is done in the same Pull Request or not.
16
+
17
+ Pull Requests should follow the "subject: message" format, where the subject describes what part of the code is being modified.
18
+
19
+ Refer to the template for more information on what goes into a PR description.
20
+
21
+ ### Design Docs
22
+
23
+ A contributor proposes a design with a PR on the repository to allow for revisions and discussions. If a design needs to be discussed before formulating a document for it, make use of Google doc and GitHub issue to involve the community on the discussion.
24
+
25
+ ### GitHub Issues
26
+
27
+ GitHub Issues are used to file bugs, work items, and feature requests with actionable items/issues (Please refer to the "Reporting Bugs/Feature Requests" section below for more information).
28
+
29
+ ### Reporting Bugs/Feature Requests
30
+
31
+ We welcome you to use the GitHub issue tracker to report bugs or suggest features that have actionable items/issues (as opposed to introducing a feature request on GitHub Discussions).
32
+
33
+ When filing an issue, please check existing open, or recently closed, issues to make sure somebody else hasn't already reported the issue. Please try to include as much information as you can. Details like these are incredibly useful:
34
+
35
+ - A reproducible test case or series of steps
36
+ - The version of the code being used
37
+ - Any modifications you've made relevant to the bug
38
+ - Anything unusual about your environment or deployment
39
+
40
+ ## Contributing via Pull Requests
41
+
42
+ ### Find interesting issue
43
+
44
+ If you spot a problem with the problem, [search if an issue already exists](https://github.com/bytedance/<NAME>/issues). If a related issue doesn't exist, you can open a new issue using [issue template](https://github.com/bytedance/<NAME>/issues/new/choose).
45
+
46
+ ### Solve an issue
47
+
48
+ Please check `DEVELOPMENT.md` in sub folder to get familar with running and testing codes.
49
+
50
+ ### Open a Pull request.
51
+
52
+ When you're done making the changes, open a pull request and fill PR template so we can better review your PR. The template helps reviewers understand your changes and the purpose of your pull request.
53
+
54
+ Don't forget to link PR to issue if you are solving one.
55
+
56
+ If you run into any merge issues, checkout this [git tutorial](https://lab.github.com/githubtraining/managing-merge-conflicts) to help you resolve merge conflicts and other issues.
57
+
58
+
59
+ ## Finding contributions to work on
60
+
61
+ Looking at the existing issues is a great way to find something to contribute on. As our projects, by default, use the default GitHub issue labels (enhancement/bug/duplicate/help wanted/invalid/question/wontfix), looking at any 'help wanted' and 'good first issue' issues are a great place to start.
LICENSE ADDED
@@ -0,0 +1,201 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Apache License
2
+ Version 2.0, January 2004
3
+ http://www.apache.org/licenses/
4
+
5
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6
+
7
+ 1. Definitions.
8
+
9
+ "License" shall mean the terms and conditions for use, reproduction,
10
+ and distribution as defined by Sections 1 through 9 of this document.
11
+
12
+ "Licensor" shall mean the copyright owner or entity authorized by
13
+ the copyright owner that is granting the License.
14
+
15
+ "Legal Entity" shall mean the union of the acting entity and all
16
+ other entities that control, are controlled by, or are under common
17
+ control with that entity. For the purposes of this definition,
18
+ "control" means (i) the power, direct or indirect, to cause the
19
+ direction or management of such entity, whether by contract or
20
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
21
+ outstanding shares, or (iii) beneficial ownership of such entity.
22
+
23
+ "You" (or "Your") shall mean an individual or Legal Entity
24
+ exercising permissions granted by this License.
25
+
26
+ "Source" form shall mean the preferred form for making modifications,
27
+ including but not limited to software source code, documentation
28
+ source, and configuration files.
29
+
30
+ "Object" form shall mean any form resulting from mechanical
31
+ transformation or translation of a Source form, including but
32
+ not limited to compiled object code, generated documentation,
33
+ and conversions to other media types.
34
+
35
+ "Work" shall mean the work of authorship, whether in Source or
36
+ Object form, made available under the License, as indicated by a
37
+ copyright notice that is included in or attached to the work
38
+ (an example is provided in the Appendix below).
39
+
40
+ "Derivative Works" shall mean any work, whether in Source or Object
41
+ form, that is based on (or derived from) the Work and for which the
42
+ editorial revisions, annotations, elaborations, or other modifications
43
+ represent, as a whole, an original work of authorship. For the purposes
44
+ of this License, Derivative Works shall not include works that remain
45
+ separable from, or merely link (or bind by name) to the interfaces of,
46
+ the Work and Derivative Works thereof.
47
+
48
+ "Contribution" shall mean any work of authorship, including
49
+ the original version of the Work and any modifications or additions
50
+ to that Work or Derivative Works thereof, that is intentionally
51
+ submitted to Licensor for inclusion in the Work by the copyright owner
52
+ or by an individual or Legal Entity authorized to submit on behalf of
53
+ the copyright owner. For the purposes of this definition, "submitted"
54
+ means any form of electronic, verbal, or written communication sent
55
+ to the Licensor or its representatives, including but not limited to
56
+ communication on electronic mailing lists, source code control systems,
57
+ and issue tracking systems that are managed by, or on behalf of, the
58
+ Licensor for the purpose of discussing and improving the Work, but
59
+ excluding communication that is conspicuously marked or otherwise
60
+ designated in writing by the copyright owner as "Not a Contribution."
61
+
62
+ "Contributor" shall mean Licensor and any individual or Legal Entity
63
+ on behalf of whom a Contribution has been received by Licensor and
64
+ subsequently incorporated within the Work.
65
+
66
+ 2. Grant of Copyright License. Subject to the terms and conditions of
67
+ this License, each Contributor hereby grants to You a perpetual,
68
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69
+ copyright license to reproduce, prepare Derivative Works of,
70
+ publicly display, publicly perform, sublicense, and distribute the
71
+ Work and such Derivative Works in Source or Object form.
72
+
73
+ 3. Grant of Patent License. Subject to the terms and conditions of
74
+ this License, each Contributor hereby grants to You a perpetual,
75
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76
+ (except as stated in this section) patent license to make, have made,
77
+ use, offer to sell, sell, import, and otherwise transfer the Work,
78
+ where such license applies only to those patent claims licensable
79
+ by such Contributor that are necessarily infringed by their
80
+ Contribution(s) alone or by combination of their Contribution(s)
81
+ with the Work to which such Contribution(s) was submitted. If You
82
+ institute patent litigation against any entity (including a
83
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
84
+ or a Contribution incorporated within the Work constitutes direct
85
+ or contributory patent infringement, then any patent licenses
86
+ granted to You under this License for that Work shall terminate
87
+ as of the date such litigation is filed.
88
+
89
+ 4. Redistribution. You may reproduce and distribute copies of the
90
+ Work or Derivative Works thereof in any medium, with or without
91
+ modifications, and in Source or Object form, provided that You
92
+ meet the following conditions:
93
+
94
+ (a) You must give any other recipients of the Work or
95
+ Derivative Works a copy of this License; and
96
+
97
+ (b) You must cause any modified files to carry prominent notices
98
+ stating that You changed the files; and
99
+
100
+ (c) You must retain, in the Source form of any Derivative Works
101
+ that You distribute, all copyright, patent, trademark, and
102
+ attribution notices from the Source form of the Work,
103
+ excluding those notices that do not pertain to any part of
104
+ the Derivative Works; and
105
+
106
+ (d) If the Work includes a "NOTICE" text file as part of its
107
+ distribution, then any Derivative Works that You distribute must
108
+ include a readable copy of the attribution notices contained
109
+ within such NOTICE file, excluding those notices that do not
110
+ pertain to any part of the Derivative Works, in at least one
111
+ of the following places: within a NOTICE text file distributed
112
+ as part of the Derivative Works; within the Source form or
113
+ documentation, if provided along with the Derivative Works; or,
114
+ within a display generated by the Derivative Works, if and
115
+ wherever such third-party notices normally appear. The contents
116
+ of the NOTICE file are for informational purposes only and
117
+ do not modify the License. You may add Your own attribution
118
+ notices within Derivative Works that You distribute, alongside
119
+ or as an addendum to the NOTICE text from the Work, provided
120
+ that such additional attribution notices cannot be construed
121
+ as modifying the License.
122
+
123
+ You may add Your own copyright statement to Your modifications and
124
+ may provide additional or different license terms and conditions
125
+ for use, reproduction, or distribution of Your modifications, or
126
+ for any such Derivative Works as a whole, provided Your use,
127
+ reproduction, and distribution of the Work otherwise complies with
128
+ the conditions stated in this License.
129
+
130
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
131
+ any Contribution intentionally submitted for inclusion in the Work
132
+ by You to the Licensor shall be under the terms and conditions of
133
+ this License, without any additional terms or conditions.
134
+ Notwithstanding the above, nothing herein shall supersede or modify
135
+ the terms of any separate license agreement you may have executed
136
+ with Licensor regarding such Contributions.
137
+
138
+ 6. Trademarks. This License does not grant permission to use the trade
139
+ names, trademarks, service marks, or product names of the Licensor,
140
+ except as required for reasonable and customary use in describing the
141
+ origin of the Work and reproducing the content of the NOTICE file.
142
+
143
+ 7. Disclaimer of Warranty. Unless required by applicable law or
144
+ agreed to in writing, Licensor provides the Work (and each
145
+ Contributor provides its Contributions) on an "AS IS" BASIS,
146
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147
+ implied, including, without limitation, any warranties or conditions
148
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149
+ PARTICULAR PURPOSE. You are solely responsible for determining the
150
+ appropriateness of using or redistributing the Work and assume any
151
+ risks associated with Your exercise of permissions under this License.
152
+
153
+ 8. Limitation of Liability. In no event and under no legal theory,
154
+ whether in tort (including negligence), contract, or otherwise,
155
+ unless required by applicable law (such as deliberate and grossly
156
+ negligent acts) or agreed to in writing, shall any Contributor be
157
+ liable to You for damages, including any direct, indirect, special,
158
+ incidental, or consequential damages of any character arising as a
159
+ result of this License or out of the use or inability to use the
160
+ Work (including but not limited to damages for loss of goodwill,
161
+ work stoppage, computer failure or malfunction, or any and all
162
+ other commercial damages or losses), even if such Contributor
163
+ has been advised of the possibility of such damages.
164
+
165
+ 9. Accepting Warranty or Additional Liability. While redistributing
166
+ the Work or Derivative Works thereof, You may choose to offer,
167
+ and charge a fee for, acceptance of support, warranty, indemnity,
168
+ or other liability obligations and/or rights consistent with this
169
+ License. However, in accepting such obligations, You may act only
170
+ on Your own behalf and on Your sole responsibility, not on behalf
171
+ of any other Contributor, and only if You agree to indemnify,
172
+ defend, and hold each Contributor harmless for any liability
173
+ incurred by, or claims asserted against, such Contributor by reason
174
+ of your accepting any such warranty or additional liability.
175
+
176
+ END OF TERMS AND CONDITIONS
177
+
178
+ APPENDIX: How to apply the Apache License to your work.
179
+
180
+ To apply the Apache License to your work, attach the following
181
+ boilerplate notice, with the fields enclosed by brackets "[]"
182
+ replaced with your own identifying information. (Don't include
183
+ the brackets!) The text should be enclosed in the appropriate
184
+ comment syntax for the file format. We also recommend that a
185
+ file or class name and description of purpose be included on the
186
+ same "printed page" as the copyright notice for easier
187
+ identification within third-party archives.
188
+
189
+ Copyright [yyyy] [name of copyright owner]
190
+
191
+ Licensed under the Apache License, Version 2.0 (the "License");
192
+ you may not use this file except in compliance with the License.
193
+ You may obtain a copy of the License at
194
+
195
+ http://www.apache.org/licenses/LICENSE-2.0
196
+
197
+ Unless required by applicable law or agreed to in writing, software
198
+ distributed under the License is distributed on an "AS IS" BASIS,
199
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200
+ See the License for the specific language governing permissions and
201
+ limitations under the License.
README.md ADDED
@@ -0,0 +1,520 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ license: apache-2.0
3
+ language:
4
+ - en
5
+ - zh
6
+ tags:
7
+ - OneScience
8
+ - life-science
9
+ - protein-design
10
+ - protein-binder
11
+ - PXDesign
12
+ - Protenix
13
+ frameworks: PyTorch
14
+ ---
15
+
16
+ <p align="center">
17
+ <strong>
18
+ <span style="font-size: 30px;">PXDesign</span>
19
+ </strong>
20
+ </p>
21
+
22
+ # Model Introduction
23
+
24
+ PXDesign is an open-source suite from the ByteDance team for de novo protein binder design. Given a target protein structure, it generates candidate binders and further filters candidate structures through structure prediction and confidence evaluation workflows.
25
+
26
+ The complete PXDesign workflow consists of the PXDesign diffusion generation model, ProteinMPNN sequence design, AF2-IG evaluation, and Protenix evaluation. The official implementation provides three primary modes, generation-only, preview, and extended, covering use cases from quick validation to complete candidate screening.
27
+
28
+ Paper:
29
+ > **PXDesign: Fast, Modular, and Accurate De Novo Design of Protein Binders**
30
+ > https://www.biorxiv.org/content/10.1101/2025.08.15.670647v1
31
+
32
+ # Model Description
33
+
34
+ The core task of PXDesign is to generate new protein binders from a target protein structure and specified design regions.
35
+
36
+ The typical workflow is:
37
+ ```text
38
+ Target protein structure and design constraints
39
+ -> PXDesign-d diffusion model
40
+ -> Binder Backbone Generation
41
+ -> ProteinMPNN sequence design
42
+ -> AF2-IG structure prediction and filtering
43
+ -> Protenix structure prediction and filtering (extended mode)
44
+ -> summary.csv
45
+ -> Filtered high-confidence binders
46
+ ```
47
+
48
+ Where:
49
+ - **PXDesign-d**: Generates candidate binder backbones from the target protein structure, hotspots, binder length, and other conditions.
50
+ - **ProteinMPNN**: Designs amino acid sequences for the generated protein backbones.
51
+ - **AF2-IG**: Predicts structures and applies quality filters to candidate binder-target complexes.
52
+ - **Protenix**: Provides additional structure prediction and confidence evaluation in extended mode.
53
+ - **summary.csv**: Summarizes AF2-IG, Protenix, and other evaluation metrics for candidate structures, along with the pass status of each filter.
54
+
55
+ # Use Cases
56
+
57
+ | Use case | Description |
58
+ | --- | --- |
59
+ | De novo protein binder design | Generate new candidate binders from a given target protein structure |
60
+ | Interface-guided design | Use hotspots to specify target residues that the binder should preferentially bind |
61
+ | Rapid validation of protein design workflows | Use preview mode to quickly evaluate whether the design task and parameters are reasonable |
62
+ | High-quality candidate screening | Use extended mode with AF2-IG and Protenix for multistage filtering |
63
+ | Structure generation research | Use `pxdesign infer` to run only the PXDesign generation stage |
64
+
65
+ # Usage
66
+
67
+ ## 1. Using OneCode
68
+
69
+ Experience intelligent one-click AI4S programming in the OneCode online environment:
70
+ [Try intelligent one-click AI4S programming](https://web-2069360198568017922-iaaj.ksai.scnet.cn:58043/home)
71
+
72
+ ## 2. Manual Installation and Usage
73
+
74
+ ### Hardware Requirements
75
+
76
+ - A GPU/DCU is recommended for the PXDesign backbone generation stage; complete inference typically requires substantial GPU memory.
77
+ - MSA generation and preparation primarily use the CPU. You can prepare MSAs in advance with `prepare-msa` or by precomputing them.
78
+ - The ProteinMPNN, AF2-IG, and Protenix prediction and screening stages depend on deep learning frameworks such as PyTorch and JAX; a GPU/DCU is recommended.
79
+ - If GPU/DCU resources are limited, prepare the MSA separately on the CPU first, then run the PXDesign generation, ProteinMPNN, AF2-IG, and Protenix evaluation stages.
80
+
81
+ ### Set Up the Runtime Environment
82
+
83
+ #### DCU Environment
84
+
85
+ ```bash
86
+ # Activate DTK and CONDA first
87
+ conda create -n onescience311 python=3.11 -y
88
+ conda activate onescience311
89
+
90
+ # Install with uv support
91
+ pip install onescience[bio] -i http://mirrors.onescience.ai:3141/pypi/simple/ --trusted-host mirrors.onescience.ai
92
+ ```
93
+
94
+ #### Environment Notes
95
+
96
+ - If you encounter missing dependencies or version issues during execution, install additional dependencies according to the versions specified in `requirements.txt`.
97
+ - Enter the project root and activate the environment:
98
+
99
+ ```bash
100
+ cd /path/to/PXDesign-main
101
+ conda activate your_env
102
+ ```
103
+
104
+ Install PXDesign in the current environment:
105
+
106
+ ```bash
107
+ python -m pip install -e model
108
+ ```
109
+
110
+ Verify the installation:
111
+
112
+ ```bash
113
+ which pxdesign
114
+ pxdesign --help
115
+ pxdesign pipeline --help
116
+ ```
117
+
118
+ ### Environment Variables
119
+
120
+ After entering the PXDesign root directory, configure the following variables together:
121
+ ```bash
122
+ export PXDESIGN_ROOT=$PWD
123
+ export TOOL_WEIGHTS_ROOT=$PWD/weight/tool_weights
124
+ export PROTENIX_DATA_ROOT_DIR=$PWD/weight/release_data/ccd_cache
125
+ ```
126
+
127
+ Check them with:
128
+ ```bash
129
+ echo $PXDESIGN_ROOT
130
+ echo $TOOL_WEIGHTS_ROOT
131
+ echo $PROTENIX_DATA_ROOT_DIR
132
+ ```
133
+
134
+ to confirm the configuration.
135
+
136
+ ## Prepare Weights and Data
137
+
138
+ The complete PXDesign workflow depends on PXDesign and Protenix model weights, as well as AlphaFold2, ProteinMPNN, and the CCD cache. This model repository already includes the CCD cache and PXDesign/Protenix checkpoints; users only need to prepare the `tool_weights/` portion separately. The complete preparation process is as follows:
139
+
140
+ ### 1) External Tool Weights and CCD Cache
141
+
142
+ PXDesign provides an official download script:
143
+ ```bash
144
+ bash scripts/download_tool_weights.sh
145
+ ```
146
+
147
+ The script uses the official default directories and generates `tool_weights/` and `release_data/ccd_cache/` in the current directory when run directly. This project has been reorganized under a `weight/` directory, so it is recommended to organize or symlink the existing weights and cache to the locations below.
148
+
149
+ In the current reorganized project structure, place the external tool weights as follows:
150
+ ```text
151
+ weight/
152
+ ├── tool_weights/
153
+ │ ├── af2/ # AlphaFold2 weights
154
+ │ └── mpnn/ # ProteinMPNN weights
155
+ └── release_data/
156
+ └── ccd_cache/ # Protenix CCD cache
157
+ ```
158
+
159
+ - The recommended default location for the CCD cache is:
160
+
161
+ ```text
162
+ weight/release_data/ccd_cache/
163
+ ```
164
+
165
+ To specify another location, set:
166
+
167
+ ```bash
168
+ export PROTENIX_DATA_ROOT_DIR=/path/to/ccd_cache
169
+ ```
170
+
171
+ ### 2) PXDesign and Protenix Checkpoints
172
+
173
+ The following model weights are downloaded on demand during the first run, or can be downloaded to the corresponding locations in advance:
174
+ ```text
175
+ PXDesign diffusion checkpoint
176
+
177
+ Protenix checkpoints:
178
+ ├── base
179
+ ├── mini
180
+ └── mini_tmpl
181
+ ```
182
+
183
+ The recommended location in the reorganized structure is:
184
+
185
+ ```text
186
+ weight/release_data/checkpoint/
187
+ ```
188
+
189
+ The required files include:
190
+ ```text
191
+ pxdesign_v0.1.0.pt
192
+ protenix_base_default_v0.5.0.pt
193
+ protenix_mini_default_v0.5.0.pt
194
+ protenix_mini_tmpl_v0.5.0.pt
195
+ ```
196
+
197
+ ### 3) Check the Installation
198
+
199
+ After preparation is complete, run:
200
+ ```bash
201
+ ls weight/tool_weights/af2/
202
+ ls weight/tool_weights/mpnn/
203
+ ls weight/release_data/ccd_cache/
204
+ ls weight/release_data/checkpoint/*.pt
205
+ ```
206
+ to confirm that the required weights and data are ready.
207
+
208
+ ## 3. Quick Start
209
+
210
+ ### Download the Model Package
211
+
212
+ ```bash
213
+ hf download OneScience-Group/PXDesign --local-dir ./PXDesign
214
+ cd PXDesign
215
+ ```
216
+
217
+ - PXDesign additionally depends on Protenix and PXDesignBench; the corresponding dependency source code is included in this model repository, so separate downloads are not required.
218
+ - The complete PXDesign workflow also depends on AlphaFold2, ProteinMPNN, and the CCD cache required by Protenix. Prepare these resources as described in "Prepare Weights and Data" first.
219
+
220
+ ### Quick Verification
221
+
222
+ First, verify that the command is available:
223
+ ```bash
224
+ pxdesign --help
225
+ ```
226
+
227
+ To save the results to `runs/` as in the examples below, first create the output directory:
228
+ ```bash
229
+ mkdir -p runs
230
+ ```
231
+
232
+ Then check the official example YAML:
233
+ ```bash
234
+ pxdesign check-input \
235
+ --yaml conf/examples/PDL1_quick_start.yaml
236
+ ```
237
+
238
+ On success, the output should be:
239
+ ```text
240
+ YAML file is valid.
241
+ ```
242
+
243
+ ### Example Data
244
+
245
+ The current project provides:
246
+ ```text
247
+ conf/examples/
248
+ ├── PDL1_quick_start.yaml
249
+ ├── 5o45.cif
250
+ └── msa/
251
+ └── PDL1/
252
+ └── 0/
253
+ ```
254
+
255
+ `PDL1_quick_start.yaml` defines the PDL1 binder design task.
256
+
257
+ The typical YAML format is:
258
+ ```yaml
259
+ target:
260
+ file: "./conf/examples/5o45.cif"
261
+ chains:
262
+ A:
263
+ crop: ["1-116"]
264
+ hotspots: [40, 99, 107]
265
+ msa: "./conf/examples/msa/PDL1/0"
266
+
267
+ binder_length: 80
268
+ ```
269
+
270
+ Key fields:
271
+ | Field | Description |
272
+ | --- | --- |
273
+ | `target.file` | Target protein structure file; mmCIF or PDB can be used |
274
+ | `target.chains` | Target chains involved in the design |
275
+ | `crop` | Residue range retained from the target chain |
276
+ | `hotspots` | Target residues used to guide binder interface generation |
277
+ | `msa` | Path to the precomputed MSA for the target chain |
278
+ | `binder_length` | Amino acid length of the binder to be designed |
279
+
280
+ PXDesign primarily uses the mmCIF `label_seq_id` as the standard residue index internally. For custom tasks, mmCIF files are recommended, and `parse-target` should be used to check that crop and hotspot specifications point to the intended positions.
281
+
282
+ ### Input Checking and Target Parsing
283
+
284
+ #### 1) Check the YAML
285
+
286
+ Run the following before formally executing a design task:
287
+
288
+ ```bash
289
+ pxdesign check-input \
290
+ --yaml conf/examples/PDL1_quick_start.yaml
291
+ ```
292
+
293
+ #### 2) Parse the Target and Generate Visualization Debug Files
294
+ ```bash
295
+ pxdesign parse-target \
296
+ --yaml conf/examples/PDL1_quick_start.yaml \
297
+ -o runs/debug_target
298
+ ```
299
+
300
+ This step is useful for checking the following before running a large-scale design:
301
+
302
+ - whether the crop is correct;
303
+ - whether the hotspots correspond to the intended residues;
304
+ - whether the structure chains and residue numbering are correct.
305
+
306
+ ## Inference Examples
307
+
308
+ PXDesign primarily provides three execution modes:
309
+ ```text
310
+ Generation Only
311
+ -> Generate only the PXDesign binder backbone
312
+
313
+ Preview Pipeline
314
+ -> PXDesign + ProteinMPNN + AF2-IG
315
+
316
+ Extended Pipeline
317
+ -> PXDesign + ProteinMPNN + AF2-IG + Protenix
318
+ ```
319
+
320
+ ### 1. Generation Only: Run PXDesign Generation Only
321
+
322
+ #### Quick Smoke Test
323
+
324
+ To first verify that the model, weights, and GPU/DCU work correctly, use a smaller number of steps:
325
+ ```bash
326
+ pxdesign infer \
327
+ -i conf/examples/PDL1_quick_start.yaml \
328
+ -o runs/test_infer \
329
+ --load_checkpoint_dir weight/release_data/checkpoint \
330
+ --N_sample 1 \
331
+ --N_step 20 \
332
+ --dtype bf16 \
333
+ --sample_diffusion_chunk_size 1
334
+ ```
335
+
336
+ #### Full-Step Generation Test
337
+
338
+ ```bash
339
+ pxdesign infer \
340
+ -i conf/examples/PDL1_quick_start.yaml \
341
+ -o runs/test_infer_full \
342
+ --load_checkpoint_dir weight/release_data/checkpoint \
343
+ --N_sample 10 \
344
+ --N_step 400 \
345
+ --dtype bf16
346
+ ```
347
+
348
+ This mode only generates binders and does not provide complete AF2/Protenix filtering results.
349
+
350
+ ### 2. Preview Pipeline
351
+
352
+ Preview mode runs:
353
+ ```text
354
+ PXDesign generation
355
+ -> ProteinMPNN sequence design
356
+ -> AF2-IG filtering
357
+ ```
358
+
359
+ ```bash
360
+ pxdesign pipeline \
361
+ --preset preview \
362
+ -i conf/examples/PDL1_quick_start.yaml \
363
+ -o runs/test_preview \
364
+ --load_checkpoint_dir weight/release_data/checkpoint \
365
+ --N_sample 2 \
366
+ --N_step 100 \
367
+ --dtype bf16 \
368
+ --use_fast_ln False \
369
+ --use_deepspeed_evo_attention False
370
+ ```
371
+
372
+ Preview mode is suitable for:
373
+ - initial validation of the complete pipeline;
374
+ - checking whether the hotspot/crop settings are reasonable;
375
+ - assessing the difficulty of the current design task;
376
+ - running a small pilot experiment before a large-scale Extended task.
377
+
378
+ ### 3. Extended Pipeline
379
+
380
+ Extended mode is the official PXDesign workflow for complete evaluation:
381
+
382
+ ```text
383
+ PXDesign generation
384
+ -> ProteinMPNN
385
+ -> AF2-IG
386
+ -> Protenix
387
+ -> summary.csv
388
+ ```
389
+
390
+ #### Small-Scale Validation
391
+ ```bash
392
+ pxdesign pipeline \
393
+ --preset extended \
394
+ -i conf/examples/PDL1_quick_start.yaml \
395
+ -o runs/test_extended \
396
+ --load_checkpoint_dir weight/release_data/checkpoint \
397
+ --N_sample 2 \
398
+ --N_step 100 \
399
+ --dtype bf16 \
400
+ --use_fast_ln False \
401
+ --use_deepspeed_evo_attention False
402
+ ```
403
+
404
+ #### Quick Start Scale
405
+
406
+ The official Quick Start example uses:
407
+ ```text
408
+ N_sample = 10
409
+ N_step = 400
410
+ ```
411
+
412
+ ```bash
413
+ pxdesign pipeline \
414
+ --preset extended \
415
+ -i conf/examples/PDL1_quick_start.yaml \
416
+ -o runs/test_extended_N10 \
417
+ --load_checkpoint_dir weight/release_data/checkpoint \
418
+ --N_sample 10 \
419
+ --N_step 400 \
420
+ --dtype bf16 \
421
+ --use_fast_ln False \
422
+ --use_deepspeed_evo_attention False
423
+ ```
424
+
425
+ ## Output Description
426
+
427
+ The core results from Extended mode are typically located at:
428
+ ```text
429
+ <OUT_DIR>/
430
+ └── design_outputs/
431
+ └── <task_name>/
432
+ ├── summary.csv
433
+ ├── task_info.json
434
+ ├── server_extended_mode.png
435
+ ├── orig_designed/
436
+ ├── passing-AF2-IG-easy/
437
+ └── passing-Protenix-basic/
438
+ ```
439
+
440
+ If no designs pass the corresponding filters, the `passing-AF2-IG-easy/` or `passing-Protenix-basic/` directories may not be generated. This is normal for small-sample tests.
441
+
442
+ # Official OneScience Information
443
+
444
+ | Platform | Main OneScience repository | Skills repository |
445
+ | --- | --- | --- |
446
+ | Gitee | https://gitee.com/onescience-ai/onescience | https://gitee.com/onescience-ai/oneskills |
447
+ | GitHub | https://github.com/onescience-ai/OneScience | https://github.com/onescience-ai/oneskills |
448
+
449
+
450
+ # Citation and License
451
+
452
+ If you use PXDesign in research, cite the official PXDesign paper:
453
+ ```bibtex
454
+ @article{ren2025pxdesign,
455
+ title={PXDesign: Fast, Modular, and Accurate De Novo Design of Protein Binders},
456
+ author={Ren, Milong and Sun, Jinyuan and Guan, Jiaqi and Liu, Cong and
457
+ Gong, Chengyue and Wang, Yuzhe and Wang, Lan and Cai, Qixu and
458
+ Chen, Xinshi and Xiao, Wenzhi},
459
+ journal={bioRxiv},
460
+ pages={2025--08},
461
+ year={2025},
462
+ publisher={Cold Spring Harbor Laboratory}
463
+ }
464
+ ```
465
+
466
+ The complete PXDesign pipeline also depends on methods such as Protenix, ProteinMPNN, and AF2-IG. If you use these modules in research, also cite the corresponding original works as described in the official PXDesign README.
467
+
468
+ Protenix:
469
+ ```bibtex
470
+ @article{bytedance2025protenix,
471
+ title={Protenix - Advancing Structure Prediction Through a Comprehensive AlphaFold3 Reproduction},
472
+ author={ByteDance AML AI4Science Team and Chen, Xinshi and Zhang, Yuxuan
473
+ and Lu, Chan and Ma, Wenzhi and Guan, Jiaqi and Gong, Chengyue
474
+ and Yang, Jincai and Zhang, Hanyu and Zhang, Ke and Wu, Shenghao
475
+ and Zhou, Kuangqi and Yang, Yanping and Liu, Zhenyu and Wang, Lan
476
+ and Shi, Bo and Shi, Shaochen and Xiao, Wenzhi},
477
+ year={2025},
478
+ journal={bioRxiv},
479
+ publisher={Cold Spring Harbor Laboratory},
480
+ doi={10.1101/2025.01.08.631967}
481
+ }
482
+ ```
483
+
484
+ ProteinMPNN:
485
+ ```bibtex
486
+ @article{dauparas2022robust,
487
+ title={Robust deep learning--based protein sequence design using ProteinMPNN},
488
+ author={Dauparas, Justas and Anishchenko, Ivan and Bennett, Nathaniel
489
+ and Bai, Hua and Ragotte, Robert J and Milles, Lukas and others},
490
+ journal={Science},
491
+ volume={378},
492
+ number={6615},
493
+ pages={49--56},
494
+ year={2022}
495
+ }
496
+ ```
497
+
498
+ AF2-IG:
499
+ ```bibtex
500
+ @article{bennett2023improving,
501
+ title={Improving de novo protein binder design with deep learning},
502
+ author={Bennett, Nathaniel R and Coventry, Brian and Goreshnik, Inna
503
+ and Huang, Buwei and Allen, Aza and Vafeados, Dionne and others},
504
+ journal={Nature Communications},
505
+ volume={14},
506
+ number={1},
507
+ pages={2625},
508
+ year={2023}
509
+ }
510
+ ```
511
+
512
+ The official PXDesign repository is released under the **Apache License 2.0**. According to the official README, this license permits academic research and commercial use. Use, modification, and redistribution of the code must comply with the specific terms in this project's `LICENSE`.
513
+
514
+ In addition:
515
+ - AlphaFold2/AF2 weights and related resources are subject to their respective licenses and terms of use.
516
+ - ProteinMPNN is subject to the license of its official repository.
517
+ - Protenix is subject to the license of its official repository.
518
+ - Models and data resources reused through SCNet shared directories remain subject to the authorization conditions of their respective original resources.
519
+
520
+ For papers, reports, or public releases, also cite PXDesign, Protenix, ProteinMPNN, AF2-IG, and any other third-party models and data resources actually used.
conf/examples/5o45.cif ADDED
The diff for this file is too large to render. See raw diff
 
conf/examples/PDL1_quick_start.yaml ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ target:
2
+ # Path to the target structure (PDB or CIF)
3
+ file: "./conf/examples/5o45.cif"
4
+ # Specify the target chain(s)
5
+ chains:
6
+ # Configuration for Target Chain A
7
+ A:
8
+ # Crop regions (Optional)
9
+ crop: ["1-116"]
10
+ # Binding hotspot residues (Optional)
11
+ hotspots: [40, 99, 107]
12
+ # Path to pre-computed MSA (Optional but recommended)
13
+ msa: "./conf/examples/msa/PDL1/0"
14
+
15
+ # Number of amino acids of the binder to be designed
16
+ binder_length: 80
conf/examples/msa/PDL1/0/non_pairing.a3m ADDED
The diff for this file is too large to render. See raw diff
 
conf/examples/msa/PDL1/0/pairing.a3m ADDED
The diff for this file is too large to render. See raw diff
 
configuration.json ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "project": "PXDesign-main",
3
+ "layout": {
4
+ "conf": "Configuration files, example inputs, license files, and reproduction notes.",
5
+ "model": "PXDesign source code, bundled Protenix/PXDesignBench source trees, original README, and assets.",
6
+ "scripts": "Installation, dependency, Docker, and download scripts.",
7
+ "weight": "Model checkpoints, CCD cache, AF2/ProteinMPNN external tool weights, and MSA cache."
8
+ },
9
+ "paths": {
10
+ "pxdesign_package": "model/pxdesign",
11
+ "protenix_source": "model/Protenix-pxd",
12
+ "pxdesignbench_source": "model/PXDesignBench",
13
+ "example_yaml": "conf/examples/PDL1_quick_start.yaml",
14
+ "checkpoint_dir": "weight/release_data/checkpoint",
15
+ "ccd_cache_dir": "weight/release_data/ccd_cache",
16
+ "tool_weights_root": "weight/tool_weights",
17
+ "af2_weights": "weight/tool_weights/af2",
18
+ "mpnn_weights": "weight/tool_weights/mpnn",
19
+ "reproduction_notes": "conf/PXDESIGN_REPRODUCTION_NOTES.md",
20
+ "original_readme": "model/README.md"
21
+ },
22
+ "environment": {
23
+ "conda_env_used": "model_bio",
24
+ "tool_weights_root_env": "TOOL_WEIGHTS_ROOT=$PWD/weight/tool_weights",
25
+ "protenix_data_root_env": "PROTENIX_DATA_ROOT_DIR=$PWD/weight/release_data/ccd_cache"
26
+ },
27
+ "validated_tasks": [
28
+ "pxdesign check-input",
29
+ "pxdesign parse-target",
30
+ "pxdesign infer",
31
+ "pxdesign pipeline --preset preview",
32
+ "pxdesign pipeline --preset extended"
33
+ ],
34
+ "hpc_runtime_overrides": {
35
+ "use_fast_ln": false,
36
+ "use_deepspeed_evo_attention": false,
37
+ "reason": "The DTK/HIP environment failed to build fastfold_layer_norm_cuda with CUDA compiler flags."
38
+ }
39
+ }
model/PXDesignBench/.gitignore ADDED
@@ -0,0 +1,168 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Byte-compiled / optimized / DLL files
2
+ *__pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+
6
+ # C extensions
7
+ *.so
8
+ *.o
9
+ *.obj
10
+ *.d
11
+ # ninjia relate
12
+ *ninja*
13
+ lock
14
+ # Distribution / packaging
15
+ .Python
16
+ .vscode
17
+ build/
18
+ develop-eggs/
19
+ dist/
20
+ downloads/
21
+ eggs/
22
+ .eggs/
23
+ lib/
24
+ lib64/
25
+ parts/
26
+ sdist/
27
+ var/
28
+ wheels/
29
+ share/python-wheels/
30
+ *.egg-info/
31
+ .installed.cfg
32
+ *.egg
33
+ MANIFEST
34
+
35
+ # PyInstaller
36
+ # Usually these files are written by a python script from a template
37
+ # before PyInstaller builds the exe, so as to inject date/other infos into it.
38
+ *.manifest
39
+ *.spec
40
+
41
+ # Installer logs
42
+ pip-log.txt
43
+ pip-delete-this-directory.txt
44
+
45
+ # Unit test / coverage reports
46
+ .tox/
47
+ .nox/
48
+ .coverage
49
+ .coverage.*
50
+ .cache
51
+ *.cover
52
+ *.py,cover
53
+ .hypothesis/
54
+ .pytest_cache/
55
+
56
+ # Translations
57
+ *.mo
58
+ *.pot
59
+
60
+ # Django stuff:
61
+ *.log
62
+ local_settings.py
63
+ db.sqlite3
64
+ db.sqlite3-journal
65
+
66
+ # Flask stuff:
67
+ instance/
68
+ .webassets-cache
69
+
70
+ # Scrapy stuff:
71
+ .scrapy
72
+
73
+ # Sphinx documentation
74
+ docs/_build/
75
+
76
+ # PyBuilder
77
+ .pybuilder/
78
+ target/
79
+
80
+ # Jupyter Notebook
81
+ .ipynb_checkpoints
82
+
83
+ # IPython
84
+ profile_default/
85
+ ipython_config.py
86
+
87
+ # data cache and checkpoints
88
+ data_cache/
89
+ checkpoints/
90
+
91
+ # pyenv
92
+ # For a library or package, you might want to ignore these files since the code is
93
+ # intended to run in multiple environments; otherwise, check them in:
94
+ # .python-version
95
+
96
+ # pipenv
97
+ # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
98
+ # However, in case of collaboration, if having platform-specific dependencies or dependencies
99
+ # having no cross-platform support, pipenv may install dependencies that don't work, or not
100
+ # install all needed dependencies.
101
+ #Pipfile.lock
102
+
103
+ # poetry
104
+ # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
105
+ # This is especially recommended for binary packages to ensure reproducibility, and is more
106
+ # commonly ignored for libraries.
107
+ # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
108
+ #poetry.lock
109
+
110
+ # pdm
111
+ # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
112
+ #pdm.lock
113
+ # pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
114
+ # in version control.
115
+ # https://pdm.fming.dev/#use-with-ide
116
+ .pdm.toml
117
+
118
+ # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
119
+ __pypackages__/
120
+
121
+ # Celery stuff
122
+ celerybeat-schedule
123
+ celerybeat.pid
124
+
125
+ # SageMath parsed files
126
+ *.sage.py
127
+
128
+ # Environments
129
+ .env
130
+ .venv
131
+ env/
132
+ venv/
133
+ ENV/
134
+ env.bak/
135
+ venv.bak/
136
+
137
+ # Spyder project settings
138
+ .spyderproject
139
+ .spyproject
140
+
141
+ # Rope project settings
142
+ .ropeproject
143
+
144
+ # mkdocs documentation
145
+ /site
146
+
147
+ # mypy
148
+ .mypy_cache/
149
+ .dmypy.json
150
+ dmypy.json
151
+
152
+ # Pyre type checker
153
+ .pyre/
154
+
155
+ # pytype static type analyzer
156
+ .pytype/
157
+
158
+ # Cython debug symbols
159
+ cython_debug/
160
+
161
+ # PyCharm
162
+ # JetBrains specific template is maintained in a separate JetBrains.gitignore that can
163
+ # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
164
+ # and can be added to the global gitignore or merged into this file. For a more nuclear
165
+ # option (not recommended) you can uncomment the following to ignore the entire idea folder.
166
+ #.idea/
167
+
168
+ output*/
model/PXDesignBench/CODE_OF_CONDUCT.md ADDED
@@ -0,0 +1,127 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Contributor Covenant Code of Conduct
2
+
3
+ ## Our Pledge
4
+
5
+ We as members, contributors, and leaders pledge to make participation in our
6
+ community a harassment-free experience for everyone, regardless of age, body
7
+ size, visible or invisible disability, ethnicity, sex characteristics, gender
8
+ identity and expression, level of experience, education, socio-economic status,
9
+ nationality, personal appearance, race, religion, or sexual identity
10
+ and orientation.
11
+
12
+ We pledge to act and interact in ways that contribute to an open, welcoming,
13
+ diverse, inclusive, and healthy community.
14
+
15
+ ## Our Standards
16
+
17
+ Examples of behavior that contributes to a positive environment for our
18
+ community include:
19
+
20
+ * Demonstrating empathy and kindness toward other people
21
+ * Being respectful of differing opinions, viewpoints, and experiences
22
+ * Giving and gracefully accepting constructive feedback
23
+ * Accepting responsibility and apologizing to those affected by our mistakes,
24
+ and learning from the experience
25
+ * Focusing on what is best not just for us as individuals, but for the
26
+ overall community
27
+
28
+ Examples of unacceptable behavior include:
29
+
30
+ * The use of sexualized language or imagery, and sexual attention or
31
+ advances of any kind
32
+ * Trolling, insulting or derogatory comments, and personal or political attacks
33
+ * Public or private harassment
34
+ * Publishing others' private information, such as a physical or email
35
+ address, without their explicit permission
36
+ * Other conduct which could reasonably be considered inappropriate in a
37
+ professional setting
38
+
39
+ ## Enforcement Responsibilities
40
+
41
+ Community leaders are responsible for clarifying and enforcing our standards of
42
+ acceptable behavior and will take appropriate and fair corrective action in
43
+ response to any behavior that they deem inappropriate, threatening, offensive,
44
+ or harmful.
45
+
46
+ Community leaders have the right and responsibility to remove, edit, or reject
47
+ comments, commits, code, wiki edits, issues, and other contributions that are
48
+ not aligned to this Code of Conduct, and will communicate reasons for moderation
49
+ decisions when appropriate.
50
+
51
+ ## Scope
52
+
53
+ This Code of Conduct applies within all community spaces, and also applies when
54
+ an individual is officially representing the community in public spaces.
55
+ Examples of representing our community include using an official e-mail address,
56
+ posting via an official social media account, or acting as an appointed
57
+ representative at an online or offline event.
58
+
59
+ ## Enforcement
60
+
61
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be
62
+ reported to the community leaders responsible for enforcement.
63
+ All complaints will be reviewed and investigated promptly and fairly.
64
+
65
+ All community leaders are obligated to respect the privacy and security of the
66
+ reporter of any incident.
67
+
68
+ ## Enforcement Guidelines
69
+
70
+ Community leaders will follow these Community Impact Guidelines in determining
71
+ the consequences for any action they deem in violation of this Code of Conduct:
72
+
73
+ ### 1. Correction
74
+
75
+ **Community Impact**: Use of inappropriate language or other behavior deemed
76
+ unprofessional or unwelcome in the community.
77
+
78
+ **Consequence**: A private, written warning from community leaders, providing
79
+ clarity around the nature of the violation and an explanation of why the
80
+ behavior was inappropriate. A public apology may be requested.
81
+
82
+ ### 2. Warning
83
+
84
+ **Community Impact**: A violation through a single incident or series
85
+ of actions.
86
+
87
+ **Consequence**: A warning with consequences for continued behavior. No
88
+ interaction with the people involved, including unsolicited interaction with
89
+ those enforcing the Code of Conduct, for a specified period of time. This
90
+ includes avoiding interactions in community spaces as well as external channels
91
+ like social media. Violating these terms may lead to a temporary or
92
+ permanent ban.
93
+
94
+ ### 3. Temporary Ban
95
+
96
+ **Community Impact**: A serious violation of community standards, including
97
+ sustained inappropriate behavior.
98
+
99
+ **Consequence**: A temporary ban from any sort of interaction or public
100
+ communication with the community for a specified period of time. No public or
101
+ private interaction with the people involved, including unsolicited interaction
102
+ with those enforcing the Code of Conduct, is allowed during this period.
103
+ Violating these terms may lead to a permanent ban.
104
+
105
+ ### 4. Permanent Ban
106
+
107
+ **Community Impact**: Demonstrating a pattern of violation of community
108
+ standards, including sustained inappropriate behavior, harassment of an
109
+ individual, or aggression toward or disparagement of classes of individuals.
110
+
111
+ **Consequence**: A permanent ban from any sort of public interaction within
112
+ the community.
113
+
114
+ ## Attribution
115
+
116
+ This Code of Conduct is adapted from the [Contributor Covenant][homepage],
117
+ version 2.0, available at
118
+ https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
119
+
120
+ Community Impact Guidelines were inspired by [Mozilla's code of conduct
121
+ enforcement ladder](https://github.com/mozilla/diversity).
122
+
123
+ [homepage]: https://www.contributor-covenant.org
124
+
125
+ For answers to common questions about this code of conduct, see the FAQ at
126
+ https://www.contributor-covenant.org/faq. Translations are available at
127
+ https://www.contributor-covenant.org/translations.
model/PXDesignBench/CONTRIBUTING.md ADDED
@@ -0,0 +1,61 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Contributing
2
+
3
+ Thank you for investing your time in contributing to PXDesignBench project!
4
+
5
+ Read our [Code of Conduct](./CODE_OF_CONDUCT.md) to keep our community approachable and respectable.
6
+
7
+ This guide details how to use issues and pull requests to improve PXDesignBench project.
8
+
9
+ ## General Guidelines
10
+
11
+ ### Pull Requests
12
+
13
+ Make sure to keep Pull Requests small and functional to make them easier to review, understand, and look up in commit history. This repository uses "Squash and Commit" to keep our history clean and make it easier to revert changes based on PR.
14
+
15
+ Adding the appropriate documentation, unit tests and e2e tests as part of a feature is the responsibility of the feature owner, whether it is done in the same Pull Request or not.
16
+
17
+ Pull Requests should follow the "subject: message" format, where the subject describes what part of the code is being modified.
18
+
19
+ Refer to the template for more information on what goes into a PR description.
20
+
21
+ ### Design Docs
22
+
23
+ A contributor proposes a design with a PR on the repository to allow for revisions and discussions. If a design needs to be discussed before formulating a document for it, make use of Google doc and GitHub issue to involve the community on the discussion.
24
+
25
+ ### GitHub Issues
26
+
27
+ GitHub Issues are used to file bugs, work items, and feature requests with actionable items/issues (Please refer to the "Reporting Bugs/Feature Requests" section below for more information).
28
+
29
+ ### Reporting Bugs/Feature Requests
30
+
31
+ We welcome you to use the GitHub issue tracker to report bugs or suggest features that have actionable items/issues (as opposed to introducing a feature request on GitHub Discussions).
32
+
33
+ When filing an issue, please check existing open, or recently closed, issues to make sure somebody else hasn't already reported the issue. Please try to include as much information as you can. Details like these are incredibly useful:
34
+
35
+ - A reproducible test case or series of steps
36
+ - The version of the code being used
37
+ - Any modifications you've made relevant to the bug
38
+ - Anything unusual about your environment or deployment
39
+
40
+ ## Contributing via Pull Requests
41
+
42
+ ### Find interesting issue
43
+
44
+ If you spot a problem with the problem, [search if an issue already exists](https://github.com/bytedance/PXDesignBench/issues). If a related issue doesn't exist, you can open a new issue using [issue template](https://github.com/bytedance/PXDesignBench/issues/new/choose).
45
+
46
+ ### Solve an issue
47
+
48
+ Please check `DEVELOPMENT.md` in sub folder to get familiar with running and testing codes.
49
+
50
+ ### Open a Pull request.
51
+
52
+ When you're done making the changes, open a pull request and fill PR template so we can better review your PR. The template helps reviewers understand your changes and the purpose of your pull request.
53
+
54
+ Don't forget to link PR to the issue if you are solving one.
55
+
56
+ If you run into any merge issues, checkout this [git tutorial](https://lab.github.com/githubtraining/managing-merge-conflicts) to help you resolve merge conflicts and other issues.
57
+
58
+
59
+ ## Finding contributions to work on
60
+
61
+ Looking at the existing issues is a great way to find something to contribute on. As our projects, by default, use the default GitHub issue labels (enhancement/bug/duplicate/help wanted/invalid/question/wontfix), looking at any 'help wanted' and 'good first issue' issues are a great place to start.
model/PXDesignBench/ColabDesign/.github/workflows/python-publish.yml ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # This workflow will upload a Python Package using Twine when a release is created
2
+ # For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python#publishing-to-package-registries
3
+
4
+ # This workflow uses actions that are not certified by GitHub.
5
+ # They are provided by a third-party and are governed by
6
+ # separate terms of service, privacy policy, and support
7
+ # documentation.
8
+
9
+ name: Upload Python Package
10
+
11
+ on:
12
+ release:
13
+ types: [published]
14
+
15
+ permissions:
16
+ contents: read
17
+
18
+ jobs:
19
+ deploy:
20
+
21
+ runs-on: ubuntu-latest
22
+
23
+ steps:
24
+ - uses: actions/checkout@v3
25
+ - name: Set up Python
26
+ uses: actions/setup-python@v3
27
+ with:
28
+ python-version: '3.x'
29
+ - name: Install dependencies
30
+ run: |
31
+ python -m pip install --upgrade pip
32
+ pip install build
33
+ - name: Build package
34
+ run: python -m build
35
+ - name: Publish package
36
+ uses: pypa/gh-action-pypi-publish@release/v1
37
+ with:
38
+ user: __token__
39
+ password: ${{ secrets.PYPI_API_TOKEN }}
model/PXDesignBench/ColabDesign/.gitignore ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ **/.DS_Store
2
+ *.pyc
model/PXDesignBench/ColabDesign/LICENSE.txt ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ /*
2
+ * ----------------------------------------------------------------------------
3
+ * "THE BEER-WARE LICENSE" (Revision 42):
4
+ * <so3@mit.edu> wrote this file. As long as you retain this notice you
5
+ * can do whatever you want with this stuff. If we meet some day, and you think
6
+ * this stuff is worth it, you can buy me a beer in return. Sergey Ovchinnikov
7
+ * ----------------------------------------------------------------------------
8
+ */
model/PXDesignBench/ColabDesign/MANIFEST.in ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ include colabdesign/mpnn/weights/*.pkl
2
+ include colabdesign/mpnn/weights_soluble/*.pkl
3
+ include colabdesign/tr/weights/*.npy
4
+ include colabdesign/af/weights/*.npy
model/PXDesignBench/ColabDesign/README.md ADDED
@@ -0,0 +1,29 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # ColabDesign
2
+ ### Making Protein Design accessible to all via Google Colab!
3
+ - P(structure | sequence)
4
+ - [TrDesign](/tr) - using TrRosetta for design
5
+ - [AfDesign](/af) - using AlphaFold for design
6
+ - [WIP] [RfDesign](https://github.com/RosettaCommons/RFDesign) - using RoseTTAFold for design
7
+ - P(sequence | structure)
8
+ - [ProteinMPNN](/mpnn)
9
+ - [WIP] TrMRF
10
+ - P(sequence)
11
+ - [WIP] [MSA_transformer](/esm_msa)
12
+ - [WIP] [SEQ](/seq) - (GREMLIN, mfDCA, arDCA, plmDCA, bmDCA, etc)
13
+ - P(structure)
14
+ - [Rfdiffusion](/rf)
15
+
16
+ ### Where can I chat with other ColabDesign users?
17
+ - See our [Discord](https://discord.gg/gna8maru7d) channel!
18
+
19
+
20
+ ### Presentations
21
+ [Slides](https://docs.google.com/presentation/d/1Zy7lf_LBK0_G3e7YQLSPP5aj_-AR5I131fTsxJrLdg4/)
22
+ [Talk](https://www.youtube.com/watch?v=2HmXwlKWMVs)
23
+
24
+ ### Contributors:
25
+ - Sergey Ovchinnikov [@sokrypton](https://github.com/sokrypton)
26
+ - Shihao Feng [@JeffSHF](https://github.com/JeffSHF)
27
+ - Justas Dauparas [@dauparas](https://github.com/dauparas)
28
+ - Weikun.Wu [@guyujun](https://github.com/guyujun) (from [Levinthal.bio](http://levinthal.bio/en/))
29
+ - Christopher Frank [@chris-kafka](https://github.com/chris-kafka)
model/PXDesignBench/ColabDesign/af/LICENSE.txt ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ /*
2
+ * ----------------------------------------------------------------------------
3
+ * "THE BEER-WARE LICENSE" (Revision 42):
4
+ * <so3@mit.edu> wrote this file. As long as you retain this notice you
5
+ * can do whatever you want with this stuff. If we meet some day, and you think
6
+ * this stuff is worth it, you can buy me a beer in return. Sergey Ovchinnikov
7
+ * ----------------------------------------------------------------------------
8
+ */
model/PXDesignBench/ColabDesign/af/README.md ADDED
@@ -0,0 +1,336 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # AfDesign (v1.1.1)
2
+ ### Google Colab
3
+ <a href="https://colab.research.google.com/github/sokrypton/ColabDesign/blob/v1.1.1/af/design.ipynb">
4
+ <img src="https://colab.research.google.com/assets/colab-badge.svg" alt="Open In Colab"/>
5
+ </a>
6
+
7
+ # Updates
8
+ - Jump to [Previous Updates](#previous-updates)
9
+ - **15Oct2022** - v1.1.0
10
+ - integrating proteinMPNN!
11
+ - bugfix for sidechain loss
12
+ - **17Nov2022**
13
+ - updating pae/plddt loss calculation to be consistent with pae/plddt outputs
14
+ - **24Dec2022** - v1.1.1
15
+ - adding af_pseudo_diffusion examples
16
+ - updating to alphafold-multimer v2.3.0
17
+ - enabling fused_triangle_multiplication by default
18
+ - **21Jan2023**
19
+ - add support for bfloat16 (enabled by default
20
+ - **01Mar2023**
21
+ - adding support for [RfDiffusion](/rf)
22
+ ### setup
23
+ first install jax (with GPU support)
24
+ ```bash
25
+ pip install "jax[cuda]" -f https://storage.googleapis.com/jax-releases/jax_cuda_releases.html
26
+ ```
27
+ second install colabdesign
28
+ ```bash
29
+ pip install git+https://github.com/sokrypton/ColabDesign.git@v1.1.1
30
+
31
+ # download alphafold weights
32
+ mkdir params
33
+ curl -fsSL https://storage.googleapis.com/alphafold/alphafold_params_2022-12-06.tar | tar x -C params
34
+ ```
35
+ By default `mk_afdesign_model()` assumes alphafold "params" are saved in the run directory (`data_dir="."`). To override:
36
+ ```python
37
+ model = mk_afdesign_model(..., data_dir="/location/of")
38
+ ```
39
+ ### import
40
+ ```python
41
+ import numpy as np
42
+ from IPython.display import HTML
43
+ from colabdesign import mk_afdesign_model, clear_mem
44
+ ```
45
+ ### fixed backbone design
46
+ For a given protein backbone, generate/design a new sequence that AlphaFold thinks folds into that conformation
47
+ ```python
48
+ model = mk_afdesign_model(protocol="fixbb")
49
+ model.prep_inputs(pdb_filename="1TEN.pdb", chain="A")
50
+ model.design_3stage()
51
+ ```
52
+ ### hallucination
53
+ For a given length, generate/hallucinate a protein sequence that AlphaFold thinks folds into a well structured
54
+ protein (high plddt, low pae, many contacts).
55
+ ```python
56
+ model = mk_afdesign_model(protocol="hallucination")
57
+ model.prep_inputs(length=100)
58
+ model.set_seq(mode="gumbel")
59
+ model.design_soft(50)
60
+ model.set_seq(model.aux["seq"]["pseudo"])
61
+ model.design_3stage(50,50,10)
62
+ ```
63
+ ### binder hallucination
64
+ For a given protein target and protein binder length, generate/hallucinate a protein binder sequence AlphaFold
65
+ thinks will bind to the target structure. To do this, we minimize PAE and maximize number of contacts at the
66
+ interface and within the binder, and we maximize pLDDT of the binder.
67
+ ```python
68
+ model = mk_afdesign_model(protocol="binder")
69
+ model.prep_inputs(pdb_filename="4MZK.pdb", chain="A", binder_len=19)
70
+ model.design_3stage(100, 100, 10)
71
+ ```
72
+ Instead of hallucination, you can redesign an existing binder:
73
+ ```python
74
+ model.prep_inputs(pdb_filename="4MZK.pdb", chain="A", binder_chain="T")
75
+ ```
76
+
77
+ ### partial hallucination
78
+ If you have a motif (binding motif, or functional motif) and you want to hallucinate a new scaffold around it,
79
+ you can use partial hallucination. Or you have a protein and you want to extend one of the loops.
80
+ ```python
81
+ af_model = mk_afdesign_model(protocol="partial")
82
+ af_model.prep_inputs(pdb_filename="6MRR.pdb", chain="A", pos="3-30,33-68", length=100)
83
+ af_model.rewire(loops=[36])
84
+ ```
85
+ # FAQ
86
+
87
+ #### Can I reuse the same model without needing to recompile?
88
+ ```python
89
+ model.restart()
90
+ ```
91
+ #### How do I change the loss weights?
92
+ This can be done using the provided function:
93
+ ```python
94
+ model.set_weights(pae=0.0, plddt=1.0)
95
+ ```
96
+ or the dictionary directly:
97
+ ```python
98
+ model.opt["weights"]["pae"] = 0.0
99
+ ```
100
+ #### How do I control number of recycles used during design?
101
+ ```python
102
+ model = mk_afdesign_model(num_recycles=1, recycle_mode="average")
103
+ # if recycle_mode in ["average",last","sample","first"] the number of recycles can change during optimization
104
+ model.set_opt(num_recycles=1)
105
+ ```
106
+ - `num_recycles` - number of recycles to use during design (for denovo proteins we find 0 is often enough)
107
+ - `recycle_mode` - optimizing across all recycles can be tricky, we experiment with a couple of ways:
108
+ - *last* - use loss from last recycle. (Default)
109
+ - *average* - compute loss at each recycle and average gradients. (Previous default from v.1.0.5)
110
+ - *sample* - Same as *last* but each iteration a different number of recycles are used.
111
+ - *first* - use loss from first recycle.
112
+ - *add_prev* - average the outputs (dgram, plddt, pae) across all recycles before computing loss.
113
+ - *backprop* - use loss from last recycle, but backprop through all recycles.
114
+
115
+ #### How do I control which model params are used during design?
116
+ By default all five models are used during optimization. If `num_models` > 1, then multiple params are evaluated at each iteration and the gradients/losses are averaged. Each iteration a random set of model params are used unless `sample_models=False`.
117
+ ```python
118
+ model = mk_afdesign_model(num_models=1, sample_models=True)
119
+ # or
120
+ model.set_opt(num_models=1, sample_models=True)
121
+ ```
122
+ - `num_models` - number of model params to use at each iteration.
123
+ - `sample_models`:
124
+ - *True* - randomly select models params to use. (Recommended)
125
+ - *False* - use the same model params each iteration.
126
+ You can also specify exactly which models are used during any of the design protocols:
127
+ ```python
128
+ model.design_(num_models=1, sample_models=True, models=[0,2,3])
129
+ # or
130
+ model.design_(num_models=2, sample_models=False, models=["model_1_ptm","model_3_ptm"])
131
+ ```
132
+ #### Can I use OpenFold model params for design instead of AlphaFold?
133
+ You may need to download them:
134
+ ```bash
135
+ for W in openfold_model_ptm_1 openfold_model_ptm_2 openfold_model_no_templ_ptm_1
136
+ do wget -qnc https://files.ipd.uw.edu/krypton/openfold/${W}.npz -P params; done
137
+ ```
138
+ Once downloaded:
139
+ ```python
140
+ model = mk_afdesign_model(use_openfold=True, use_alphafold=False)
141
+ ```
142
+ #### For binder hallucination, can I specify the site I want to bind?
143
+ ```python
144
+ model.prep_inputs(..., hotspot="1-10,15,3")
145
+ ```
146
+ #### Can I input more than one chain?
147
+ ```python
148
+ model.prep_inputs(..., chain="A,B")
149
+ ```
150
+ #### For fixed backbone design, how do I force the sequence to be the same for homo-dimer optimization?
151
+ ```python
152
+ model.prep_inputs(pdb_filename="6Q40.pdb", chain="A,B", copies=2, homooligomer=True)
153
+ ```
154
+ WARNING, this functionality assumes the input chains are of equal length.
155
+ #### How do I disable certain amino acids?
156
+ ```python
157
+ model.restart(rm_aa="C,W")
158
+ ```
159
+ #### How do I set the random seed for reproducibility?
160
+ ```python
161
+ model.restart(seed=0)
162
+ ```
163
+ #### What are all the different `design_???` methods?
164
+ - For **design** we provide 5 different functions:
165
+ - `design_logits()` - optimize *logits* inputs (continious)
166
+ - `design_soft()` - optimize *softmax(logits)* inputs (probabilities)
167
+ - `design_hard()` - optimize *one_hot(logits)* inputs (discrete)
168
+
169
+ - For complex topologies, we find directly optimizing one_hot encoded sequence `design_hard()` to be very challenging.
170
+ To get around this problem, we propose optimizing in 3 stages or first learning logits then switching to semigreedy optimization.
171
+ - `design_3stage()` - gradient based optimization (GD) (logits → soft → hard)
172
+ - `design_semigreedy(tries=X)` - tries X random mutations, accepts those that decrease loss
173
+ - `design_pssm_semigreey(tries=X)` - uses GD to get a sequence profile (PSSM), then uses the PSSM to bias semigreedy opt. (Recommended)
174
+
175
+ #### What are all the different losses being optimized?
176
+ - general losses
177
+ - *pae* - minimizes the predicted alignment error
178
+ - *plddt* - maximizes the predicted LDDT
179
+ - *pae* and *plddt* values are between 0 and 1 (where lower is better for both)
180
+
181
+ - fixbb specific losses
182
+ - *dgram_cce* - minimizes the categorical-crossentropy between predicted distogram and one extracted from pdb.
183
+ - *fape* - minimize difference between coordinates (see AlphaFold paper)
184
+ - we find *dgram_cce* loss to be more stable for design (compared to *fape*)
185
+
186
+ - hallucination specific losses
187
+ - *con* - maximize `1` contacts per position. `model.set_opt("con",num=1)`
188
+
189
+ - binder specific losses
190
+ - *pae* - minimize PAE at interface and within binder
191
+ - *con* - - maximize `2` contacts per binder position, within binder. `model.set_opt("con",num=2)`
192
+ - *i_con* - maximize `1` contacts per binder position `model.set_opt("i_con",num=1)`
193
+
194
+ - partial hallucination specific losses
195
+ - *sc_fape* - sidechain-specific fape
196
+
197
+ #### How is contact defined? How do I change it?
198
+ By default, 2 [con]tacts per positions are optimized to be within cβ-cβ < 14.0Å and sequence seperation ≥ 9. This can be changed with:
199
+ ```python
200
+ model.set_opt(con=dict(cutoff=8, seqsep=5, num=1))
201
+ ```
202
+ For interface:
203
+ ```python
204
+ model.set_opt(i_con=dict(...))
205
+ ```
206
+
207
+ #### Optax Optimizers
208
+ By default, we use stochastic gradient descent `set_optimizer(optimizer="sgd", learning_rate=0.1, norm_seq_grad=True)` for optimization. This seems to work quite well for the default problems. But if you want to try other optimizers, ColabDesign is now fully integrated with all [Optax optimizers](https://optax.readthedocs.io/en/latest/api.html).
209
+ Example how to change optimizer. Note the default learning_rate of 0.1 was calibrated for sgd with gradient normalization. A different learning_rate may be more optimal for other optimization settings.
210
+ ```python
211
+ model = mk_afdesign_model(optimizer="adam", learning_rate=0.01)
212
+ ```
213
+ Or for more control (or to change settings after model initialization), use:
214
+ ```python
215
+ model.set_optimizer(optimizer="adam", learning_rate=0.01, b1=0.9, b2=0.999)
216
+ ```
217
+ By default, the gradients for the sequence parameters are normalized. We find this helps with convergence. To disable:
218
+ ```python
219
+ model.set_opt(norm_seq_grad=False)
220
+ ```
221
+
222
+ # Advanced FAQ
223
+ #### loss during Gradient descent is too jumpy, can I do some kind of greedy search towards the end?
224
+ Gradient descent updates multiple positions each iteration, which can be a little too aggressive during hard (discrete) mode.
225
+ Instead, one can try (`tries`) a few random mutations and accept one with lowest loss. If `use_plddt=True` the random mutations will be biased towards positions with low pLDDT.
226
+ ```python
227
+ model.design_3stage(hard_iters=0)
228
+ # set number of model params to evaluate at each iteration
229
+ num_models = 2 if model.args["use_templates"] else 5
230
+ model.design_semigreedy(iters=10, tries=20, num_models=num_models, use_plddt=True)
231
+ ```
232
+ #### I was getting better results before the major update (19June2022), how do I revert back to the old settings?
233
+ We are actively trying to find the best weights `model.opt["weights"]`, settings `model.opt` for each protocol.
234
+ Please send us a note if you find something better! To revert back to old settings do this after prepping the model:
235
+ - fixbb:
236
+ ```python
237
+ model.set_weights(dgram_cce=1, pae=0.1, plddt=0.1)
238
+ model.design_3stage()
239
+ ```
240
+ - hallucination:
241
+ ```python
242
+ model.set_seq(mode="gumbel")
243
+ model.set_weights(pae=1, plddt=1, con=0.5)
244
+ model.set_opt("con", binary=True, cutoff=21.6875, num=model._len, seqsep=0)
245
+ model.design_2stage(100, 100, 10)
246
+ ```
247
+ - binder hallucination:
248
+ ```python
249
+ model.set_weights(plddt=0.1, pae=0.1, i_pae=1.0, con=0.1, i_con=0.5)
250
+ model.set_opt("con", binary=True, cutoff=21.6875, num=model._binder_len, seqsep=0)
251
+ model.set_opt("i_con", binary=True, cutoff=21.6875, num=model._target_len)
252
+ model.design_3stage(100, 100, 10)
253
+ ```
254
+ #### I don't like your design_??? function, can I write my own with more detailed control?
255
+ ```python
256
+ def design_custom(self):
257
+ # set options
258
+ self.set_opt(dropout=True, soft=False, hard=False)
259
+ # set number of recycles
260
+ self.set_opt(num_recycles=0)
261
+ # take 100 steps
262
+ for _ in range(100): self.step()
263
+ # increase weight for plddt
264
+ self.set_weights(plddt=2.0)
265
+ # take another 100 steps
266
+ for _ in range(100): self.step()
267
+ # increase number of recycles
268
+ self.set_opt(num_recycles=1)
269
+ # take another 100 steps
270
+ for _ in range(100): self.step()
271
+ # etc...
272
+
273
+ model = mk_afdesign_model()
274
+ design_custom(model)
275
+ ```
276
+
277
+ #### custom callback examples
278
+ Looking for more control over afdesign? The callback functions have gotten much smarter. Based on your input arguments, it will automatically fetch the variable of interest. You can now define your own custom losses, params to optimize, modify inputs before alphafold is run, and modify auxiliary outputs.
279
+ ```python
280
+ def custom_pre_callback(inputs, aux, opt, key):
281
+ inputs["aatype"] = inputs["aatype"].at[:].set(0)
282
+ aux["pre"] = opt["pre"] + jax.random.randint(key,[],0,10)
283
+
284
+ def custom_post_callback(outputs, aux):
285
+ aux["post"] = outputs["structure_module"]
286
+
287
+ def custom_loss_callback(outputs, params):
288
+ loss = jnp.square(outputs["structure_module"]["final_atom14_positions"] + params["custom_param"]).mean()
289
+ return {"custom_loss":loss}
290
+
291
+ af_model = mk_afdesign_model(protocol="fixbb",
292
+ pre_callback=custom_pre_callback,
293
+ post_callback=custom_post_callback,
294
+ loss_callback=custom_loss_callback)
295
+ af_model._params["custom_param"] = 1.0
296
+ af_model.opt["weights"]["custom_loss"] = 0.1
297
+ af_model.opt["pre"] = 100
298
+
299
+ af_model.prep_inputs(pdb_filename=get_pdb("1TEN"), chain="A")
300
+ ```
301
+
302
+ # Previous Updates
303
+ - **24Feb2022** - "Beta" branch started. Refactoring code to allow homooligomeric hallucination/design and averaging gradients across recycles (which is now the default).
304
+ Minor changes changes include renaming intra_pae/inter_con to pae/con and inter_pae/inter_con to i_pae/i_con for clarity.
305
+ - **28Feb2022** - We find backprop through structure module to be unstable, all functions have been updated to only use distogram by default. The definition of contact has changed to minimize entropy within distance cutoff.
306
+ - **02May2022** - The `design.py` code has been split up into multiple python files under `src/`
307
+ - **14May2022** - Adding support for partial hallucination (if you want to constrain one part and generate structure/sequence for rest).
308
+ - **19June2022** - "Beta" branch is now the "Main" branch. WARNING: Lots of default settings and weights were changed. [Click here](#i-was-getting-better-results-before-the-major-update-19june2022-how-do-i-revert-back-to-the-old-settings) for info on how to revert back to old settings.
309
+ - **28June2022** - v1.0.1 - Major code reorganization/refactoring to add support for callbacks (to allow integration w/ other tools during design) and to avoid clashes with existing trrosetta/alphafold installations. (eg. `af → colabdesign`, `af.src → colabdesign.af` and `alphafold → colabdesign.af.alphafold`).
310
+ - **05July2022** - v1.0.2 - Major code cleanup, removing duplicate code. Adding support for custom loss functions.
311
+ - **11July2022** - v1.0.3 - Improved homo-oligomeric support. RMSD and dgram losses have been refactored to automatically save aligned coordinates. Multimeric coordinates now saved with chain identifiers.
312
+ - **23July2022** - v1.0.4 - Adding support for openfold weights. To enable set `mk_afdesign_model(..., use_openfold=True)`.
313
+ - **31July2022** - v1.0.5 - Refactoring to add support for swapping batch features without recompile. Allowing for implementation of [AF2Rank](https://github.com/sokrypton/ColabDesign/blob/main/af/examples/AF2Rank.ipynb)!
314
+ - **09Sept2022** - v1.0.6
315
+ - support for alphafold-multimer `model = mk_afdesign_model(..., use_multimer=True)`
316
+ - support for experimentally resolved loss `model.set_weights(exp_res=1)`
317
+ - support for multichain design/hallucination for fixbb, hallucination and partial protocols: `model.prep_inputs(..., copies=2)`
318
+ - support to fix the sequence for certain positions `model.prep_inputs(..., fix_pos="1-10")` (supported in protocols "fixbb" and "partial")
319
+ - binder protocol improved, prior protocol would try to optimize number of contacts per target, new default is to optimize number of contacts per binder position. Number of contacts per binder position can be controlled with `model.set_opt("i_con",num=1)` and number of positions that should be contact with `model.set_opt("i_con",num_pos=5)`
320
+ - implementing David Jones'-like protocol for semi-greedy optimization, where positions are selected based on plddt, and after 20 tries, the mutation that decreasing loss the most is accepted. `model.design_semigreedy()`
321
+ - WARNING: the returned pLDDT is now in the "correct" direction (higher is better)
322
+ - removing recycle dimension from the input features (to standardize with multimer inputs)
323
+ - removing all dependence on TensorFlow
324
+ - **14Sept2022** - v1.0.7
325
+ - refactoring design.py to add `design_pssm_semigreedy()` protocol, which is a wrapper around `design_semigreedy(seq_logits=)`, and can be used to input/learn PSSM for biased optimization.
326
+ - adding example [peptide_binder_design.ipynb](https://colab.research.google.com/github/sokrypton/ColabDesign/blob/main/af/examples/peptide_binder_design.ipynb) targeted for peptide binder hallucination/design.
327
+ - adding [finer control](#how-do-i-control-which-model-params-are-used-during-design) over what models are used during optimization.
328
+ - fixing RAM memory leaks, `clear_mem()` now also does garbage collection
329
+ - fixing integration with TrDesign that got broken in v1.0.6
330
+ - **22Sept2022** - v1.0.8
331
+ - [custom callback functions](#custom-callback-examples) (\[pre|loss|pos\]_callback) have been refactored to be more flexible.
332
+ - Supported input arguments include: ["inputs", "outputs", "params", "opt", "seq", "aux", "key"].
333
+ - The pre_callback function can be used to modify inputs before prediction, loss_callback to add cutstom loss.
334
+ - adding support for [Optax optimizers](#optax-optimizers)
335
+ - **24Sept2022** - v1.0.9
336
+ - adding [contrib section](/af/contrib) where user contributed modifications and protocols will go.
model/PXDesignBench/ColabDesign/af/contrib/README.md ADDED
@@ -0,0 +1 @@
 
 
1
+ WIP
model/PXDesignBench/ColabDesign/af/design.ipynb ADDED
@@ -0,0 +1,452 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "cells": [
3
+ {
4
+ "cell_type": "markdown",
5
+ "metadata": {
6
+ "id": "view-in-github",
7
+ "colab_type": "text"
8
+ },
9
+ "source": [
10
+ "<a href=\"https://colab.research.google.com/github/sokrypton/ColabDesign/blob/v1.1.1/af/design.ipynb\" target=\"_parent\"><img src=\"https://colab.research.google.com/assets/colab-badge.svg\" alt=\"Open In Colab\"/></a>"
11
+ ]
12
+ },
13
+ {
14
+ "cell_type": "markdown",
15
+ "metadata": {
16
+ "id": "OA2k3sAYuiXe"
17
+ },
18
+ "source": [
19
+ "#AfDesign (v1.1.1)\n",
20
+ "Backprop through AlphaFold for protein design.\n",
21
+ "\n",
22
+ "**WARNING**\n",
23
+ "1. This notebook is in active development and was designed for demonstration purposes only.\n",
24
+ "2. Using AfDesign as the only \"loss\" function for design might be a bad idea, you may find adversarial sequences (aka. sequences that trick AlphaFold)."
25
+ ]
26
+ },
27
+ {
28
+ "cell_type": "code",
29
+ "execution_count": null,
30
+ "metadata": {
31
+ "cellView": "form",
32
+ "id": "-AXy0s_4cKaK"
33
+ },
34
+ "outputs": [],
35
+ "source": [
36
+ "#@title setup\n",
37
+ "%%time\n",
38
+ "import os\n",
39
+ "if not os.path.isdir(\"params\"):\n",
40
+ " # get code\n",
41
+ " os.system(\"pip -q install git+https://github.com/sokrypton/ColabDesign.git@v1.1.1\")\n",
42
+ " # for debugging\n",
43
+ " os.system(\"ln -s /usr/local/lib/python3.*/dist-packages/colabdesign colabdesign\")\n",
44
+ " # download params\n",
45
+ " os.system(\"mkdir params\")\n",
46
+ " os.system(\"apt-get install aria2 -qq\")\n",
47
+ " os.system(\"aria2c -q -x 16 https://storage.googleapis.com/alphafold/alphafold_params_2022-12-06.tar\")\n",
48
+ " os.system(\"tar -xf alphafold_params_2022-12-06.tar -C params\")\n",
49
+ "\n",
50
+ "import warnings\n",
51
+ "warnings.simplefilter(action='ignore', category=FutureWarning)\n",
52
+ "\n",
53
+ "import os\n",
54
+ "from colabdesign import mk_afdesign_model, clear_mem\n",
55
+ "from IPython.display import HTML\n",
56
+ "from google.colab import files\n",
57
+ "import numpy as np\n",
58
+ "\n",
59
+ "def get_pdb(pdb_code=\"\"):\n",
60
+ " if pdb_code is None or pdb_code == \"\":\n",
61
+ " upload_dict = files.upload()\n",
62
+ " pdb_string = upload_dict[list(upload_dict.keys())[0]]\n",
63
+ " with open(\"tmp.pdb\",\"wb\") as out: out.write(pdb_string)\n",
64
+ " return \"tmp.pdb\"\n",
65
+ " elif os.path.isfile(pdb_code):\n",
66
+ " return pdb_code\n",
67
+ " elif len(pdb_code) == 4:\n",
68
+ " os.system(f\"wget -qnc https://files.rcsb.org/view/{pdb_code}.pdb\")\n",
69
+ " return f\"{pdb_code}.pdb\"\n",
70
+ " else:\n",
71
+ " os.system(f\"wget -qnc https://alphafold.ebi.ac.uk/files/AF-{pdb_code}-F1-model_v3.pdb\")\n",
72
+ " return f\"AF-{pdb_code}-F1-model_v3.pdb\""
73
+ ]
74
+ },
75
+ {
76
+ "cell_type": "markdown",
77
+ "metadata": {
78
+ "id": "UUfKrOzT0gOS"
79
+ },
80
+ "source": [
81
+ "# fixed backbone design (fixbb)\n",
82
+ "For a given protein backbone, generate/design a new sequence that AlphaFold thinks folds into that conformation. "
83
+ ]
84
+ },
85
+ {
86
+ "cell_type": "code",
87
+ "execution_count": null,
88
+ "metadata": {
89
+ "id": "qLd1DsnKzxBJ"
90
+ },
91
+ "outputs": [],
92
+ "source": [
93
+ "clear_mem()\n",
94
+ "af_model = mk_afdesign_model(protocol=\"fixbb\")\n",
95
+ "af_model.prep_inputs(pdb_filename=get_pdb(\"1TEN\"), chain=\"A\")\n",
96
+ "\n",
97
+ "print(\"length\", af_model._len)\n",
98
+ "print(\"weights\", af_model.opt[\"weights\"])"
99
+ ]
100
+ },
101
+ {
102
+ "cell_type": "code",
103
+ "source": [
104
+ "af_model.restart()\n",
105
+ "af_model.design_3stage()"
106
+ ],
107
+ "metadata": {
108
+ "id": "u0AwskJ84NGx"
109
+ },
110
+ "execution_count": null,
111
+ "outputs": []
112
+ },
113
+ {
114
+ "cell_type": "code",
115
+ "source": [
116
+ "af_model.plot_traj() "
117
+ ],
118
+ "metadata": {
119
+ "id": "8FB1v7dn1LL6"
120
+ },
121
+ "execution_count": null,
122
+ "outputs": []
123
+ },
124
+ {
125
+ "cell_type": "code",
126
+ "execution_count": null,
127
+ "metadata": {
128
+ "id": "YEApO8YzBoS0"
129
+ },
130
+ "outputs": [],
131
+ "source": [
132
+ "af_model.save_pdb(f\"{af_model.protocol}.pdb\")\n",
133
+ "af_model.plot_pdb()"
134
+ ]
135
+ },
136
+ {
137
+ "cell_type": "code",
138
+ "execution_count": null,
139
+ "metadata": {
140
+ "id": "cW1KQiHKJpfp"
141
+ },
142
+ "outputs": [],
143
+ "source": [
144
+ "HTML(af_model.animate())"
145
+ ]
146
+ },
147
+ {
148
+ "cell_type": "code",
149
+ "source": [
150
+ "af_model.get_seqs()"
151
+ ],
152
+ "metadata": {
153
+ "id": "YDrChASGVUUx"
154
+ },
155
+ "execution_count": null,
156
+ "outputs": []
157
+ },
158
+ {
159
+ "cell_type": "markdown",
160
+ "source": [
161
+ "# hallucination\n",
162
+ "For a given length, generate/hallucinate a protein sequence that AlphaFold thinks folds into a well structured protein (high plddt, low pae, many contacts)."
163
+ ],
164
+ "metadata": {
165
+ "id": "qLwS2s_xcjRI"
166
+ }
167
+ },
168
+ {
169
+ "cell_type": "code",
170
+ "execution_count": null,
171
+ "metadata": {
172
+ "id": "sZnYfCbfEvol"
173
+ },
174
+ "outputs": [],
175
+ "source": [
176
+ "clear_mem()\n",
177
+ "af_model = mk_afdesign_model(protocol=\"hallucination\")\n",
178
+ "af_model.prep_inputs(length=100)\n",
179
+ "\n",
180
+ "print(\"length\",af_model._len)\n",
181
+ "print(\"weights\",af_model.opt[\"weights\"])"
182
+ ]
183
+ },
184
+ {
185
+ "cell_type": "code",
186
+ "source": [
187
+ "# pre-design with gumbel initialization and softmax activation\n",
188
+ "af_model.restart(mode=\"gumbel\")\n",
189
+ "af_model.design_soft(50)\n",
190
+ "\n",
191
+ "# three stage design \n",
192
+ "af_model.set_seq(af_model.aux[\"seq\"][\"pseudo\"])\n",
193
+ "af_model.design_3stage(50,50,10)"
194
+ ],
195
+ "metadata": {
196
+ "id": "f76xqCkw0vj9"
197
+ },
198
+ "execution_count": null,
199
+ "outputs": []
200
+ },
201
+ {
202
+ "cell_type": "code",
203
+ "execution_count": null,
204
+ "metadata": {
205
+ "id": "A1GxeLZdTTya"
206
+ },
207
+ "outputs": [],
208
+ "source": [
209
+ "af_model.save_pdb(f\"{af_model.protocol}.pdb\")\n",
210
+ "af_model.plot_pdb()"
211
+ ]
212
+ },
213
+ {
214
+ "cell_type": "code",
215
+ "execution_count": null,
216
+ "metadata": {
217
+ "id": "L2E9Tn2Acchj"
218
+ },
219
+ "outputs": [],
220
+ "source": [
221
+ "HTML(af_model.animate())"
222
+ ]
223
+ },
224
+ {
225
+ "cell_type": "code",
226
+ "execution_count": null,
227
+ "metadata": {
228
+ "id": "YSKWYu0_GlUH"
229
+ },
230
+ "outputs": [],
231
+ "source": [
232
+ "af_model.get_seqs()"
233
+ ]
234
+ },
235
+ {
236
+ "cell_type": "markdown",
237
+ "metadata": {
238
+ "id": "dXfm4B8ISLuL"
239
+ },
240
+ "source": [
241
+ "# binder hallucination\n",
242
+ "For a given protein target and protein binder length, generate/hallucinate a protein binder sequence AlphaFold thinks will bind to the target structure.\n",
243
+ "To do this, we minimize PAE and maximize number of contacts at the interface and within the binder, and we maximize pLDDT of the binder.\n",
244
+ "By default, AlphaFold-ptm with residue index offset hack is used. To enable AlphaFold-multimer set: mk_afdesign_model(use_multimer=True).\n"
245
+ ]
246
+ },
247
+ {
248
+ "cell_type": "code",
249
+ "execution_count": null,
250
+ "metadata": {
251
+ "id": "3XLJPiRKx5Mw"
252
+ },
253
+ "outputs": [],
254
+ "source": [
255
+ "clear_mem()\n",
256
+ "af_model = mk_afdesign_model(protocol=\"binder\")\n",
257
+ "af_model.prep_inputs(pdb_filename=get_pdb(\"4MZK\"), chain=\"A\", binder_len=19)\n",
258
+ "\n",
259
+ "print(\"target_length\",af_model._target_len)\n",
260
+ "print(\"binder_length\",af_model._binder_len)\n",
261
+ "print(\"weights\",af_model.opt[\"weights\"])"
262
+ ]
263
+ },
264
+ {
265
+ "cell_type": "code",
266
+ "execution_count": null,
267
+ "metadata": {
268
+ "id": "u6VxjuinyCZa"
269
+ },
270
+ "outputs": [],
271
+ "source": [
272
+ "af_model.restart()\n",
273
+ "af_model.design_3stage(100,100,10)"
274
+ ]
275
+ },
276
+ {
277
+ "cell_type": "code",
278
+ "source": [
279
+ "af_model.save_pdb(f\"{af_model.protocol}.pdb\")\n",
280
+ "af_model.plot_pdb()"
281
+ ],
282
+ "metadata": {
283
+ "id": "sTlS7_L8Zfwf"
284
+ },
285
+ "execution_count": null,
286
+ "outputs": []
287
+ },
288
+ {
289
+ "cell_type": "code",
290
+ "execution_count": null,
291
+ "metadata": {
292
+ "id": "9cARoviGyIKb"
293
+ },
294
+ "outputs": [],
295
+ "source": [
296
+ "HTML(af_model.animate())"
297
+ ]
298
+ },
299
+ {
300
+ "cell_type": "code",
301
+ "source": [
302
+ "af_model.get_seqs()"
303
+ ],
304
+ "metadata": {
305
+ "id": "RzE137NDZdZc"
306
+ },
307
+ "execution_count": null,
308
+ "outputs": []
309
+ },
310
+ {
311
+ "cell_type": "markdown",
312
+ "source": [
313
+ "#**ADVANCED**"
314
+ ],
315
+ "metadata": {
316
+ "id": "SK0IJLoen_EC"
317
+ }
318
+ },
319
+ {
320
+ "cell_type": "markdown",
321
+ "source": [
322
+ "## partial hallucination + custom Radius of Gyration (rg) loss\n",
323
+ "mix supervised (fixbb) and unsupervised (hallucination) losses to constrain the halluciation process."
324
+ ],
325
+ "metadata": {
326
+ "id": "zl6JGTUzXRnk"
327
+ }
328
+ },
329
+ {
330
+ "cell_type": "code",
331
+ "source": [
332
+ "import jax\n",
333
+ "import jax.numpy as jnp\n",
334
+ "from colabdesign.af.alphafold.common import residue_constants\n",
335
+ "\n",
336
+ "# first off, let's implement a custom Radius of Gyration loss function\n",
337
+ "def rg_loss(inputs, outputs):\n",
338
+ " positions = outputs[\"structure_module\"][\"final_atom_positions\"]\n",
339
+ " ca = positions[:,residue_constants.atom_order[\"CA\"]]\n",
340
+ " center = ca.mean(0)\n",
341
+ " rg = jnp.sqrt(jnp.square(ca - center).sum(-1).mean() + 1e-8)\n",
342
+ " rg_th = 2.38 * ca.shape[0] ** 0.365\n",
343
+ " rg = jax.nn.elu(rg - rg_th)\n",
344
+ " return {\"rg\":rg}"
345
+ ],
346
+ "metadata": {
347
+ "id": "spec3m8BlGer"
348
+ },
349
+ "execution_count": null,
350
+ "outputs": []
351
+ },
352
+ {
353
+ "cell_type": "code",
354
+ "source": [
355
+ "clear_mem()\n",
356
+ "af_model = mk_afdesign_model(protocol=\"partial\",\n",
357
+ " loss_callback=rg_loss, # add rg_loss\n",
358
+ " use_templates=False) # set True to constrain positions using template input\n",
359
+ "\n",
360
+ "af_model.opt[\"weights\"][\"rg\"] = 0.1 # optional: specify weight for rg_loss\n",
361
+ "\n",
362
+ "af_model.prep_inputs(pdb_filename=get_pdb(\"6MRR\"),\n",
363
+ " chain=\"A\",\n",
364
+ " pos=\"3-30,33-68\", # define positions to contrain\n",
365
+ " length=100) # total length if different from input pdb\n",
366
+ "\n",
367
+ "af_model.rewire(loops=[36]) # set loop length between segments "
368
+ ],
369
+ "metadata": {
370
+ "id": "h_BvzwbAKo6V"
371
+ },
372
+ "execution_count": null,
373
+ "outputs": []
374
+ },
375
+ {
376
+ "cell_type": "code",
377
+ "source": [
378
+ "# initialize with wildtype seq, fill in the rest with soft_gumbel distribution\n",
379
+ "af_model.restart(mode=[\"soft\",\"gumbel\",\"wildtype\"])\n",
380
+ "af_model.design_3stage(100, 100, 10)"
381
+ ],
382
+ "metadata": {
383
+ "id": "5Unr9u2GYKRD"
384
+ },
385
+ "execution_count": null,
386
+ "outputs": []
387
+ },
388
+ {
389
+ "cell_type": "code",
390
+ "source": [
391
+ "af_model.save_pdb(f\"{af_model.protocol}.pdb\")\n",
392
+ "af_model.plot_pdb()"
393
+ ],
394
+ "metadata": {
395
+ "id": "BFweaqNWYuF0"
396
+ },
397
+ "execution_count": null,
398
+ "outputs": []
399
+ },
400
+ {
401
+ "cell_type": "code",
402
+ "source": [
403
+ "HTML(af_model.animate())"
404
+ ],
405
+ "metadata": {
406
+ "id": "GSu2lB9HYw-t"
407
+ },
408
+ "execution_count": null,
409
+ "outputs": []
410
+ },
411
+ {
412
+ "cell_type": "code",
413
+ "source": [
414
+ "af_model.get_seqs()"
415
+ ],
416
+ "metadata": {
417
+ "id": "2EG2t2_KY4Td"
418
+ },
419
+ "execution_count": null,
420
+ "outputs": []
421
+ },
422
+ {
423
+ "cell_type": "code",
424
+ "source": [],
425
+ "metadata": {
426
+ "id": "rTGKbhsI0t8k"
427
+ },
428
+ "execution_count": null,
429
+ "outputs": []
430
+ }
431
+ ],
432
+ "metadata": {
433
+ "accelerator": "GPU",
434
+ "colab": {
435
+ "collapsed_sections": [
436
+ "q4qiU9I0QHSz"
437
+ ],
438
+ "name": "design.ipynb",
439
+ "provenance": [],
440
+ "include_colab_link": true
441
+ },
442
+ "kernelspec": {
443
+ "display_name": "Python 3",
444
+ "name": "python3"
445
+ },
446
+ "language_info": {
447
+ "name": "python"
448
+ }
449
+ },
450
+ "nbformat": 4,
451
+ "nbformat_minor": 0
452
+ }
model/PXDesignBench/ColabDesign/af/examples/AF2Rank.ipynb ADDED
The diff for this file is too large to render. See raw diff
 
model/PXDesignBench/ColabDesign/af/examples/RSO.ipynb ADDED
@@ -0,0 +1,1297 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "cells": [
3
+ {
4
+ "cell_type": "markdown",
5
+ "metadata": {
6
+ "id": "view-in-github",
7
+ "colab_type": "text"
8
+ },
9
+ "source": [
10
+ "<a href=\"https://colab.research.google.com/github/sokrypton/ColabDesign/blob/main/af/examples/RSO.ipynb\" target=\"_parent\"><img src=\"https://colab.research.google.com/assets/colab-badge.svg\" alt=\"Open In Colab\"/></a>"
11
+ ]
12
+ },
13
+ {
14
+ "cell_type": "markdown",
15
+ "metadata": {
16
+ "id": "OA2k3sAYuiXe"
17
+ },
18
+ "source": [
19
+ "\n",
20
+ "\n",
21
+ "\n",
22
+ "#Protein Design using Relaxed Sequence Optimization\n",
23
+ "\n",
24
+ "\n",
25
+ "**Scalable protein design using optimization in a relaxed sequence space**\n",
26
+ "\n",
27
+ "\n",
28
+ "\n",
29
+ "\n",
30
+ "Christopher Frank, Ali Khoshouei, Lara Fuß, Lara Weber Dominik Schiewitz,Zhixuan Zhao, Motoyuki Hattori, Yosta de Stigter, Shihao Feng, Sergey Ovchinnikov and Hendrik Dietz\n",
31
+ "\n",
32
+ "\n",
33
+ "This notebook contains code to run relaxed sequence optimisation for de novo protein design as described in the manuscript. There are additional options to modify the pipeline according to ones needs\n",
34
+ "\n",
35
+ "We recommend using at least an L4 GPU to run this notebook, as the free T4 GPU struggles with larger proteins\n",
36
+ "\n",
37
+ "Alternativly a local installation of ColabDesign is strongly recommendet, especially for the design of larger proteins.\n",
38
+ "\n",
39
+ "For questions feel free to reach out to the authors\n"
40
+ ]
41
+ },
42
+ {
43
+ "cell_type": "code",
44
+ "execution_count": null,
45
+ "metadata": {
46
+ "cellView": "form",
47
+ "id": "-AXy0s_4cKaK"
48
+ },
49
+ "outputs": [],
50
+ "source": [
51
+ "#@title setup\n",
52
+ "%%time\n",
53
+ "import os\n",
54
+ "if not os.path.isdir(\"params\"):\n",
55
+ " # get code\n",
56
+ " os.system(\"pip -q install pyppeteer nest_asyncio\")\n",
57
+ " os.system(\"pip -q install git+https://github.com/sokrypton/ColabDesign.git\")\n",
58
+ " # for debugging\n",
59
+ " os.system(\"ln -s /usr/local/lib/python3.*/dist-packages/colabdesign colabdesign\")\n",
60
+ " # download params\n",
61
+ " os.system(\"mkdir params\")\n",
62
+ " os.system(\"apt-get install aria2 -qq\")\n",
63
+ " os.system(\"aria2c -q -x 16 https://storage.googleapis.com/alphafold/alphafold_params_2022-12-06.tar\")\n",
64
+ " os.system(\"tar -xf alphafold_params_2022-12-06.tar -C params\")\n",
65
+ "\n",
66
+ "import warnings\n",
67
+ "warnings.simplefilter(action='ignore', category=FutureWarning)\n",
68
+ "\n",
69
+ "import os\n",
70
+ "from colabdesign import mk_afdesign_model, clear_mem\n",
71
+ "from colabdesign.mpnn import mk_mpnn_model\n",
72
+ "\n",
73
+ "from IPython.display import HTML\n",
74
+ "from google.colab import files\n",
75
+ "import numpy as np\n",
76
+ "\n",
77
+ "import requests, time\n",
78
+ "if not os.path.isfile(\"TMscore\"):\n",
79
+ " os.system(\"wget -qnc https://zhanggroup.org/TM-score/TMscore.cpp\")\n",
80
+ " os.system(\"g++ -static -O3 -ffast-math -lm -o TMscore TMscore.cpp\")\n",
81
+ "def tmscore(x,y):\n",
82
+ " # pass to TMscore\n",
83
+ " output = os.popen(f'./TMscore {x} {y}')\n",
84
+ " # parse outputs\n",
85
+ " parse_float = lambda x: float(x.split(\"=\")[1].split()[0])\n",
86
+ " o = {}\n",
87
+ " for line in output:\n",
88
+ " line = line.rstrip()\n",
89
+ " if line.startswith(\"RMSD\"): o[\"rms\"] = parse_float(line)\n",
90
+ " if line.startswith(\"TM-score\"): o[\"tms\"] = parse_float(line)\n",
91
+ " if line.startswith(\"GDT-TS-score\"): o[\"gdt\"] = parse_float(line)\n",
92
+ " return o\n",
93
+ "\n",
94
+ "import asyncio\n",
95
+ "import nest_asyncio\n",
96
+ "from pyppeteer import launch\n",
97
+ "import base64\n",
98
+ "\n",
99
+ "# Apply nest_asyncio to enable nested event loops\n",
100
+ "nest_asyncio.apply()\n",
101
+ "\n",
102
+ "async def fetch_blob_content(page, blob_url):\n",
103
+ " blob_to_base64 = \"\"\"\n",
104
+ " async (blobUrl) => {\n",
105
+ " const blob = await fetch(blobUrl).then(r => r.blob());\n",
106
+ " return new Promise((resolve) => {\n",
107
+ " const reader = new FileReader();\n",
108
+ " reader.onloadend = () => resolve(reader.result);\n",
109
+ " reader.readAsDataURL(blob);\n",
110
+ " });\n",
111
+ " }\n",
112
+ " \"\"\"\n",
113
+ " base64_data = await page.evaluate(blob_to_base64, blob_url)\n",
114
+ " _, encoded = base64_data.split(',', 1)\n",
115
+ " return base64.b64decode(encoded)\n",
116
+ "\n",
117
+ "async def extract_pdb_file_download_link_and_content(url):\n",
118
+ " browser = await launch(headless=True, args=['--no-sandbox', '--disable-setuid-sandbox'])\n",
119
+ " page = await browser.newPage()\n",
120
+ " await page.goto(url, {'waitUntil': 'networkidle0'})\n",
121
+ " elements = await page.querySelectorAll('a.btn.bg-purple')\n",
122
+ " for element in elements:\n",
123
+ " href = await page.evaluate('(element) => element.getAttribute(\"href\")', element)\n",
124
+ " if 'blob:https://esmatlas.com/' in href:\n",
125
+ " content = await fetch_blob_content(page, href)\n",
126
+ " await browser.close()\n",
127
+ " return href, content\n",
128
+ " await browser.close()\n",
129
+ " return \"No PDB file link found.\", None\n",
130
+ "\n",
131
+ "def esmfold_api(sequence):\n",
132
+ " url = f'https://esmatlas.com/resources/fold/result?fasta_header=%3Eunnamed&sequence={sequence}'\n",
133
+ " result = asyncio.get_event_loop().run_until_complete(extract_pdb_file_download_link_and_content(url))\n",
134
+ " if result[1]:\n",
135
+ " pdb_str = result[1].decode('utf-8')\n",
136
+ " return pdb_str\n",
137
+ " else:\n",
138
+ " return \"Failed to retrieve PDB content.\"\n",
139
+ "\n",
140
+ "import jax\n",
141
+ "import jax.numpy as jnp\n",
142
+ "from colabdesign.af.alphafold.common import residue_constants"
143
+ ]
144
+ },
145
+ {
146
+ "cell_type": "code",
147
+ "execution_count": null,
148
+ "metadata": {
149
+ "id": "sZnYfCbfEvol",
150
+ "cellView": "form"
151
+ },
152
+ "outputs": [],
153
+ "source": [
154
+ "#@title # Unconditional Generation (Custom)\n",
155
+ "#@markdown For a given length, generate/hallucinate a protein sequence that AlphaFold thinks folds into a well structured protein (high plddt, low pae, many contacts).\n",
156
+ "LENGTH = 100 #@param {type:\"integer\"}\n",
157
+ "#@markdown With copies you can specify the number of identical sequences design, resulting in homo oligomers. Copies = 1 is the standard, resulting in a monomer\n",
158
+ "\n",
159
+ "COPIES = 1 #@param [\"1\", \"2\", \"3\", \"4\", \"5\", \"6\", \"7\", \"8\"] {type:\"raw\"}\n",
160
+ "MODE = \"manuscript\"\n",
161
+ "\n",
162
+ "#@markdown Select the losses you want to use. For unconditional generation as reported in the manuscript use all the losses. To increase the diversity of designes remove confidence losses and/or increase the weight of the helix loss.\n",
163
+ "\n",
164
+ "use_rg_loss = True #@param {type:\"boolean\"}\n",
165
+ "#@markdown A too strong rg loss can lead to problems and clashes. Use 0.1 for backbones smaller then 600 AA and 0.01 for larger proteins (0.001 for 1000 AA).\n",
166
+ "rg_weight = 0.1 #@param {type:\"raw\"}\n",
167
+ "use_helix_loss = True #@param {type:\"boolean\"}\n",
168
+ "use_con_loss = True #@param {type:\"boolean\"}\n",
169
+ "use_confidence_loss = True #@param {type:\"boolean\"}\n",
170
+ "#@markdown How many halluicnation iteration you want to perform. The standard in the manuscript is 100.\n",
171
+ "\n",
172
+ "iters = 50 #@param [\"100\", \"50\", \"30\"] {type:\"raw\"}\n",
173
+ "\n",
174
+ "\n",
175
+ "#@markdown Select if you want to use the 'standard\" ProteinMPNN weights or the soluble ones. The soluble ones usually result in higher in silico as well as experimental sucess, but will increase the negative net charge of the protein which sould potentially interfer with certain protein design problems. The manuscript settings are soluble MPNN\n",
176
+ "\n",
177
+ "use_solubleMPNN = True #@param {type:\"boolean\"}\n",
178
+ "#@markdown Select this to use an experimental ProteinMPNN loss, also backpropagating through ProteinMPNN. This was not used in the manuscript\n",
179
+ "\n",
180
+ "use_mpnn_loss = False #@param {type:\"boolean\"}\n",
181
+ "#@markdown\n",
182
+ "\n",
183
+ "def add_rg_loss(self, weight=0.1):\n",
184
+ " '''add radius of gyration loss'''\n",
185
+ " def loss_fn(inputs, outputs):\n",
186
+ " xyz = outputs[\"structure_module\"]\n",
187
+ " ca = xyz[\"final_atom_positions\"][:,residue_constants.atom_order[\"CA\"]]\n",
188
+ " if self.protocol == \"binder\":\n",
189
+ " ca = ca[-self._binder_len:]\n",
190
+ " #This uses a scaled version of the rg loss, only looking at every 5th residue\n",
191
+ " if MODE == \"manuscript\":\n",
192
+ " ca = ca[::5]\n",
193
+ " rg = jnp.sqrt(jnp.square(ca - ca.mean(0)).sum(-1).mean() + 1e-8)\n",
194
+ "\n",
195
+ " if MODE == \"original\":\n",
196
+ " rg_th = 2.38 * ca.shape[0] ** 0.365\n",
197
+ " rg = jax.nn.elu(rg - rg_th)\n",
198
+ " return {\"rg\":rg}\n",
199
+ " self._callbacks[\"model\"][\"loss\"].append(loss_fn)\n",
200
+ " self.opt[\"weights\"][\"rg\"] = weight\n",
201
+ "\n",
202
+ "def add_mpnn_loss(self, mpnn=0.1, mpnn_seq=0.0):\n",
203
+ " '''\n",
204
+ " add mpnn loss\n",
205
+ " mpnn = maximize confidence of proteinmpnn\n",
206
+ " mpnn_seq = push designed sequence to match proteinmpnn logits\n",
207
+ " '''\n",
208
+ "\n",
209
+ " self._mpnn = mk_mpnn_model(weights = \"soluble\" if use_solubleMPNN else \"original\")\n",
210
+ " def loss_fn(inputs, outputs, aux, key):\n",
211
+ "\n",
212
+ " # get structure\n",
213
+ " atom_idx = tuple(residue_constants.atom_order[k] for k in [\"N\",\"CA\",\"C\",\"O\"])\n",
214
+ " I = {\"S\": inputs[\"aatype\"],\n",
215
+ " \"residue_idx\": inputs[\"residue_index\"],\n",
216
+ " \"chain_idx\": inputs[\"asym_id\"],\n",
217
+ " \"X\": outputs[\"structure_module\"][\"final_atom_positions\"][:,atom_idx],\n",
218
+ " \"mask\": outputs[\"structure_module\"][\"final_atom_mask\"][:,1],\n",
219
+ " \"lengths\": self._lengths,\n",
220
+ " \"key\": key}\n",
221
+ "\n",
222
+ " if \"offset\" in inputs:\n",
223
+ " I[\"offset\"] = inputs[\"offset\"]\n",
224
+ "\n",
225
+ " # set autoregressive mask\n",
226
+ " L = sum(self._lengths)\n",
227
+ " if self.protocol == \"binder\":\n",
228
+ " I[\"ar_mask\"] = 1 - np.eye(L)\n",
229
+ " I[\"ar_mask\"][-self._len:,-self._len:] = 0\n",
230
+ " else:\n",
231
+ " I[\"ar_mask\"] = np.zeros((L,L))\n",
232
+ "\n",
233
+ " # get logits\n",
234
+ " logits = self._mpnn._score(**I)[\"logits\"][:,:20]\n",
235
+ " if self.protocol == \"binder\":\n",
236
+ " logits = logits[-self._len:]\n",
237
+ " else:\n",
238
+ " logits = logits[:self._len]\n",
239
+ " aux[\"mpnn_logits\"] = logits\n",
240
+ "\n",
241
+ " # compute loss\n",
242
+ " log_q = jax.nn.log_softmax(logits)\n",
243
+ " p = inputs[\"seq\"][\"hard\"]\n",
244
+ " q = jax.nn.softmax(logits)\n",
245
+ " losses = {}\n",
246
+ " losses[\"mpnn\"] = -log_q.max(-1).mean()\n",
247
+ " losses[\"mpnn_seq\"] = -(p * jax.lax.stop_gradient(log_q)).sum(-1).mean()\n",
248
+ " return losses\n",
249
+ "\n",
250
+ " self._callbacks[\"model\"][\"loss\"].append(loss_fn)\n",
251
+ " self.opt[\"weights\"][\"mpnn\"] = mpnn\n",
252
+ " self.opt[\"weights\"][\"mpnn_seq\"] = mpnn_seq\n",
253
+ "\n",
254
+ "clear_mem()\n",
255
+ "af_model = mk_afdesign_model(protocol=\"hallucination\")\n",
256
+ "af_model.prep_inputs(length=LENGTH, copies=COPIES)\n",
257
+ "\n",
258
+ "# add extra losses\n",
259
+ "\n",
260
+ "if use_mpnn_loss: add_mpnn_loss(af_model)\n",
261
+ "\n",
262
+ "print(\"length\",af_model._lengths)\n",
263
+ "print(\"weights\",af_model.opt[\"weights\"])"
264
+ ]
265
+ },
266
+ {
267
+ "cell_type": "code",
268
+ "source": [
269
+ "#This cell runs the design loop. Run this in a for loop for design of multiple proteins\n",
270
+ "\n",
271
+ "af_model.restart()\n",
272
+ "af_model.set_seq(mode=[\"gumbel\",\"soft\"])\n",
273
+ "if use_rg_loss: add_rg_loss(af_model,rg_weight)\n",
274
+ "if use_helix_loss : af_model.set_weights(helix=-0.2)\n",
275
+ "if use_con_loss : af_model.set_weights(con=1.0)\n",
276
+ "if use_confidence_loss : af_model.set_weights(plddt=0.5, pae=0.5)\n",
277
+ "print(\"weights\",af_model.opt[\"weights\"])\n",
278
+ "af_model.design_logits(iters-10)\n",
279
+ "af_model.design_logits(10, save_best=True)"
280
+ ],
281
+ "metadata": {
282
+ "id": "f76xqCkw0vj9"
283
+ },
284
+ "execution_count": null,
285
+ "outputs": []
286
+ },
287
+ {
288
+ "cell_type": "code",
289
+ "execution_count": null,
290
+ "metadata": {
291
+ "id": "A1GxeLZdTTya"
292
+ },
293
+ "outputs": [],
294
+ "source": [
295
+ "#This cell plots and saves the results as a pdb file\n",
296
+ "af_model.save_pdb(f\"{af_model.protocol}.pdb\")\n",
297
+ "af_model.plot_pdb()"
298
+ ]
299
+ },
300
+ {
301
+ "cell_type": "code",
302
+ "execution_count": null,
303
+ "metadata": {
304
+ "id": "L2E9Tn2Acchj"
305
+ },
306
+ "outputs": [],
307
+ "source": [
308
+ "HTML(af_model.animate())"
309
+ ]
310
+ },
311
+ {
312
+ "cell_type": "code",
313
+ "execution_count": null,
314
+ "metadata": {
315
+ "id": "YSKWYu0_GlUH"
316
+ },
317
+ "outputs": [],
318
+ "source": [
319
+ "af_model.get_seqs()"
320
+ ]
321
+ },
322
+ {
323
+ "cell_type": "code",
324
+ "source": [
325
+ "import pandas as pd\n",
326
+ "#@title # Designability test\n",
327
+ "#@markdown Test the designability of the backbone, taking in the backbone, generating sequences with solubleMPNN and predicting the sequence with AF2 in single sequence mode.\n",
328
+ "#@markdown Use Initial Guess (IG) and All Atom Initialisation (AA) for larger proteins\n",
329
+ "\n",
330
+ "AA = False #@param {type:\"boolean\"}\n",
331
+ "IG = False #@param {type:\"boolean\"}\n",
332
+ "#@markdown NOTE: we remove cysteines from all designed proteins. Additionally for large proteins we also exclude methions to reduce the number of internal start codons\n",
333
+ "\n",
334
+ "def designability_test(af_model_test, mpnn_model_test,\n",
335
+ " num_seqs=8, sampling_temp=0.1, num_recycles=3,\n",
336
+ " model_num=4, best_metric=\"rmsd\",\n",
337
+ " in_pdb=\"init.pdb\", out_pdb=\"final.pdb\",\n",
338
+ " verbose=False):\n",
339
+ " alphafold_model = f\"model_{model_num}_ptm\"\n",
340
+ "\n",
341
+ " af_model_test.prep_inputs(in_pdb)\n",
342
+ " af_model_test.restart(rm_aa=\"C,M\")\n",
343
+ " af_model_test._args[\"best_metric\"] = best_metric\n",
344
+ " L = sum(af_model_test._lengths)\n",
345
+ " mpnn_model_test.get_af_inputs(af_model_test)\n",
346
+ " out = mpnn_model_test.sample(num=num_seqs // 8, batch=8,\n",
347
+ " temperature=sampling_temp)\n",
348
+ "\n",
349
+ " af_terms = [\"plddt\", \"ptm\", \"pae\", \"rmsd\", \"dgram_cce\"]\n",
350
+ " for k in af_terms: out[k] = []\n",
351
+ "\n",
352
+ " for n in range(num_seqs):\n",
353
+ " seq = out[\"seq\"][n]\n",
354
+ " af_model_test.predict(seq=seq,\n",
355
+ " num_recycles=num_recycles,\n",
356
+ " num_models=1,\n",
357
+ " verbose=False,\n",
358
+ " models=alphafold_model)\n",
359
+ "\n",
360
+ " for k in af_terms: out[k].append(af_model_test.aux[\"log\"][k])\n",
361
+ " out[\"pae\"][-1] = out[\"pae\"][-1] * 31\n",
362
+ " af_model_test._save_results(save_best=True, verbose=verbose)\n",
363
+ " af_model_test._k += 1\n",
364
+ "\n",
365
+ " af_model_test.save_pdb(out_pdb)\n",
366
+ " labels = [\"score\"] + af_terms + [\"seq\"]\n",
367
+ " data = [[out[k][n] for k in labels] for n in range(num_seqs)]\n",
368
+ " labels[0] = \"mpnn\"\n",
369
+ " df = pd.DataFrame(data, columns=labels)\n",
370
+ " return df\n",
371
+ "\n",
372
+ "af_model_test = mk_afdesign_model(protocol=\"fixbb\",best_metric=\"rmsd\",use_initial_guess=IG,use_initial_atom_pos=AA,use_templates=False)\n",
373
+ "mpnn_model_test = mk_mpnn_model(weights=\"soluble\")\n",
374
+ "\n",
375
+ "\n",
376
+ "lowest_rmsd = float('inf')\n",
377
+ "lowest_rmsd_data = None\n",
378
+ "\n",
379
+ "in_pdb = f\"{af_model.protocol}.pdb\"\n",
380
+ "out_pdb = f\"{af_model.protocol}_out.pdb\"\n",
381
+ "\n",
382
+ "\n",
383
+ "out = designability_test(af_model_test, mpnn_model_test,\n",
384
+ " num_seqs=8, sampling_temp=0.1, num_recycles=3,\n",
385
+ " model_num=4, best_metric=\"rmsd\",\n",
386
+ " in_pdb=in_pdb, out_pdb=out_pdb,\n",
387
+ " verbose=True)\n",
388
+ "\n"
389
+ ],
390
+ "metadata": {
391
+ "cellView": "form",
392
+ "id": "Y_-8_Ya4Q8oo"
393
+ },
394
+ "execution_count": null,
395
+ "outputs": []
396
+ },
397
+ {
398
+ "cell_type": "code",
399
+ "source": [
400
+ "from colabdesign import mk_afdesign_model, clear_mem\n",
401
+ "from colabdesign.af.alphafold.common import residue_constants\n",
402
+ "import jax\n",
403
+ "import jax.numpy as jnp\n",
404
+ "#@title # OPTIONAL Unconditional Generation (Manuscript Code)\n",
405
+ "\n",
406
+ "#@markdown This code generates a sample of 10 unconditional proteins for lengths between 100 and 800 AA exactly as in the manuscript. For larger proteins CUDA_UNIFIED_MEMORY is needed. This can be done by localy running the code on a CUDA capeable GPU with sufficient memory (A100 80GB e.g.) and running the code with the environment variables XLA_PYTHON_CLIENT_MEM_FRACTION=100.0 TF_FORCE_UNIFIED_MEMORY=1\n",
407
+ "def rg_loss(inputs, outputs):\n",
408
+ " positions = outputs[\"structure_module\"][\"final_atom_positions\"]\n",
409
+ " ca = positions[::5,residue_constants.atom_order[\"CA\"]]\n",
410
+ " center = ca.mean(0)\n",
411
+ " rg = jnp.sqrt(jnp.square(ca - center).sum(-1).mean() + 1e-8)\n",
412
+ " rg_th = 2.38 * ca.shape[0] ** 0.365\n",
413
+ " rg = jax.nn.elu(rg - rg_th)\n",
414
+ " return {\"rg\":rg}\n",
415
+ "\n",
416
+ "\n",
417
+ "\n",
418
+ "\n",
419
+ "for length in [100,200,300,400,500,600,700,800]:\n",
420
+ " model = mk_afdesign_model(protocol=\"hallucination\",loss_callback=rg_loss)\n",
421
+ " model.prep_inputs(length=length)\n",
422
+ " print(\"weights\",model.opt[\"weights\"])\n",
423
+ " print('Starting up and compiling JAX model....')\n",
424
+ "\n",
425
+ " for i in range(10):\n",
426
+ " model.restart(mode=[\"gumbel\", \"soft\"],rm_aa=\"C\")\n",
427
+ " model.opt[\"weights\"][\"rg\"] = 0.1\n",
428
+ " if length > 600:\n",
429
+ " model.opt[\"weights\"][\"rg\"] = 0.01\n",
430
+ " #model.opt[\"weights\"]['helix'] = -0.1\n",
431
+ " model.opt[\"weights\"]['plddt'] = 1.0\n",
432
+ " model.opt[\"weights\"]['pae'] = 1.0\n",
433
+ " model.opt[\"weights\"]['helix'] = -0.1\n",
434
+ " print(\"weights\", model.opt[\"weights\"])\n",
435
+ " model.design_logits(100)\n",
436
+ "\n",
437
+ " #change the output path for local execution\n",
438
+ " model.save_pdb(f\"Hallo_{i}.pdb\")"
439
+ ],
440
+ "metadata": {
441
+ "cellView": "form",
442
+ "id": "gPby7oP25b5i"
443
+ },
444
+ "execution_count": null,
445
+ "outputs": []
446
+ },
447
+ {
448
+ "cell_type": "code",
449
+ "source": [
450
+ "#@markdown #Redesign with ProteinMPNN for ESMFold prediction\n",
451
+ "#@markdown The standard manuscript settings were 8 sequences, 0.1 sampling temperature and the removal of cysteines\n",
452
+ "import pickle\n",
453
+ "num_seqs = 8 #@param [\"8\", \"16\", \"32\", \"64\"] {type:\"raw\"}\n",
454
+ "mpnn_sampling_temp = 0.1 #@param [\"0.0001\", \"0.1\", \"0.15\", \"0.2\", \"0.25\", \"0.3\", \"0.5\", \"1.0\"] {type:\"raw\"}\n",
455
+ "rm_aa = \"C\" #@param {type:\"string\"}\n",
456
+ "use_solubleMPNN = False #@param {type:\"boolean\"}\n",
457
+ "#@markdown - `mpnn_sampling_temp` - control diversity of sampled sequences. (higher = more diverse).\n",
458
+ "#@markdown - `rm_aa='C'` - do not use [C]ysteines.\n",
459
+ "#@markdown - `use_solubleMPNN` - use weights trained only on soluble proteins.\n",
460
+ "#@markdown\n",
461
+ "\n",
462
+ "from colabdesign.shared.protein import alphabet_list as chain_list\n",
463
+ "mpnn_model = mk_mpnn_model()\n",
464
+ "mpnn_model.prep_inputs(pdb_filename=f\"{af_model.protocol}.pdb\",\n",
465
+ " chain=\",\".join(chain_list[:COPIES]),\n",
466
+ " homooligmer=COPIES>1,\n",
467
+ " rm_aa=rm_aa,\n",
468
+ " weights = \"soluble\" if use_solubleMPNN else\"original\")\n",
469
+ "out = mpnn_model.sample(num=num_seqs//8,\n",
470
+ " batch=8,\n",
471
+ " temperature=mpnn_sampling_temp)\n",
472
+ "for seq,score in zip(out[\"seq\"],out[\"score\"]):\n",
473
+ " print(score,seq.split(\"/\")[0])\n",
474
+ "df = pd.DataFrame(out[\"seq\"])\n",
475
+ "\n",
476
+ "# Define the output path for saving the sequences as a .pkl file\n",
477
+ "output_pkl_file = \"redesigned_sequences.pkl\"\n",
478
+ "\n",
479
+ "# Save the DataFrame to a .pkl file\n",
480
+ "with open(output_pkl_file, 'wb') as f:\n",
481
+ " pickle.dump(df, f)"
482
+ ],
483
+ "metadata": {
484
+ "id": "m2qAYsDsCfqJ",
485
+ "cellView": "form"
486
+ },
487
+ "execution_count": null,
488
+ "outputs": []
489
+ },
490
+ {
491
+ "cell_type": "code",
492
+ "source": [
493
+ "#@markdown #Run ESMFold to test designability\n",
494
+ "#@markdown This cells runs ESMFold from huggingface and automatically calculates the RMSD to the designed backbone\n",
495
+ "#@markdown NOTE: GPU memory can be a big problem here. If you get memory errors please restart the runtime and run this cell again. It should be self contained. Additionally, after finish the ESMFold prediction rerun the setup cell\n",
496
+ "\n",
497
+ "import os\n",
498
+ "import pandas as pd\n",
499
+ "from Bio.PDB import PDBParser, Superimposer\n",
500
+ "import pickle\n",
501
+ "import torch\n",
502
+ "import numpy as np\n",
503
+ "from transformers import AutoTokenizer, EsmForProteinFolding\n",
504
+ "from transformers.models.esm.openfold_utils.protein import to_pdb, Protein as OFProtein\n",
505
+ "from transformers.models.esm.openfold_utils.feats import atom14_to_atom37\n",
506
+ "output_pkl_file = \"redesigned_sequences.pkl\"\n",
507
+ "\n",
508
+ "with open(output_pkl_file, 'rb') as f:\n",
509
+ " seq = pickle.load(f)\n",
510
+ "seq_list = []\n",
511
+ "for i in np.asarray(seq):\n",
512
+ " seq_list.append(i[0])\n",
513
+ "\n",
514
+ "pdb_file = \"hallucination.pdb\"\n",
515
+ "print(seq_list)\n",
516
+ "\n",
517
+ "\n",
518
+ "tokenizer = AutoTokenizer.from_pretrained(\"facebook/esmfold_v1\")\n",
519
+ "model = EsmForProteinFolding.from_pretrained(\"facebook/esmfold_v1\", low_cpu_mem_usage=True)\n",
520
+ "\n",
521
+ "device = 'cuda:0'\n",
522
+ "model = model.cuda(device)\n",
523
+ "model.esm = model.esm.half()\n",
524
+ "model.trunk.set_chunk_size(64)\n",
525
+ "torch.backends.cuda.matmul.allow_tf32 = True\n",
526
+ "\n",
527
+ "def convert_outputs_to_pdb(outputs):\n",
528
+ " final_atom_positions = atom14_to_atom37(outputs[\"positions\"][-1], outputs)\n",
529
+ " outputs = {k: v.to(\"cpu\").numpy() for k, v in outputs.items()}\n",
530
+ " final_atom_positions = final_atom_positions.cpu().numpy()\n",
531
+ " final_atom_mask = outputs[\"atom37_atom_exists\"]\n",
532
+ " pdbs = []\n",
533
+ " for i in range(outputs[\"aatype\"].shape[0]):\n",
534
+ " aa = outputs[\"aatype\"][i]\n",
535
+ " pred_pos = final_atom_positions[i]\n",
536
+ " mask = final_atom_mask[i]\n",
537
+ " resid = outputs[\"residue_index\"][i] + 1\n",
538
+ " pred = OFProtein(\n",
539
+ " aatype=aa,\n",
540
+ " atom_positions=pred_pos,\n",
541
+ " atom_mask=mask,\n",
542
+ " residue_index=resid,\n",
543
+ " b_factors=outputs[\"plddt\"][i],\n",
544
+ " chain_index=outputs[\"chain_index\"][i] if \"chain_index\" in outputs else None,\n",
545
+ " )\n",
546
+ " pdbs.append(to_pdb(pred))\n",
547
+ " return pdbs\n",
548
+ "\n",
549
+ "def calculate_ca_rmsd(pdb_file1, pdb_file2):\n",
550
+ " parser = PDBParser(QUIET=True)\n",
551
+ "\n",
552
+ " structure1 = parser.get_structure(\"Protein1\", pdb_file1)\n",
553
+ " structure2 = parser.get_structure(\"Protein2\", pdb_file2)\n",
554
+ "\n",
555
+ " ca_atoms1 = [atom for atom in structure1.get_atoms() if atom.get_name() == \"CA\"]\n",
556
+ " ca_atoms2 = [atom for atom in structure2.get_atoms() if atom.get_name() == \"CA\"]\n",
557
+ "\n",
558
+ " super_imposer = Superimposer()\n",
559
+ " super_imposer.set_atoms(ca_atoms1, ca_atoms2)\n",
560
+ " super_imposer.apply(structure2.get_atoms())\n",
561
+ " rmsd = super_imposer.rms\n",
562
+ " return rmsd\n",
563
+ "\n",
564
+ "def process_sequences(seq_list, pdb_file):\n",
565
+ " lowest_rmsd = float('inf')\n",
566
+ " lowest_rmsd_data = None\n",
567
+ " out_ss_path = \"./output\"\n",
568
+ "\n",
569
+ " if not os.path.exists(out_ss_path):\n",
570
+ " os.mkdir(out_ss_path)\n",
571
+ "\n",
572
+ " for test_protein in seq_list:\n",
573
+ " data = {}\n",
574
+ " tokenized_input = tokenizer([test_protein], return_tensors=\"pt\", add_special_tokens=False)['input_ids']\n",
575
+ " tokenized_input = tokenized_input.cuda(device)\n",
576
+ "\n",
577
+ " with torch.no_grad():\n",
578
+ " output = model(tokenized_input)\n",
579
+ "\n",
580
+ " data['out'] = output\n",
581
+ " data[\"plddt\"] = torch.mean(output['plddt']).item()\n",
582
+ " data['pae'] = torch.mean(output['predicted_aligned_error']).item()\n",
583
+ "\n",
584
+ " pdb_data = convert_outputs_to_pdb(output)\n",
585
+ " tmp_pdb_file = os.path.join(out_ss_path, \"TMP.pdb\")\n",
586
+ "\n",
587
+ " with open(tmp_pdb_file, 'w') as file:\n",
588
+ " for line in pdb_data:\n",
589
+ " file.write(line)\n",
590
+ "\n",
591
+ " data['rmsd'] = calculate_ca_rmsd(tmp_pdb_file, pdb_file)\n",
592
+ " print(f'Sequence: {test_protein}, plddt: {data[\"plddt\"]}, PAE: {data[\"pae\"]}, RMSD: {data[\"rmsd\"]}')\n",
593
+ "\n",
594
+ " if data['rmsd'] < lowest_rmsd:\n",
595
+ " lowest_rmsd = data['rmsd']\n",
596
+ " lowest_rmsd_data = data\n",
597
+ "\n",
598
+ " if lowest_rmsd_data is not None:\n",
599
+ " print(f'Lowest RMSD: {lowest_rmsd}')\n",
600
+ " best_pdb_data = convert_outputs_to_pdb(lowest_rmsd_data['out'])\n",
601
+ " best_pdb_file = os.path.join(out_ss_path, \"best_structure.pdb\")\n",
602
+ "\n",
603
+ " with open(best_pdb_file, 'w') as file:\n",
604
+ " for line in best_pdb_data:\n",
605
+ " file.write(line)\n",
606
+ "\n",
607
+ " original_dict = lowest_rmsd_data\n",
608
+ " key_to_exclude = 'out'\n",
609
+ " data_out = {k: v for k, v in original_dict.items() if k != key_to_exclude}\n",
610
+ "\n",
611
+ " with open(os.path.join(out_ss_path, \"best_structure_data.pkl\"), 'wb') as f:\n",
612
+ " pickle.dump(data_out, f)\n",
613
+ "\n",
614
+ " return lowest_rmsd, best_pdb_file, data_out\n",
615
+ "\n",
616
+ " return None, None, None\n",
617
+ "\n",
618
+ "\n",
619
+ "\n",
620
+ "lowest_rmsd, best_pdb_file, best_data = process_sequences(seq_list, pdb_file)\n",
621
+ "if lowest_rmsd is not None:\n",
622
+ " print(f\"Lowest RMSD: {lowest_rmsd}, Best PDB file: {best_pdb_file}\")\n",
623
+ "else:\n",
624
+ " print(\"No valid result found.\")\n"
625
+ ],
626
+ "metadata": {
627
+ "id": "Ey29NmNAFtK0",
628
+ "cellView": "form"
629
+ },
630
+ "execution_count": null,
631
+ "outputs": []
632
+ },
633
+ {
634
+ "cell_type": "code",
635
+ "source": [
636
+ "#@title # Heterodimer Design Prep\n",
637
+ "#@markdown Design a set of heterodimeric proteins with two chains making a complex. The settings are excatly the ones used in the manuscript to design the heterodimer binders.\n",
638
+ "LENGTH1 = 100 #@param {type:\"integer\"}\n",
639
+ "LENGTH2 = 100 #@param {type:\"integer\"}\n",
640
+ "\n",
641
+ "#@markdown ProteinMPNN Settings\n",
642
+ "use_solubleMPNN = True #@param {type:\"boolean\"}\n",
643
+ "#@markdown\n",
644
+ "\n",
645
+ "\n",
646
+ "from colabdesign.af.alphafold.common import residue_constants\n",
647
+ "import jax\n",
648
+ "import jax.numpy as jnp\n",
649
+ "\n",
650
+ "def hd_loss(inputs, outputs):\n",
651
+ " positions = outputs[\"structure_module\"][\"final_atom_positions\"]\n",
652
+ " ca1 = positions[:LENGTH1, residue_constants.atom_order[\"CA\"]]\n",
653
+ " center1 = ca1.mean(0)\n",
654
+ " rg1 = jnp.sqrt(jnp.square(ca1 - center1).sum(-1).mean() + 1e-8)\n",
655
+ " rg_th = 2.38 * ca1.shape[0] ** 0.365\n",
656
+ " rg1 = jax.nn.elu(rg1 - rg_th)\n",
657
+ "\n",
658
+ "\n",
659
+ " ca2 = positions[LENGTH2:, residue_constants.atom_order[\"CA\"]]\n",
660
+ " center2 = ca2.mean(0)\n",
661
+ " rg2 = jnp.sqrt(jnp.square(ca2 - center2).sum(-1).mean() + 1e-8)\n",
662
+ " rg_th = 2.38 * ca2.shape[0] ** 0.365\n",
663
+ " rg2 = jax.nn.elu(rg2 - rg_th)\n",
664
+ "\n",
665
+ "\n",
666
+ "\n",
667
+ " return {\"hd\":rg1+rg2}\n",
668
+ "\n",
669
+ "total_length = LENGTH1 + LENGTH2\n",
670
+ "clear_mem()\n",
671
+ "af_model = mk_afdesign_model(protocol=\"hallucination\", loss_callback=hd_loss)\n",
672
+ "af_model.prep_inputs(length=total_length)\n",
673
+ "af_model._inputs['residue_index'][LENGTH1:] = np.arange(LENGTH2) + 50 + LENGTH1\n",
674
+ "# add extra losses\n",
675
+ "af_model.restart(mode=[\"gumbel\", \"soft\"])\n",
676
+ "af_model.opt[\"weights\"][\"hd\"] = 0.1\n",
677
+ "af_model.opt[\"weights\"]['plddt'] = 1.0\n",
678
+ "af_model.opt[\"weights\"]['pae'] = 1.0\n",
679
+ "af_model.opt[\"weights\"]['helix'] = -0.5\n",
680
+ "print(\"weights\", af_model.opt[\"weights\"])\n",
681
+ "print('Starting up and compiling JAX model....')\n"
682
+ ],
683
+ "metadata": {
684
+ "id": "88HCs0ID6CGc",
685
+ "cellView": "form"
686
+ },
687
+ "execution_count": null,
688
+ "outputs": []
689
+ },
690
+ {
691
+ "cell_type": "code",
692
+ "source": [
693
+ "#@title # Run Design\n",
694
+ "af_model.design_logits(100)\n",
695
+ "af_model.save_pdb(\"Heterodimer.pdb\")"
696
+ ],
697
+ "metadata": {
698
+ "id": "5KVtj6LM7RQ4"
699
+ },
700
+ "execution_count": null,
701
+ "outputs": []
702
+ },
703
+ {
704
+ "cell_type": "code",
705
+ "source": [
706
+ "af_model.save_pdb(\"Heterodimer.pdb\")\n",
707
+ "af_model.plot_pdb()"
708
+ ],
709
+ "metadata": {
710
+ "id": "qfOEMo4qpWfm"
711
+ },
712
+ "execution_count": null,
713
+ "outputs": []
714
+ },
715
+ {
716
+ "cell_type": "code",
717
+ "source": [
718
+ "#@title # Design Sequence using Homooligomer Filter\n",
719
+ "#@markdown We first test if the two protomers are predictd to fold into a high confidence protein on their own, removing proteins that are not likely to be expressed on their own. Then we predict the heterodimer using the AF multimer model. Generally the AF multimer model has a hard time predicting de novo designed proteins. This is why we use templates and remove any interchain information. Finally we predict each individual protomer with a copy of itself, testing for homooligomerisation.\n",
720
+ "\n",
721
+ "\n",
722
+ "file_path =\"Heterodimer.pdb\"\n",
723
+ "\n",
724
+ "folder_path = \"/content/\"\n",
725
+ "\n",
726
+ "######## make A - B chain file\n",
727
+ "\n",
728
+ "from Bio.PDB import PDBParser, PDBIO, Chain\n",
729
+ "\n",
730
+ "# Set the input and output PDB file names\n",
731
+ "input_pdb_file = file_path\n",
732
+ "if not os.path.exists(os.path.join(folder_path, 'AB')):\n",
733
+ " os.mkdir(os.path.join(folder_path, 'AB'))\n",
734
+ "output_pdb_file = os.path.join(folder_path, 'AB',\"Heterodimer.pdb\")\n",
735
+ "\n",
736
+ "# Create a PDB parser and read the input PDB file\n",
737
+ "parser = PDBParser()\n",
738
+ "structure = parser.get_structure(\"input_structure\", input_pdb_file)\n",
739
+ "\n",
740
+ "# Find the initial chain id\n",
741
+ "initial_chain_id = None\n",
742
+ "for chain in structure[0]:\n",
743
+ " initial_chain_id = chain.get_id()\n",
744
+ " break\n",
745
+ "\n",
746
+ "# Create new chains A and B\n",
747
+ "chain_A = Chain.Chain(\"A\")\n",
748
+ "chain_B = Chain.Chain(\"B\")\n",
749
+ "\n",
750
+ "# Iterate over the residues in the original chain\n",
751
+ "for residue in structure[0][initial_chain_id]:\n",
752
+ " res_id = residue.get_id()[1]\n",
753
+ "\n",
754
+ " # Add residues 1-200 to chain A\n",
755
+ " if 1 <= res_id <= 100:\n",
756
+ " chain_A.add(residue.copy())\n",
757
+ "\n",
758
+ " # Add residues 201-400 to chain B\n",
759
+ " elif 151 <= res_id <= 450:\n",
760
+ " chain_B.add(residue.copy())\n",
761
+ "\n",
762
+ "# Remove the existing chain\n",
763
+ "for model in structure:\n",
764
+ " model.detach_child(initial_chain_id)\n",
765
+ "\n",
766
+ "# Add the new chains to the model\n",
767
+ "structure[0].add(chain_A)\n",
768
+ "structure[0].add(chain_B)\n",
769
+ "\n",
770
+ "# Save the modified structure to a new PDB file\n",
771
+ "io = PDBIO()\n",
772
+ "io.set_structure(structure)\n",
773
+ "io.save(output_pdb_file)\n",
774
+ "\n",
775
+ "\n",
776
+ "clear_mem()\n",
777
+ "he_model = mk_afdesign_model(protocol=\"fixbb\", use_templates=True, use_multimer=True)\n",
778
+ "\n",
779
+ "\n",
780
+ "ho_model = mk_afdesign_model(protocol=\"hallucination\")\n",
781
+ "ho_model.prep_inputs(length=LENGTH1, copies=2)\n",
782
+ "\n",
783
+ "ho_model.set_weights(i_pae=1.0)\n",
784
+ "s_model = mk_afdesign_model(protocol=\"hallucination\")\n",
785
+ "s_model.prep_inputs(length=LENGTH2)\n",
786
+ "mpnn_model = mk_mpnn_model(weights=\"soluble\")\n",
787
+ "\n",
788
+ "\n",
789
+ "mpnn_model.prep_inputs(pdb_filename=output_pdb_file, chain='A,B',rm_aa=\"C\")\n",
790
+ "samples = mpnn_model.sample_parallel(8)\n",
791
+ "\n",
792
+ "he_model.prep_inputs(pdb_filename=output_pdb_file, chain='A,B',rm_template_ic=True)\n",
793
+ "he_model._inputs['residue_index'][LENGTH1:] = np.arange(LENGTH2) + 50 + LENGTH1\n",
794
+ "\n",
795
+ "k = 0\n",
796
+ "for seq in samples['seq']:\n",
797
+ " print('Predicting Protomer 1...')\n",
798
+ " s_model.predict(seq=seq[:LENGTH1], num_recycles=3)\n",
799
+ " plddt1 = s_model.aux['losses']['plddt']\n",
800
+ " print('Predicting Protomer 2...')\n",
801
+ " s_model.predict(seq=seq[LENGTH1+1:], num_recycles=3)\n",
802
+ " plddt2 = s_model.aux['losses']['plddt']\n",
803
+ " k = k + 1\n",
804
+ " if plddt1 < 0.20 and plddt2 < 0.20:\n",
805
+ " print('Passed Protomer Check! Predicting Heterodimer...')\n",
806
+ " he_model.predict(seq=''.join([seq[:LENGTH1], seq[LENGTH1+1:]]), num_recycles=3)\n",
807
+ "\n",
808
+ " if he_model.aux['losses']['plddt'] < 0.15 and he_model.aux['losses']['rmsd'] < 2.0:\n",
809
+ " print('Passed Heterodimer Check! Predicting Homodimer 1...')\n",
810
+ " ho_model.predict(seq=seq[:LENGTH1],num_recycles=3)\n",
811
+ " print('Predicting Homodimer 2...')\n",
812
+ " ipae1 = ho_model.aux['losses']['i_pae']\n",
813
+ " ho_model.predict(seq=seq[LENGTH1+1:],num_recycles=3)\n",
814
+ " ipae2 = ho_model.aux['losses']['i_pae']\n",
815
+ " if ipae1 > 0.8 and ipae2 > 0.8:\n",
816
+ " print('Passed Homodimer check!')\n",
817
+ " he_model.save_pdb(f'Heterodimer_seq_{k}.pdb')\n",
818
+ "\n"
819
+ ],
820
+ "metadata": {
821
+ "id": "mII01sjwhAqX",
822
+ "cellView": "form"
823
+ },
824
+ "execution_count": null,
825
+ "outputs": []
826
+ },
827
+ {
828
+ "cell_type": "code",
829
+ "source": [
830
+ "def get_pdb(pdb_code=\"\"):\n",
831
+ " if pdb_code is None or pdb_code == \"\":\n",
832
+ " upload_dict = files.upload()\n",
833
+ " pdb_string = upload_dict[list(upload_dict.keys())[0]]\n",
834
+ " with open(\"tmp.pdb\",\"wb\") as out: out.write(pdb_string)\n",
835
+ " return \"tmp.pdb\"\n",
836
+ " elif os.path.isfile(pdb_code):\n",
837
+ " return pdb_code\n",
838
+ " elif len(pdb_code) == 4:\n",
839
+ " os.system(f\"wget -qnc https://files.rcsb.org/view/{pdb_code}.pdb\")\n",
840
+ " return f\"{pdb_code}.pdb\"\n",
841
+ " else:\n",
842
+ " os.system(f\"wget -qnc https://alphafold.ebi.ac.uk/files/AF-{pdb_code}-F1-model_v3.pdb\")\n",
843
+ " return f\"AF-{pdb_code}-F1-model_v3.pdb\"\n",
844
+ "\n",
845
+ "def add_rg_loss(self, weight=0.1):\n",
846
+ " '''add radius of gyration loss'''\n",
847
+ " def loss_fn(inputs, outputs):\n",
848
+ " xyz = outputs[\"structure_module\"]\n",
849
+ " ca = xyz[\"final_atom_positions\"][:,residue_constants.atom_order[\"CA\"]]\n",
850
+ "\n",
851
+ " ca = ca[-self._binder_len:]\n",
852
+ "\n",
853
+ " rg = jnp.sqrt(jnp.square(ca - ca.mean(0)).sum(-1).mean() + 1e-8)\n",
854
+ " rg_th = 2.38 * ca.shape[0] ** 0.365\n",
855
+ " rg = jax.nn.elu(rg - rg_th)\n",
856
+ " return {\"rg\":rg}\n",
857
+ " self._callbacks[\"model\"][\"loss\"].append(loss_fn)\n",
858
+ " self.opt[\"weights\"][\"rg\"] = weight\n",
859
+ "\n",
860
+ "\n",
861
+ "\n",
862
+ "#@title # Binder Design\n",
863
+ "#@markdown For a given length, generate/hallucinate a protein sequence that AlphaFold thinks folds into a well structured protein (high plddt, low pae, many contacts).\n",
864
+ "LENGTH = 100 #@param {type:\"integer\"}\n",
865
+ "binder_pdb = '5NGV' #@param {type:\"string\"}\n",
866
+ "binder_chain ='A' #@param {type:\"string\"}\n",
867
+ "hotspot ='' #@param {type:\"string\"}\n",
868
+ "if hotspot == \"\": hotspot = None\n",
869
+ "#@markdown ProteinMPNN Settings\n",
870
+ "use_solubleMPNN = True #@param {type:\"boolean\"}\n",
871
+ "#@markdown\n",
872
+ "\n",
873
+ "clear_mem()\n",
874
+ "af_model = mk_afdesign_model(protocol=\"binder\")\n",
875
+ "add_rg_loss(af_model)\n",
876
+ "af_model.prep_inputs(pdb_filename=get_pdb(binder_pdb), chain=binder_chain,hotspot=hotspot, binder_len=LENGTH)\n",
877
+ "\n",
878
+ "\n",
879
+ "af_model.restart(mode=[\"gumbel\", \"soft\"])\n",
880
+ "\n",
881
+ "af_model.opt[\"weights\"][\"rg\"] = 0.5\n",
882
+ "\n",
883
+ "af_model.opt[\"weights\"]['helix'] = -0.2\n",
884
+ "af_model.opt[\"weights\"]['plddt'] = 0.1\n",
885
+ "af_model.opt[\"weights\"]['pae'] = 0.1\n",
886
+ "af_model.opt[\"weights\"]['i_pae'] = 0.1\n",
887
+ "af_model.opt[\"weights\"]['i_con'] = 2.0\n",
888
+ "\n",
889
+ "print(\"weights\", af_model.opt[\"weights\"])\n",
890
+ "print('Starting up and compiling JAX model....')\n"
891
+ ],
892
+ "metadata": {
893
+ "id": "H4WqduyJ785H",
894
+ "cellView": "form"
895
+ },
896
+ "execution_count": null,
897
+ "outputs": []
898
+ },
899
+ {
900
+ "cell_type": "code",
901
+ "source": [
902
+ "af_model.design_logits(100)\n",
903
+ "af_model.save_pdb(\"Binder.pdb\")"
904
+ ],
905
+ "metadata": {
906
+ "id": "bS83MeVd99FN"
907
+ },
908
+ "execution_count": null,
909
+ "outputs": []
910
+ },
911
+ {
912
+ "cell_type": "code",
913
+ "source": [
914
+ "af_model.plot_pdb()"
915
+ ],
916
+ "metadata": {
917
+ "id": "UQMYKLCNZK2L"
918
+ },
919
+ "execution_count": null,
920
+ "outputs": []
921
+ },
922
+ {
923
+ "cell_type": "code",
924
+ "source": [
925
+ "\n",
926
+ "#@title # Binder Sequence Design with AF Multimer filtering\n",
927
+ "#@markdown Use this to generate sequences for the binder candidate generated in the previous step\n",
928
+ "\n",
929
+ "#@markdown First we use the AF2 PTM model to predict the binder without receptor, acting as a fast pre filter. Then we use the AF Multimer model to predict the Receptor Binder complex. Again we use a template for the binder to help AF Multimer predicting the de novo designed protein\n",
930
+ "\n",
931
+ "binder_model = mk_afdesign_model(protocol=\"binder\",use_multimer=True,use_initial_guess=True)\n",
932
+ "hall_model = mk_afdesign_model(protocol=\"fixbb\")\n",
933
+ "\n",
934
+ "\n",
935
+ "binder_model.set_weights(i_pae=1.0)\n",
936
+ "\n",
937
+ "\n",
938
+ "mpnn_model = mk_mpnn_model(weights=\"soluble\")\n",
939
+ "mpnn_model.prep_inputs(pdb_filename=\"Binder.pdb\", chain='A,B', fix_pos='A',rm_aa=\"C\")\n",
940
+ "\n",
941
+ "samples = mpnn_model.sample_parallel(8,temperature=0.01)\n",
942
+ "hall_model.prep_inputs(pdb_filename=\"Binder.pdb\", chain='B')\n",
943
+ "binder_model.prep_inputs(pdb_filename=\"Binder.pdb\", chain='A', binder_chain='B',use_binder_template=True,rm_template_ic=True)\n",
944
+ "k=0\n",
945
+ "for seq in samples['seq']:\n",
946
+ " print(\"Predicting binder only\")\n",
947
+ " hall_model.predict(seq=seq[-LENGTH:], num_recycles=3)\n",
948
+ " if hall_model.aux['losses']['rmsd'] < 2.0 :\n",
949
+ " print(\"Passed! Predicting binder with receptor using AF Multimer\")\n",
950
+ " binder_model.predict(seq=seq[-LENGTH:], num_recycles=3)\n",
951
+ " plddt1 = binder_model.aux['losses']['plddt']\n",
952
+ " i_pae = binder_model.aux['losses']['i_pae']\n",
953
+ " if plddt1 < 0.15 and i_pae < 0.4:\n",
954
+ " print(f\"Passed! Final I_PAE is {i_pae*31}\")\n",
955
+ " binder_model.save_pdb(f'Binder_seq_{k}.pdb')\n",
956
+ " binder_model.plot_pdb()\n",
957
+ "\n",
958
+ " k = k + 1"
959
+ ],
960
+ "metadata": {
961
+ "id": "QfrRhvwTAyK-",
962
+ "cellView": "form"
963
+ },
964
+ "execution_count": null,
965
+ "outputs": []
966
+ },
967
+ {
968
+ "cell_type": "code",
969
+ "source": [
970
+ "#@title # Site scaffolding example\n",
971
+ "#@markdown This cell provides the code to perform the site scaffolding in bulk.\n",
972
+ "#@markdown Just go to the commented section with names, contigs and length to insert the desired PDB identifier, contigs and final size and start designing.\n",
973
+ "#@markdown Num_designs controls how many backbones one designes per PDB file\n",
974
+ "\n",
975
+ "num_designs = 1 #@param {type:\"integer\"}\n",
976
+ "\n",
977
+ "\n",
978
+ "def get_pdb(pdb_code=\"\"):\n",
979
+ " if pdb_code is None or pdb_code == \"\":\n",
980
+ " upload_dict = files.upload()\n",
981
+ " pdb_string = upload_dict[list(upload_dict.keys())[0]]\n",
982
+ " with open(\"tmp.pdb\",\"wb\") as out: out.write(pdb_string)\n",
983
+ " return \"tmp.pdb\"\n",
984
+ " elif os.path.isfile(pdb_code):\n",
985
+ " return pdb_code\n",
986
+ " elif len(pdb_code) == 4:\n",
987
+ " os.system(f\"wget -qnc https://files.rcsb.org/view/{pdb_code}.pdb\")\n",
988
+ " return f\"{pdb_code}.pdb\"\n",
989
+ " else:\n",
990
+ " os.system(f\"wget -qnc https://alphafold.ebi.ac.uk/files/AF-{pdb_code}-F1-model_v3.pdb\")\n",
991
+ " return f\"AF-{pdb_code}-F1-model_v3.pdb\"\n",
992
+ "\n",
993
+ "\n",
994
+ "\n",
995
+ "from colabdesign import mk_afdesign_model, clear_mem\n",
996
+ "import contextlib\n",
997
+ "\n",
998
+ "from colabdesign.af.alphafold.common import residue_constants\n",
999
+ "import jax\n",
1000
+ "import jax.numpy as jnp\n",
1001
+ "import pickle\n",
1002
+ "from colabdesign.mpnn import mk_mpnn_model\n",
1003
+ "\n",
1004
+ "import re\n",
1005
+ "import os\n",
1006
+ "\n",
1007
+ "\n",
1008
+ "#Add the names of the PDB files for the scaffolding problem here\n",
1009
+ "names = [\n",
1010
+ " \"1PRW\"\n",
1011
+ "]\n",
1012
+ "print(len(names))\n",
1013
+ "#Add the design contigs here\n",
1014
+ "\n",
1015
+ "inputs = [\n",
1016
+ " \"5-20,A16-35,10-25,A52-71,5-20\"\n",
1017
+ "]\n",
1018
+ "#Add the total length here. We only use the maximum length specified\n",
1019
+ "lengths = [\n",
1020
+ " \"60-105\"\n",
1021
+ "]\n",
1022
+ "\n",
1023
+ "\n",
1024
+ "def rg_loss(inputs, outputs):\n",
1025
+ " positions = outputs[\"structure_module\"][\"final_atom_positions\"]\n",
1026
+ " ca = positions[::5, residue_constants.atom_order[\"CA\"]]\n",
1027
+ " center = ca.mean(0)\n",
1028
+ " rg = jnp.sqrt(jnp.square(ca - center).sum(-1).mean() + 1e-8)\n",
1029
+ " rg_th = 2.38 * ca.shape[0] ** 0.365\n",
1030
+ " rg = jax.nn.elu(rg - rg_th)\n",
1031
+ " return {\"rg\": rg}\n",
1032
+ "\n",
1033
+ "\n",
1034
+ "clear_mem()\n",
1035
+ "\n",
1036
+ "for _name, _input, _length in zip(\n",
1037
+ " names, inputs, lengths\n",
1038
+ "):\n",
1039
+ " print(f\"Starting on {_name}\")\n",
1040
+ " _input = _input.replace(\" \", \"\")\n",
1041
+ " __name = _name.split(\"_\")[0]\n",
1042
+ " model = mk_afdesign_model(\n",
1043
+ " protocol=\"partial\"\n",
1044
+ " )\n",
1045
+ " wire_loop_repr = [\"l\" if re.search(\"[A-Z]\", x) else \"w\" for x in _input.split(\",\")]\n",
1046
+ "\n",
1047
+ " _lengths = []\n",
1048
+ " for _id, rep in zip(wire_loop_repr, _input.split(\",\")):\n",
1049
+ " if \"-\" in rep: # loop or range\n",
1050
+ " if _id == \"l\": # loop\n",
1051
+ " rep = rep[1:]\n",
1052
+ " _len = int(rep.split(\"-\")[1]) - int(rep.split(\"-\")[0]) + 1\n",
1053
+ " else: # range\n",
1054
+ " _len = int(rep.split(\"-\")[1])\n",
1055
+ " else:\n",
1056
+ " if _id == \"l\":\n",
1057
+ " rep = rep[1:]\n",
1058
+ " _len = int(1)\n",
1059
+ " _lengths.append(_len)\n",
1060
+ "\n",
1061
+ " overall_length = sum(_lengths)\n",
1062
+ " print(overall_length)\n",
1063
+ " old_pos = list(filter(lambda x: re.search(\"[A-Z]\", x), _input.split(\",\")))\n",
1064
+ " order = list(range(len(old_pos)))\n",
1065
+ " old_pos = \",\".join(old_pos)\n",
1066
+ " wires = list(filter(lambda x: not re.search(\"[A-Z]\", x), _input.split(\",\")))\n",
1067
+ " wires = [\n",
1068
+ " int(wire) if \"-\" not in wire else int(wire.split(\"-\")[1]) for wire in wires\n",
1069
+ " ]\n",
1070
+ " offset = wires[0] if not wire_loop_repr[0] == \"l\" else 0\n",
1071
+ " if wire_loop_repr[0] == \"w\":\n",
1072
+ " wires = wires[1:]\n",
1073
+ " if wire_loop_repr[-1] == \"w\":\n",
1074
+ " wires = wires[:-1]\n",
1075
+ "\n",
1076
+ " chain = re.findall(\"[A-Z]\", _input)\n",
1077
+ " chain = list(set(chain))\n",
1078
+ " assert len(chain) == 1\n",
1079
+ " chain = chain[0]\n",
1080
+ " if \"-\" in _length:\n",
1081
+ " _length = _length.split(\"-\")[1]\n",
1082
+ " _length = int(_length)\n",
1083
+ " if _length < overall_length:\n",
1084
+ " _length = overall_length\n",
1085
+ "\n",
1086
+ " debug = False\n",
1087
+ " if debug:\n",
1088
+ " print(\"chain \" + str(chain))\n",
1089
+ " print(\"old_pos \" + str(old_pos))\n",
1090
+ " print(\"wires \" + str(wires))\n",
1091
+ " print(\"offset \" + str(offset))\n",
1092
+ " print(\"_length \" + str(_length))\n",
1093
+ " print(\"order \" + str(order))\n",
1094
+ " print(_name)\n",
1095
+ " pdb_file = get_pdb(_name)\n",
1096
+ " model.prep_inputs(\n",
1097
+ " pdb_file,\n",
1098
+ " chain=chain,\n",
1099
+ " pos=old_pos,\n",
1100
+ " length=_length,\n",
1101
+ " fix_seq=True,\n",
1102
+ " )\n",
1103
+ "\n",
1104
+ "\n",
1105
+ " model.rewire(\n",
1106
+ " order=order, # set order of segments\n",
1107
+ " loops=wires, # change loop length inbetween segments\n",
1108
+ " offset=offset,\n",
1109
+ " ) # essentially loop length at the N term\n",
1110
+ "\n",
1111
+ " print(\" Starting up and compiling JAX model....\")\n",
1112
+ "\n",
1113
+ " for i in range(num_designs):\n",
1114
+ " print(f\" Iteration {i} of 100\")\n",
1115
+ " model.restart(mode=[\"gumbel\", \"soft\"], rm_aa=\"C\")\n",
1116
+ " model.opt[\"weights\"][\"rg\"] = 0.1\n",
1117
+ " model.opt[\"weights\"][\"dgram_cce\"] = 2.0\n",
1118
+ " model.opt[\"weights\"][\"plddt\"] = 0.1\n",
1119
+ " model.opt[\"weights\"][\"pae\"] = 0.1\n",
1120
+ " model.opt[\"weights\"][\"rmsd\"] = 1.0\n",
1121
+ " model.opt[\"weights\"]['sc_rmsd'] = 1.0\n",
1122
+ " # model.opt[\"weights\"]['fape'] = 1.0\n",
1123
+ "\n",
1124
+ " model.design_logits(190)\n",
1125
+ " model.design_logits(10, save_best=True)\n",
1126
+ " outfile = f\"out_sc/{_name}_resesigned/{_name}_redesigned_{i}.pdb\"\n",
1127
+ " os.makedirs(os.path.dirname(outfile), exist_ok=True)\n",
1128
+ " model.save_pdb(outfile)\n",
1129
+ " mpnn_model = mk_mpnn_model()\n",
1130
+ "\n",
1131
+ " p = (\n",
1132
+ " []\n",
1133
+ " ) # [homo if not n in _interfaceFixturesIndexSecChain else hetero for n, (homo, hetero) in enumerate(zip(list(ho2), list(he[-len(ho2):])))]\n",
1134
+ " for k in model.opt[\"pos\"]:\n",
1135
+ " p.append(str(k + 1)) # Might be wrong\n",
1136
+ " p.append(\",\")\n",
1137
+ " posf = \"\".join(p[:-1])\n",
1138
+ "\n",
1139
+ " repredictionModel = mk_afdesign_model(\n",
1140
+ " protocol=\"fixbb\", use_templates=False\n",
1141
+ " )\n",
1142
+ " os.makedirs(os.path.dirname('out_sc_Redesigned/'), exist_ok=True)\n",
1143
+ "\n",
1144
+ " for j in range(num_designs):\n",
1145
+ " print(f\" Reprediction Iteration {j} of 100\")\n",
1146
+ " repredictionModel.prep_inputs(\n",
1147
+ " f\"out_sc/{_name}_resesigned/{_name}_redesigned_{j}.pdb\"\n",
1148
+ " )\n",
1149
+ "\n",
1150
+ " mpnn_model.prep_inputs(\n",
1151
+ " pdb_filename=f\"out_sc/{_name}_resesigned/{_name}_redesigned_{j}.pdb\",\n",
1152
+ " chain=\"A\",\n",
1153
+ " fix_pos=posf,\n",
1154
+ " rm_aa=\"C\",\n",
1155
+ " )\n",
1156
+ " out = mpnn_model.sample(num=1, batch=8, temperature=0.1)\n",
1157
+ "\n",
1158
+ " for n, i in enumerate(out[\"seq\"]):\n",
1159
+ "\n",
1160
+ " repredictionModel.predict(seq=i, num_recycles=3)\n",
1161
+ " if (\n",
1162
+ " repredictionModel.aux[\"log\"][\"rmsd\"] < 2.0\n",
1163
+ " and repredictionModel.aux[\"log\"][\"plddt\"] > 0.85\n",
1164
+ " ):\n",
1165
+ " filename = f'out_sc_Redesigned/{_name}_resesigned/{_name}_redesigned-{j}_num-{n}_rmsd-{int(repredictionModel.aux[\"log\"][\"rmsd\"]*100)}.pdb'\n",
1166
+ " os.makedirs(os.path.dirname(filename), exist_ok=True)\n",
1167
+ " repredictionModel.save_pdb(filename)\n",
1168
+ "\n",
1169
+ "for _name, _input, _length in zip(\n",
1170
+ " names, inputs, lengths\n",
1171
+ "):\n",
1172
+ " print(f\"Starting on {_name}\")\n",
1173
+ " clear_mem()\n",
1174
+ "\n",
1175
+ " _input = _input.replace(\" \", \"\")\n",
1176
+ " __name = _name.split(\"_\")[0]\n",
1177
+ "\n",
1178
+ " test_model = mk_afdesign_model(protocol='fixbb')\n",
1179
+ " model = mk_afdesign_model(\n",
1180
+ " protocol=\"partial\", use_templates=False\n",
1181
+ " ) # set True to constrain positions using template input\n",
1182
+ " # define positions we want to constrain (input PDB numbering)\n",
1183
+ "\n",
1184
+ " wire_loop_repr = [\"l\" if re.search(\"[A-Z]\", x) else \"w\" for x in _input.split(\",\")]\n",
1185
+ "\n",
1186
+ " _lengths = []\n",
1187
+ " for _id, rep in zip(wire_loop_repr, _input.split(\",\")):\n",
1188
+ " if \"-\" in rep: # loop or range\n",
1189
+ " if _id == \"l\": # loop\n",
1190
+ " rep = rep[1:]\n",
1191
+ " _len = int(rep.split(\"-\")[1]) - int(rep.split(\"-\")[0]) + 1\n",
1192
+ " else: # range\n",
1193
+ " _len = int(rep.split(\"-\")[1])\n",
1194
+ " else:\n",
1195
+ " if _id == \"l\":\n",
1196
+ " rep = rep[1:]\n",
1197
+ " _len = 1\n",
1198
+ " _lengths.append(_len)\n",
1199
+ "\n",
1200
+ " overall_length = sum(_lengths)\n",
1201
+ "\n",
1202
+ " old_pos = list(filter(lambda x: re.search(\"[A-Z]\", x), _input.split(\",\")))\n",
1203
+ " order = list(range(len(old_pos)))\n",
1204
+ " old_pos = \",\".join(old_pos)\n",
1205
+ " wires = list(filter(lambda x: not re.search(\"[A-Z]\", x), _input.split(\",\")))\n",
1206
+ " wires = [\n",
1207
+ " int(wire) if \"-\" not in wire else int(wire.split(\"-\")[1]) for wire in wires\n",
1208
+ " ]\n",
1209
+ " offset = wires[0] if not wire_loop_repr[0] == \"l\" else 0\n",
1210
+ " if wire_loop_repr[0] == \"w\":\n",
1211
+ " wires = wires[1:]\n",
1212
+ " if wire_loop_repr[-1] == \"w\":\n",
1213
+ " wires = wires[:-1]\n",
1214
+ "\n",
1215
+ " chain = re.findall(\"[A-Z]\", _input)\n",
1216
+ " chain = list(set(chain))\n",
1217
+ " assert len(chain) == 1\n",
1218
+ " chain = chain[0]\n",
1219
+ " if \"-\" in _length:\n",
1220
+ " _length = _length.split(\"-\")[1]\n",
1221
+ " _length = int(_length)\n",
1222
+ " if _length < overall_length:\n",
1223
+ " _length = overall_length\n",
1224
+ "\n",
1225
+ "\n",
1226
+ " print(_name)\n",
1227
+ " pdb_file = get_pdb(_name)\n",
1228
+ "\n",
1229
+ "\n",
1230
+ "\n",
1231
+ " model.prep_inputs(\n",
1232
+ " pdb_file,\n",
1233
+ " chain=chain,\n",
1234
+ " pos=old_pos, # define positions to contrain\n",
1235
+ " length=_length, # define if the desired length is different from input PDB\n",
1236
+ " fix_seq=True,\n",
1237
+ " ) # set True to constrain the sequence\n",
1238
+ "\n",
1239
+ " # set positions (if different from PDB)\n",
1240
+ " # reorder the segments,\n",
1241
+ " model.rewire(\n",
1242
+ " order=order, # set order of segments\n",
1243
+ " loops=wires, # change loop length inbetween segments\n",
1244
+ " offset=offset,\n",
1245
+ " ) # essentially loop length at the N term\n",
1246
+ "\n",
1247
+ " in_files = os.listdir(f'out_sc_Redesigned/{_name}_resesigned/')\n",
1248
+ " if not os.path.exists(f'out_sc_Redesigned/{_name}_resesigned/out/'):\n",
1249
+ " os.mkdir(f'out_sc_Redesigned/{_name}_resesigned/out/')\n",
1250
+ " for ii in in_files:\n",
1251
+ " if ii[-1] == 'b':\n",
1252
+ " test_model.prep_inputs(pdb_filename=f'out_sc_Redesigned/{_name}_resesigned/{ii}')\n",
1253
+ " seq = test_model._inputs['batch'][\"aatype\"]\n",
1254
+ " #print(seq)\n",
1255
+ " model.predict(seq=seq, num_recycles=3)\n",
1256
+ " if model.aux[\"losses\"][\"rmsd\"] < 1.0:\n",
1257
+ " model.save_pdb(f'out_sc_Redesigned/{_name}_resesigned/out/{ii}')\n",
1258
+ " with open(f'out_sc_Redesigned/{_name}_resesigned/out/{ii[:-4]}_data.pkl', 'wb') as f:\n",
1259
+ " pickle.dump(model.aux[\"losses\"][\"rmsd\"], f)\n",
1260
+ "\n"
1261
+ ],
1262
+ "metadata": {
1263
+ "id": "8sLixVvGGJ47",
1264
+ "cellView": "form"
1265
+ },
1266
+ "execution_count": null,
1267
+ "outputs": []
1268
+ },
1269
+ {
1270
+ "cell_type": "code",
1271
+ "source": [],
1272
+ "metadata": {
1273
+ "id": "QHFiJeHjB4sM"
1274
+ },
1275
+ "execution_count": null,
1276
+ "outputs": []
1277
+ }
1278
+ ],
1279
+ "metadata": {
1280
+ "accelerator": "GPU",
1281
+ "colab": {
1282
+ "provenance": [],
1283
+ "machine_shape": "hm",
1284
+ "gpuType": "L4",
1285
+ "include_colab_link": true
1286
+ },
1287
+ "kernelspec": {
1288
+ "display_name": "Python 3",
1289
+ "name": "python3"
1290
+ },
1291
+ "language_info": {
1292
+ "name": "python"
1293
+ }
1294
+ },
1295
+ "nbformat": 4,
1296
+ "nbformat_minor": 0
1297
+ }
model/PXDesignBench/ColabDesign/af/examples/af2cycler.ipynb ADDED
@@ -0,0 +1,741 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "nbformat": 4,
3
+ "nbformat_minor": 0,
4
+ "metadata": {
5
+ "colab": {
6
+ "provenance": [],
7
+ "machine_shape": "hm",
8
+ "gpuType": "L4",
9
+ "include_colab_link": true
10
+ },
11
+ "kernelspec": {
12
+ "name": "python3",
13
+ "display_name": "Python 3"
14
+ },
15
+ "language_info": {
16
+ "name": "python"
17
+ },
18
+ "accelerator": "GPU"
19
+ },
20
+ "cells": [
21
+ {
22
+ "cell_type": "markdown",
23
+ "metadata": {
24
+ "id": "view-in-github",
25
+ "colab_type": "text"
26
+ },
27
+ "source": [
28
+ "<a href=\"https://colab.research.google.com/github/sokrypton/ColabDesign/blob/main/af/examples/af2cycler.ipynb\" target=\"_parent\"><img src=\"https://colab.research.google.com/assets/colab-badge.svg\" alt=\"Open In Colab\"/></a>"
29
+ ]
30
+ },
31
+ {
32
+ "cell_type": "markdown",
33
+ "source": [
34
+ "# The AF2cycler\n",
35
+ "This notebook contains the code to run the af2cycler and use for improvement of suboptimal designed protein backbones.\n",
36
+ "Based on:\n",
37
+ "\n",
38
+ "**Alphafold2 refinement improves designability of large de novo proteins**\n",
39
+ "\n",
40
+ "Christopher Frank, Dominik Schiwietz, Lara Fuß, Sergey Ovchinnikov and Hendrik Dietz\n",
41
+ "\n",
42
+ "We recommend to run this Notebook with at leat a L4 or better a A100 GPU as the GPU memeory needed for ESMFold is quite significant\n",
43
+ "\n"
44
+ ],
45
+ "metadata": {
46
+ "id": "wsji9enfo8aM"
47
+ }
48
+ },
49
+ {
50
+ "cell_type": "code",
51
+ "execution_count": null,
52
+ "metadata": {
53
+ "cellView": "form",
54
+ "id": "yv2S1XouoxZF"
55
+ },
56
+ "outputs": [],
57
+ "source": [
58
+ "#@title setup\n",
59
+ "%%time\n",
60
+ "import os\n",
61
+ "if not os.path.isdir(\"params\"):\n",
62
+ " # get code\n",
63
+ " os.system(\"pip -q install pyppeteer nest_asyncio\")\n",
64
+ " os.system(\"pip -q install git+https://github.com/sokrypton/ColabDesign.git\")\n",
65
+ " # for debugging\n",
66
+ " os.system(\"ln -s /usr/local/lib/python3.*/dist-packages/colabdesign colabdesign\")\n",
67
+ " # download params\n",
68
+ " os.system(\"mkdir params\")\n",
69
+ " os.system(\"apt-get install aria2 -qq\")\n",
70
+ " os.system(\"aria2c -q -x 16 https://storage.googleapis.com/alphafold/alphafold_params_2022-12-06.tar\")\n",
71
+ " os.system(\"tar -xf alphafold_params_2022-12-06.tar -C params\")\n",
72
+ "\n",
73
+ "import warnings\n",
74
+ "warnings.simplefilter(action='ignore', category=FutureWarning)\n",
75
+ "\n",
76
+ "import os\n",
77
+ "from colabdesign import mk_afdesign_model, clear_mem\n",
78
+ "from colabdesign.mpnn import mk_mpnn_model\n",
79
+ "\n",
80
+ "from IPython.display import HTML\n",
81
+ "from google.colab import files\n",
82
+ "import numpy as np\n",
83
+ "\n",
84
+ "import requests, time\n",
85
+ "if not os.path.isfile(\"TMscore\"):\n",
86
+ " os.system(\"wget -qnc https://zhanggroup.org/TM-score/TMscore.cpp\")\n",
87
+ " os.system(\"g++ -static -O3 -ffast-math -lm -o TMscore TMscore.cpp\")\n",
88
+ "def tmscore(x,y):\n",
89
+ " # pass to TMscore\n",
90
+ " output = os.popen(f'./TMscore {x} {y}')\n",
91
+ " # parse outputs\n",
92
+ " parse_float = lambda x: float(x.split(\"=\")[1].split()[0])\n",
93
+ " o = {}\n",
94
+ " for line in output:\n",
95
+ " line = line.rstrip()\n",
96
+ " if line.startswith(\"RMSD\"): o[\"rms\"] = parse_float(line)\n",
97
+ " if line.startswith(\"TM-score\"): o[\"tms\"] = parse_float(line)\n",
98
+ " if line.startswith(\"GDT-TS-score\"): o[\"gdt\"] = parse_float(line)\n",
99
+ " return o\n",
100
+ "\n",
101
+ "import asyncio\n",
102
+ "import nest_asyncio\n",
103
+ "from pyppeteer import launch\n",
104
+ "import base64\n",
105
+ "\n",
106
+ "# Apply nest_asyncio to enable nested event loops\n",
107
+ "nest_asyncio.apply()\n",
108
+ "\n",
109
+ "async def fetch_blob_content(page, blob_url):\n",
110
+ " blob_to_base64 = \"\"\"\n",
111
+ " async (blobUrl) => {\n",
112
+ " const blob = await fetch(blobUrl).then(r => r.blob());\n",
113
+ " return new Promise((resolve) => {\n",
114
+ " const reader = new FileReader();\n",
115
+ " reader.onloadend = () => resolve(reader.result);\n",
116
+ " reader.readAsDataURL(blob);\n",
117
+ " });\n",
118
+ " }\n",
119
+ " \"\"\"\n",
120
+ " base64_data = await page.evaluate(blob_to_base64, blob_url)\n",
121
+ " _, encoded = base64_data.split(',', 1)\n",
122
+ " return base64.b64decode(encoded)\n",
123
+ "\n",
124
+ "async def extract_pdb_file_download_link_and_content(url):\n",
125
+ " browser = await launch(headless=True, args=['--no-sandbox', '--disable-setuid-sandbox'])\n",
126
+ " page = await browser.newPage()\n",
127
+ " await page.goto(url, {'waitUntil': 'networkidle0'})\n",
128
+ " elements = await page.querySelectorAll('a.btn.bg-purple')\n",
129
+ " for element in elements:\n",
130
+ " href = await page.evaluate('(element) => element.getAttribute(\"href\")', element)\n",
131
+ " if 'blob:https://esmatlas.com/' in href:\n",
132
+ " content = await fetch_blob_content(page, href)\n",
133
+ " await browser.close()\n",
134
+ " return href, content\n",
135
+ " await browser.close()\n",
136
+ " return \"No PDB file link found.\", None\n",
137
+ "\n",
138
+ "def esmfold_api(sequence):\n",
139
+ " url = f'https://esmatlas.com/resources/fold/result?fasta_header=%3Eunnamed&sequence={sequence}'\n",
140
+ " result = asyncio.get_event_loop().run_until_complete(extract_pdb_file_download_link_and_content(url))\n",
141
+ " if result[1]:\n",
142
+ " pdb_str = result[1].decode('utf-8')\n",
143
+ " return pdb_str\n",
144
+ " else:\n",
145
+ " return \"Failed to retrieve PDB content.\"\n",
146
+ "\n",
147
+ "import jax\n",
148
+ "import jax.numpy as jnp\n",
149
+ "from colabdesign.af.alphafold.common import residue_constants\n",
150
+ "\n",
151
+ "if not os.path.exists('/content/in/'):\n",
152
+ " os.mkdir('/content/in/')\n",
153
+ "\n",
154
+ "import py3Dmol\n",
155
+ "\n",
156
+ "def visualize_pdb_overlay(pdb1_path, pdb2_path):\n",
157
+ " viewer = py3Dmol.view(width=800, height=600)\n",
158
+ "\n",
159
+ " with open(pdb1_path, 'r') as f:\n",
160
+ " pdb1_data = f.read()\n",
161
+ " viewer.addModel(pdb1_data, 'pdb')\n",
162
+ " viewer.setStyle({'model': 0}, {'cartoon': {'color': 'grey'}})\n",
163
+ "\n",
164
+ " with open(pdb2_path, 'r') as f:\n",
165
+ " pdb2_data = f.read()\n",
166
+ " viewer.addModel(pdb2_data, 'pdb')\n",
167
+ " viewer.setStyle({'model': 1}, {'cartoon': {'color' : 'red'}})\n",
168
+ "\n",
169
+ " viewer.zoomTo()\n",
170
+ " viewer.show()\n",
171
+ "\n",
172
+ "\n"
173
+ ]
174
+ },
175
+ {
176
+ "cell_type": "code",
177
+ "source": [],
178
+ "metadata": {
179
+ "id": "bxL_tvmGqg-S"
180
+ },
181
+ "execution_count": null,
182
+ "outputs": []
183
+ },
184
+ {
185
+ "cell_type": "markdown",
186
+ "source": [
187
+ "# Chroma Design\n",
188
+ "\n",
189
+ "On the start of this pipeline is the creation of draft backbones using Chroma or any other design method you want to use. We suggest you check out this two notebooks on Chroma to generate your desired proteins:\n",
190
+ "**Chroma Quickstart**\n",
191
+ "https://colab.research.google.com/github/generatebio/chroma/blob/main/notebooks/ChromaDemo.ipynb\n",
192
+ "\n",
193
+ "**Chroma API Tutorial**\n",
194
+ "https://colab.research.google.com/github/generatebio/chroma/blob/main/notebooks/ChromaAPI.ipynb\n",
195
+ "\n",
196
+ "If you have your PDB files please upload them into the **in/** folder and proceed\n"
197
+ ],
198
+ "metadata": {
199
+ "id": "WMpjGEyGqgSH"
200
+ }
201
+ },
202
+ {
203
+ "cell_type": "code",
204
+ "source": [
205
+ "#@title Monomer af2cycling\n",
206
+ "#@markdown The af2cycler takes in the Chroma design and returns a new pdb file with improved structure\n",
207
+ "iterations = 10 #@param {type:\"integer\"}\n",
208
+ "#@markdown The af2cycled model is shown in red, while the chroma model is shown in grey\n",
209
+ "\n",
210
+ "\n",
211
+ "\n",
212
+ "import numpy as np\n",
213
+ "import warnings\n",
214
+ "\n",
215
+ "warnings.simplefilter(action='ignore', category=FutureWarning)\n",
216
+ "\n",
217
+ "import os, re\n",
218
+ "from colabdesign import mk_afdesign_model, clear_mem\n",
219
+ "from colabdesign.mpnn import mk_mpnn_model\n",
220
+ "\n",
221
+ "import os, re\n",
222
+ "from colabdesign import mk_afdesign_model, clear_mem\n",
223
+ "from colabdesign.mpnn import mk_mpnn_model\n",
224
+ "\n",
225
+ "import numpy as np\n",
226
+ "\n",
227
+ "def sample_gumbel(shape, eps=1e-20):\n",
228
+ " \"\"\"Sample from Gumbel(0, 1)\"\"\"\n",
229
+ " U = np.random.uniform(size=shape)\n",
230
+ " return -np.log(-np.log(U + eps) + eps)\n",
231
+ "\n",
232
+ "\n",
233
+ "clear_mem()\n",
234
+ "\n",
235
+ "iters = iterations\n",
236
+ "in_path = '/content/in/'\n",
237
+ "out_path = 'out/'\n",
238
+ "if not os.path.exists('/content/in/out/'):\n",
239
+ " os.mkdir('/content/in/out/')\n",
240
+ "\n",
241
+ "\n",
242
+ "starting_seq = \"\"\n",
243
+ "starting_seq = re.sub(\"[^A-Z]\", \"\", starting_seq.upper())\n",
244
+ "\n",
245
+ "\n",
246
+ "file_list = os.listdir(in_path)\n",
247
+ "\n",
248
+ "clear_mem()\n",
249
+ "mpnn_model = mk_mpnn_model()\n",
250
+ "af_model = mk_afdesign_model(protocol=\"fixbb\",use_templates=True,use_initial_atom_pos=True,use_initial_guess=True)\n",
251
+ "\n",
252
+ "for file_name in file_list:\n",
253
+ " if file_name[-1] == 'b':\n",
254
+ "\n",
255
+ " in_pdb = in_path + file_name\n",
256
+ " out_pdb = in_path + out_path + 'Out_' + file_name\n",
257
+ "\n",
258
+ "\n",
259
+ "\n",
260
+ "\n",
261
+ " af_model.prep_inputs(pdb_filename=in_pdb, chain='A')\n",
262
+ "\n",
263
+ " starting_seq = af_model._inputs['batch'][\"aatype\"]\n",
264
+ "\n",
265
+ " iterations = iters\n",
266
+ "\n",
267
+ " use_dropout = True\n",
268
+ " num_recycles = 0\n",
269
+ "\n",
270
+ " mpnn_mode = \"conditional\"\n",
271
+ " cmap_seqsep = 9\n",
272
+ "\n",
273
+ " cmap_num = 2\n",
274
+ " #cmap_cutoff = 14\n",
275
+ " L = sum(af_model._lengths)\n",
276
+ " af_model.restart(mode=\"gumbel\")\n",
277
+ " af_model._args[\"clear_prev\"] = False\n",
278
+ " #af_model.set_opt(cmap_cutoff=cmap_cutoff)\n",
279
+ " af_model.set_weights(helix=1e-8)\n",
280
+ " # gather info about inputs\n",
281
+ " if \"offset\" in af_model._inputs:\n",
282
+ " offset = af_model._inputs\n",
283
+ " else:\n",
284
+ " idx = af_model._inputs[\"residue_index\"]\n",
285
+ " offset = idx[:, None] - idx[None, :]\n",
286
+ " # initialize sequence\n",
287
+ " if len(starting_seq) > 1:\n",
288
+ " af_model.set_seq(seq=starting_seq)\n",
289
+ " # initialize coordinates\n",
290
+ " af_model._inputs.pop(\"prev\", None)\n",
291
+ " init = af_model._inputs[\"batch\"]['all_atom_positions'].copy()\n",
292
+ "\n",
293
+ " save_best = False\n",
294
+ " for k in range(iterations):\n",
295
+ "\n",
296
+ " if k > (iterations - 10):\n",
297
+ " use_dropout = False\n",
298
+ " save_best = True\n",
299
+ "\n",
300
+ " # denoise\n",
301
+ " aux = af_model.predict(return_aux=True, verbose=False,\n",
302
+ " dropout=use_dropout,\n",
303
+ " num_recycles=num_recycles)\n",
304
+ "\n",
305
+ " #af_model._inputs[\"prev\"] = aux[\"prev\"]\n",
306
+ " #af_model._inputs[\"prev\"][\"prev_msa_first_row\"] *= 0\n",
307
+ " #af_model._inputs[\"prev\"][\"prev_pos\"] *= 0\n",
308
+ "\n",
309
+ " cmap = aux[\"cmap\"] * (np.abs(offset) > cmap_seqsep)\n",
310
+ " conf = np.sort(cmap)[:, -cmap_num:].mean(-1)\n",
311
+ "\n",
312
+ " plddt = aux[\"plddt\"]\n",
313
+ " seq = aux[\"seq\"][\"hard\"][0].argmax(-1)\n",
314
+ " xyz = aux[\"atom_positions\"].copy()\n",
315
+ " # update inputs\n",
316
+ " af_model._inputs[\"batch\"][\"aatype\"] = seq\n",
317
+ " af_model._inputs[\"batch\"][\"all_atom_positions\"] = xyz\n",
318
+ "\n",
319
+ " if mpnn_mode != \"none\":\n",
320
+ "\n",
321
+ " mpnn_model.get_af_inputs(af_model)\n",
322
+ " opt = {\"mask\": np.sqrt(conf)}\n",
323
+ " if mpnn_mode == \"unconditional\":\n",
324
+ " opt[\"ar_mask\"] = np.zeros((L, L))\n",
325
+ " mpnn_out = mpnn_model.score(**opt)\n",
326
+ " mpnn_logits = mpnn_out[\"logits\"][:, :20]\n",
327
+ " aux[\"log\"][\"mpnn\"] = mpnn_out[\"score\"]\n",
328
+ "\n",
329
+ " c = conf[:, None]\n",
330
+ "\n",
331
+ " new_logits = (1 - c) * sample_gumbel(mpnn_logits.shape) + c * mpnn_logits\n",
332
+ "\n",
333
+ " af_model._params[\"seq\"] = 0.9 * af_model._params[\"seq\"] + 0.1 * new_logits\n",
334
+ "\n",
335
+ " # save results\n",
336
+ " af_model._save_results(aux, save_best=save_best)\n",
337
+ " af_model._k += 1\n",
338
+ "\n",
339
+ " af_model.save_pdb(out_pdb)\n",
340
+ " visualize_pdb_overlay(in_pdb, out_pdb)\n",
341
+ "\n"
342
+ ],
343
+ "metadata": {
344
+ "cellView": "form",
345
+ "id": "KeWmENFFqf1S"
346
+ },
347
+ "execution_count": null,
348
+ "outputs": []
349
+ },
350
+ {
351
+ "cell_type": "code",
352
+ "source": [
353
+ "HTML(af_model.animate())"
354
+ ],
355
+ "metadata": {
356
+ "id": "HtpnTpvZtHi6"
357
+ },
358
+ "execution_count": null,
359
+ "outputs": []
360
+ },
361
+ {
362
+ "cell_type": "code",
363
+ "source": [
364
+ "#@markdown #Redesign with solubleMPNN for ESMFold prediction\n",
365
+ "#@markdown The standard manuscript settings were 8 sequences, 0.1 sampling temperature and the removal of cysteines\n",
366
+ "import pickle\n",
367
+ "import pandas as pd\n",
368
+ "in_path = '/content/in/out/'\n",
369
+ "out_path = 'out_sMPNN/'\n",
370
+ "if not os.path.exists(out_path):\n",
371
+ " os.mkdir(out_path)\n",
372
+ "\n",
373
+ "file_list = os.listdir(in_path)\n",
374
+ "\n",
375
+ "\n",
376
+ "num_seqs = 8 #@param [\"8\", \"16\", \"32\", \"64\"] {type:\"raw\"}\n",
377
+ "mpnn_sampling_temp = 0.1 #@param [\"0.0001\", \"0.1\", \"0.15\", \"0.2\", \"0.25\", \"0.3\", \"0.5\", \"1.0\"] {type:\"raw\"}\n",
378
+ "rm_aa = \"C\" #@param {type:\"string\"}\n",
379
+ "use_solubleMPNN = True #@param {type:\"boolean\"}\n",
380
+ "#@markdown - `mpnn_sampling_temp` - control diversity of sampled sequences. (higher = more diverse).\n",
381
+ "#@markdown - `rm_aa='C'` - do not use [C]ysteines.\n",
382
+ "#@markdown - `use_solubleMPNN` - use weights trained only on soluble proteins.\n",
383
+ "#@markdown\n",
384
+ "\n",
385
+ "from colabdesign.shared.protein import alphabet_list as chain_list\n",
386
+ "mpnn_model = mk_mpnn_model()\n",
387
+ "\n",
388
+ "\n",
389
+ "for file in file_list:\n",
390
+ " if file[-4:] == '.pdb':\n",
391
+ "\n",
392
+ " in_file1 = in_path + file\n",
393
+ " mpnn_model.prep_inputs(pdb_filename=in_file1,\n",
394
+ " chain='A',\n",
395
+ " rm_aa=rm_aa,weights = \"soluble\")\n",
396
+ " out = mpnn_model.sample(num=num_seqs//8,\n",
397
+ " batch=8,\n",
398
+ " temperature=mpnn_sampling_temp)\n",
399
+ " for seq,score in zip(out[\"seq\"],out[\"score\"]):\n",
400
+ " print(score,seq.split(\"/\")[0])\n",
401
+ " df = pd.DataFrame(out[\"seq\"])\n",
402
+ "\n",
403
+ " # Define the output path for saving the sequences as a .pkl file\n",
404
+ " output_pkl_file = out_path + file[:-4] + \"_sequences.pkl\"\n",
405
+ "\n",
406
+ " # Save the DataFrame to a .pkl file\n",
407
+ " with open(output_pkl_file, 'wb') as f:\n",
408
+ " pickle.dump(df, f)"
409
+ ],
410
+ "metadata": {
411
+ "cellView": "form",
412
+ "id": "KNcTvB5XzG-X"
413
+ },
414
+ "execution_count": null,
415
+ "outputs": []
416
+ },
417
+ {
418
+ "cell_type": "code",
419
+ "source": [
420
+ "#@markdown #Run ESMFold to test designability\n",
421
+ "\n",
422
+ "#@markdown **This cell is a little bit tricky. The problem is the compatibility between the JAX and PYTORCH frameworks between ColabDesign and ESMFold and GPU memory requirements**\n",
423
+ "\n",
424
+ "#@markdown Go to *Runtime* >> *Restart Session*\n",
425
+ "\n",
426
+ "#@markdown then Run this cell\n",
427
+ "\n",
428
+ "#@markdown Runtime 2-5 min\n",
429
+ "\n",
430
+ "#@markdown This cells runs ESMFold from huggingface and automatically calculates the RMSD to the designed backbone\n",
431
+ "#@markdown NOTE: GPU memory can be a big problem here. If you get memory errors please restart the runtime and run this cell again. It should be self contained. Additionally, after finish the ESMFold prediction rerun the setup cell\n",
432
+ "\n",
433
+ "import os\n",
434
+ "import pandas as pd\n",
435
+ "from Bio.PDB import PDBParser, Superimposer\n",
436
+ "import pickle\n",
437
+ "import torch\n",
438
+ "import numpy as np\n",
439
+ "from transformers import AutoTokenizer, EsmForProteinFolding\n",
440
+ "from transformers.models.esm.openfold_utils.protein import to_pdb, Protein as OFProtein\n",
441
+ "from transformers.models.esm.openfold_utils.feats import atom14_to_atom37\n",
442
+ "\n",
443
+ "import py3Dmol\n",
444
+ "\n",
445
+ "def visualize_pdb_overlay(pdb1_path, pdb2_path):\n",
446
+ " viewer = py3Dmol.view(width=800, height=600)\n",
447
+ "\n",
448
+ " with open(pdb1_path, 'r') as f:\n",
449
+ " pdb1_data = f.read()\n",
450
+ " viewer.addModel(pdb1_data, 'pdb')\n",
451
+ " viewer.setStyle({'model': 0}, {'cartoon': {'color': 'grey'}})\n",
452
+ "\n",
453
+ " with open(pdb2_path, 'r') as f:\n",
454
+ " pdb2_data = f.read()\n",
455
+ " viewer.addModel(pdb2_data, 'pdb')\n",
456
+ " viewer.setStyle({'model': 1}, {'cartoon': {'color' : 'red'}})\n",
457
+ "\n",
458
+ " viewer.zoomTo()\n",
459
+ " viewer.show()\n",
460
+ "\n",
461
+ "\n",
462
+ "\n",
463
+ "\n",
464
+ "\n",
465
+ "tokenizer = AutoTokenizer.from_pretrained(\"facebook/esmfold_v1\")\n",
466
+ "model = EsmForProteinFolding.from_pretrained(\"facebook/esmfold_v1\", low_cpu_mem_usage=True)\n",
467
+ "\n",
468
+ "device = 'cuda:0'\n",
469
+ "model = model.cuda(device)\n",
470
+ "model.esm = model.esm.half()\n",
471
+ "model.trunk.set_chunk_size(64)\n",
472
+ "torch.backends.cuda.matmul.allow_tf32 = True\n",
473
+ "\n",
474
+ "def convert_outputs_to_pdb(outputs):\n",
475
+ " final_atom_positions = atom14_to_atom37(outputs[\"positions\"][-1], outputs)\n",
476
+ " outputs = {k: v.to(\"cpu\").numpy() for k, v in outputs.items()}\n",
477
+ " final_atom_positions = final_atom_positions.cpu().numpy()\n",
478
+ " final_atom_mask = outputs[\"atom37_atom_exists\"]\n",
479
+ " pdbs = []\n",
480
+ " for i in range(outputs[\"aatype\"].shape[0]):\n",
481
+ " aa = outputs[\"aatype\"][i]\n",
482
+ " pred_pos = final_atom_positions[i]\n",
483
+ " mask = final_atom_mask[i]\n",
484
+ " resid = outputs[\"residue_index\"][i] + 1\n",
485
+ " pred = OFProtein(\n",
486
+ " aatype=aa,\n",
487
+ " atom_positions=pred_pos,\n",
488
+ " atom_mask=mask,\n",
489
+ " residue_index=resid,\n",
490
+ " b_factors=outputs[\"plddt\"][i],\n",
491
+ " chain_index=outputs[\"chain_index\"][i] if \"chain_index\" in outputs else None,\n",
492
+ " )\n",
493
+ " pdbs.append(to_pdb(pred))\n",
494
+ " return pdbs\n",
495
+ "\n",
496
+ "def calculate_ca_rmsd(pdb_file1, pdb_file2):\n",
497
+ " parser = PDBParser(QUIET=True)\n",
498
+ "\n",
499
+ " structure1 = parser.get_structure(\"Protein1\", pdb_file1)\n",
500
+ " structure2 = parser.get_structure(\"Protein2\", pdb_file2)\n",
501
+ "\n",
502
+ " ca_atoms1 = [atom for atom in structure1.get_atoms() if atom.get_name() == \"CA\"]\n",
503
+ " ca_atoms2 = [atom for atom in structure2.get_atoms() if atom.get_name() == \"CA\"]\n",
504
+ "\n",
505
+ " super_imposer = Superimposer()\n",
506
+ " super_imposer.set_atoms(ca_atoms1, ca_atoms2)\n",
507
+ " super_imposer.apply(structure2.get_atoms())\n",
508
+ " rmsd = super_imposer.rms\n",
509
+ " return rmsd\n",
510
+ "\n",
511
+ "def process_sequences(seq_list, pdb_file,in_path_pdb):\n",
512
+ " lowest_rmsd = float('inf')\n",
513
+ " lowest_rmsd_data = None\n",
514
+ " pdb_id = pdb_file[16:-4]\n",
515
+ " out_ss_path = in_path_pdb + \"output/\"\n",
516
+ "\n",
517
+ " if not os.path.exists(out_ss_path):\n",
518
+ " os.mkdir(out_ss_path)\n",
519
+ "\n",
520
+ " for test_protein in seq_list:\n",
521
+ " data = {}\n",
522
+ " tokenized_input = tokenizer([test_protein], return_tensors=\"pt\", add_special_tokens=False)['input_ids']\n",
523
+ " tokenized_input = tokenized_input.cuda(device)\n",
524
+ "\n",
525
+ " with torch.no_grad():\n",
526
+ " output = model(tokenized_input)\n",
527
+ "\n",
528
+ " data['out'] = output\n",
529
+ " data[\"plddt\"] = torch.mean(output['plddt']).item()\n",
530
+ " data['pae'] = torch.mean(output['predicted_aligned_error']).item()\n",
531
+ "\n",
532
+ " pdb_data = convert_outputs_to_pdb(output)\n",
533
+ " tmp_pdb_file = os.path.join(out_ss_path, \"TMP.pdb\")\n",
534
+ "\n",
535
+ " with open(tmp_pdb_file, 'w') as file:\n",
536
+ " for line in pdb_data:\n",
537
+ " file.write(line)\n",
538
+ "\n",
539
+ " data['rmsd'] = calculate_ca_rmsd(tmp_pdb_file, pdb_file)\n",
540
+ " print(f'Sequence: {test_protein}, plddt: {data[\"plddt\"]}, PAE: {data[\"pae\"]}, RMSD: {data[\"rmsd\"]}')\n",
541
+ "\n",
542
+ " if data['rmsd'] < lowest_rmsd:\n",
543
+ " lowest_rmsd = data['rmsd']\n",
544
+ " lowest_rmsd_data = data\n",
545
+ "\n",
546
+ " if lowest_rmsd_data is not None:\n",
547
+ " print(f'Lowest RMSD: {lowest_rmsd}')\n",
548
+ " best_pdb_data = convert_outputs_to_pdb(lowest_rmsd_data['out'])\n",
549
+ " best_pdb_file = os.path.join(out_ss_path, f\"{pdb_id}_best_structure.pdb\")\n",
550
+ "\n",
551
+ " with open(best_pdb_file, 'w') as file:\n",
552
+ " for line in best_pdb_data:\n",
553
+ " file.write(line)\n",
554
+ "\n",
555
+ " original_dict = lowest_rmsd_data\n",
556
+ " key_to_exclude = 'out'\n",
557
+ " data_out = {k: v for k, v in original_dict.items() if k != key_to_exclude}\n",
558
+ "\n",
559
+ " with open(os.path.join(out_ss_path, f\"{pdb_id}_best_structure_data.pkl\"), 'wb') as f:\n",
560
+ " pickle.dump(data_out, f)\n",
561
+ "\n",
562
+ " return lowest_rmsd, best_pdb_file, data_out\n",
563
+ "\n",
564
+ " return None, None, None\n",
565
+ "\n",
566
+ "\n",
567
+ "in_path= '/content/out_sMPNN/'\n",
568
+ "file_list = os.listdir(in_path)\n",
569
+ "\n",
570
+ "for file in file_list:\n",
571
+ " if file[-1] =='l':\n",
572
+ "\n",
573
+ "\n",
574
+ "\n",
575
+ " output_pkl_file = in_path + file\n",
576
+ "\n",
577
+ " with open(output_pkl_file, 'rb') as f:\n",
578
+ " seq = pickle.load(f)\n",
579
+ " seq_list = []\n",
580
+ " for i in np.asarray(seq):\n",
581
+ " seq_list.append(i[0])\n",
582
+ "\n",
583
+ " pdb_file = \"/content/in/out/\" + file[:-14] + '.pdb'\n",
584
+ " print(seq_list)\n",
585
+ "\n",
586
+ "\n",
587
+ "\n",
588
+ "\n",
589
+ "\n",
590
+ "\n",
591
+ "\n",
592
+ " lowest_rmsd, best_pdb_file, best_data = process_sequences(seq_list, pdb_file,in_path)\n",
593
+ " if lowest_rmsd is not None:\n",
594
+ " print(f\"Lowest RMSD: {lowest_rmsd}, Best PDB file: {best_pdb_file}\")\n",
595
+ " else:\n",
596
+ " print(\"No valid result found.\")\n",
597
+ " #visualize_pdb_overlay(pdb_file, best_pdb_file)\n"
598
+ ],
599
+ "metadata": {
600
+ "cellView": "form",
601
+ "collapsed": true,
602
+ "id": "Ctyijhvu0UVe"
603
+ },
604
+ "execution_count": null,
605
+ "outputs": []
606
+ },
607
+ {
608
+ "cell_type": "code",
609
+ "source": [
610
+ "#@markdown #Optional: Run AF2 based designability test\n",
611
+ "\n",
612
+ "\n",
613
+ "#@markdown Rerun **setup cell** if you tested ESMFold prediction before!\n",
614
+ "\n",
615
+ "#@markdown This cell predicts the solubleMPNN generated seuqneces with AF2 with Initial Guess & All atom initialisation\n",
616
+ "import re\n",
617
+ "clear_mem()\n",
618
+ "\n",
619
+ "in_path = '/content/in/'\n",
620
+ "out_path = 'out/'\n",
621
+ "if not os.path.exists('/content/in/out/'):\n",
622
+ " os.mkdir('/content/in/out/')\n",
623
+ "\n",
624
+ "\n",
625
+ "starting_seq = \"\"\n",
626
+ "starting_seq = re.sub(\"[^A-Z]\", \"\", starting_seq.upper())\n",
627
+ "\n",
628
+ "\n",
629
+ "file_list = os.listdir(in_path)\n",
630
+ "\n",
631
+ "clear_mem()\n",
632
+ "\n",
633
+ "af_model = mk_afdesign_model(protocol=\"fixbb\",use_initial_atom_pos=True,use_initial_guess=True)\n",
634
+ "\n",
635
+ "\n",
636
+ "def process_sequences(seq_list, pdb_file,in_path_pdb):\n",
637
+ " lowest_rmsd = float('inf')\n",
638
+ " lowest_rmsd_data = None\n",
639
+ " pdb_id = pdb_file[16:-4]\n",
640
+ " out_ss_path = in_path_pdb + \"output_AF2/\"\n",
641
+ "\n",
642
+ " if not os.path.exists(out_ss_path):\n",
643
+ " os.mkdir(out_ss_path)\n",
644
+ " kk=0\n",
645
+ " for test_protein in seq_list:\n",
646
+ " data = {}\n",
647
+ " af_model.prep_inputs(pdb_filename=pdb_file, chain='A')\n",
648
+ " af_model.predict(seq=test_protein,num_recycles=3)\n",
649
+ "\n",
650
+ "\n",
651
+ "\n",
652
+ " data[\"plddt\"] = af_model.aux['losses']['plddt']\n",
653
+ " data['pae'] = af_model.aux['losses']['pae']*31\n",
654
+ " data['rmsd'] = af_model.aux['losses']['rmsd']\n",
655
+ " af_model.save_pdb(f'{out_ss_path}{pdb_id}_{kk}.pdb')\n",
656
+ " print(f'Sequence: {test_protein}, plddt: {data[\"plddt\"]}, PAE: {data[\"pae\"]}, RMSD: {data[\"rmsd\"]}')\n",
657
+ "\n",
658
+ " if data['rmsd'] < lowest_rmsd:\n",
659
+ " lowest_rmsd = data['rmsd']\n",
660
+ " lowest_rmsd_data = data\n",
661
+ "\n",
662
+ " if lowest_rmsd_data is not None:\n",
663
+ " print(f'Lowest RMSD: {lowest_rmsd}')\n",
664
+ "\n",
665
+ " best_pdb_file = os.path.join(out_ss_path, f\"{pdb_id}_best_structure.pdb\")\n",
666
+ "\n",
667
+ " return lowest_rmsd, best_pdb_file\n",
668
+ "\n",
669
+ " return None, None, None\n",
670
+ "\n",
671
+ "\n",
672
+ "in_path= '/content/out_sMPNN/'\n",
673
+ "file_list = os.listdir(in_path)\n",
674
+ "\n",
675
+ "for file in file_list:\n",
676
+ " if file[-1] =='l':\n",
677
+ "\n",
678
+ "\n",
679
+ "\n",
680
+ " output_pkl_file = in_path + file\n",
681
+ "\n",
682
+ " with open(output_pkl_file, 'rb') as f:\n",
683
+ " seq = pickle.load(f)\n",
684
+ " seq_list = []\n",
685
+ " for i in np.asarray(seq):\n",
686
+ " seq_list.append(i[0])\n",
687
+ "\n",
688
+ " pdb_file = \"/content/in/out/\" + file[:-14] + '.pdb'\n",
689
+ " print(seq_list)\n",
690
+ "\n",
691
+ "\n",
692
+ "\n",
693
+ "\n",
694
+ "\n",
695
+ "\n",
696
+ "\n",
697
+ " lowest_rmsd, best_pdb_file = process_sequences(seq_list, pdb_file,in_path)\n",
698
+ " if lowest_rmsd is not None:\n",
699
+ " print(f\"Lowest RMSD: {lowest_rmsd}, Best PDB file: {best_pdb_file}\")\n",
700
+ " else:\n",
701
+ " print(\"No valid result found.\")\n",
702
+ " #visualize_pdb_overlay(pdb_file, best_pdb_file)\n",
703
+ "\n",
704
+ "\n"
705
+ ],
706
+ "metadata": {
707
+ "cellView": "form",
708
+ "id": "s1EVl7Ee8ne-"
709
+ },
710
+ "execution_count": null,
711
+ "outputs": []
712
+ },
713
+ {
714
+ "cell_type": "code",
715
+ "source": [],
716
+ "metadata": {
717
+ "id": "ZQljfnQl8oTc"
718
+ },
719
+ "execution_count": null,
720
+ "outputs": []
721
+ },
722
+ {
723
+ "cell_type": "code",
724
+ "source": [],
725
+ "metadata": {
726
+ "id": "16XTY0u9YyxP"
727
+ },
728
+ "execution_count": null,
729
+ "outputs": []
730
+ },
731
+ {
732
+ "cell_type": "code",
733
+ "source": [],
734
+ "metadata": {
735
+ "id": "u6mCraHrdqM3"
736
+ },
737
+ "execution_count": null,
738
+ "outputs": []
739
+ }
740
+ ]
741
+ }
model/PXDesignBench/ColabDesign/af/examples/af_cyc_design.ipynb ADDED
@@ -0,0 +1,320 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "cells": [
3
+ {
4
+ "cell_type": "markdown",
5
+ "metadata": {
6
+ "id": "view-in-github",
7
+ "colab_type": "text"
8
+ },
9
+ "source": [
10
+ "<a href=\"https://colab.research.google.com/github/sokrypton/ColabDesign/blob/main/af/examples/af_cyc_design.ipynb\" target=\"_parent\"><img src=\"https://colab.research.google.com/assets/colab-badge.svg\" alt=\"Open In Colab\"/></a>"
11
+ ]
12
+ },
13
+ {
14
+ "cell_type": "markdown",
15
+ "metadata": {
16
+ "id": "OA2k3sAYuiXe"
17
+ },
18
+ "source": [
19
+ "#af_cyc_design\n",
20
+ "\n",
21
+ "**Cyclic peptide structure prediction and design using AlphaFold**\n",
22
+ "\n",
23
+ "Stephen Rettie, Katelyn Campbell, Asim Bera, Alex Kang, Simon Kozlov, Joshmyn De La Cruz, Victor Adebomi, Guangfeng Zhou, Frank DiMaio, Sergey Ovchinnikov, Gaurav Bhardwaj\n",
24
+ "\n",
25
+ "doi: https://doi.org/10.1101/2023.02.25.529956\n"
26
+ ]
27
+ },
28
+ {
29
+ "cell_type": "code",
30
+ "execution_count": null,
31
+ "metadata": {
32
+ "cellView": "form",
33
+ "id": "-AXy0s_4cKaK"
34
+ },
35
+ "outputs": [],
36
+ "source": [
37
+ "#@title setup (~2 minutes)\n",
38
+ "%%time\n",
39
+ "import os\n",
40
+ "if not os.path.isdir(\"params\"):\n",
41
+ " # get code\n",
42
+ " os.system(\"pip -q install git+https://github.com/sokrypton/ColabDesign.git@v1.1.1\")\n",
43
+ " # for debugging\n",
44
+ " os.system(\"ln -s /usr/local/lib/python3.*/dist-packages/colabdesign colabdesign\")\n",
45
+ " # download params\n",
46
+ " os.system(\"mkdir params\")\n",
47
+ " os.system(\"apt-get install aria2 -qq\")\n",
48
+ " os.system(\"aria2c -q -x 16 https://storage.googleapis.com/alphafold/alphafold_params_2022-12-06.tar\")\n",
49
+ " os.system(\"tar -xf alphafold_params_2022-12-06.tar -C params\")\n",
50
+ "\n",
51
+ "import warnings\n",
52
+ "warnings.simplefilter(action='ignore', category=FutureWarning)\n",
53
+ "\n",
54
+ "import os\n",
55
+ "from colabdesign import mk_afdesign_model, clear_mem\n",
56
+ "from IPython.display import HTML\n",
57
+ "from google.colab import files\n",
58
+ "import numpy as np\n",
59
+ "\n",
60
+ "import jax\n",
61
+ "import jax.numpy as jnp\n",
62
+ "from colabdesign.af.alphafold.common import residue_constants\n",
63
+ "\n",
64
+ "def get_pdb(pdb_code=\"\"):\n",
65
+ " if pdb_code is None or pdb_code == \"\":\n",
66
+ " upload_dict = files.upload()\n",
67
+ " pdb_string = upload_dict[list(upload_dict.keys())[0]]\n",
68
+ " with open(\"tmp.pdb\",\"wb\") as out: out.write(pdb_string)\n",
69
+ " return \"tmp.pdb\"\n",
70
+ " elif os.path.isfile(pdb_code):\n",
71
+ " return pdb_code\n",
72
+ " elif len(pdb_code) == 4:\n",
73
+ " os.system(f\"wget -qnc https://files.rcsb.org/view/{pdb_code}.pdb\")\n",
74
+ " return f\"{pdb_code}.pdb\"\n",
75
+ " else:\n",
76
+ " os.system(f\"wget -qnc https://alphafold.ebi.ac.uk/files/AF-{pdb_code}-F1-model_v3.pdb\")\n",
77
+ " return f\"AF-{pdb_code}-F1-model_v3.pdb\"\n",
78
+ "\n",
79
+ "def add_cyclic_offset(self, offset_type=2):\n",
80
+ " '''add cyclic offset to connect N and C term'''\n",
81
+ " def cyclic_offset(L):\n",
82
+ " i = np.arange(L)\n",
83
+ " ij = np.stack([i,i+L],-1)\n",
84
+ " offset = i[:,None] - i[None,:]\n",
85
+ " c_offset = np.abs(ij[:,None,:,None] - ij[None,:,None,:]).min((2,3))\n",
86
+ " if offset_type == 1:\n",
87
+ " c_offset = c_offset\n",
88
+ " elif offset_type >= 2:\n",
89
+ " a = c_offset < np.abs(offset)\n",
90
+ " c_offset[a] = -c_offset[a]\n",
91
+ " if offset_type == 3:\n",
92
+ " idx = np.abs(c_offset) > 2\n",
93
+ " c_offset[idx] = (32 * c_offset[idx] )/ abs(c_offset[idx])\n",
94
+ " return c_offset * np.sign(offset)\n",
95
+ " idx = self._inputs[\"residue_index\"]\n",
96
+ " offset = np.array(idx[:,None] - idx[None,:])\n",
97
+ "\n",
98
+ " if self.protocol == \"binder\":\n",
99
+ " c_offset = cyclic_offset(self._binder_len)\n",
100
+ " offset[self._target_len:,self._target_len:] = c_offset\n",
101
+ "\n",
102
+ " if self.protocol in [\"fixbb\",\"partial\",\"hallucination\"]:\n",
103
+ " Ln = 0\n",
104
+ " for L in self._lengths:\n",
105
+ " offset[Ln:Ln+L,Ln:Ln+L] = cyclic_offset(L)\n",
106
+ " Ln += L\n",
107
+ " self._inputs[\"offset\"] = offset\n",
108
+ "\n",
109
+ "def add_rg_loss(self, weight=0.1):\n",
110
+ " '''add radius of gyration loss'''\n",
111
+ " def loss_fn(inputs, outputs):\n",
112
+ " xyz = outputs[\"structure_module\"]\n",
113
+ " ca = xyz[\"final_atom_positions\"][:,residue_constants.atom_order[\"CA\"]]\n",
114
+ " rg = jnp.sqrt(jnp.square(ca - ca.mean(0)).sum(-1).mean() + 1e-8)\n",
115
+ " rg_th = 2.38 * ca.shape[0] ** 0.365\n",
116
+ " rg = jax.nn.elu(rg - rg_th)\n",
117
+ " return {\"rg\":rg}\n",
118
+ " self._callbacks[\"model\"][\"loss\"].append(loss_fn)\n",
119
+ " self.opt[\"weights\"][\"rg\"] = weight"
120
+ ]
121
+ },
122
+ {
123
+ "cell_type": "markdown",
124
+ "metadata": {
125
+ "id": "UUfKrOzT0gOS"
126
+ },
127
+ "source": [
128
+ "# fixed backbone design (fixbb) (~2 minutes)\n",
129
+ "For a given protein backbone, generate/design a new sequence that AlphaFold thinks folds into that conformation."
130
+ ]
131
+ },
132
+ {
133
+ "cell_type": "code",
134
+ "execution_count": null,
135
+ "metadata": {
136
+ "id": "qLd1DsnKzxBJ"
137
+ },
138
+ "outputs": [],
139
+ "source": [
140
+ "clear_mem()\n",
141
+ "af_model = mk_afdesign_model(protocol=\"fixbb\")\n",
142
+ "af_model.prep_inputs(pdb_filename=get_pdb(\"7m28\"), chain=\"A\")\n",
143
+ "add_cyclic_offset(af_model, offset_type=2)\n",
144
+ "\n",
145
+ "print(\"length\", af_model._len)\n",
146
+ "print(\"weights\", af_model.opt[\"weights\"])"
147
+ ]
148
+ },
149
+ {
150
+ "cell_type": "code",
151
+ "source": [
152
+ "import matplotlib.pyplot as plt\n",
153
+ "plt.imshow(af_model._inputs[\"offset\"],cmap=\"bwr\")"
154
+ ],
155
+ "metadata": {
156
+ "id": "xr6mw-CXl_o3"
157
+ },
158
+ "execution_count": null,
159
+ "outputs": []
160
+ },
161
+ {
162
+ "cell_type": "code",
163
+ "source": [
164
+ "af_model.restart()\n",
165
+ "af_model.design_3stage()"
166
+ ],
167
+ "metadata": {
168
+ "id": "u0AwskJ84NGx"
169
+ },
170
+ "execution_count": null,
171
+ "outputs": []
172
+ },
173
+ {
174
+ "cell_type": "code",
175
+ "source": [
176
+ "af_model.plot_traj()"
177
+ ],
178
+ "metadata": {
179
+ "id": "8FB1v7dn1LL6"
180
+ },
181
+ "execution_count": null,
182
+ "outputs": []
183
+ },
184
+ {
185
+ "cell_type": "code",
186
+ "execution_count": null,
187
+ "metadata": {
188
+ "id": "YEApO8YzBoS0"
189
+ },
190
+ "outputs": [],
191
+ "source": [
192
+ "af_model.save_pdb(f\"{af_model.protocol}.pdb\")\n",
193
+ "af_model.plot_pdb(show_mainchains=True)"
194
+ ]
195
+ },
196
+ {
197
+ "cell_type": "code",
198
+ "execution_count": null,
199
+ "metadata": {
200
+ "id": "cW1KQiHKJpfp"
201
+ },
202
+ "outputs": [],
203
+ "source": [
204
+ "HTML(af_model.animate())"
205
+ ]
206
+ },
207
+ {
208
+ "cell_type": "code",
209
+ "source": [
210
+ "af_model.get_seqs()"
211
+ ],
212
+ "metadata": {
213
+ "id": "YDrChASGVUUx"
214
+ },
215
+ "execution_count": null,
216
+ "outputs": []
217
+ },
218
+ {
219
+ "cell_type": "markdown",
220
+ "source": [
221
+ "# hallucination (~1 minute)\n",
222
+ "For a given length, generate/hallucinate a protein sequence that AlphaFold thinks folds into a well structured protein (high plddt, low pae, many contacts)."
223
+ ],
224
+ "metadata": {
225
+ "id": "qLwS2s_xcjRI"
226
+ }
227
+ },
228
+ {
229
+ "cell_type": "code",
230
+ "execution_count": null,
231
+ "metadata": {
232
+ "id": "sZnYfCbfEvol"
233
+ },
234
+ "outputs": [],
235
+ "source": [
236
+ "clear_mem()\n",
237
+ "af_model = mk_afdesign_model(protocol=\"hallucination\")\n",
238
+ "af_model.prep_inputs(length=13, rm_aa=\"C\")\n",
239
+ "add_cyclic_offset(af_model)\n",
240
+ "# add_rg_loss(af_model)\n",
241
+ "\n",
242
+ "print(\"length\",af_model._len)\n",
243
+ "print(\"weights\",af_model.opt[\"weights\"])"
244
+ ]
245
+ },
246
+ {
247
+ "cell_type": "code",
248
+ "source": [
249
+ "# pre-design with gumbel initialization and softmax activation\n",
250
+ "af_model.restart()\n",
251
+ "af_model.set_seq(mode=\"gumbel\")\n",
252
+ "af_model.set_opt(\"con\", binary=True, cutoff=21.6875, num=af_model._len, seqsep=0)\n",
253
+ "af_model.set_weights(pae=1, plddt=1, con=0.5)\n",
254
+ "af_model.design_soft(50)\n",
255
+ "\n",
256
+ "# three stage design\n",
257
+ "af_model.set_seq(seq=af_model.aux[\"seq\"][\"pseudo\"])\n",
258
+ "af_model.design_3stage(50,50,10)"
259
+ ],
260
+ "metadata": {
261
+ "id": "f76xqCkw0vj9"
262
+ },
263
+ "execution_count": null,
264
+ "outputs": []
265
+ },
266
+ {
267
+ "cell_type": "code",
268
+ "execution_count": null,
269
+ "metadata": {
270
+ "id": "A1GxeLZdTTya"
271
+ },
272
+ "outputs": [],
273
+ "source": [
274
+ "af_model.save_pdb(f\"{af_model.protocol}.pdb\")\n",
275
+ "af_model.plot_pdb(show_mainchains=True)"
276
+ ]
277
+ },
278
+ {
279
+ "cell_type": "code",
280
+ "execution_count": null,
281
+ "metadata": {
282
+ "id": "L2E9Tn2Acchj"
283
+ },
284
+ "outputs": [],
285
+ "source": [
286
+ "HTML(af_model.animate())"
287
+ ]
288
+ },
289
+ {
290
+ "cell_type": "code",
291
+ "execution_count": null,
292
+ "metadata": {
293
+ "id": "YSKWYu0_GlUH"
294
+ },
295
+ "outputs": [],
296
+ "source": [
297
+ "af_model.get_seqs()"
298
+ ]
299
+ }
300
+ ],
301
+ "metadata": {
302
+ "accelerator": "GPU",
303
+ "colab": {
304
+ "collapsed_sections": [
305
+ "q4qiU9I0QHSz"
306
+ ],
307
+ "provenance": [],
308
+ "include_colab_link": true
309
+ },
310
+ "kernelspec": {
311
+ "display_name": "Python 3",
312
+ "name": "python3"
313
+ },
314
+ "language_info": {
315
+ "name": "python"
316
+ }
317
+ },
318
+ "nbformat": 4,
319
+ "nbformat_minor": 0
320
+ }
model/PXDesignBench/ColabDesign/af/examples/af_pseudo_diffusion.ipynb ADDED
@@ -0,0 +1,266 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "cells": [
3
+ {
4
+ "cell_type": "markdown",
5
+ "metadata": {
6
+ "id": "view-in-github",
7
+ "colab_type": "text"
8
+ },
9
+ "source": [
10
+ "<a href=\"https://colab.research.google.com/github/sokrypton/ColabDesign/blob/v1.1.1/af/examples/af_pseudo_diffusion.ipynb\" target=\"_parent\"><img src=\"https://colab.research.google.com/assets/colab-badge.svg\" alt=\"Open In Colab\"/></a>"
11
+ ]
12
+ },
13
+ {
14
+ "cell_type": "markdown",
15
+ "metadata": {
16
+ "id": "VD9K5H2cnFxL"
17
+ },
18
+ "source": [
19
+ "#AF_pseudo_diffusion + proteinMPNN\n",
20
+ "Hacking AlphaFold to be a diffusion model (for backbone generation). At each step add logits from proteinMPNN.\n",
21
+ "\n",
22
+ "\n",
23
+ "**WARNING**: This notebook is experimental, designed as a control. Not intended for practical use at this stage.\n",
24
+ "\n",
25
+ "---\n",
26
+ "**NEW**\n",
27
+ "For latest version of notebook (reconfigured to work in distogram space) go here:\n",
28
+ "[af_pseudo_diffusion_dgram.ipynb](https://colab.research.google.com/github/sokrypton/ColabDesign/blob/v1.1.1/af/examples/af_pseudo_diffusion_dgram.ipynb)"
29
+ ]
30
+ },
31
+ {
32
+ "cell_type": "code",
33
+ "execution_count": null,
34
+ "metadata": {
35
+ "cellView": "form",
36
+ "id": "YCRzPGdTZfEe"
37
+ },
38
+ "outputs": [],
39
+ "source": [
40
+ "#@title setup\n",
41
+ "%%time\n",
42
+ "import os\n",
43
+ "if not os.path.isdir(\"params\"):\n",
44
+ " # get code\n",
45
+ " os.system(\"pip -q install git+https://github.com/sokrypton/ColabDesign.git@v1.1.1\")\n",
46
+ " # for debugging\n",
47
+ " os.system(\"ln -s /usr/local/lib/python3.*/dist-packages/colabdesign colabdesign\")\n",
48
+ " # download params\n",
49
+ " os.system(\"mkdir params\")\n",
50
+ " os.system(\"apt-get install aria2 -qq\")\n",
51
+ " os.system(\"aria2c -q -x 16 https://storage.googleapis.com/alphafold/alphafold_params_2022-12-06.tar\")\n",
52
+ " os.system(\"tar -xf alphafold_params_2022-12-06.tar -C params\")\n",
53
+ "\n",
54
+ "import warnings\n",
55
+ "warnings.simplefilter(action='ignore', category=FutureWarning)\n",
56
+ "\n",
57
+ "import os, re\n",
58
+ "from colabdesign import mk_afdesign_model, clear_mem\n",
59
+ "from colabdesign.mpnn import mk_mpnn_model\n",
60
+ "from IPython.display import HTML\n",
61
+ "from google.colab import files\n",
62
+ "import numpy as np\n",
63
+ "\n",
64
+ "def get_pdb(pdb_code=\"\"):\n",
65
+ " if pdb_code is None or pdb_code == \"\":\n",
66
+ " upload_dict = files.upload()\n",
67
+ " pdb_string = upload_dict[list(upload_dict.keys())[0]]\n",
68
+ " with open(\"tmp.pdb\",\"wb\") as out: out.write(pdb_string)\n",
69
+ " return \"tmp.pdb\"\n",
70
+ " elif os.path.isfile(pdb_code):\n",
71
+ " return pdb_code\n",
72
+ " elif len(pdb_code) == 4:\n",
73
+ " os.system(f\"wget -qnc https://files.rcsb.org/view/{pdb_code}.pdb\")\n",
74
+ " return f\"{pdb_code}.pdb\"\n",
75
+ " else:\n",
76
+ " os.system(f\"wget -qnc https://alphafold.ebi.ac.uk/files/AF-{pdb_code}-F1-model_v3.pdb\")\n",
77
+ " return f\"AF-{pdb_code}-F1-model_v3.pdb\"\n",
78
+ "\n",
79
+ "def sample_gumbel(shape, eps=1e-20): \n",
80
+ " \"\"\"Sample from Gumbel(0, 1)\"\"\"\n",
81
+ " U = np.random.uniform(size=shape)\n",
82
+ " return -np.log(-np.log(U + eps) + eps)"
83
+ ]
84
+ },
85
+ {
86
+ "cell_type": "code",
87
+ "execution_count": null,
88
+ "metadata": {
89
+ "id": "wxYMB4A9Zmrf",
90
+ "cellView": "form"
91
+ },
92
+ "outputs": [],
93
+ "source": [
94
+ "#@title initialize the model\n",
95
+ "length = 100 #@param {type:\"integer\"}\n",
96
+ "#@markdown Provide a starting point (optional)\n",
97
+ "starting_seq = \"\" #@param {type:\"string\"}\n",
98
+ "starting_seq = re.sub(\"[^A-Z]\", \"\", starting_seq.upper())\n",
99
+ "#@markdown - if `starting_seq` provided the `length` option will be overwritten by length of starting sequence.\n",
100
+ "use_starting_pdb = False #@param {type:\"boolean\"}\n",
101
+ "pdb = \"\" #@param {type:\"string\"}\n",
102
+ "#@markdown - specify PDB or Uniprot code or leave pdb blank for upload prompt\n",
103
+ "chains = \"A\" #@param {type:\"string\"}\n",
104
+ "#@markdown - (example `A` or `A,B` for complexes)\n",
105
+ "fix_pos = \"\" #@param {type:\"string\"}\n",
106
+ "#@markdown - specify which positions to keep fixed in the sequence (example: `1,2-10`)\n",
107
+ "#@markdown - you can also specify chain specific constraints (example: `A1-10,B1-20`)\n",
108
+ "#@markdown - you can also specify to fix entire chain(s) (example: `A`)\n",
109
+ "\n",
110
+ "if len(starting_seq) > 0:\n",
111
+ " length = len(starting_seq)\n",
112
+ "\n",
113
+ "clear_mem()\n",
114
+ "if use_starting_pdb:\n",
115
+ " af_model = mk_afdesign_model(protocol=\"fixbb\", use_templates=True)\n",
116
+ " af_model.prep_inputs(get_pdb(pdb), chains, fix_pos=fix_pos) \n",
117
+ "else:\n",
118
+ " af_model = mk_afdesign_model(protocol=\"hallucination\", use_templates=True)\n",
119
+ " af_model.prep_inputs(length=length)\n",
120
+ "mpnn_model = mk_mpnn_model()\n",
121
+ "print(\"lengths\",af_model._lengths)"
122
+ ]
123
+ },
124
+ {
125
+ "cell_type": "code",
126
+ "execution_count": null,
127
+ "metadata": {
128
+ "id": "3Dt8i00UbxtW",
129
+ "cellView": "form"
130
+ },
131
+ "outputs": [],
132
+ "source": [
133
+ "#@title run protocol\n",
134
+ "#@markdown Optimization options\n",
135
+ "iterations = 100 #@param [\"50\", \"100\"] {type:\"raw\"}\n",
136
+ "use_xyz_noise = True #@param {type:\"boolean\"}\n",
137
+ "use_seq_noise = True #@param {type:\"boolean\"}\n",
138
+ "use_dropout = True #@param {type:\"boolean\"}\n",
139
+ "use_plddt = True #@param {type:\"boolean\"}\n",
140
+ "store_denoised = True #@param {type:\"boolean\"}\n",
141
+ "#@markdown - this does not change results, but toggle between storing noised vs denoised coordinates for animation.\n",
142
+ "\n",
143
+ "#@markdown AlphaFold options\n",
144
+ "sample_models = False #@param {type:\"boolean\"}\n",
145
+ "rm_template_seq = True #@param {type:\"boolean\"}\n",
146
+ "\n",
147
+ "#@markdown proteinMPNN options (disable to keep sequence the same)\n",
148
+ "use_mpnn = True #@param {type:\"boolean\"}\n",
149
+ "mpnn_mode = \"conditional\" #@param [\"conditional\", \"unconditional\"]\n",
150
+ "\n",
151
+ "af_model.restart(mode=\"gumbel\")\n",
152
+ "\n",
153
+ "if len(starting_seq) > 1:\n",
154
+ " af_model.set_seq(seq=starting_seq)\n",
155
+ "elif use_starting_pdb:\n",
156
+ " af_model.set_seq(mode=\"wildtype\")\n",
157
+ "\n",
158
+ "af_model._inputs[\"rm_template_seq\"] = rm_template_seq\n",
159
+ "L = sum(af_model._lengths)\n",
160
+ "\n",
161
+ "af_model._inputs[\"bias\"] = np.zeros((L,20))\n",
162
+ "\n",
163
+ "if not use_starting_pdb:\n",
164
+ " af_model._inputs[\"batch\"] = {\"aatype\":np.zeros(L).astype(int),\n",
165
+ " \"all_atom_mask\":np.zeros((L,37)),\n",
166
+ " \"all_atom_positions\":np.zeros((L,37,3))}\n",
167
+ "\n",
168
+ "for k in range(iterations):\n",
169
+ " # add noise\n",
170
+ " if use_seq_noise:\n",
171
+ " af_model._inputs[\"bias\"] = 0.1 * sample_gumbel((L,20))\n",
172
+ "\n",
173
+ " if use_xyz_noise:\n",
174
+ " n = np.random.normal(size=(L,37,3)) * (1-k/iterations)\n",
175
+ " af_model._inputs[\"batch\"][\"all_atom_positions\"] += n\n",
176
+ " if not store_denoised and k > 0:\n",
177
+ " af_model._tmp[\"traj\"][\"xyz\"][-1] += n[:,1]\n",
178
+ "\n",
179
+ " # denoise\n",
180
+ " aux = af_model.predict(return_aux=True, verbose=False,\n",
181
+ " sample_models=sample_models, dropout=use_dropout)\n",
182
+ " plddt = af_model.aux[\"plddt\"]\n",
183
+ " # update inputs\n",
184
+ " af_model._inputs[\"batch\"][\"aatype\"] = af_model.aux[\"seq\"][\"hard\"].argmax(-1)[0]\n",
185
+ " af_model._inputs[\"batch\"][\"all_atom_mask\"][:,:4] = 1\n",
186
+ " if use_plddt:\n",
187
+ " af_model._inputs[\"batch\"][\"all_atom_mask\"][:,(1,3)] = np.sqrt(plddt)[:,None]\n",
188
+ " af_model._inputs[\"batch\"][\"all_atom_positions\"] = af_model.aux[\"atom_positions\"].copy()\n",
189
+ "\n",
190
+ " # add logits from proteinmpnn at each stage\n",
191
+ " if use_mpnn:\n",
192
+ " mpnn_model.get_af_inputs(af_model)\n",
193
+ " opt = {} if mpnn_mode == \"conditional\" else {\"ar_mask\":np.zeros((L,L))}\n",
194
+ " mpnn_out = mpnn_model.score(**opt)\n",
195
+ " aux[\"log\"][\"mpnn\"] = mpnn_out[\"score\"]\n",
196
+ " mpnn_logits = mpnn_out[\"logits\"][:,:20]\n",
197
+ " m = (k/iterations)\n",
198
+ " af_model._params[\"seq\"] = (1-m) * af_model._params[\"seq\"] + m * mpnn_logits\n",
199
+ "\n",
200
+ " # save results\n",
201
+ " af_model._save_results(aux)\n",
202
+ " af_model._k += 1"
203
+ ]
204
+ },
205
+ {
206
+ "cell_type": "code",
207
+ "execution_count": null,
208
+ "metadata": {
209
+ "id": "v3dPQeEQcAcT"
210
+ },
211
+ "outputs": [],
212
+ "source": [
213
+ "af_model.plot_pdb()"
214
+ ]
215
+ },
216
+ {
217
+ "cell_type": "code",
218
+ "source": [
219
+ "af_model.save_pdb(\"tmp.pdb\")\n",
220
+ "af_model.get_seqs()"
221
+ ],
222
+ "metadata": {
223
+ "id": "6Ck-ME5_99qE"
224
+ },
225
+ "execution_count": null,
226
+ "outputs": []
227
+ },
228
+ {
229
+ "cell_type": "code",
230
+ "execution_count": null,
231
+ "metadata": {
232
+ "id": "6cJhizcYcUxm"
233
+ },
234
+ "outputs": [],
235
+ "source": [
236
+ "HTML(af_model.animate(dpi=100))"
237
+ ]
238
+ },
239
+ {
240
+ "cell_type": "code",
241
+ "source": [],
242
+ "metadata": {
243
+ "id": "aVS6VC7wKyhD"
244
+ },
245
+ "execution_count": null,
246
+ "outputs": []
247
+ }
248
+ ],
249
+ "metadata": {
250
+ "accelerator": "GPU",
251
+ "colab": {
252
+ "provenance": [],
253
+ "include_colab_link": true
254
+ },
255
+ "gpuClass": "standard",
256
+ "kernelspec": {
257
+ "display_name": "Python 3",
258
+ "name": "python3"
259
+ },
260
+ "language_info": {
261
+ "name": "python"
262
+ }
263
+ },
264
+ "nbformat": 4,
265
+ "nbformat_minor": 0
266
+ }
model/PXDesignBench/ColabDesign/af/examples/af_pseudo_diffusion_dgram.ipynb ADDED
@@ -0,0 +1,376 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "cells": [
3
+ {
4
+ "cell_type": "markdown",
5
+ "metadata": {
6
+ "id": "view-in-github",
7
+ "colab_type": "text"
8
+ },
9
+ "source": [
10
+ "<a href=\"https://colab.research.google.com/github/sokrypton/ColabDesign/blob/v1.1.1/af/examples/af_pseudo_diffusion_dgram.ipynb\" target=\"_parent\"><img src=\"https://colab.research.google.com/assets/colab-badge.svg\" alt=\"Open In Colab\"/></a>"
11
+ ]
12
+ },
13
+ {
14
+ "cell_type": "markdown",
15
+ "metadata": {
16
+ "id": "VD9K5H2cnFxL"
17
+ },
18
+ "source": [
19
+ "#AF_pseudo_diffusion + proteinMPNN\n",
20
+ "Hacking AlphaFold to be a diffusion model (for backbone generation) via distogram. At each step add logits from proteinMPNN.\n",
21
+ "\n",
22
+ "\n",
23
+ "**WARNING**: This notebook is experimental, designed as a control. Not intended for practical use at this stage."
24
+ ]
25
+ },
26
+ {
27
+ "cell_type": "code",
28
+ "execution_count": null,
29
+ "metadata": {
30
+ "cellView": "form",
31
+ "id": "YCRzPGdTZfEe"
32
+ },
33
+ "outputs": [],
34
+ "source": [
35
+ "#@title setup\n",
36
+ "%%time\n",
37
+ "import os\n",
38
+ "if not os.path.isdir(\"params\"):\n",
39
+ " # get code\n",
40
+ " os.system(\"pip -q install git+https://github.com/sokrypton/ColabDesign.git@v1.1.1\")\n",
41
+ " # for debugging\n",
42
+ " os.system(\"ln -s /usr/local/lib/python3.*/dist-packages/colabdesign colabdesign\")\n",
43
+ " # download params\n",
44
+ " os.system(\"mkdir params\")\n",
45
+ " os.system(\"apt-get install aria2 -qq\")\n",
46
+ " os.system(\"aria2c -q -x 16 https://storage.googleapis.com/alphafold/alphafold_params_2022-12-06.tar\")\n",
47
+ " os.system(\"tar -xf alphafold_params_2022-12-06.tar -C params\")\n",
48
+ "\n",
49
+ "import warnings\n",
50
+ "warnings.simplefilter(action='ignore', category=FutureWarning)\n",
51
+ "\n",
52
+ "import os, re\n",
53
+ "from colabdesign import mk_afdesign_model, clear_mem\n",
54
+ "from colabdesign.mpnn import mk_mpnn_model\n",
55
+ "from colabdesign.af.alphafold.common import residue_constants\n",
56
+ "from colabdesign.shared.protein import _np_get_cb\n",
57
+ "\n",
58
+ "from IPython.display import HTML\n",
59
+ "from google.colab import files\n",
60
+ "import numpy as np\n",
61
+ "import jax.numpy as jnp\n",
62
+ "import jax\n",
63
+ "from scipy.special import softmax\n",
64
+ "\n",
65
+ "import tqdm.notebook\n",
66
+ "TQDM_BAR_FORMAT = '{l_bar}{bar}| {n_fmt}/{total_fmt} [elapsed: {elapsed} remaining: {remaining}]'\n",
67
+ "\n",
68
+ "def get_pdb(pdb_code=\"\"):\n",
69
+ " if pdb_code is None or pdb_code == \"\":\n",
70
+ " upload_dict = files.upload()\n",
71
+ " pdb_string = upload_dict[list(upload_dict.keys())[0]]\n",
72
+ " with open(\"tmp.pdb\",\"wb\") as out: out.write(pdb_string)\n",
73
+ " return \"tmp.pdb\"\n",
74
+ " elif os.path.isfile(pdb_code):\n",
75
+ " return pdb_code\n",
76
+ " elif len(pdb_code) == 4:\n",
77
+ " os.system(f\"wget -qnc https://files.rcsb.org/view/{pdb_code}.pdb\")\n",
78
+ " return f\"{pdb_code}.pdb\"\n",
79
+ " else:\n",
80
+ " os.system(f\"wget -qnc https://alphafold.ebi.ac.uk/files/AF-{pdb_code}-F1-model_v3.pdb\")\n",
81
+ " return f\"AF-{pdb_code}-F1-model_v3.pdb\"\n",
82
+ "\n",
83
+ "def sample_gumbel(shape, eps=1e-20): \n",
84
+ " \"\"\"Sample from Gumbel(0, 1)\"\"\"\n",
85
+ " U = np.random.uniform(size=shape)\n",
86
+ " return -np.log(-np.log(U + eps) + eps)"
87
+ ]
88
+ },
89
+ {
90
+ "cell_type": "code",
91
+ "execution_count": null,
92
+ "metadata": {
93
+ "id": "wxYMB4A9Zmrf",
94
+ "cellView": "form"
95
+ },
96
+ "outputs": [],
97
+ "source": [
98
+ "#@title initialize the model\n",
99
+ "length = 100 #@param {type:\"integer\"}\n",
100
+ "#symmetry = \"C\" #@param [\"C\"]\n",
101
+ "#copies = 1 #@param {type:\"integer\"}\n",
102
+ "#@markdown Provide a starting point (optional)\n",
103
+ "starting_seq = \"\" #@param {type:\"string\"}\n",
104
+ "starting_seq = re.sub(\"[^A-Z]\", \"\", starting_seq.upper())\n",
105
+ "#@markdown - if `starting_seq` provided the `length` option will be overwritten by length of starting sequence.\n",
106
+ "\n",
107
+ "#@markdown Experimental options\n",
108
+ "use_multimer = False \n",
109
+ "mode = \"dgram_retrain\" #@param [\"dgram\",\"dgram_retrain\"]\n",
110
+ "##@markdown - `xyz` - use structure output as template input\n",
111
+ "#@markdown - `dgram` - use distogram output as template input\n",
112
+ "#@markdown - `dgram_retrain` - replace distogram head from AlphaFold with one retrained to map output bins to template bins.\n",
113
+ "\n",
114
+ "if len(starting_seq) > 0:\n",
115
+ " length = len(starting_seq)\n",
116
+ "\n",
117
+ "clear_mem()\n",
118
+ "af_model = mk_afdesign_model(protocol=\"hallucination\",\n",
119
+ " use_templates=True,\n",
120
+ " debug=True, \n",
121
+ " use_multimer=use_multimer)\n",
122
+ "af_model.prep_inputs(length=length)\n",
123
+ "mpnn_model = mk_mpnn_model()\n",
124
+ "print(\"lengths\",af_model._lengths)\n",
125
+ "\n",
126
+ "if \"dgram\" in mode:\n",
127
+ " if \"retrain\" in mode and not use_multimer:\n",
128
+ " # update distogram head to return all 39 bins\n",
129
+ " af_model._cfg.model.heads.distogram.first_break = 3.25\n",
130
+ " af_model._cfg.model.heads.distogram.last_break = 50.75\n",
131
+ " af_model._cfg.model.heads.distogram.num_bins = 39\n",
132
+ " af_model._model = af_model._get_model(af_model._cfg)\n",
133
+ " from colabdesign.af.weights import __file__ as af_path\n",
134
+ " template_dgram_head = np.load(os.path.join(os.path.dirname(af_path),'template_dgram_head.npy'))\n",
135
+ " for k in range(len(af_model._model_params)):\n",
136
+ " params = {\"weights\":jnp.array(template_dgram_head[k]),\"bias\":jnp.zeros(39)}\n",
137
+ " af_model._model_params[k][\"alphafold/alphafold_iteration/distogram_head/half_logits\"] = params\n",
138
+ " else:\n",
139
+ " dgram_map = np.eye(39)[np.repeat(np.append(0,np.arange(15)),4)]\n",
140
+ " dgram_map[-1,:] = 0 \n",
141
+ "\n",
142
+ "def get_dgram(positions, num_bins=39, min_bin=3.25, max_bin=50.75):\n",
143
+ " atom_idx = residue_constants.atom_order\n",
144
+ " atoms = {k:positions[...,atom_idx[k],:] for k in [\"N\",\"CA\",\"C\"]}\n",
145
+ " cb = _np_get_cb(**atoms, use_jax=False)\n",
146
+ " dist2 = np.square(cb[None,:] - cb[:,None]).sum(-1,keepdims=True)\n",
147
+ " lower_breaks = np.linspace(min_bin, max_bin, num_bins)\n",
148
+ " lower_breaks = np.square(lower_breaks)\n",
149
+ " upper_breaks = np.concatenate([lower_breaks[1:],np.array([1e8], dtype=jnp.float32)], axis=-1)\n",
150
+ " return ((dist2 > lower_breaks) * (dist2 < upper_breaks)).astype(float)"
151
+ ]
152
+ },
153
+ {
154
+ "cell_type": "code",
155
+ "execution_count": null,
156
+ "metadata": {
157
+ "id": "3Dt8i00UbxtW",
158
+ "cellView": "form"
159
+ },
160
+ "outputs": [],
161
+ "source": [
162
+ "#@title run protocol\n",
163
+ "#@markdown Optimization options\n",
164
+ "iterations = 100 #@param [\"50\", \"100\"] {type:\"raw\"}\n",
165
+ "use_dgram_noise = True #@param {type:\"boolean\"}\n",
166
+ "use_seq_noise = True #@param {type:\"boolean\"}\n",
167
+ "use_dropout = True #@param {type:\"boolean\"}\n",
168
+ "seqsep_mask = 6 #@param {type:\"integer\"}\n",
169
+ "\n",
170
+ "#@markdown AlphaFold options\n",
171
+ "sample_models = True #@param {type:\"boolean\"}\n",
172
+ "num_recycles = 0 #@param [\"0\", \"1\", \"2\", \"3\"] {type:\"raw\"}\n",
173
+ "\n",
174
+ "#@markdown proteinMPNN options (set to `none` to disable)\n",
175
+ "mpnn_mode = \"conditional\" #@param [\"none\",\"sample\", \"conditional\", \"unconditional\"]\n",
176
+ "\n",
177
+ "L = sum(af_model._lengths)\n",
178
+ "af_model.restart(mode=\"gumbel\")\n",
179
+ "af_model._inputs[\"rm_template_seq\"] = True\n",
180
+ "\n",
181
+ "# gather info about inputs\n",
182
+ "if \"offset\" in af_model._inputs:\n",
183
+ " offset = af_model._inputs\n",
184
+ "else:\n",
185
+ " idx = af_model._inputs[\"residue_index\"]\n",
186
+ " offset = idx[:,None] - idx[None,:]\n",
187
+ "\n",
188
+ "# initialize sequence\n",
189
+ "if len(starting_seq) > 1:\n",
190
+ " af_model.set_seq(seq=starting_seq)\n",
191
+ "af_model._inputs[\"bias\"] = np.zeros((L,20))\n",
192
+ "\n",
193
+ "# initialize coordinates/dgram\n",
194
+ "af_model._inputs[\"batch\"] = {\"aatype\":np.zeros(L).astype(int),\n",
195
+ " \"all_atom_mask\":np.zeros((L,37)),\n",
196
+ " \"all_atom_positions\":np.zeros((L,37,3)),\n",
197
+ " \"dgram\":np.zeros((L,L,39))}\n",
198
+ "\n",
199
+ "for k in range(iterations):\n",
200
+ "\n",
201
+ " # disable stochastic part for the last 10 steps\n",
202
+ " if k > (iterations - 10):\n",
203
+ " use_dropout = False\n",
204
+ " sample_models = False\n",
205
+ " use_seq_noise = False\n",
206
+ " seqsep_mask = 0.0\n",
207
+ "\n",
208
+ " # noise\n",
209
+ " if k > 0:\n",
210
+ " dgram_xyz = get_dgram(xyz)\n",
211
+ " dgram_prob = softmax(dgram_logits,-1)\n",
212
+ "\n",
213
+ " if use_seq_noise:\n",
214
+ " af_model._inputs[\"bias\"] = 0.1 * sample_gumbel((L,20))\n",
215
+ "\n",
216
+ " if mode == \"xyz\":\n",
217
+ " dgram = dgram_xyz\n",
218
+ " if mode == \"dgram\":\n",
219
+ " dgram = dgram_prob @ dgram_map\n",
220
+ " dgram[...,14:] = dgram_xyz[...,14:] * dgram_prob[...,-1:]\n",
221
+ " if mode == \"dgram_retrain\":\n",
222
+ " dgram = dgram_prob\n",
223
+ " \n",
224
+ " if use_dgram_noise:\n",
225
+ " noise = sample_gumbel(dgram.shape) * (1 - k/iterations)\n",
226
+ " dgram = softmax(np.log(dgram + 1e-8) + noise, -1)\n",
227
+ "\n",
228
+ " # add mask to avoid local contacts being fixed (otherwise there is a bias toward helix)\n",
229
+ " mask = np.abs(offset) > seqsep_mask\n",
230
+ " af_model._inputs[\"batch\"][\"dgram\"] = dgram * mask[:,:,None]\n",
231
+ "\n",
232
+ " # denoise\n",
233
+ " aux = af_model.predict(return_aux=True, verbose=False,\n",
234
+ " sample_models=sample_models,\n",
235
+ " dropout=use_dropout, num_recycles=num_recycles)\n",
236
+ " plddt = aux[\"plddt\"]\n",
237
+ " seq = aux[\"seq\"][\"hard\"][0].argmax(-1)\n",
238
+ " xyz = aux[\"atom_positions\"].copy()\n",
239
+ " dgram_logits = aux[\"debug\"][\"outputs\"][\"distogram\"][\"logits\"] \n",
240
+ " \n",
241
+ " # update inputs \n",
242
+ " af_model._inputs[\"batch\"][\"aatype\"] = seq\n",
243
+ " af_model._inputs[\"batch\"][\"all_atom_mask\"][:,:4] = np.sqrt(plddt)[:,None]\n",
244
+ " af_model._inputs[\"batch\"][\"all_atom_positions\"] = xyz\n",
245
+ "\n",
246
+ " # add logits from proteinmpnn at each stage\n",
247
+ " if mpnn_mode != \"none\":\n",
248
+ " mpnn_model.get_af_inputs(af_model)\n",
249
+ " if mpnn_mode == \"sample\":\n",
250
+ " mpnn_out = mpnn_model.sample(temp = 1-k/iterations)\n",
251
+ " mpnn_logits = mpnn_out[\"logits\"][0,:,:20]\n",
252
+ " aux[\"log\"][\"mpnn\"] = mpnn_out[\"score\"][0]\n",
253
+ " else:\n",
254
+ " opt = {} if mpnn_mode == \"conditional\" else {\"ar_mask\":np.zeros((L,L))}\n",
255
+ " mpnn_out = mpnn_model.score(**opt)\n",
256
+ " mpnn_logits = mpnn_out[\"logits\"][:,:20]\n",
257
+ " aux[\"log\"][\"mpnn\"] = mpnn_out[\"score\"]\n",
258
+ " \n",
259
+ " beta = np.square(k/iterations) * plddt[:,None]\n",
260
+ " af_model._params[\"seq\"] = (1-beta) * af_model._params[\"seq\"] + beta * mpnn_logits\n",
261
+ "\n",
262
+ " # save results\n",
263
+ " af_model._save_results(aux)\n",
264
+ " af_model._k += 1"
265
+ ]
266
+ },
267
+ {
268
+ "cell_type": "code",
269
+ "source": [
270
+ "af_model.save_pdb(\"0.pdb\")\n",
271
+ "af_model.plot_pdb()\n",
272
+ "af_model.get_seqs()"
273
+ ],
274
+ "metadata": {
275
+ "id": "YeYD4KF8MUA_"
276
+ },
277
+ "execution_count": null,
278
+ "outputs": []
279
+ },
280
+ {
281
+ "cell_type": "code",
282
+ "execution_count": null,
283
+ "metadata": {
284
+ "id": "6cJhizcYcUxm"
285
+ },
286
+ "outputs": [],
287
+ "source": [
288
+ "HTML(af_model.animate(dpi=100))"
289
+ ]
290
+ },
291
+ {
292
+ "cell_type": "code",
293
+ "source": [
294
+ "#@title sample new sequences using proteinMPNN and rescore with alphafold (w/o template)\n",
295
+ "#@markdown #### Design Options\n",
296
+ "num_seqs = 32 #@param [\"32\", \"64\", \"128\", \"256\", \"512\", \"1024\"] {type:\"raw\"}\n",
297
+ "sampling_temp = 0.1 \n",
298
+ "import pandas as pd\n",
299
+ "from google.colab import data_table\n",
300
+ "data_table.enable_dataframe_formatter()\n",
301
+ "\n",
302
+ "# zero out template inputs\n",
303
+ "out = mpnn_model.sample(num=num_seqs//32, batch=32,\n",
304
+ " temperature=sampling_temp)\n",
305
+ "af_terms = [\"plddt\",\"ptm\",\"pae\"]\n",
306
+ "for k in af_terms: out[k] = []\n",
307
+ "os.system(\"mkdir -p output/all_pdb\")\n",
308
+ "\n",
309
+ "af_model._inputs[\"batch\"][\"dgram\"] = np.zeros((L,L,39))\n",
310
+ "with tqdm.notebook.tqdm(total=out[\"S\"].shape[0], bar_format=TQDM_BAR_FORMAT) as pbar:\n",
311
+ " with open(\"design.fasta\",\"w\") as fasta:\n",
312
+ " for n in range(num_seqs):\n",
313
+ " seq = out[\"seq\"][n]\n",
314
+ " af_model.predict(seq=seq,\n",
315
+ " num_recycles=1,\n",
316
+ " num_models=1,\n",
317
+ " verbose=False)\n",
318
+ "\n",
319
+ " for t in af_terms:\n",
320
+ " out[t].append(af_model.aux[\"log\"][t])\n",
321
+ " out[\"pae\"][-1] = out[\"pae\"][-1] * 31\n",
322
+ " af_model._save_results(save_best=True, verbose=False)\n",
323
+ " af_model.save_current_pdb(f\"output/all_pdb/n{n}.pdb\")\n",
324
+ " af_model._k += 1\n",
325
+ "\n",
326
+ " line = f'>mpnn:{out[\"score\"][n]:.3f}_plddt:{out[\"plddt\"][n]:.3f}_ptm:{out[\"ptm\"][n]:.3f}_pae:{out[\"pae\"][n]:.3f}\\n{out[\"seq\"][n]}'\n",
327
+ " fasta.write(line+\"\\n\")\n",
328
+ " pbar.update(1)\n",
329
+ "\n",
330
+ "labels = [\"score\"] + af_terms + [\"seq\"]\n",
331
+ "data = [[out[k][n] for k in labels] for n in range(num_seqs)]\n",
332
+ "labels[0] = \"mpnn\"\n",
333
+ "\n",
334
+ "df = pd.DataFrame(data, columns=labels)\n",
335
+ "df.to_csv('output/mpnn_results.csv')\n",
336
+ "data_table.DataTable(df.round(3).sort_values(\"pae\"))"
337
+ ],
338
+ "metadata": {
339
+ "cellView": "form",
340
+ "id": "3H_B0AoYIiWH"
341
+ },
342
+ "execution_count": null,
343
+ "outputs": []
344
+ },
345
+ {
346
+ "cell_type": "code",
347
+ "execution_count": null,
348
+ "metadata": {
349
+ "id": "v3dPQeEQcAcT"
350
+ },
351
+ "outputs": [],
352
+ "source": [
353
+ "af_model.save_pdb(\"1.pdb\")\n",
354
+ "af_model.plot_pdb()\n",
355
+ "af_model.get_seqs()"
356
+ ]
357
+ }
358
+ ],
359
+ "metadata": {
360
+ "accelerator": "GPU",
361
+ "colab": {
362
+ "provenance": [],
363
+ "include_colab_link": true
364
+ },
365
+ "gpuClass": "standard",
366
+ "kernelspec": {
367
+ "display_name": "Python 3",
368
+ "name": "python3"
369
+ },
370
+ "language_info": {
371
+ "name": "python"
372
+ }
373
+ },
374
+ "nbformat": 4,
375
+ "nbformat_minor": 0
376
+ }
model/PXDesignBench/ColabDesign/af/examples/af_pseudo_diffusion_recycle.ipynb ADDED
@@ -0,0 +1,329 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "cells": [
3
+ {
4
+ "cell_type": "markdown",
5
+ "metadata": {
6
+ "id": "view-in-github",
7
+ "colab_type": "text"
8
+ },
9
+ "source": [
10
+ "<a href=\"https://colab.research.google.com/github/sokrypton/ColabDesign/blob/v1.1.1/af/examples/af_pseudo_diffusion_recycle.ipynb\" target=\"_parent\"><img src=\"https://colab.research.google.com/assets/colab-badge.svg\" alt=\"Open In Colab\"/></a>"
11
+ ]
12
+ },
13
+ {
14
+ "cell_type": "markdown",
15
+ "metadata": {
16
+ "id": "VD9K5H2cnFxL"
17
+ },
18
+ "source": [
19
+ "#AF_pseudo_diffusion + proteinMPNN\n",
20
+ "Hacking AlphaFold to be a diffusion model (for backbone generation) via recycling mechanism. At each step add logits from proteinMPNN.\n",
21
+ "\n",
22
+ "\n",
23
+ "**WARNING**: This notebook is experimental, designed as a control. Not intended for practical use at this stage."
24
+ ]
25
+ },
26
+ {
27
+ "cell_type": "code",
28
+ "execution_count": null,
29
+ "metadata": {
30
+ "cellView": "form",
31
+ "id": "YCRzPGdTZfEe"
32
+ },
33
+ "outputs": [],
34
+ "source": [
35
+ "#@title setup\n",
36
+ "%%time\n",
37
+ "import os\n",
38
+ "if not os.path.isdir(\"params\"):\n",
39
+ " # get code\n",
40
+ " os.system(\"pip -q install git+https://github.com/sokrypton/ColabDesign.git@v1.1.1\")\n",
41
+ " # for debugging\n",
42
+ " os.system(\"ln -s /usr/local/lib/python3.*/dist-packages/colabdesign colabdesign\")\n",
43
+ " # download params\n",
44
+ " os.system(\"mkdir params\")\n",
45
+ " os.system(\"apt-get install aria2 -qq\")\n",
46
+ " os.system(\"aria2c -q -x 16 https://storage.googleapis.com/alphafold/alphafold_params_2022-12-06.tar\")\n",
47
+ " os.system(\"tar -xf alphafold_params_2022-12-06.tar -C params\")\n",
48
+ "\n",
49
+ "import warnings\n",
50
+ "warnings.simplefilter(action='ignore', category=FutureWarning)\n",
51
+ "\n",
52
+ "import os, re\n",
53
+ "from colabdesign import mk_afdesign_model, clear_mem\n",
54
+ "from colabdesign.mpnn import mk_mpnn_model\n",
55
+ "from colabdesign.af.alphafold.common import residue_constants\n",
56
+ "from colabdesign.shared.protein import _np_get_cb\n",
57
+ "\n",
58
+ "from IPython.display import HTML\n",
59
+ "from google.colab import files\n",
60
+ "import numpy as np\n",
61
+ "import jax.numpy as jnp\n",
62
+ "import jax\n",
63
+ "from scipy.special import softmax, log_softmax\n",
64
+ "\n",
65
+ "import tqdm.notebook\n",
66
+ "TQDM_BAR_FORMAT = '{l_bar}{bar}| {n_fmt}/{total_fmt} [elapsed: {elapsed} remaining: {remaining}]'\n",
67
+ "\n",
68
+ "def get_pdb(pdb_code=\"\"):\n",
69
+ " if pdb_code is None or pdb_code == \"\":\n",
70
+ " upload_dict = files.upload()\n",
71
+ " pdb_string = upload_dict[list(upload_dict.keys())[0]]\n",
72
+ " with open(\"tmp.pdb\",\"wb\") as out: out.write(pdb_string)\n",
73
+ " return \"tmp.pdb\"\n",
74
+ " elif os.path.isfile(pdb_code):\n",
75
+ " return pdb_code\n",
76
+ " elif len(pdb_code) == 4:\n",
77
+ " os.system(f\"wget -qnc https://files.rcsb.org/view/{pdb_code}.pdb\")\n",
78
+ " return f\"{pdb_code}.pdb\"\n",
79
+ " else:\n",
80
+ " os.system(f\"wget -qnc https://alphafold.ebi.ac.uk/files/AF-{pdb_code}-F1-model_v3.pdb\")\n",
81
+ " return f\"AF-{pdb_code}-F1-model_v3.pdb\"\n",
82
+ "\n",
83
+ "def sample_gumbel(shape, eps=1e-20): \n",
84
+ " \"\"\"Sample from Gumbel(0, 1)\"\"\"\n",
85
+ " U = np.random.uniform(size=shape)\n",
86
+ " return -np.log(-np.log(U + eps) + eps)"
87
+ ]
88
+ },
89
+ {
90
+ "cell_type": "code",
91
+ "execution_count": null,
92
+ "metadata": {
93
+ "cellView": "form",
94
+ "id": "wxYMB4A9Zmrf"
95
+ },
96
+ "outputs": [],
97
+ "source": [
98
+ "#@title initialize the model\n",
99
+ "length = 100 #@param {type:\"integer\"}\n",
100
+ "#@markdown Provide a starting point (optional)\n",
101
+ "starting_seq = \"\" #@param {type:\"string\"}\n",
102
+ "starting_seq = re.sub(\"[^A-Z]\", \"\", starting_seq.upper())\n",
103
+ "#@markdown - if `starting_seq` provided the `length` option will be overwritten by length of starting sequence.\n",
104
+ "\n",
105
+ "if len(starting_seq) > 0:\n",
106
+ " length = len(starting_seq)\n",
107
+ "\n",
108
+ "clear_mem()\n",
109
+ "af_model = mk_afdesign_model(protocol=\"hallucination\")\n",
110
+ "af_model.prep_inputs(length=length)\n",
111
+ "mpnn_model = mk_mpnn_model()\n",
112
+ "\n",
113
+ "af_model_test = mk_afdesign_model(protocol=\"fixbb\", best_metric=\"rmsd\")\n",
114
+ "mpnn_model_test = mk_mpnn_model()\n",
115
+ "\n",
116
+ "print(\"lengths\",af_model._lengths)"
117
+ ]
118
+ },
119
+ {
120
+ "cell_type": "code",
121
+ "execution_count": null,
122
+ "metadata": {
123
+ "id": "3Dt8i00UbxtW",
124
+ "cellView": "form"
125
+ },
126
+ "outputs": [],
127
+ "source": [
128
+ "#@title run protocol\n",
129
+ "#@markdown Optimization options\n",
130
+ "iterations = 100 #@param [\"50\", \"100\", \"200\"] {type:\"raw\"}\n",
131
+ "\n",
132
+ "#AlphaFold options\n",
133
+ "use_dropout = True\n",
134
+ "num_recycles = 0\n",
135
+ "\n",
136
+ "#@markdown proteinMPNN options (set to `none` to disable)\n",
137
+ "mpnn_mode = \"conditional\" #@param [\"none\",\"conditional\", \"unconditional\"]\n",
138
+ "\n",
139
+ "#@markdown proteinMPNN contact map masking options\n",
140
+ "cmap_seqsep = 6 #@param {type:\"raw\"}\n",
141
+ "cmap_num = 1 #@param {type:\"integer\"}\n",
142
+ "cmap_cutoff = 8 #@param {type:\"raw\"}\n",
143
+ "\n",
144
+ "L = sum(af_model._lengths)\n",
145
+ "af_model.restart(mode=\"gumbel\")\n",
146
+ "af_model._args[\"clear_prev\"] = False\n",
147
+ "af_model.set_opt(cmap_cutoff=cmap_cutoff)\n",
148
+ "af_model.set_weights(helix=1e-8)\n",
149
+ "\n",
150
+ "# gather info about inputs\n",
151
+ "if \"offset\" in af_model._inputs:\n",
152
+ " offset = af_model._inputs\n",
153
+ "else:\n",
154
+ " idx = af_model._inputs[\"residue_index\"]\n",
155
+ " offset = idx[:,None] - idx[None,:]\n",
156
+ "\n",
157
+ "# initialize sequence\n",
158
+ "if len(starting_seq) > 1:\n",
159
+ " af_model.set_seq(seq=starting_seq)\n",
160
+ "\n",
161
+ "# initialize coordinates\n",
162
+ "af_model._inputs.pop(\"prev\",None)\n",
163
+ "af_model._inputs[\"batch\"] = {\"aatype\":np.zeros(L).astype(int),\n",
164
+ " \"all_atom_mask\":np.zeros((L,37)),\n",
165
+ " \"all_atom_positions\":np.zeros((L,37,3))}\n",
166
+ "\n",
167
+ "save_best = False\n",
168
+ "for k in range(iterations):\n",
169
+ "\n",
170
+ " if k > (iterations - 10):\n",
171
+ " use_dropout = False\n",
172
+ " save_best = True\n",
173
+ "\n",
174
+ "\n",
175
+ " # denoise\n",
176
+ " aux = af_model.predict(return_aux=True, verbose=False,\n",
177
+ " dropout=use_dropout,\n",
178
+ " num_recycles=num_recycles)\n",
179
+ " af_model._inputs[\"prev\"] = aux[\"prev\"]\n",
180
+ " af_model._inputs[\"prev\"][\"prev_msa_first_row\"] *= 0\n",
181
+ " af_model._inputs[\"prev\"][\"prev_pos\"] *= 0\n",
182
+ "\n",
183
+ " # per position confidence\n",
184
+ " cmap = aux[\"cmap\"] * (np.abs(offset) > cmap_seqsep)\n",
185
+ " conf = np.sort(cmap)[:,-cmap_num:].mean(-1)\n",
186
+ "\n",
187
+ " # gather features\n",
188
+ " plddt = aux[\"plddt\"]\n",
189
+ " seq = aux[\"seq\"][\"hard\"][0].argmax(-1)\n",
190
+ " xyz = aux[\"atom_positions\"].copy()\n",
191
+ " \n",
192
+ " # update inputs \n",
193
+ " af_model._inputs[\"batch\"][\"aatype\"] = seq\n",
194
+ " af_model._inputs[\"batch\"][\"all_atom_positions\"] = xyz\n",
195
+ "\n",
196
+ " # add logits from proteinmpnn at each stage\n",
197
+ " if mpnn_mode != \"none\": \n",
198
+ " mpnn_model.get_af_inputs(af_model)\n",
199
+ " opt = {\"mask\":np.sqrt(conf)} \n",
200
+ " if mpnn_mode == \"unconditional\":\n",
201
+ " opt[\"ar_mask\"] = np.zeros((L,L))\n",
202
+ " mpnn_out = mpnn_model.score(**opt)\n",
203
+ " mpnn_logits = mpnn_out[\"logits\"][:,:20]\n",
204
+ " aux[\"log\"][\"mpnn\"] = mpnn_out[\"score\"]\n",
205
+ " \n",
206
+ " c = conf[:,None]\n",
207
+ " new_logits = (1 - c) * sample_gumbel(mpnn_logits.shape) + c * mpnn_logits\n",
208
+ " af_model._params[\"seq\"] = 0.9 * af_model._params[\"seq\"] + 0.1 * new_logits\n",
209
+ "\n",
210
+ " # save results\n",
211
+ " af_model._save_results(aux, save_best=save_best)\n",
212
+ " af_model._k += 1\n",
213
+ "\n",
214
+ "af_model.save_pdb(\"init.pdb\")"
215
+ ]
216
+ },
217
+ {
218
+ "cell_type": "code",
219
+ "execution_count": null,
220
+ "metadata": {
221
+ "id": "YeYD4KF8MUA_"
222
+ },
223
+ "outputs": [],
224
+ "source": [
225
+ "af_model.plot_pdb()\n",
226
+ "af_model.get_seqs()"
227
+ ]
228
+ },
229
+ {
230
+ "cell_type": "code",
231
+ "execution_count": null,
232
+ "metadata": {
233
+ "id": "6cJhizcYcUxm"
234
+ },
235
+ "outputs": [],
236
+ "source": [
237
+ "HTML(af_model.animate(dpi=100))"
238
+ ]
239
+ },
240
+ {
241
+ "cell_type": "code",
242
+ "execution_count": null,
243
+ "metadata": {
244
+ "cellView": "form",
245
+ "id": "3H_B0AoYIiWH"
246
+ },
247
+ "outputs": [],
248
+ "source": [
249
+ "#@title sample new sequences using proteinMPNN and rescore with alphafold (w/o template)\n",
250
+ "#@markdown #### MPNN Options\n",
251
+ "num_seqs = 16 #@param [\"8\", \"16\", \"32\", \"64\", \"128\", \"256\", \"512\", \"1024\"] {type:\"raw\"}\n",
252
+ "sampling_temp = 0.1 \n",
253
+ "#@markdown #### AlphaFold Options\n",
254
+ "alphafold_model = \"model_4_ptm\" #@param [\"model_1_ptm\", \"model_2_ptm\", \"model_3_ptm\", \"model_4_ptm\", \"model_5_ptm\"]\n",
255
+ "num_recycles = 3 #@param [\"0\", \"1\", \"2\", \"3\"] {type:\"raw\"}\n",
256
+ "import pandas as pd\n",
257
+ "\n",
258
+ "# zero out template inputs\n",
259
+ "af_model_test.prep_inputs(\"init.pdb\")\n",
260
+ "mpnn_model_test.get_af_inputs(af_model_test)\n",
261
+ "out = mpnn_model_test.sample(num=num_seqs//8, batch=8,\n",
262
+ " temperature=sampling_temp)\n",
263
+ "af_terms = [\"plddt\",\"ptm\",\"pae\",\"rmsd\",\"dgram_cce\"]\n",
264
+ "for k in af_terms: out[k] = []\n",
265
+ "os.system(\"mkdir -p output/all_pdb\")\n",
266
+ "\n",
267
+ "with tqdm.notebook.tqdm(total=out[\"S\"].shape[0], bar_format=TQDM_BAR_FORMAT) as pbar:\n",
268
+ " with open(\"design.fasta\",\"w\") as fasta:\n",
269
+ " for n in range(num_seqs):\n",
270
+ " seq = out[\"seq\"][n]\n",
271
+ " af_model_test.predict(seq=seq,\n",
272
+ " num_recycles=num_recycles,\n",
273
+ " num_models=1,\n",
274
+ " verbose=False,\n",
275
+ " models=alphafold_model)\n",
276
+ "\n",
277
+ " for t in af_terms:\n",
278
+ " out[t].append(af_model_test.aux[\"log\"][t])\n",
279
+ " out[\"pae\"][-1] = out[\"pae\"][-1] * 31\n",
280
+ " af_model_test._save_results(save_best=True, verbose=False)\n",
281
+ " af_model_test.save_current_pdb(f\"output/all_pdb/n{n}.pdb\")\n",
282
+ " af_model_test._k += 1\n",
283
+ "\n",
284
+ " line = f'>mpnn:{out[\"score\"][n]:.3f}_plddt:{out[\"plddt\"][n]:.3f}_ptm:{out[\"ptm\"][n]:.3f}_pae:{out[\"pae\"][n]:.3f}\\n{out[\"seq\"][n]}'\n",
285
+ " fasta.write(line+\"\\n\")\n",
286
+ " pbar.update(1)\n",
287
+ "\n",
288
+ "af_model_test.save_pdb(\"final.pdb\")\n",
289
+ "\n",
290
+ "labels = [\"score\"] + af_terms + [\"seq\"]\n",
291
+ "data = [[out[k][n] for k in labels] for n in range(num_seqs)]\n",
292
+ "labels[0] = \"mpnn\"\n",
293
+ "\n",
294
+ "df = pd.DataFrame(data, columns=labels)\n",
295
+ "df.to_csv('output/mpnn_results.csv')\n",
296
+ "df.round(3).sort_values(\"rmsd\")"
297
+ ]
298
+ },
299
+ {
300
+ "cell_type": "code",
301
+ "execution_count": null,
302
+ "metadata": {
303
+ "id": "v3dPQeEQcAcT"
304
+ },
305
+ "outputs": [],
306
+ "source": [
307
+ "af_model_test.plot_pdb()\n",
308
+ "af_model_test.get_seqs()"
309
+ ]
310
+ }
311
+ ],
312
+ "metadata": {
313
+ "accelerator": "GPU",
314
+ "colab": {
315
+ "provenance": [],
316
+ "include_colab_link": true
317
+ },
318
+ "gpuClass": "standard",
319
+ "kernelspec": {
320
+ "display_name": "Python 3",
321
+ "name": "python3"
322
+ },
323
+ "language_info": {
324
+ "name": "python"
325
+ }
326
+ },
327
+ "nbformat": 4,
328
+ "nbformat_minor": 0
329
+ }
model/PXDesignBench/ColabDesign/af/examples/af_relax_design.ipynb ADDED
@@ -0,0 +1,400 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "cells": [
3
+ {
4
+ "cell_type": "markdown",
5
+ "metadata": {
6
+ "id": "view-in-github",
7
+ "colab_type": "text"
8
+ },
9
+ "source": [
10
+ "<a href=\"https://colab.research.google.com/github/sokrypton/ColabDesign/blob/main/af/examples/af_relax_design.ipynb\" target=\"_parent\"><img src=\"https://colab.research.google.com/assets/colab-badge.svg\" alt=\"Open In Colab\"/></a>"
11
+ ]
12
+ },
13
+ {
14
+ "cell_type": "markdown",
15
+ "metadata": {
16
+ "id": "OA2k3sAYuiXe"
17
+ },
18
+ "source": [
19
+ "#af_relax_design (WIP)\n",
20
+ "\n",
21
+ "\n",
22
+ "**Efficient and scalable de novo protein design using a relaxed sequence space**\n",
23
+ "\n",
24
+ "Christopher Josef Frank, Ali Khoshouei, Yosta de Stigter, Dominik Schiewitz, Shihao Feng, Sergey Ovchinnikov, Hendrik Dietz\n",
25
+ "\n",
26
+ "doi: https://doi.org/10.1101/2023.02.24.529906\n",
27
+ "\n",
28
+ "**<font color=\"red\">WARNING</font>** This notebook is in development, we are still working on adding all the options from the manuscript above."
29
+ ]
30
+ },
31
+ {
32
+ "cell_type": "code",
33
+ "execution_count": null,
34
+ "metadata": {
35
+ "cellView": "form",
36
+ "id": "-AXy0s_4cKaK"
37
+ },
38
+ "outputs": [],
39
+ "source": [
40
+ "#@title setup\n",
41
+ "%%time\n",
42
+ "import os\n",
43
+ "if not os.path.isdir(\"params\"):\n",
44
+ " # get code\n",
45
+ " os.system(\"pip -q install pyppeteer nest_asyncio\")\n",
46
+ " os.system(\"pip -q install git+https://github.com/sokrypton/ColabDesign.git\")\n",
47
+ " # for debugging\n",
48
+ " os.system(\"ln -s /usr/local/lib/python3.*/dist-packages/colabdesign colabdesign\")\n",
49
+ " # download params\n",
50
+ " os.system(\"mkdir params\")\n",
51
+ " os.system(\"apt-get install aria2 -qq\")\n",
52
+ " os.system(\"aria2c -q -x 16 https://storage.googleapis.com/alphafold/alphafold_params_2022-12-06.tar\")\n",
53
+ " os.system(\"tar -xf alphafold_params_2022-12-06.tar -C params\")\n",
54
+ "\n",
55
+ "import warnings\n",
56
+ "warnings.simplefilter(action='ignore', category=FutureWarning)\n",
57
+ "\n",
58
+ "import os\n",
59
+ "from colabdesign import mk_afdesign_model, clear_mem\n",
60
+ "from colabdesign.mpnn import mk_mpnn_model\n",
61
+ "\n",
62
+ "from IPython.display import HTML\n",
63
+ "from google.colab import files\n",
64
+ "import numpy as np\n",
65
+ "\n",
66
+ "import requests, time\n",
67
+ "if not os.path.isfile(\"TMscore\"):\n",
68
+ " os.system(\"wget -qnc https://zhanggroup.org/TM-score/TMscore.cpp\")\n",
69
+ " os.system(\"g++ -static -O3 -ffast-math -lm -o TMscore TMscore.cpp\")\n",
70
+ "def tmscore(x,y):\n",
71
+ " # pass to TMscore\n",
72
+ " output = os.popen(f'./TMscore {x} {y}')\n",
73
+ " # parse outputs\n",
74
+ " parse_float = lambda x: float(x.split(\"=\")[1].split()[0])\n",
75
+ " o = {}\n",
76
+ " for line in output:\n",
77
+ " line = line.rstrip()\n",
78
+ " if line.startswith(\"RMSD\"): o[\"rms\"] = parse_float(line)\n",
79
+ " if line.startswith(\"TM-score\"): o[\"tms\"] = parse_float(line)\n",
80
+ " if line.startswith(\"GDT-TS-score\"): o[\"gdt\"] = parse_float(line)\n",
81
+ " return o\n",
82
+ "\n",
83
+ "import asyncio\n",
84
+ "import nest_asyncio\n",
85
+ "from pyppeteer import launch\n",
86
+ "import base64\n",
87
+ "\n",
88
+ "# Apply nest_asyncio to enable nested event loops\n",
89
+ "nest_asyncio.apply()\n",
90
+ "\n",
91
+ "async def fetch_blob_content(page, blob_url):\n",
92
+ " blob_to_base64 = \"\"\"\n",
93
+ " async (blobUrl) => {\n",
94
+ " const blob = await fetch(blobUrl).then(r => r.blob());\n",
95
+ " return new Promise((resolve) => {\n",
96
+ " const reader = new FileReader();\n",
97
+ " reader.onloadend = () => resolve(reader.result);\n",
98
+ " reader.readAsDataURL(blob);\n",
99
+ " });\n",
100
+ " }\n",
101
+ " \"\"\"\n",
102
+ " base64_data = await page.evaluate(blob_to_base64, blob_url)\n",
103
+ " _, encoded = base64_data.split(',', 1)\n",
104
+ " return base64.b64decode(encoded)\n",
105
+ "\n",
106
+ "async def extract_pdb_file_download_link_and_content(url):\n",
107
+ " browser = await launch(headless=True, args=['--no-sandbox', '--disable-setuid-sandbox'])\n",
108
+ " page = await browser.newPage()\n",
109
+ " await page.goto(url, {'waitUntil': 'networkidle0'})\n",
110
+ " elements = await page.querySelectorAll('a.btn.bg-purple')\n",
111
+ " for element in elements:\n",
112
+ " href = await page.evaluate('(element) => element.getAttribute(\"href\")', element)\n",
113
+ " if 'blob:https://esmatlas.com/' in href:\n",
114
+ " content = await fetch_blob_content(page, href)\n",
115
+ " await browser.close()\n",
116
+ " return href, content\n",
117
+ " await browser.close()\n",
118
+ " return \"No PDB file link found.\", None\n",
119
+ "\n",
120
+ "def esmfold_api(sequence):\n",
121
+ " url = f'https://esmatlas.com/resources/fold/result?fasta_header=%3Eunnamed&sequence={sequence}'\n",
122
+ " result = asyncio.get_event_loop().run_until_complete(extract_pdb_file_download_link_and_content(url))\n",
123
+ " if result[1]:\n",
124
+ " pdb_str = result[1].decode('utf-8')\n",
125
+ " return pdb_str\n",
126
+ " else:\n",
127
+ " return \"Failed to retrieve PDB content.\"\n",
128
+ "\n",
129
+ "import jax\n",
130
+ "import jax.numpy as jnp\n",
131
+ "from colabdesign.af.alphafold.common import residue_constants"
132
+ ]
133
+ },
134
+ {
135
+ "cell_type": "code",
136
+ "execution_count": null,
137
+ "metadata": {
138
+ "id": "sZnYfCbfEvol",
139
+ "cellView": "form"
140
+ },
141
+ "outputs": [],
142
+ "source": [
143
+ "#@title # hallucination\n",
144
+ "#@markdown For a given length, generate/hallucinate a protein sequence that AlphaFold thinks folds into a well structured protein (high plddt, low pae, many contacts).\n",
145
+ "LENGTH = 100 #@param {type:\"integer\"}\n",
146
+ "COPIES = 1 #@param [\"1\", \"2\", \"3\", \"4\", \"5\", \"6\", \"7\", \"8\"] {type:\"raw\"}\n",
147
+ "MODE = \"manuscript\" #@param [\"original\", \"manuscript\"]\n",
148
+ "use_rg_loss = True #@param {type:\"boolean\"}\n",
149
+ "\n",
150
+ "#@markdown ProteinMPNN Settings\n",
151
+ "use_mpnn_loss = False #@param {type:\"boolean\"}\n",
152
+ "use_solubleMPNN = False #@param {type:\"boolean\"}\n",
153
+ "#@markdown\n",
154
+ "\n",
155
+ "def add_rg_loss(self, weight=0.1):\n",
156
+ " '''add radius of gyration loss'''\n",
157
+ " def loss_fn(inputs, outputs):\n",
158
+ " xyz = outputs[\"structure_module\"]\n",
159
+ " ca = xyz[\"final_atom_positions\"][:,residue_constants.atom_order[\"CA\"]]\n",
160
+ " if self.protocol == \"binder\":\n",
161
+ " ca = ca[-self._binder_len:]\n",
162
+ " if MODE == \"manuscript\":\n",
163
+ " ca = ca[::5]\n",
164
+ " rg = jnp.sqrt(jnp.square(ca - ca.mean(0)).sum(-1).mean() + 1e-8)\n",
165
+ " if MODE == \"original\":\n",
166
+ " rg_th = 2.38 * ca.shape[0] ** 0.365\n",
167
+ " rg = jax.nn.elu(rg - rg_th)\n",
168
+ " return {\"rg\":rg}\n",
169
+ " self._callbacks[\"model\"][\"loss\"].append(loss_fn)\n",
170
+ " self.opt[\"weights\"][\"rg\"] = weight\n",
171
+ "\n",
172
+ "def add_mpnn_loss(self, mpnn=0.1, mpnn_seq=0.0):\n",
173
+ " '''\n",
174
+ " add mpnn loss\n",
175
+ " mpnn = maximize confidence of proteinmpnn\n",
176
+ " mpnn_seq = push designed sequence to match proteinmpnn logits\n",
177
+ " '''\n",
178
+ "\n",
179
+ " self._mpnn = mk_mpnn_model(weights = \"soluble\" if use_solubleMPNN else \"original\")\n",
180
+ " def loss_fn(inputs, outputs, aux, key):\n",
181
+ "\n",
182
+ " # get structure\n",
183
+ " atom_idx = tuple(residue_constants.atom_order[k] for k in [\"N\",\"CA\",\"C\",\"O\"])\n",
184
+ " I = {\"S\": inputs[\"aatype\"],\n",
185
+ " \"residue_idx\": inputs[\"residue_index\"],\n",
186
+ " \"chain_idx\": inputs[\"asym_id\"],\n",
187
+ " \"X\": outputs[\"structure_module\"][\"final_atom_positions\"][:,atom_idx],\n",
188
+ " \"mask\": outputs[\"structure_module\"][\"final_atom_mask\"][:,1],\n",
189
+ " \"lengths\": self._lengths,\n",
190
+ " \"key\": key}\n",
191
+ "\n",
192
+ " if \"offset\" in inputs:\n",
193
+ " I[\"offset\"] = inputs[\"offset\"]\n",
194
+ "\n",
195
+ " # set autoregressive mask\n",
196
+ " L = sum(self._lengths)\n",
197
+ " if self.protocol == \"binder\":\n",
198
+ " I[\"ar_mask\"] = 1 - np.eye(L)\n",
199
+ " I[\"ar_mask\"][-self._len:,-self._len:] = 0\n",
200
+ " else:\n",
201
+ " I[\"ar_mask\"] = np.zeros((L,L))\n",
202
+ "\n",
203
+ " # get logits\n",
204
+ " logits = self._mpnn._score(**I)[\"logits\"][:,:20]\n",
205
+ " if self.protocol == \"binder\":\n",
206
+ " logits = logits[-self._len:]\n",
207
+ " else:\n",
208
+ " logits = logits[:self._len]\n",
209
+ " aux[\"mpnn_logits\"] = logits\n",
210
+ "\n",
211
+ " # compute loss\n",
212
+ " log_q = jax.nn.log_softmax(logits)\n",
213
+ " p = inputs[\"seq\"][\"hard\"]\n",
214
+ " q = jax.nn.softmax(logits)\n",
215
+ " losses = {}\n",
216
+ " losses[\"mpnn\"] = -log_q.max(-1).mean()\n",
217
+ " losses[\"mpnn_seq\"] = -(p * jax.lax.stop_gradient(log_q)).sum(-1).mean()\n",
218
+ " return losses\n",
219
+ "\n",
220
+ " self._callbacks[\"model\"][\"loss\"].append(loss_fn)\n",
221
+ " self.opt[\"weights\"][\"mpnn\"] = mpnn\n",
222
+ " self.opt[\"weights\"][\"mpnn_seq\"] = mpnn_seq\n",
223
+ "\n",
224
+ "clear_mem()\n",
225
+ "af_model = mk_afdesign_model(protocol=\"hallucination\")\n",
226
+ "af_model.prep_inputs(length=LENGTH, copies=COPIES)\n",
227
+ "\n",
228
+ "# add extra losses\n",
229
+ "if use_rg_loss: add_rg_loss(af_model)\n",
230
+ "if use_mpnn_loss: add_mpnn_loss(af_model)\n",
231
+ "\n",
232
+ "print(\"length\",af_model._lengths)\n",
233
+ "print(\"weights\",af_model.opt[\"weights\"])"
234
+ ]
235
+ },
236
+ {
237
+ "cell_type": "code",
238
+ "source": [
239
+ "af_model.restart()\n",
240
+ "if MODE == \"original\":\n",
241
+ " # pre-design with gumbel initialization and softmax activation\n",
242
+ " af_model.set_weights(plddt=0.0, pae=0.0)\n",
243
+ " af_model.set_seq(mode=[\"gumbel\"])\n",
244
+ " af_model.design_soft(50)\n",
245
+ " af_model.set_seq(af_model.aux[\"seq\"][\"pseudo\"])\n",
246
+ "\n",
247
+ "if MODE == \"manuscript\":\n",
248
+ " af_model.set_seq(mode=[\"gumbel\",\"soft\"])\n",
249
+ "\n",
250
+ "af_model.set_weights(plddt=1.0, pae=1.0)\n",
251
+ "af_model.design_logits(40)\n",
252
+ "af_model.design_logits(10, save_best=True)"
253
+ ],
254
+ "metadata": {
255
+ "id": "f76xqCkw0vj9"
256
+ },
257
+ "execution_count": null,
258
+ "outputs": []
259
+ },
260
+ {
261
+ "cell_type": "code",
262
+ "execution_count": null,
263
+ "metadata": {
264
+ "id": "A1GxeLZdTTya"
265
+ },
266
+ "outputs": [],
267
+ "source": [
268
+ "af_model.save_pdb(f\"{af_model.protocol}.pdb\")\n",
269
+ "af_model.plot_pdb()"
270
+ ]
271
+ },
272
+ {
273
+ "cell_type": "code",
274
+ "execution_count": null,
275
+ "metadata": {
276
+ "id": "L2E9Tn2Acchj"
277
+ },
278
+ "outputs": [],
279
+ "source": [
280
+ "HTML(af_model.animate())"
281
+ ]
282
+ },
283
+ {
284
+ "cell_type": "code",
285
+ "execution_count": null,
286
+ "metadata": {
287
+ "id": "YSKWYu0_GlUH"
288
+ },
289
+ "outputs": [],
290
+ "source": [
291
+ "af_model.get_seqs()"
292
+ ]
293
+ },
294
+ {
295
+ "cell_type": "code",
296
+ "source": [
297
+ "#@markdown #Redesign with ProteinMPNN\n",
298
+ "num_seqs = 8 #@param [\"8\", \"16\", \"32\", \"64\"] {type:\"raw\"}\n",
299
+ "mpnn_sampling_temp = 0.1 #@param [\"0.0001\", \"0.1\", \"0.15\", \"0.2\", \"0.25\", \"0.3\", \"0.5\", \"1.0\"] {type:\"raw\"}\n",
300
+ "rm_aa = \"C\" #@param {type:\"string\"}\n",
301
+ "use_solubleMPNN = False #@param {type:\"boolean\"}\n",
302
+ "#@markdown - `mpnn_sampling_temp` - control diversity of sampled sequences. (higher = more diverse).\n",
303
+ "#@markdown - `rm_aa='C'` - do not use [C]ysteines.\n",
304
+ "#@markdown - `use_solubleMPNN` - use weights trained only on soluble proteins. See [preprint](https://www.biorxiv.org/content/10.1101/2023.05.09.540044v2).\n",
305
+ "#@markdown"
306
+ ],
307
+ "metadata": {
308
+ "cellView": "form",
309
+ "id": "m2qAYsDsCfqJ"
310
+ },
311
+ "execution_count": null,
312
+ "outputs": []
313
+ },
314
+ {
315
+ "cell_type": "code",
316
+ "source": [
317
+ "from colabdesign.shared.protein import alphabet_list as chain_list\n",
318
+ "mpnn_model = mk_mpnn_model()\n",
319
+ "mpnn_model.prep_inputs(pdb_filename=f\"{af_model.protocol}.pdb\",\n",
320
+ " chain=\",\".join(chain_list[:COPIES]),\n",
321
+ " homooligmer=COPIES>1,\n",
322
+ " rm_aa=rm_aa,\n",
323
+ " weights = \"soluble\" if use_solubleMPNN else\"original\")\n",
324
+ "out = mpnn_model.sample(num=num_seqs//8,\n",
325
+ " batch=8,\n",
326
+ " temperature=mpnn_sampling_temp)\n",
327
+ "for seq,score in zip(out[\"seq\"],out[\"score\"]):\n",
328
+ " print(score,seq.split(\"/\")[0])"
329
+ ],
330
+ "metadata": {
331
+ "id": "uQa0FAp7bGQo"
332
+ },
333
+ "execution_count": null,
334
+ "outputs": []
335
+ },
336
+ {
337
+ "cell_type": "markdown",
338
+ "source": [
339
+ "#Run ESMfold"
340
+ ],
341
+ "metadata": {
342
+ "id": "eDvyemgjNbX4"
343
+ }
344
+ },
345
+ {
346
+ "cell_type": "code",
347
+ "source": [
348
+ "print(\"# rmsd tmscore sequence\")\n",
349
+ "best = {}\n",
350
+ "best_rmsd = None\n",
351
+ "for n,seq in enumerate(out[\"seq\"]):\n",
352
+ " x = seq.split(\"/\")[0]\n",
353
+ " with open(f\"{af_model.protocol}.esmfold.{n}.pdb\",\"w\") as handle:\n",
354
+ " pdb_str = esmfold_api(x)\n",
355
+ " handle.write(pdb_str)\n",
356
+ " o = tmscore(f\"{af_model.protocol}.pdb\",\n",
357
+ " f\"{af_model.protocol}.esmfold.{n}.pdb\")\n",
358
+ " print(n,o[\"rms\"],o[\"tms\"],x)\n",
359
+ " if best_rmsd is None or o[\"rms\"] < best_rmsd:\n",
360
+ " best_rmsd = o[\"rms\"]\n",
361
+ " best = {**o,\"seq\":x}"
362
+ ],
363
+ "metadata": {
364
+ "id": "Ey29NmNAFtK0"
365
+ },
366
+ "execution_count": null,
367
+ "outputs": []
368
+ },
369
+ {
370
+ "cell_type": "code",
371
+ "source": [
372
+ "best"
373
+ ],
374
+ "metadata": {
375
+ "id": "ltH6cLw5NhuX"
376
+ },
377
+ "execution_count": null,
378
+ "outputs": []
379
+ }
380
+ ],
381
+ "metadata": {
382
+ "accelerator": "GPU",
383
+ "colab": {
384
+ "collapsed_sections": [
385
+ "q4qiU9I0QHSz"
386
+ ],
387
+ "provenance": [],
388
+ "include_colab_link": true
389
+ },
390
+ "kernelspec": {
391
+ "display_name": "Python 3",
392
+ "name": "python3"
393
+ },
394
+ "language_info": {
395
+ "name": "python"
396
+ }
397
+ },
398
+ "nbformat": 4,
399
+ "nbformat_minor": 0
400
+ }
model/PXDesignBench/ColabDesign/af/examples/af_single_sequential.ipynb ADDED
@@ -0,0 +1,164 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "cells": [
3
+ {
4
+ "cell_type": "markdown",
5
+ "metadata": {
6
+ "id": "view-in-github",
7
+ "colab_type": "text"
8
+ },
9
+ "source": [
10
+ "<a href=\"https://colab.research.google.com/github/sokrypton/ColabDesign/blob/v1.1.1/af/examples/af_single_sequential.ipynb\" target=\"_parent\"><img src=\"https://colab.research.google.com/assets/colab-badge.svg\" alt=\"Open In Colab\"/></a>"
11
+ ]
12
+ },
13
+ {
14
+ "cell_type": "code",
15
+ "execution_count": null,
16
+ "metadata": {
17
+ "cellView": "form",
18
+ "id": "-AXy0s_4cKaK"
19
+ },
20
+ "outputs": [],
21
+ "source": [
22
+ "#@title af_single_sequential\n",
23
+ "#@markdown implementing [@MartinPacesa](https://twitter.com/MartinPacesa/status/1640005299124707328)'s idea\n",
24
+ "import os\n",
25
+ "if not os.path.isdir(\"params\"):\n",
26
+ " print(\"installing AlphaFold...\")\n",
27
+ " # get code\n",
28
+ " os.system(\"pip -q install git+https://github.com/sokrypton/ColabDesign.git@v1.1.1\")\n",
29
+ " # for debugging\n",
30
+ " os.system(\"ln -s /usr/local/lib/python3.*/dist-packages/colabdesign colabdesign\")\n",
31
+ " print(\"downloading AlphaFold params...\")\n",
32
+ " # download params\n",
33
+ " os.system(\"mkdir params\")\n",
34
+ " os.system(\"apt-get install aria2 -qq\")\n",
35
+ " os.system(\"aria2c -q -x 16 https://storage.googleapis.com/alphafold/alphafold_params_2022-03-02.tar\")\n",
36
+ " os.system(\"tar -xf alphafold_params_2022-03-02.tar -C params\")\n",
37
+ "\n",
38
+ "import os\n",
39
+ "from colabdesign import mk_afdesign_model, clear_mem\n",
40
+ "from IPython.display import HTML\n",
41
+ "from google.colab import files\n",
42
+ "import numpy as np\n",
43
+ "import tqdm.notebook\n",
44
+ "TQDM_BAR_FORMAT = '{l_bar}{bar}| {n_fmt}/{total_fmt} [elapsed: {elapsed} remaining: {remaining}]'\n",
45
+ "def get_pdb(pdb_code=\"\"):\n",
46
+ " if pdb_code is None or pdb_code == \"\":\n",
47
+ " upload_dict = files.upload()\n",
48
+ " pdb_string = upload_dict[list(upload_dict.keys())[0]]\n",
49
+ " with open(\"tmp.pdb\",\"wb\") as out: out.write(pdb_string)\n",
50
+ " return \"tmp.pdb\"\n",
51
+ " elif os.path.isfile(pdb_code):\n",
52
+ " return pdb_code\n",
53
+ " elif len(pdb_code) == 4:\n",
54
+ " os.system(f\"wget -qnc https://files.rcsb.org/view/{pdb_code}.pdb\")\n",
55
+ " return f\"{pdb_code}.pdb\"\n",
56
+ " else:\n",
57
+ " os.system(f\"wget -qnc https://alphafold.ebi.ac.uk/files/AF-{pdb_code}-F1-model_v3.pdb\")\n",
58
+ " return f\"AF-{pdb_code}-F1-model_v3.pdb\"\n",
59
+ "\n",
60
+ "#@markdown Specify either pdb/pdb_chain or sequence:\n",
61
+ "pdb = \"6D0T\" #@param {type:\"string\"}\n",
62
+ "pdb_chain = \"A\" #@param {type:\"string\"}\n",
63
+ "sequence = \"\" #@param {type:\"string\"}\n",
64
+ "num_recycles = 0 #@param [\"0\", \"1\", \"2\", \"4\", \"8\", \"16\"] {type:\"raw\"}\n",
65
+ "clear_mem()\n",
66
+ "if sequence == \"\":\n",
67
+ " pdb_filename = get_pdb(pdb)\n",
68
+ " af_model = mk_afdesign_model(protocol=\"fixbb\")\n",
69
+ " af_model.prep_inputs(pdb_filename=pdb_filename, chain=pdb_chain)\n",
70
+ " af_model.set_seq(mode=\"wildtype\")\n",
71
+ " mode = \"pdb\"\n",
72
+ "else:\n",
73
+ " af_model = mk_afdesign_model(protocol=\"hallucination\")\n",
74
+ " af_model.prep_inputs(length=len(sequence))\n",
75
+ " af_model.set_seq(sequence)\n",
76
+ " mode = \"free\"\n",
77
+ "\n",
78
+ "import random, string\n",
79
+ "path = ''.join(random.choices(string.ascii_lowercase + string.digits, k=5))\n",
80
+ "while os.path.isdir(path):\n",
81
+ " path = ''.join(random.choices(string.ascii_lowercase + string.digits, k=5))\n",
82
+ "\n",
83
+ "seq = af_model._params[\"seq\"].copy()\n",
84
+ "os.makedirs(path, exist_ok=True)\n",
85
+ "with tqdm.notebook.tqdm(total=af_model._len, bar_format=TQDM_BAR_FORMAT) as pbar:\n",
86
+ " for n in range(1,af_model._len+1):\n",
87
+ " \n",
88
+ " # replace sequence (this is just for visualization)\n",
89
+ " af_model._params[\"seq\"] = seq.copy()\n",
90
+ " af_model._params[\"seq\"][:,n:] = 0\n",
91
+ " \n",
92
+ " # mask part of the input features\n",
93
+ " af_model._inputs[\"seq_mask\"] = (np.arange(af_model._len) < n).astype(float)\n",
94
+ " af_model.predict(verbose=False, hard=False, num_recycles=num_recycles)\n",
95
+ " af_model._save_results(verbose=False)\n",
96
+ " af_model.save_current_pdb(f\"{path}/{n:04d}.pdb\")\n",
97
+ " pbar.update(1)"
98
+ ]
99
+ },
100
+ {
101
+ "cell_type": "code",
102
+ "source": [
103
+ "HTML(af_model.animate(dpi=100))"
104
+ ],
105
+ "metadata": {
106
+ "id": "lphWx8wkEpwP"
107
+ },
108
+ "execution_count": null,
109
+ "outputs": []
110
+ },
111
+ {
112
+ "cell_type": "code",
113
+ "source": [
114
+ "af_model.plot_pdb()"
115
+ ],
116
+ "metadata": {
117
+ "id": "9h1uXK44TygM"
118
+ },
119
+ "execution_count": null,
120
+ "outputs": []
121
+ },
122
+ {
123
+ "cell_type": "code",
124
+ "source": [
125
+ "#@title Package and download results\n",
126
+ "#@markdown If you are having issues downloading the result archive, \n",
127
+ "#@markdown try disabling your adblocker and run this cell again. \n",
128
+ "#@markdown If that fails click on the little folder icon to the \n",
129
+ "#@markdown left, navigate to file: `name.result.zip`, \n",
130
+ "#@markdown right-click and select \\\"Download\\\" \n",
131
+ "#@markdown (see [screenshot](https://pbs.twimg.com/media/E6wRW2lWUAEOuoe?format=jpg&name=small)).\n",
132
+ "from google.colab import files\n",
133
+ "!zip -r {path}.result.zip {path}/*\n",
134
+ "files.download(f\"{path}.result.zip\")"
135
+ ],
136
+ "metadata": {
137
+ "id": "zGE1CJxuTzyQ",
138
+ "cellView": "form"
139
+ },
140
+ "execution_count": null,
141
+ "outputs": []
142
+ }
143
+ ],
144
+ "metadata": {
145
+ "accelerator": "GPU",
146
+ "colab": {
147
+ "collapsed_sections": [
148
+ "q4qiU9I0QHSz"
149
+ ],
150
+ "provenance": [],
151
+ "include_colab_link": true
152
+ },
153
+ "kernelspec": {
154
+ "display_name": "Python 3",
155
+ "name": "python3"
156
+ },
157
+ "language_info": {
158
+ "name": "python"
159
+ },
160
+ "gpuClass": "standard"
161
+ },
162
+ "nbformat": 4,
163
+ "nbformat_minor": 0
164
+ }
model/PXDesignBench/ColabDesign/af/examples/afdesign_hotspot_test.ipynb ADDED
@@ -0,0 +1,247 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "cells": [
3
+ {
4
+ "cell_type": "markdown",
5
+ "metadata": {
6
+ "id": "view-in-github",
7
+ "colab_type": "text"
8
+ },
9
+ "source": [
10
+ "<a href=\"https://colab.research.google.com/github/sokrypton/ColabDesign/blob/v1.1.1/af/examples/afdesign_hotspot_test.ipynb\" target=\"_parent\"><img src=\"https://colab.research.google.com/assets/colab-badge.svg\" alt=\"Open In Colab\"/></a>"
11
+ ]
12
+ },
13
+ {
14
+ "cell_type": "markdown",
15
+ "metadata": {
16
+ "id": "OA2k3sAYuiXe"
17
+ },
18
+ "source": [
19
+ "# AfDesign - binder + hotspot test"
20
+ ]
21
+ },
22
+ {
23
+ "cell_type": "code",
24
+ "execution_count": null,
25
+ "metadata": {
26
+ "id": "-AXy0s_4cKaK",
27
+ "cellView": "form"
28
+ },
29
+ "outputs": [],
30
+ "source": [
31
+ "#@title setup\n",
32
+ "%%time\n",
33
+ "import os\n",
34
+ "if not os.path.isdir(\"params\"):\n",
35
+ " # get code\n",
36
+ " os.system(\"pip -q install git+https://github.com/sokrypton/ColabDesign.git@v1.1.1\")\n",
37
+ " # for debugging\n",
38
+ " os.system(\"ln -s /usr/local/lib/python3.*/dist-packages/colabdesign colabdesign\")\n",
39
+ " # download params\n",
40
+ " os.system(\"mkdir params\")\n",
41
+ " os.system(\"apt-get install aria2 -qq\")\n",
42
+ " os.system(\"aria2c -q -x 16 https://storage.googleapis.com/alphafold/alphafold_params_2022-12-06.tar\")\n",
43
+ " os.system(\"tar -xf alphafold_params_2022-12-06.tar -C params\")\n",
44
+ "\n",
45
+ "import warnings\n",
46
+ "warnings.simplefilter(action='ignore', category=FutureWarning)\n",
47
+ "\n",
48
+ "import os\n",
49
+ "from colabdesign import mk_afdesign_model, clear_mem\n",
50
+ "from IPython.display import HTML\n",
51
+ "from google.colab import files\n",
52
+ "import numpy as np\n",
53
+ "\n",
54
+ "def get_pdb(pdb_code=\"\"):\n",
55
+ " if pdb_code is None or pdb_code == \"\":\n",
56
+ " upload_dict = files.upload()\n",
57
+ " pdb_string = upload_dict[list(upload_dict.keys())[0]]\n",
58
+ " with open(\"tmp.pdb\",\"wb\") as out: out.write(pdb_string)\n",
59
+ " return \"tmp.pdb\"\n",
60
+ " elif os.path.isfile(pdb_code):\n",
61
+ " return pdb_code\n",
62
+ " elif len(pdb_code) == 4:\n",
63
+ " os.system(f\"wget -qnc https://files.rcsb.org/view/{pdb_code}.pdb\")\n",
64
+ " return f\"{pdb_code}.pdb\"\n",
65
+ " else:\n",
66
+ " os.system(f\"wget -qnc https://alphafold.ebi.ac.uk/files/AF-{pdb_code}-F1-model_v3.pdb\")\n",
67
+ " return f\"AF-{pdb_code}-F1-model_v3.pdb\""
68
+ ]
69
+ },
70
+ {
71
+ "cell_type": "code",
72
+ "source": [
73
+ "%%bash\n",
74
+ "wget -qnc https://raw.githubusercontent.com/casperg92/MaSIF_colab/main/example/monomerexample.pdb"
75
+ ],
76
+ "metadata": {
77
+ "id": "TIGDV-NqGMAw"
78
+ },
79
+ "execution_count": null,
80
+ "outputs": []
81
+ },
82
+ {
83
+ "cell_type": "code",
84
+ "execution_count": null,
85
+ "metadata": {
86
+ "id": "3XLJPiRKx5Mw"
87
+ },
88
+ "outputs": [],
89
+ "source": [
90
+ "clear_mem()\n",
91
+ "model = mk_afdesign_model(protocol=\"binder\")\n",
92
+ "\n",
93
+ "# pos = define positions (hotspot) on target you want to target for binder\n",
94
+ "model.prep_inputs(pdb_filename=\"monomerexample.pdb\", chain=\"A\",\n",
95
+ " binder_len=20,\n",
96
+ " hotspot=\"33,17,6,34,30,19,37,15\") \n",
97
+ "\n",
98
+ "print(\"target_length\",model._target_len)\n",
99
+ "print(\"binder_length\",model._binder_len)\n",
100
+ "print(\"weights\",model.opt[\"weights\"])"
101
+ ]
102
+ },
103
+ {
104
+ "cell_type": "code",
105
+ "execution_count": null,
106
+ "metadata": {
107
+ "id": "u6VxjuinyCZa"
108
+ },
109
+ "outputs": [],
110
+ "source": [
111
+ "model.restart(mode=\"soft_gumbel\")\n",
112
+ "model.design_3stage(100, 100, 10)"
113
+ ]
114
+ },
115
+ {
116
+ "cell_type": "code",
117
+ "execution_count": null,
118
+ "metadata": {
119
+ "id": "9cARoviGyIKb"
120
+ },
121
+ "outputs": [],
122
+ "source": [
123
+ "HTML(model.animate())"
124
+ ]
125
+ },
126
+ {
127
+ "cell_type": "code",
128
+ "source": [
129
+ "model.get_seqs()"
130
+ ],
131
+ "metadata": {
132
+ "id": "RzE137NDZdZc"
133
+ },
134
+ "execution_count": null,
135
+ "outputs": []
136
+ },
137
+ {
138
+ "cell_type": "code",
139
+ "source": [
140
+ "model.plot_pdb()\n",
141
+ "model.save_pdb(f\"{model.protocol}.pdb\")"
142
+ ],
143
+ "metadata": {
144
+ "id": "sTlS7_L8Zfwf"
145
+ },
146
+ "execution_count": null,
147
+ "outputs": []
148
+ },
149
+ {
150
+ "cell_type": "markdown",
151
+ "source": [
152
+ "as a control, let's try hallucinate a binder without defining a hotspot"
153
+ ],
154
+ "metadata": {
155
+ "id": "aGW9s5t3Xlk4"
156
+ }
157
+ },
158
+ {
159
+ "cell_type": "code",
160
+ "source": [
161
+ "clear_mem()\n",
162
+ "model = mk_afdesign_model(protocol=\"binder\")\n",
163
+ "model.prep_inputs(pdb_filename=\"monomerexample.pdb\", chain=\"A\", binder_len=20)"
164
+ ],
165
+ "metadata": {
166
+ "id": "KzkNzuS6Xpqj"
167
+ },
168
+ "execution_count": null,
169
+ "outputs": []
170
+ },
171
+ {
172
+ "cell_type": "code",
173
+ "source": [
174
+ "model.restart(mode=\"soft_gumbel\")\n",
175
+ "model.design_3stage(100, 100, 10)"
176
+ ],
177
+ "metadata": {
178
+ "id": "wjFi2uhwXtPz"
179
+ },
180
+ "execution_count": null,
181
+ "outputs": []
182
+ },
183
+ {
184
+ "cell_type": "code",
185
+ "source": [
186
+ "HTML(model.animate())"
187
+ ],
188
+ "metadata": {
189
+ "id": "pBRNpspoX6pR"
190
+ },
191
+ "execution_count": null,
192
+ "outputs": []
193
+ },
194
+ {
195
+ "cell_type": "code",
196
+ "source": [
197
+ "model.get_seqs()"
198
+ ],
199
+ "metadata": {
200
+ "id": "J43oqomrYA8v"
201
+ },
202
+ "execution_count": null,
203
+ "outputs": []
204
+ },
205
+ {
206
+ "cell_type": "code",
207
+ "source": [
208
+ "model.plot_pdb()\n",
209
+ "model.save_pdb(f\"{model.protocol}.control.pdb\")"
210
+ ],
211
+ "metadata": {
212
+ "id": "r2d86kMVX_SL"
213
+ },
214
+ "execution_count": null,
215
+ "outputs": []
216
+ },
217
+ {
218
+ "cell_type": "code",
219
+ "source": [],
220
+ "metadata": {
221
+ "id": "xw_5hblQmRqn"
222
+ },
223
+ "execution_count": null,
224
+ "outputs": []
225
+ }
226
+ ],
227
+ "metadata": {
228
+ "accelerator": "GPU",
229
+ "colab": {
230
+ "collapsed_sections": [
231
+ "q4qiU9I0QHSz"
232
+ ],
233
+ "name": "afdesign_hotspot_test.ipynb",
234
+ "provenance": [],
235
+ "include_colab_link": true
236
+ },
237
+ "kernelspec": {
238
+ "display_name": "Python 3",
239
+ "name": "python3"
240
+ },
241
+ "language_info": {
242
+ "name": "python"
243
+ }
244
+ },
245
+ "nbformat": 4,
246
+ "nbformat_minor": 0
247
+ }
model/PXDesignBench/ColabDesign/af/examples/binder_hallucination.ipynb ADDED
@@ -0,0 +1,42 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "cells": [
3
+ {
4
+ "cell_type": "markdown",
5
+ "metadata": {
6
+ "id": "view-in-github",
7
+ "colab_type": "text"
8
+ },
9
+ "source": [
10
+ "<a href=\"https://colab.research.google.com/github/sokrypton/ColabDesign/blob/v1.1.1/af/examples/peptide_binder_design.ipynb\" target=\"_parent\"><img src=\"https://colab.research.google.com/assets/colab-badge.svg\" alt=\"Open In Colab\"/></a>"
11
+ ]
12
+ },
13
+ {
14
+ "cell_type": "markdown",
15
+ "metadata": {
16
+ "id": "OA2k3sAYuiXe"
17
+ },
18
+ "source": [
19
+ "this notebook moved to: [peptide_binder_design.ipynb](https://colab.research.google.com/github/sokrypton/ColabDesign/blob/v1.1.1/af/examples/peptide_binder_design.ipynb)"
20
+ ]
21
+ }
22
+ ],
23
+ "metadata": {
24
+ "accelerator": "GPU",
25
+ "colab": {
26
+ "collapsed_sections": [
27
+ "q4qiU9I0QHSz"
28
+ ],
29
+ "provenance": [],
30
+ "include_colab_link": true
31
+ },
32
+ "kernelspec": {
33
+ "display_name": "Python 3",
34
+ "name": "python3"
35
+ },
36
+ "language_info": {
37
+ "name": "python"
38
+ }
39
+ },
40
+ "nbformat": 4,
41
+ "nbformat_minor": 0
42
+ }
model/PXDesignBench/ColabDesign/af/examples/disulfide_design.ipynb ADDED
@@ -0,0 +1,348 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "cells": [
3
+ {
4
+ "cell_type": "markdown",
5
+ "metadata": {
6
+ "id": "view-in-github",
7
+ "colab_type": "text"
8
+ },
9
+ "source": [
10
+ "<a href=\"https://colab.research.google.com/github/sokrypton/ColabDesign/blob/v1.1.1/af/examples/disulfide_design.ipynb\" target=\"_parent\"><img src=\"https://colab.research.google.com/assets/colab-badge.svg\" alt=\"Open In Colab\"/></a>"
11
+ ]
12
+ },
13
+ {
14
+ "cell_type": "markdown",
15
+ "metadata": {
16
+ "id": "YRk_XS2NILil"
17
+ },
18
+ "source": [
19
+ "# disulfide-hallucination\n",
20
+ "For a given length, generate/hallucinate a disulfide-rich sequence that AlphaFold thinks folds into a well structured protein"
21
+ ]
22
+ },
23
+ {
24
+ "cell_type": "code",
25
+ "execution_count": null,
26
+ "metadata": {
27
+ "cellView": "form",
28
+ "id": "-AXy0s_4cKaK"
29
+ },
30
+ "outputs": [],
31
+ "source": [
32
+ "#@title setup\n",
33
+ "%%time\n",
34
+ "import os\n",
35
+ "if not os.path.isdir(\"params\"):\n",
36
+ " # get code\n",
37
+ " os.system(\"pip -q install git+https://github.com/sokrypton/ColabDesign.git@v1.1.1\")\n",
38
+ " # for debugging\n",
39
+ " os.system(\"ln -s /usr/local/lib/python3.*/dist-packages/colabdesign colabdesign\")\n",
40
+ " # download params\n",
41
+ " os.system(\"mkdir params\")\n",
42
+ " os.system(\"apt-get install aria2 -qq\")\n",
43
+ " os.system(\"aria2c -q -x 16 https://storage.googleapis.com/alphafold/alphafold_params_2022-12-06.tar\")\n",
44
+ " os.system(\"tar -xf alphafold_params_2022-12-06.tar -C params\")\n",
45
+ "\n",
46
+ "import warnings\n",
47
+ "warnings.simplefilter(action='ignore', category=FutureWarning)\n",
48
+ "\n",
49
+ "import os\n",
50
+ "from colabdesign import mk_afdesign_model, clear_mem\n",
51
+ "from IPython.display import HTML\n",
52
+ "from google.colab import files\n",
53
+ "import numpy as np\n",
54
+ "\n",
55
+ "def get_pdb(pdb_code=\"\"):\n",
56
+ " if pdb_code is None or pdb_code == \"\":\n",
57
+ " upload_dict = files.upload()\n",
58
+ " pdb_string = upload_dict[list(upload_dict.keys())[0]]\n",
59
+ " with open(\"tmp.pdb\",\"wb\") as out: out.write(pdb_string)\n",
60
+ " return \"tmp.pdb\"\n",
61
+ " elif os.path.isfile(pdb_code):\n",
62
+ " return pdb_code\n",
63
+ " elif len(pdb_code) == 4:\n",
64
+ " os.system(f\"wget -qnc https://files.rcsb.org/view/{pdb_code}.pdb\")\n",
65
+ " return f\"{pdb_code}.pdb\"\n",
66
+ " else:\n",
67
+ " os.system(f\"wget -qnc https://alphafold.ebi.ac.uk/files/AF-{pdb_code}-F1-model_v3.pdb\")\n",
68
+ " return f\"AF-{pdb_code}-F1-model_v3.pdb\""
69
+ ]
70
+ },
71
+ {
72
+ "cell_type": "code",
73
+ "execution_count": null,
74
+ "metadata": {
75
+ "id": "7JbLyVu4ILil"
76
+ },
77
+ "outputs": [],
78
+ "source": [
79
+ "import random\n",
80
+ "from jax.lax import dynamic_slice\n",
81
+ "import jax.numpy as jnp\n",
82
+ "\n",
83
+ "from colabdesign.af.loss import _get_con_loss\n",
84
+ "def get_con_loss(dgram, dgram_bins, cutoff=None, binary=True,\n",
85
+ " num=1, seqsep=0, offset=None):\n",
86
+ " '''convert distogram into contact loss''' \n",
87
+ " x = _get_con_loss(dgram, dgram_bins, cutoff, binary) \n",
88
+ " a,b = x.shape\n",
89
+ " if offset is None:\n",
90
+ " mask = jnp.abs(jnp.arange(a)[:,None] - jnp.arange(b)[None,:]) >= seqsep\n",
91
+ " else:\n",
92
+ " mask = jnp.abs(offset) >= seqsep\n",
93
+ " x = jnp.sort(jnp.where(mask,x,jnp.nan))\n",
94
+ " k_mask = (jnp.arange(b) < num) * (jnp.isnan(x) == False) \n",
95
+ " return jnp.where(k_mask,x,0.0).sum(-1) / (k_mask.sum(-1) + 1e-8)\n",
96
+ "\n",
97
+ "def generate_disulfide_pattern(L, disulfide_num, min_sep=5):\n",
98
+ " disulfide_pattern = []\n",
99
+ " positions = list(range(L))\n",
100
+ " for n in range(disulfide_num):\n",
101
+ " for _ in range(100): # try 100 time per postion.\n",
102
+ " i,j = random.sample(positions, k=2)\n",
103
+ " if abs(i-j)<=min_sep: continue # set min loop len.\n",
104
+ " positions.remove(i)\n",
105
+ " positions.remove(j)\n",
106
+ " disulfide_pattern.append((i,j))\n",
107
+ " # check\n",
108
+ " if _ > 99:\n",
109
+ " print('Not find good disulfide_pos! exit....')\n",
110
+ " return 0 # not good pose!\n",
111
+ " else:\n",
112
+ " break\n",
113
+ " sequence_pattern = list('X'*L)\n",
114
+ " for pair in disulfide_pattern:\n",
115
+ " for i in pair: sequence_pattern[i] = 'C'\n",
116
+ "\n",
117
+ " return disulfide_pattern, ''.join(sequence_pattern), L\n",
118
+ "\n",
119
+ "def disulfide_loss(inputs, outputs):\n",
120
+ " def get_disulfide_loss(dgram, dgram_bins, disulfide_pattern):\n",
121
+ " '''\n",
122
+ " Func: simple disulfide loss, make the contacts < 7.0/7.5A.\n",
123
+ " # see: https://www.ncbi.nlm.nih.gov/pmc/articles/PMC7316719/\n",
124
+ " params: disulfide_pattern: List[(pos1, pos2), (pos3, pos4)...]\n",
125
+ " '''\n",
126
+ " disulfide_loss = 0.0\n",
127
+ " for pair in disulfide_pattern:\n",
128
+ " i,j = pair\n",
129
+ " pair_dgram = dynamic_slice(dgram, (i,j,0), (1,1,len(dgram_bins))) + dynamic_slice(dgram, (j,i,0), (1,1,len(dgram_bins)))\n",
130
+ " disulfide_loss += get_con_loss(pair_dgram, dgram_bins, cutoff=7.0, binary=False, num=1)\n",
131
+ " return disulfide_loss.mean()\n",
132
+ "\n",
133
+ " # add disulfide loss here:\n",
134
+ " dgram_logits = outputs['distogram']['logits']\n",
135
+ " dgram_bins = jnp.append(0, outputs[\"distogram\"][\"bin_edges\"])\n",
136
+ " return {\"disulfide\":get_disulfide_loss(dgram_logits, dgram_bins, inputs['opt']['disulfide_pattern'])}"
137
+ ]
138
+ },
139
+ {
140
+ "cell_type": "markdown",
141
+ "metadata": {
142
+ "id": "aU4e-ZkfILim"
143
+ },
144
+ "source": [
145
+ "0. generate_cys_pattern"
146
+ ]
147
+ },
148
+ {
149
+ "cell_type": "code",
150
+ "execution_count": null,
151
+ "metadata": {
152
+ "id": "vrSatV2sILim"
153
+ },
154
+ "outputs": [],
155
+ "source": [
156
+ "disulfide_pattern, sequence_pattern, L = generate_disulfide_pattern(35, 3)\n",
157
+ "print(disulfide_pattern)\n",
158
+ "print(sequence_pattern)\n",
159
+ "print(L)"
160
+ ]
161
+ },
162
+ {
163
+ "cell_type": "markdown",
164
+ "metadata": {
165
+ "id": "jGNGjHeyILim"
166
+ },
167
+ "source": [
168
+ "1. hallucination with disulfide-pattern"
169
+ ]
170
+ },
171
+ {
172
+ "cell_type": "code",
173
+ "execution_count": null,
174
+ "metadata": {
175
+ "id": "HmsBDNhmILin"
176
+ },
177
+ "outputs": [],
178
+ "source": [
179
+ "# using some disulfide sequence as input:\n",
180
+ "clear_mem()\n",
181
+ "af_model = mk_afdesign_model(protocol=\"hallucination\", loss_callback=disulfide_loss)\n",
182
+ "af_model.opt[\"weights\"][\"disulfide\"] = 1.0\n",
183
+ "af_model.prep_inputs(length=L)\n",
184
+ "\n",
185
+ "print(\"length\",af_model._len)\n",
186
+ "print(\"weights\",af_model.opt[\"weights\"])"
187
+ ]
188
+ },
189
+ {
190
+ "cell_type": "code",
191
+ "execution_count": null,
192
+ "metadata": {
193
+ "id": "MmBtBMnBILin"
194
+ },
195
+ "outputs": [],
196
+ "source": [
197
+ "# set disulfide_pattern sequence.\n",
198
+ "af_model.restart(seq=sequence_pattern, add_seq=True, rm_aa='C')\n",
199
+ "# set disulfide_pattern:\n",
200
+ "af_model.opt['disulfide_pattern'] = disulfide_pattern\n",
201
+ "# reweight con:\n",
202
+ "af_model.opt[\"weights\"]['con'] = 0.5"
203
+ ]
204
+ },
205
+ {
206
+ "cell_type": "code",
207
+ "source": [
208
+ "af_model.design_3stage(50,50,10)"
209
+ ],
210
+ "metadata": {
211
+ "id": "wstI0n4zMydi"
212
+ },
213
+ "execution_count": null,
214
+ "outputs": []
215
+ },
216
+ {
217
+ "cell_type": "code",
218
+ "execution_count": null,
219
+ "metadata": {
220
+ "id": "ewlj8671ILio"
221
+ },
222
+ "outputs": [],
223
+ "source": [
224
+ "af_model.save_pdb(f\"{af_model.protocol}.pdb\")\n",
225
+ "af_model.plot_pdb(show_sidechains=True)"
226
+ ]
227
+ },
228
+ {
229
+ "cell_type": "markdown",
230
+ "metadata": {
231
+ "id": "iVEqJKaKILio"
232
+ },
233
+ "source": [
234
+ "2. fix-sidechain with pyRosetta"
235
+ ]
236
+ },
237
+ {
238
+ "cell_type": "code",
239
+ "execution_count": null,
240
+ "metadata": {
241
+ "id": "VGwyvaodILio"
242
+ },
243
+ "outputs": [],
244
+ "source": [
245
+ "from pyrosetta import init, pose_from_pdb, Pose, create_score_function\n",
246
+ "from pyrosetta.rosetta.protocols.relax import FastRelax\n",
247
+ "from pyrosetta.rosetta.core.pack.task import TaskFactory\n",
248
+ "from pyrosetta.rosetta.core.kinematics import MoveMap\n",
249
+ "from pyrosetta.rosetta.core.pack.task.operation import InitializeFromCommandline\n",
250
+ "from pyrosetta.rosetta.protocols.denovo_design import DisulfidizeMover\n",
251
+ "from pyrosetta.rosetta.core.pack.task.operation import RestrictToRepacking\n",
252
+ "from pyrosetta.rosetta.core.select.residue_selector import ChainSelector\n",
253
+ "\n",
254
+ "def fastrelax(pose):\n",
255
+ " full_score = create_score_function('ref2015')\n",
256
+ " tf = TaskFactory()\n",
257
+ " # tf.push_back(InitializeFromCommandline())\n",
258
+ " tf.push_back(RestrictToRepacking())\n",
259
+ " mmap = MoveMap()\n",
260
+ " mmap.set_bb(True)\n",
261
+ " mmap.set_chi(True)\n",
262
+ "\n",
263
+ " # FastRelax:\n",
264
+ " fast_design = FastRelax(full_score, 4) # repeat:6\n",
265
+ " fast_design.set_task_factory(tf)\n",
266
+ " fast_design.set_movemap(mmap)\n",
267
+ " fast_design.apply(pose)\n",
268
+ " \n",
269
+ "def build_stapled_pose(pose, cys_pattern):\n",
270
+ " # rebuild \n",
271
+ " disulfidizer = DisulfidizeMover()\n",
272
+ " disulfidizer.set_match_rt_limit(999.0)\n",
273
+ " disulfidizer.set_max_disulf_score(999.0)\n",
274
+ " for pair in cys_pattern:\n",
275
+ " full_score = create_score_function('ref2015')\n",
276
+ " stapled_pose = Pose().assign(pose) # pose for disulfides stapled\n",
277
+ " residue1, residue2 = pair\n",
278
+ " disulfidizer.make_disulfide(stapled_pose, residue1+1, residue2+1, False, full_score)\n",
279
+ " # fastdesign mover\n",
280
+ " pdbnum1 = stapled_pose.pdb_info().pose2pdb(residue1)\n",
281
+ " pdbnum2 = stapled_pose.pdb_info().pose2pdb(residue2)\n",
282
+ " print('# OPTIMIZE: Around These Residues: %s %s' % (pdbnum1, pdbnum2))\n",
283
+ "\n",
284
+ " # save pdb:\n",
285
+ " fastrelax(stapled_pose)\n",
286
+ " \n",
287
+ " # filter: all stapled?\n",
288
+ " v = ChainSelector(1).apply(stapled_pose)\n",
289
+ " l = disulfidizer.find_current_disulfides(stapled_pose, v, v)\n",
290
+ " print(len([i for i in l]), len(cys_pattern))\n",
291
+ " if len([i for i in l]) == len(cys_pattern):\n",
292
+ " return stapled_pose\n",
293
+ " else:\n",
294
+ " return 0\n",
295
+ " "
296
+ ]
297
+ },
298
+ {
299
+ "cell_type": "code",
300
+ "execution_count": null,
301
+ "metadata": {
302
+ "id": "zhMey-4lILip"
303
+ },
304
+ "outputs": [],
305
+ "source": [
306
+ "# optimze the side-chain\n",
307
+ "init('-mute all')\n",
308
+ "pose = pose_from_pdb(f\"{af_model.protocol}.pdb\")\n",
309
+ "stapled_pose = build_stapled_pose(pose, disulfide_pattern)"
310
+ ]
311
+ }
312
+ ],
313
+ "metadata": {
314
+ "accelerator": "GPU",
315
+ "colab": {
316
+ "collapsed_sections": [
317
+ "q4qiU9I0QHSz"
318
+ ],
319
+ "name": "disulfide_design.ipynb",
320
+ "provenance": [],
321
+ "include_colab_link": true
322
+ },
323
+ "kernelspec": {
324
+ "display_name": "Python 3.8.10 64-bit",
325
+ "language": "python",
326
+ "name": "python3"
327
+ },
328
+ "language_info": {
329
+ "codemirror_mode": {
330
+ "name": "ipython",
331
+ "version": 3
332
+ },
333
+ "file_extension": ".py",
334
+ "mimetype": "text/x-python",
335
+ "name": "python",
336
+ "nbconvert_exporter": "python",
337
+ "pygments_lexer": "ipython3",
338
+ "version": "3.8.10"
339
+ },
340
+ "vscode": {
341
+ "interpreter": {
342
+ "hash": "31f2aee4e71d21fbe5cf8b01ff0e069b9275f58929596ceb00d14d90e3e16cd6"
343
+ }
344
+ }
345
+ },
346
+ "nbformat": 4,
347
+ "nbformat_minor": 0
348
+ }
model/PXDesignBench/ColabDesign/af/examples/hallucination.ipynb ADDED
@@ -0,0 +1,193 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "cells": [
3
+ {
4
+ "cell_type": "markdown",
5
+ "metadata": {
6
+ "id": "view-in-github",
7
+ "colab_type": "text"
8
+ },
9
+ "source": [
10
+ "<a href=\"https://colab.research.google.com/github/sokrypton/ColabDesign/blob/v1.1.1/af/examples/hallucination.ipynb\" target=\"_parent\"><img src=\"https://colab.research.google.com/assets/colab-badge.svg\" alt=\"Open In Colab\"/></a>"
11
+ ]
12
+ },
13
+ {
14
+ "cell_type": "markdown",
15
+ "metadata": {
16
+ "id": "OA2k3sAYuiXe"
17
+ },
18
+ "source": [
19
+ "# AfDesign - hallucination\n",
20
+ "For a given length, generate/hallucinate a protein sequence that AlphaFold thinks folds into a well structured protein (high plddt, low pae, many contacts).\n",
21
+ "\n",
22
+ "**WARNING**\n",
23
+ "1. This notebook is in active development and was designed for demonstration purposes only.\n",
24
+ "2. Using AfDesign as the only \"loss\" function for design might be a bad idea, you may find adversarial sequences (aka. sequences that trick AlphaFold)."
25
+ ]
26
+ },
27
+ {
28
+ "cell_type": "code",
29
+ "execution_count": null,
30
+ "metadata": {
31
+ "cellView": "form",
32
+ "id": "-AXy0s_4cKaK"
33
+ },
34
+ "outputs": [],
35
+ "source": [
36
+ "#@title setup\n",
37
+ "%%time\n",
38
+ "import os\n",
39
+ "if not os.path.isdir(\"params\"):\n",
40
+ " # get code\n",
41
+ " os.system(\"pip -q install git+https://github.com/sokrypton/ColabDesign.git@v1.1.1\")\n",
42
+ " # for debugging\n",
43
+ " os.system(\"ln -s /usr/local/lib/python3.*/dist-packages/colabdesign colabdesign\")\n",
44
+ " # download params\n",
45
+ " os.system(\"mkdir params\")\n",
46
+ " os.system(\"apt-get install aria2 -qq\")\n",
47
+ " os.system(\"aria2c -q -x 16 https://storage.googleapis.com/alphafold/alphafold_params_2022-12-06.tar\")\n",
48
+ " os.system(\"tar -xf alphafold_params_2022-12-06.tar -C params\")\n",
49
+ "\n",
50
+ "import warnings\n",
51
+ "warnings.simplefilter(action='ignore', category=FutureWarning)\n",
52
+ "\n",
53
+ "import os\n",
54
+ "from colabdesign import mk_afdesign_model, clear_mem\n",
55
+ "from IPython.display import HTML\n",
56
+ "from google.colab import files\n",
57
+ "import numpy as np\n",
58
+ "\n",
59
+ "def get_pdb(pdb_code=\"\"):\n",
60
+ " if pdb_code is None or pdb_code == \"\":\n",
61
+ " upload_dict = files.upload()\n",
62
+ " pdb_string = upload_dict[list(upload_dict.keys())[0]]\n",
63
+ " with open(\"tmp.pdb\",\"wb\") as out: out.write(pdb_string)\n",
64
+ " return \"tmp.pdb\"\n",
65
+ " elif os.path.isfile(pdb_code):\n",
66
+ " return pdb_code\n",
67
+ " elif len(pdb_code) == 4:\n",
68
+ " os.system(f\"wget -qnc https://files.rcsb.org/view/{pdb_code}.pdb\")\n",
69
+ " return f\"{pdb_code}.pdb\"\n",
70
+ " else:\n",
71
+ " os.system(f\"wget -qnc https://alphafold.ebi.ac.uk/files/AF-{pdb_code}-F1-model_v3.pdb\")\n",
72
+ " return f\"AF-{pdb_code}-F1-model_v3.pdb\""
73
+ ]
74
+ },
75
+ {
76
+ "cell_type": "code",
77
+ "source": [
78
+ "#@title Hallucination Options\n",
79
+ "length = 100#@param {type:\"integer\"}\n",
80
+ "copies = 1#@param {type:\"integer\"}\n",
81
+ "#@markdown ####Weights\n",
82
+ "#@markdown - Minimizing `pae` or maximizing `plddt` often results in a single helix.\n",
83
+ "#@markdown To avoid this, we start with a random sequence and instead try to optimize \n",
84
+ "#@markdown defined `num`ber of `con`tacts per position. \n",
85
+ "pae = 0.1 #@param [\"0.01\", \"0.1\", \"0.5\", \"1.0\"] {type:\"raw\"}\n",
86
+ "plddt = 0.1 #@param [\"0.01\", \"0.1\", \"0.5\", \"1.0\"] {type:\"raw\"}\n",
87
+ "con = 1.0 #@param [\"0.01\", \"0.1\", \"0.5\", \"1.0\"] {type:\"raw\"}\n",
88
+ "#@markdown ####Contact Definition\n",
89
+ "#@markdown - The contact definition is based on Cb-Cb diststance `cutoff`. To avoid \n",
90
+ "#@markdown biasing towards helical contact, only contacts with sequence seperation > \n",
91
+ "#@markdown `seqsep` are considered.\n",
92
+ "\n",
93
+ "\n",
94
+ "seqsep = 9 #@param [\"0\",\"5\",\"9\"] {type:\"raw\"}\n",
95
+ "cutoff = \"14\" #@param [\"8\", \"14\", \"max\"]\n",
96
+ "num = \"2\" #@param [\"1\", \"2\", \"4\", \"8\", \"max\"]\n",
97
+ "binary = False #@param {type:\"boolean\"}\n",
98
+ "if cutoff == \"max\": cutoff = 21.6875\n",
99
+ "if num == \"max\": num = length\n",
100
+ "\n",
101
+ "opt = {\"con\":{\"seqsep\":int(seqsep),\"cutoff\":float(cutoff),\"num\":int(num),\n",
102
+ " \"binary\":binary}}\n",
103
+ "weights = {\"con\":float(con), \"pae\":float(pae),\"plddt\":float(plddt)}\n",
104
+ "\n",
105
+ "if \"model\" not in dir() or model._len != length or model._args[\"copies\"] != copies:\n",
106
+ " clear_mem()\n",
107
+ " model = mk_afdesign_model(protocol=\"hallucination\")\n",
108
+ " model.prep_inputs(length=length, copies=copies)\n",
109
+ "\n",
110
+ "#@markdown ####Optimizer settings\n",
111
+ "pre_iters = 100 #@param {type:\"integer\"}\n",
112
+ "soft_iters = 50 #@param {type:\"integer\"}\n",
113
+ "temp_iters = 50 #@param {type:\"integer\"}\n",
114
+ "hard_iters = 10 #@param {type:\"integer\"}\n",
115
+ "\n",
116
+ "# pre-design with gumbel initialization and softmax activation\n",
117
+ "model.restart(mode=\"gumbel\",opt=opt,weights=weights)\n",
118
+ "model.design_soft(pre_iters)\n",
119
+ "\n",
120
+ "# three stage design \n",
121
+ "model.set_seq(model.aux[\"seq\"][\"pseudo\"])\n",
122
+ "model.design_3stage(soft_iters,temp_iters,hard_iters)"
123
+ ],
124
+ "metadata": {
125
+ "cellView": "form",
126
+ "id": "eCGc3J663NGz"
127
+ },
128
+ "execution_count": null,
129
+ "outputs": []
130
+ },
131
+ {
132
+ "cell_type": "code",
133
+ "execution_count": null,
134
+ "metadata": {
135
+ "id": "A1GxeLZdTTya",
136
+ "cellView": "form"
137
+ },
138
+ "outputs": [],
139
+ "source": [
140
+ "#@markdown ## display hallucinated protein {run: \"auto\"}\n",
141
+ "color = \"pLDDT\" #@param [\"chain\", \"pLDDT\", \"rainbow\"]\n",
142
+ "show_sidechains = False #@param {type:\"boolean\"}\n",
143
+ "show_mainchains = False #@param {type:\"boolean\"}\n",
144
+ "model.save_pdb(f\"{model.protocol}.pdb\")\n",
145
+ "model.plot_pdb(show_sidechains=show_sidechains,\n",
146
+ " show_mainchains=show_mainchains,\n",
147
+ " color=color)"
148
+ ]
149
+ },
150
+ {
151
+ "cell_type": "code",
152
+ "execution_count": null,
153
+ "metadata": {
154
+ "id": "L2E9Tn2Acchj"
155
+ },
156
+ "outputs": [],
157
+ "source": [
158
+ "HTML(model.animate())"
159
+ ]
160
+ },
161
+ {
162
+ "cell_type": "code",
163
+ "execution_count": null,
164
+ "metadata": {
165
+ "id": "YSKWYu0_GlUH"
166
+ },
167
+ "outputs": [],
168
+ "source": [
169
+ "model.get_seqs()"
170
+ ]
171
+ }
172
+ ],
173
+ "metadata": {
174
+ "accelerator": "GPU",
175
+ "colab": {
176
+ "collapsed_sections": [
177
+ "q4qiU9I0QHSz"
178
+ ],
179
+ "name": "hallucination.ipynb",
180
+ "provenance": [],
181
+ "include_colab_link": true
182
+ },
183
+ "kernelspec": {
184
+ "display_name": "Python 3",
185
+ "name": "python3"
186
+ },
187
+ "language_info": {
188
+ "name": "python"
189
+ }
190
+ },
191
+ "nbformat": 4,
192
+ "nbformat_minor": 0
193
+ }
model/PXDesignBench/ColabDesign/af/examples/hallucination_custom_loss.ipynb ADDED
@@ -0,0 +1,260 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "cells": [
3
+ {
4
+ "cell_type": "markdown",
5
+ "metadata": {
6
+ "id": "view-in-github",
7
+ "colab_type": "text"
8
+ },
9
+ "source": [
10
+ "<a href=\"https://colab.research.google.com/github/sokrypton/ColabDesign/blob/v1.1.1/af/examples/hallucination_custom_loss.ipynb\" target=\"_parent\"><img src=\"https://colab.research.google.com/assets/colab-badge.svg\" alt=\"Open In Colab\"/></a>"
11
+ ]
12
+ },
13
+ {
14
+ "cell_type": "markdown",
15
+ "metadata": {
16
+ "id": "OA2k3sAYuiXe"
17
+ },
18
+ "source": [
19
+ "# AfDesign - hallucination custom loss example\n",
20
+ "Backprop through AlphaFold for protein design."
21
+ ]
22
+ },
23
+ {
24
+ "cell_type": "code",
25
+ "execution_count": null,
26
+ "metadata": {
27
+ "cellView": "form",
28
+ "id": "-AXy0s_4cKaK"
29
+ },
30
+ "outputs": [],
31
+ "source": [
32
+ "#@title setup\n",
33
+ "%%time\n",
34
+ "import os\n",
35
+ "if not os.path.isdir(\"params\"):\n",
36
+ " # get code\n",
37
+ " os.system(\"pip -q install git+https://github.com/sokrypton/ColabDesign.git@v1.1.1\")\n",
38
+ " # for debugging\n",
39
+ " os.system(\"ln -s /usr/local/lib/python3.*/dist-packages/colabdesign colabdesign\")\n",
40
+ " # download params\n",
41
+ " os.system(\"mkdir params\")\n",
42
+ " os.system(\"apt-get install aria2 -qq\")\n",
43
+ " os.system(\"aria2c -q -x 16 https://storage.googleapis.com/alphafold/alphafold_params_2022-12-06.tar\")\n",
44
+ " os.system(\"tar -xf alphafold_params_2022-12-06.tar -C params\")\n",
45
+ "\n",
46
+ "import warnings\n",
47
+ "warnings.simplefilter(action='ignore', category=FutureWarning)\n",
48
+ "\n",
49
+ "import os\n",
50
+ "from colabdesign import mk_afdesign_model, clear_mem\n",
51
+ "from IPython.display import HTML\n",
52
+ "from google.colab import files\n",
53
+ "import numpy as np\n",
54
+ "\n",
55
+ "def get_pdb(pdb_code=\"\"):\n",
56
+ " if pdb_code is None or pdb_code == \"\":\n",
57
+ " upload_dict = files.upload()\n",
58
+ " pdb_string = upload_dict[list(upload_dict.keys())[0]]\n",
59
+ " with open(\"tmp.pdb\",\"wb\") as out: out.write(pdb_string)\n",
60
+ " return \"tmp.pdb\"\n",
61
+ " elif os.path.isfile(pdb_code):\n",
62
+ " return pdb_code\n",
63
+ " elif len(pdb_code) == 4:\n",
64
+ " os.system(f\"wget -qnc https://files.rcsb.org/view/{pdb_code}.pdb\")\n",
65
+ " return f\"{pdb_code}.pdb\"\n",
66
+ " else:\n",
67
+ " os.system(f\"wget -qnc https://alphafold.ebi.ac.uk/files/AF-{pdb_code}-F1-model_v3.pdb\")\n",
68
+ " return f\"AF-{pdb_code}-F1-model_v3.pdb\""
69
+ ]
70
+ },
71
+ {
72
+ "cell_type": "markdown",
73
+ "metadata": {
74
+ "id": "UUfKrOzT0gOS"
75
+ },
76
+ "source": [
77
+ "# Custom loss"
78
+ ]
79
+ },
80
+ {
81
+ "cell_type": "code",
82
+ "execution_count": null,
83
+ "metadata": {
84
+ "id": "qLd1DsnKzxBJ"
85
+ },
86
+ "outputs": [],
87
+ "source": [
88
+ "clear_mem()\n",
89
+ "af_model = mk_afdesign_model(protocol=\"hallucination\", debug=True)\n",
90
+ "af_model.prep_inputs(length=100)\n",
91
+ "\n",
92
+ "print(\"length\", af_model._len)\n",
93
+ "print(\"weights\", af_model.opt[\"weights\"])"
94
+ ]
95
+ },
96
+ {
97
+ "cell_type": "code",
98
+ "source": [
99
+ "af_model.restart(mode=\"gumbel\",seed=0)\n",
100
+ "af_model.set_opt(soft=True)\n",
101
+ "af_model.run(backprop=False)"
102
+ ],
103
+ "metadata": {
104
+ "id": "u0AwskJ84NGx"
105
+ },
106
+ "execution_count": null,
107
+ "outputs": []
108
+ },
109
+ {
110
+ "cell_type": "code",
111
+ "source": [
112
+ "from colabdesign.af.alphafold.common import residue_constants\n",
113
+ "import jax\n",
114
+ "import jax.numpy as jnp\n",
115
+ "\n",
116
+ "# first off, let's implement a custom Radius of Gyration loss function\n",
117
+ "def rg_loss(inputs, outputs):\n",
118
+ " positions = outputs[\"structure_module\"][\"final_atom_positions\"]\n",
119
+ " ca = positions[:,residue_constants.atom_order[\"CA\"]]\n",
120
+ " center = ca.mean(0)\n",
121
+ " rg = jnp.sqrt(jnp.square(ca - center).sum(-1).mean() + 1e-8)\n",
122
+ " rg_th = 2.38 * ca.shape[0] ** 0.365\n",
123
+ " rg = jax.nn.elu(rg - rg_th)\n",
124
+ " return {\"rg\":rg}"
125
+ ],
126
+ "metadata": {
127
+ "id": "SGxkLR_4VsQI"
128
+ },
129
+ "execution_count": null,
130
+ "outputs": []
131
+ },
132
+ {
133
+ "cell_type": "code",
134
+ "source": [
135
+ "af_model.aux[\"debug\"].keys()"
136
+ ],
137
+ "metadata": {
138
+ "id": "LAgsoVLhcJdr"
139
+ },
140
+ "execution_count": null,
141
+ "outputs": []
142
+ },
143
+ {
144
+ "cell_type": "code",
145
+ "source": [
146
+ "rg_loss(**af_model.aux[\"debug\"])"
147
+ ],
148
+ "metadata": {
149
+ "id": "enMbbgFnWLwF"
150
+ },
151
+ "execution_count": null,
152
+ "outputs": []
153
+ },
154
+ {
155
+ "cell_type": "markdown",
156
+ "source": [
157
+ "#Let's add it to the model!"
158
+ ],
159
+ "metadata": {
160
+ "id": "jmHGCynter0p"
161
+ }
162
+ },
163
+ {
164
+ "cell_type": "code",
165
+ "source": [
166
+ "clear_mem()\n",
167
+ "af_model = mk_afdesign_model(protocol=\"hallucination\",\n",
168
+ " debug=False,\n",
169
+ " loss_callback=rg_loss) # add our custom loss\n",
170
+ "af_model.opt[\"weights\"][\"rg\"] = 0.1 # add our loss to weights (so we can later control it)\n",
171
+ "af_model.prep_inputs(length=100)\n",
172
+ "print(\"weights\", af_model.opt[\"weights\"])"
173
+ ],
174
+ "metadata": {
175
+ "id": "0D7Z0U6aVD1V"
176
+ },
177
+ "execution_count": null,
178
+ "outputs": []
179
+ },
180
+ {
181
+ "cell_type": "code",
182
+ "source": [
183
+ "af_model.restart(mode=\"gumbel\", seed=0)\n",
184
+ "af_model.design_soft(50)\n",
185
+ "\n",
186
+ "# three stage design \n",
187
+ "af_model.set_seq(af_model.aux[\"seq\"][\"pseudo\"])\n",
188
+ "af_model.design_3stage(50,50,10)"
189
+ ],
190
+ "metadata": {
191
+ "id": "Wsc9IWsqXreX"
192
+ },
193
+ "execution_count": null,
194
+ "outputs": []
195
+ },
196
+ {
197
+ "cell_type": "code",
198
+ "execution_count": null,
199
+ "metadata": {
200
+ "id": "YEApO8YzBoS0"
201
+ },
202
+ "outputs": [],
203
+ "source": [
204
+ "af_model.save_pdb(f\"{af_model.protocol}.pdb\")\n",
205
+ "af_model.plot_pdb()"
206
+ ]
207
+ },
208
+ {
209
+ "cell_type": "code",
210
+ "execution_count": null,
211
+ "metadata": {
212
+ "id": "cW1KQiHKJpfp"
213
+ },
214
+ "outputs": [],
215
+ "source": [
216
+ "HTML(af_model.animate())"
217
+ ]
218
+ },
219
+ {
220
+ "cell_type": "code",
221
+ "source": [
222
+ "af_model.get_seqs()"
223
+ ],
224
+ "metadata": {
225
+ "id": "YDrChASGVUUx"
226
+ },
227
+ "execution_count": null,
228
+ "outputs": []
229
+ },
230
+ {
231
+ "cell_type": "code",
232
+ "source": [],
233
+ "metadata": {
234
+ "id": "-js6TX9ZytR9"
235
+ },
236
+ "execution_count": null,
237
+ "outputs": []
238
+ }
239
+ ],
240
+ "metadata": {
241
+ "accelerator": "GPU",
242
+ "colab": {
243
+ "collapsed_sections": [
244
+ "q4qiU9I0QHSz"
245
+ ],
246
+ "name": "hallucination_custom_loss.ipynb",
247
+ "provenance": [],
248
+ "include_colab_link": true
249
+ },
250
+ "kernelspec": {
251
+ "display_name": "Python 3",
252
+ "name": "python3"
253
+ },
254
+ "language_info": {
255
+ "name": "python"
256
+ }
257
+ },
258
+ "nbformat": 4,
259
+ "nbformat_minor": 0
260
+ }
model/PXDesignBench/ColabDesign/af/examples/partial_hallucination_rewire.ipynb ADDED
@@ -0,0 +1,161 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "cells": [
3
+ {
4
+ "cell_type": "markdown",
5
+ "metadata": {
6
+ "id": "view-in-github",
7
+ "colab_type": "text"
8
+ },
9
+ "source": [
10
+ "<a href=\"https://colab.research.google.com/github/sokrypton/ColabDesign/blob/v1.1.1/af/examples/partial_hallucination_rewire.ipynb\" target=\"_parent\"><img src=\"https://colab.research.google.com/assets/colab-badge.svg\" alt=\"Open In Colab\"/></a>"
11
+ ]
12
+ },
13
+ {
14
+ "cell_type": "markdown",
15
+ "metadata": {
16
+ "id": "OA2k3sAYuiXe"
17
+ },
18
+ "source": [
19
+ "# AfDesign - rewire (partial hallucination)"
20
+ ]
21
+ },
22
+ {
23
+ "cell_type": "code",
24
+ "execution_count": null,
25
+ "metadata": {
26
+ "cellView": "form",
27
+ "id": "-AXy0s_4cKaK"
28
+ },
29
+ "outputs": [],
30
+ "source": [
31
+ "#@title setup\n",
32
+ "%%time\n",
33
+ "import os\n",
34
+ "if not os.path.isdir(\"params\"):\n",
35
+ " # get code\n",
36
+ " os.system(\"pip -q install git+https://github.com/sokrypton/ColabDesign.git@v1.1.1\")\n",
37
+ " # for debugging\n",
38
+ " os.system(\"ln -s /usr/local/lib/python3.*/dist-packages/colabdesign colabdesign\")\n",
39
+ " # download params\n",
40
+ " os.system(\"mkdir params\")\n",
41
+ " os.system(\"apt-get install aria2 -qq\")\n",
42
+ " os.system(\"aria2c -q -x 16 https://storage.googleapis.com/alphafold/alphafold_params_2022-12-06.tar\")\n",
43
+ " os.system(\"tar -xf alphafold_params_2022-12-06.tar -C params\")\n",
44
+ "\n",
45
+ "import warnings\n",
46
+ "warnings.simplefilter(action='ignore', category=FutureWarning)\n",
47
+ "\n",
48
+ "import os\n",
49
+ "from colabdesign import mk_afdesign_model, clear_mem\n",
50
+ "from IPython.display import HTML\n",
51
+ "from google.colab import files\n",
52
+ "import numpy as np\n",
53
+ "\n",
54
+ "def get_pdb(pdb_code=\"\"):\n",
55
+ " if pdb_code is None or pdb_code == \"\":\n",
56
+ " upload_dict = files.upload()\n",
57
+ " pdb_string = upload_dict[list(upload_dict.keys())[0]]\n",
58
+ " with open(\"tmp.pdb\",\"wb\") as out: out.write(pdb_string)\n",
59
+ " return \"tmp.pdb\"\n",
60
+ " elif os.path.isfile(pdb_code):\n",
61
+ " return pdb_code\n",
62
+ " elif len(pdb_code) == 4:\n",
63
+ " os.system(f\"wget -qnc https://files.rcsb.org/view/{pdb_code}.pdb\")\n",
64
+ " return f\"{pdb_code}.pdb\"\n",
65
+ " else:\n",
66
+ " os.system(f\"wget -qnc https://alphafold.ebi.ac.uk/files/AF-{pdb_code}-F1-model_v3.pdb\")\n",
67
+ " return f\"AF-{pdb_code}-F1-model_v3.pdb\""
68
+ ]
69
+ },
70
+ {
71
+ "cell_type": "code",
72
+ "source": [
73
+ "# setup the model\n",
74
+ "clear_mem()\n",
75
+ "model = mk_afdesign_model(protocol=\"partial\",\n",
76
+ " use_templates=False) # set True to constrain positions using template input\n",
77
+ " \n",
78
+ "# define positions we want to constrain (input PDB numbering)\n",
79
+ "old_pos = \"4-9,13-26,30-33,37-50,54-59,63-76,80-84,112-125\"\n",
80
+ "\n",
81
+ "model.prep_inputs(get_pdb(\"2MR5\"), chain=\"A\",\n",
82
+ " pos=old_pos, # define positions to contrain\n",
83
+ " length=100, # define if the desired length is different from input PDB\n",
84
+ " fix_seq=False) # set True to constrain the sequence\n",
85
+ "\n",
86
+ "# set positions (if different from PDB)\n",
87
+ "# reorder the segments, \n",
88
+ "model.rewire(order = [1,2,3,0,7,4,5,6], # set order of segments\n",
89
+ " loops = [3,3,3,4,3,3,4], # change loop length inbetween segments\n",
90
+ " offset=0) # essentially loop length at the N term\n",
91
+ "\n",
92
+ "print(model.opt[\"pos\"])"
93
+ ],
94
+ "metadata": {
95
+ "id": "_m7ZaaP4NkII"
96
+ },
97
+ "execution_count": null,
98
+ "outputs": []
99
+ },
100
+ {
101
+ "cell_type": "code",
102
+ "source": [
103
+ "# restart optimization\n",
104
+ "model.restart()\n",
105
+ "# model.set_seq(mode=\"wildtype\") # initialize with wildtype sequence\n",
106
+ "\n",
107
+ "# balance weights [dgram_cce = restraint weight], [con = hallucination weight]\n",
108
+ "model.set_weights(dgram_cce=1, con=0)\n",
109
+ "model.design_3stage(300,100,10)"
110
+ ],
111
+ "metadata": {
112
+ "id": "bDA8cPqMT_eY"
113
+ },
114
+ "execution_count": null,
115
+ "outputs": []
116
+ },
117
+ {
118
+ "cell_type": "code",
119
+ "source": [
120
+ "model.save_pdb(f\"{model.protocol}.pdb\")\n",
121
+ "model.plot_pdb()"
122
+ ],
123
+ "metadata": {
124
+ "id": "qFegtgcnHdqr"
125
+ },
126
+ "execution_count": null,
127
+ "outputs": []
128
+ },
129
+ {
130
+ "cell_type": "code",
131
+ "source": [
132
+ "HTML(model.animate())"
133
+ ],
134
+ "metadata": {
135
+ "id": "9sjG7kvoHaVi"
136
+ },
137
+ "execution_count": null,
138
+ "outputs": []
139
+ }
140
+ ],
141
+ "metadata": {
142
+ "accelerator": "GPU",
143
+ "colab": {
144
+ "collapsed_sections": [
145
+ "q4qiU9I0QHSz"
146
+ ],
147
+ "name": "partial_hallucination_rewire.ipynb",
148
+ "provenance": [],
149
+ "include_colab_link": true
150
+ },
151
+ "kernelspec": {
152
+ "display_name": "Python 3",
153
+ "name": "python3"
154
+ },
155
+ "language_info": {
156
+ "name": "python"
157
+ }
158
+ },
159
+ "nbformat": 4,
160
+ "nbformat_minor": 0
161
+ }
model/PXDesignBench/ColabDesign/af/examples/peptide_binder_design.ipynb ADDED
@@ -0,0 +1,319 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "cells": [
3
+ {
4
+ "cell_type": "markdown",
5
+ "metadata": {
6
+ "id": "view-in-github",
7
+ "colab_type": "text"
8
+ },
9
+ "source": [
10
+ "<a href=\"https://colab.research.google.com/github/sokrypton/ColabDesign/blob/v1.1.1/af/examples/peptide_binder_design.ipynb\" target=\"_parent\"><img src=\"https://colab.research.google.com/assets/colab-badge.svg\" alt=\"Open In Colab\"/></a>"
11
+ ]
12
+ },
13
+ {
14
+ "cell_type": "markdown",
15
+ "metadata": {
16
+ "id": "OA2k3sAYuiXe"
17
+ },
18
+ "source": [
19
+ "# AfDesign - peptide binder design\n",
20
+ "For a given protein target and protein binder length, generate/hallucinate a protein binder sequence AlphaFold thinks will bind to the target structure. To do this, we maximize number of contacts at the interface and maximize pLDDT of the binder.\n",
21
+ "\n",
22
+ "**WARNING**\n",
23
+ "1. This notebook is in active development and was designed for demonstration purposes only.\n",
24
+ "2. Using AfDesign as the only \"loss\" function for design might be a bad idea, you may find adversarial sequences (aka. sequences that trick AlphaFold)."
25
+ ]
26
+ },
27
+ {
28
+ "cell_type": "code",
29
+ "execution_count": null,
30
+ "metadata": {
31
+ "cellView": "form",
32
+ "id": "-AXy0s_4cKaK"
33
+ },
34
+ "outputs": [],
35
+ "source": [
36
+ "#@title **setup**\n",
37
+ "import os\n",
38
+ "if not os.path.isdir(\"params\"):\n",
39
+ " # get code\n",
40
+ " os.system(\"pip -q install git+https://github.com/sokrypton/ColabDesign.git@v1.1.1\")\n",
41
+ " # for debugging\n",
42
+ " os.system(\"ln -s /usr/local/lib/python3.*/dist-packages/colabdesign colabdesign\")\n",
43
+ " # download params\n",
44
+ " os.system(\"mkdir params\")\n",
45
+ " os.system(\"apt-get install aria2 -qq\")\n",
46
+ " os.system(\"aria2c -q -x 16 https://storage.googleapis.com/alphafold/alphafold_params_2022-12-06.tar\")\n",
47
+ " os.system(\"tar -xf alphafold_params_2022-12-06.tar -C params\")\n",
48
+ "\n",
49
+ "import warnings\n",
50
+ "warnings.simplefilter(action='ignore', category=FutureWarning)\n",
51
+ "\n",
52
+ "import os\n",
53
+ "from colabdesign import mk_afdesign_model, clear_mem\n",
54
+ "from colabdesign.shared.utils import copy_dict\n",
55
+ "from colabdesign.af.alphafold.common import residue_constants\n",
56
+ "\n",
57
+ "from IPython.display import HTML\n",
58
+ "from google.colab import files\n",
59
+ "import numpy as np\n",
60
+ "\n",
61
+ "#########################\n",
62
+ "def get_pdb(pdb_code=\"\"):\n",
63
+ " if pdb_code is None or pdb_code == \"\":\n",
64
+ " upload_dict = files.upload()\n",
65
+ " pdb_string = upload_dict[list(upload_dict.keys())[0]]\n",
66
+ " with open(\"tmp.pdb\",\"wb\") as out: out.write(pdb_string)\n",
67
+ " return \"tmp.pdb\"\n",
68
+ " elif os.path.isfile(pdb_code):\n",
69
+ " return pdb_code\n",
70
+ " elif len(pdb_code) == 4:\n",
71
+ " os.system(f\"wget -qnc https://files.rcsb.org/view/{pdb_code}.pdb\")\n",
72
+ " return f\"{pdb_code}.pdb\"\n",
73
+ " else:\n",
74
+ " os.system(f\"wget -qnc https://alphafold.ebi.ac.uk/files/AF-{pdb_code}-F1-model_v3.pdb\")\n",
75
+ " return f\"AF-{pdb_code}-F1-model_v3.pdb\""
76
+ ]
77
+ },
78
+ {
79
+ "cell_type": "code",
80
+ "source": [
81
+ "#@title **prep inputs**\n",
82
+ "import re\n",
83
+ "#@markdown ---\n",
84
+ "#@markdown **target info**\n",
85
+ "pdb = \"4N5T\" #@param {type:\"string\"}\n",
86
+ "#@markdown - enter PDB code or UniProt code (to fetch AlphaFoldDB model) or leave blink to upload your own\n",
87
+ "target_chain = \"A\" #@param {type:\"string\"}\n",
88
+ "target_hotspot = \"\" #@param {type:\"string\"}\n",
89
+ "if target_hotspot == \"\": target_hotspot = None\n",
90
+ "#@markdown - restrict loss to predefined positions on target (eg. \"1-10,12,15\")\n",
91
+ "target_flexible = False #@param {type:\"boolean\"}\n",
92
+ "#@markdown - allow backbone of target structure to be flexible\n",
93
+ "\n",
94
+ "#@markdown ---\n",
95
+ "#@markdown **binder info**\n",
96
+ "binder_len = 14 #@param {type:\"integer\"}\n",
97
+ "#@markdown - length of binder to hallucination\n",
98
+ "binder_seq = \"\" #@param {type:\"string\"}\n",
99
+ "binder_seq = re.sub(\"[^A-Z]\", \"\", binder_seq.upper())\n",
100
+ "if len(binder_seq) > 0:\n",
101
+ " binder_len = len(binder_seq)\n",
102
+ "else:\n",
103
+ " binder_seq = None\n",
104
+ "#@markdown - if defined, will initialize design with this sequence\n",
105
+ "\n",
106
+ "binder_chain = \"\" #@param {type:\"string\"}\n",
107
+ "if binder_chain == \"\": binder_chain = None\n",
108
+ "#@markdown - if defined, supervised loss is used (binder_len is ignored)\n",
109
+ "\n",
110
+ "#@markdown ---\n",
111
+ "#@markdown **model config**\n",
112
+ "use_multimer = False #@param {type:\"boolean\"}\n",
113
+ "#@markdown - use alphafold-multimer for design\n",
114
+ "num_recycles = 0 #@param [\"0\", \"1\", \"3\", \"6\"] {type:\"raw\"}\n",
115
+ "num_models = \"2\" #@param [\"1\", \"2\", \"3\", \"4\", \"5\", \"all\"]\n",
116
+ "num_models = 5 if num_models == \"all\" else int(num_models)\n",
117
+ "#@markdown - number of trained models to use during optimization\n",
118
+ "\n",
119
+ "\n",
120
+ "x = {\"pdb_filename\":pdb,\n",
121
+ " \"chain\":target_chain,\n",
122
+ " \"binder_len\":binder_len,\n",
123
+ " \"binder_chain\":binder_chain,\n",
124
+ " \"hotspot\":target_hotspot,\n",
125
+ " \"use_multimer\":use_multimer,\n",
126
+ " \"rm_target_seq\":target_flexible}\n",
127
+ " \n",
128
+ "x[\"pdb_filename\"] = get_pdb(x[\"pdb_filename\"]) \n",
129
+ "\n",
130
+ "if \"x_prev\" not in dir() or x != x_prev:\n",
131
+ " clear_mem()\n",
132
+ " model = mk_afdesign_model(protocol=\"binder\",\n",
133
+ " use_multimer=x[\"use_multimer\"],\n",
134
+ " num_recycles=num_recycles,\n",
135
+ " recycle_mode=\"sample\")\n",
136
+ " model.prep_inputs(**x,\n",
137
+ " ignore_missing=False)\n",
138
+ " x_prev = copy_dict(x)\n",
139
+ " print(\"target length:\", model._target_len)\n",
140
+ " print(\"binder length:\", model._binder_len)\n",
141
+ " binder_len = model._binder_len"
142
+ ],
143
+ "metadata": {
144
+ "id": "HSgE99WALOE-",
145
+ "cellView": "form"
146
+ },
147
+ "execution_count": null,
148
+ "outputs": []
149
+ },
150
+ {
151
+ "cell_type": "code",
152
+ "source": [
153
+ "#@title **run AfDesign**\n",
154
+ "from scipy.special import softmax\n",
155
+ "\n",
156
+ "optimizer = \"pssm_semigreedy\" #@param [\"pssm_semigreedy\", \"3stage\", \"semigreedy\", \"pssm\", \"logits\", \"soft\", \"hard\"]\n",
157
+ "#@markdown - `pssm_semigreedy` - uses the designed PSSM to bias semigreedy opt. (Recommended)\n",
158
+ "#@markdown - `3stage` - gradient based optimization (GD) (logits → soft → hard)\n",
159
+ "#@markdown - `pssm` - GD optimize (logits → soft) to get a sequence profile (PSSM).\n",
160
+ "#@markdown - `semigreedy` - tries X random mutations, accepts those that decrease loss\n",
161
+ "#@markdown - `logits` - GD optimize logits inputs (continious)\n",
162
+ "#@markdown - `soft` - GD optimize softmax(logits) inputs (probabilities)\n",
163
+ "#@markdown - `hard` - GD optimize one_hot(logits) inputs (discrete)\n",
164
+ "\n",
165
+ "#@markdown WARNING: The output sequence from `pssm`,`logits`,`soft` is not one_hot. To get a valid sequence use the other optimizers, or redesign the output backbone with another protocol like ProteinMPNN.\n",
166
+ "\n",
167
+ "#@markdown ----\n",
168
+ "#@markdown #### advanced GD settings\n",
169
+ "GD_method = \"sgd\" #@param [\"adabelief\", \"adafactor\", \"adagrad\", \"adam\", \"adamw\", \"fromage\", \"lamb\", \"lars\", \"noisy_sgd\", \"dpsgd\", \"radam\", \"rmsprop\", \"sgd\", \"sm3\", \"yogi\"]\n",
170
+ "learning_rate = 0.1 #@param {type:\"raw\"}\n",
171
+ "norm_seq_grad = True #@param {type:\"boolean\"}\n",
172
+ "dropout = True #@param {type:\"boolean\"}\n",
173
+ "\n",
174
+ "model.restart(seq=binder_seq)\n",
175
+ "model.set_optimizer(optimizer=GD_method,\n",
176
+ " learning_rate=learning_rate,\n",
177
+ " norm_seq_grad=norm_seq_grad)\n",
178
+ "models = model._model_names[:num_models]\n",
179
+ "\n",
180
+ "flags = {\"num_recycles\":num_recycles,\n",
181
+ " \"models\":models,\n",
182
+ " \"dropout\":dropout}\n",
183
+ "\n",
184
+ "if optimizer == \"3stage\":\n",
185
+ " model.design_3stage(120, 60, 10, **flags)\n",
186
+ " pssm = softmax(model._tmp[\"seq_logits\"],-1)\n",
187
+ "\n",
188
+ "if optimizer == \"pssm_semigreedy\":\n",
189
+ " model.design_pssm_semigreedy(120, 32, **flags)\n",
190
+ " pssm = softmax(model._tmp[\"seq_logits\"],1)\n",
191
+ "\n",
192
+ "if optimizer == \"semigreedy\":\n",
193
+ " model.design_pssm_semigreedy(0, 32, **flags)\n",
194
+ " pssm = None\n",
195
+ "\n",
196
+ "if optimizer == \"pssm\":\n",
197
+ " model.design_logits(120, e_soft=1.0, num_models=1, ramp_recycles=True, **flags)\n",
198
+ " model.design_soft(32, num_models=1, **flags)\n",
199
+ " flags.update({\"dropout\":False,\"save_best\":True})\n",
200
+ " model.design_soft(10, num_models=num_models, **flags)\n",
201
+ " pssm = softmax(model.aux[\"seq\"][\"logits\"],-1)\n",
202
+ "\n",
203
+ "O = {\"logits\":model.design_logits,\n",
204
+ " \"soft\":model.design_soft,\n",
205
+ " \"hard\":model.design_hard}\n",
206
+ "\n",
207
+ "if optimizer in O:\n",
208
+ " O[optimizer](120, num_models=1, ramp_recycles=True, **flags)\n",
209
+ " flags.update({\"dropout\":False,\"save_best\":True})\n",
210
+ " O[optimizer](10, num_models=num_models, **flags)\n",
211
+ " pssm = softmax(model.aux[\"seq\"][\"logits\"],-1)\n",
212
+ "\n",
213
+ "model.save_pdb(f\"{model.protocol}.pdb\")"
214
+ ],
215
+ "metadata": {
216
+ "cellView": "form",
217
+ "id": "60qmxpzno0yV"
218
+ },
219
+ "execution_count": null,
220
+ "outputs": []
221
+ },
222
+ {
223
+ "cell_type": "code",
224
+ "execution_count": null,
225
+ "metadata": {
226
+ "id": "A1GxeLZdTTya",
227
+ "cellView": "form"
228
+ },
229
+ "outputs": [],
230
+ "source": [
231
+ "#@title display hallucinated protein {run: \"auto\"}\n",
232
+ "color = \"pLDDT\" #@param [\"chain\", \"pLDDT\", \"rainbow\"]\n",
233
+ "show_sidechains = False #@param {type:\"boolean\"}\n",
234
+ "show_mainchains = False #@param {type:\"boolean\"}\n",
235
+ "color_HP = False #@param {type:\"boolean\"}\n",
236
+ "animate = True #@param {type:\"boolean\"}\n",
237
+ "model.plot_pdb(show_sidechains=show_sidechains,\n",
238
+ " show_mainchains=show_mainchains,\n",
239
+ " color=color, color_HP=color_HP, animate=animate)"
240
+ ]
241
+ },
242
+ {
243
+ "cell_type": "code",
244
+ "execution_count": null,
245
+ "metadata": {
246
+ "id": "L2E9Tn2Acchj"
247
+ },
248
+ "outputs": [],
249
+ "source": [
250
+ "HTML(model.animate(dpi=100))"
251
+ ]
252
+ },
253
+ {
254
+ "cell_type": "code",
255
+ "execution_count": null,
256
+ "metadata": {
257
+ "id": "YSKWYu0_GlUH"
258
+ },
259
+ "outputs": [],
260
+ "source": [
261
+ "model.save_pdb(f\"{model.protocol}.pdb\")\n",
262
+ "model.get_seqs()"
263
+ ]
264
+ },
265
+ {
266
+ "cell_type": "code",
267
+ "source": [
268
+ "#@markdown ### Amino acid probabilties\n",
269
+ "import plotly.express as px\n",
270
+ "alphabet = \"ACDEFGHIKLMNPQRSTVWY\"\n",
271
+ "if \"pssm\" in dir() and pssm is not None:\n",
272
+ " fig = px.imshow(pssm.mean(0).T,\n",
273
+ " labels=dict(x=\"positions\", y=\"amino acids\", color=\"probability\"),\n",
274
+ " y=residue_constants.restypes,\n",
275
+ " zmin=0,\n",
276
+ " zmax=1,\n",
277
+ " template=\"simple_white\",\n",
278
+ " )\n",
279
+ " fig.update_xaxes(side=\"top\")\n",
280
+ " fig.show()"
281
+ ],
282
+ "metadata": {
283
+ "cellView": "form",
284
+ "id": "3pvptBM55GHU"
285
+ },
286
+ "execution_count": null,
287
+ "outputs": []
288
+ },
289
+ {
290
+ "cell_type": "code",
291
+ "source": [
292
+ "# log\n",
293
+ "model._tmp[\"best\"][\"aux\"][\"log\"]"
294
+ ],
295
+ "metadata": {
296
+ "id": "1SGmdJKLNKvb"
297
+ },
298
+ "execution_count": null,
299
+ "outputs": []
300
+ }
301
+ ],
302
+ "metadata": {
303
+ "accelerator": "GPU",
304
+ "colab": {
305
+ "collapsed_sections": [],
306
+ "provenance": [],
307
+ "include_colab_link": true
308
+ },
309
+ "kernelspec": {
310
+ "display_name": "Python 3",
311
+ "name": "python3"
312
+ },
313
+ "language_info": {
314
+ "name": "python"
315
+ }
316
+ },
317
+ "nbformat": 4,
318
+ "nbformat_minor": 0
319
+ }
model/PXDesignBench/ColabDesign/af/examples/use_esm_1b_bias.ipynb ADDED
@@ -0,0 +1,329 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "cells": [
3
+ {
4
+ "cell_type": "markdown",
5
+ "metadata": {
6
+ "id": "view-in-github",
7
+ "colab_type": "text"
8
+ },
9
+ "source": [
10
+ "<a href=\"https://colab.research.google.com/github/sokrypton/ColabDesign/blob/v1.1.1/af/examples/use_esm_1b_bias.ipynb\" target=\"_parent\"><img src=\"https://colab.research.google.com/assets/colab-badge.svg\" alt=\"Open In Colab\"/></a>"
11
+ ]
12
+ },
13
+ {
14
+ "cell_type": "markdown",
15
+ "source": [
16
+ "# Gather inputs"
17
+ ],
18
+ "metadata": {
19
+ "id": "M9xamJDvx1pd"
20
+ }
21
+ },
22
+ {
23
+ "cell_type": "code",
24
+ "source": [
25
+ "import requests, re\n",
26
+ "from google.colab import files\n",
27
+ "\n",
28
+ "def get_uniprot_seq(uid):\n",
29
+ " url = f'https://rest.uniprot.org/uniprotkb/stream?compressed=false&format=fasta&query={uid}'\n",
30
+ " sequence = \"\".join(re.split(r'\\n(?=>)', requests.get(url).text)[0].split(\"\\n\")[1:])\n",
31
+ " return sequence\n",
32
+ "\n",
33
+ "def get_pdb(pdb_code=\"\",alphafold_model=False):\n",
34
+ " if pdb_code is None or pdb_code == \"\":\n",
35
+ " upload_dict = files.upload()\n",
36
+ " pdb_string = upload_dict[list(upload_dict.keys())[0]]\n",
37
+ " with open(\"tmp.pdb\",\"wb\") as out: out.write(pdb_string)\n",
38
+ " return \"tmp.pdb\"\n",
39
+ " else:\n",
40
+ " if alphafold_model:\n",
41
+ " os.system(f\"wget -qnc https://alphafold.ebi.ac.uk/files/AF-{pdb_code}-F1-model_v3.pdb\")\n",
42
+ " return f\"AF-{pdb_code}-F1-model_v3.pdb\" \n",
43
+ " else:\n",
44
+ " os.system(f\"wget -qnc https://files.rcsb.org/view/{pdb_code}.pdb\")\n",
45
+ " return f\"{pdb_code}.pdb\""
46
+ ],
47
+ "metadata": {
48
+ "id": "lev6Nc_-vx2D"
49
+ },
50
+ "execution_count": null,
51
+ "outputs": []
52
+ },
53
+ {
54
+ "cell_type": "code",
55
+ "source": [
56
+ "UNIPROT = \"P0A6A8\"\n",
57
+ "SEQUENCE = get_uniprot_seq(UNIPROT)\n",
58
+ "PDB_FILENAME = get_pdb(UNIPROT, alphafold_model=True)"
59
+ ],
60
+ "metadata": {
61
+ "id": "VkPdQj-Fv1LQ"
62
+ },
63
+ "execution_count": null,
64
+ "outputs": []
65
+ },
66
+ {
67
+ "cell_type": "markdown",
68
+ "metadata": {
69
+ "id": "H5LVw2BwijkB"
70
+ },
71
+ "source": [
72
+ "#ESM_1b\n",
73
+ "use logits from ESM_1b as prior to AfDesign"
74
+ ]
75
+ },
76
+ {
77
+ "cell_type": "code",
78
+ "execution_count": null,
79
+ "metadata": {
80
+ "id": "8j12AU-SikvN"
81
+ },
82
+ "outputs": [],
83
+ "source": [
84
+ "!pip -q install fair-esm\n",
85
+ "import esm\n",
86
+ "import gc\n",
87
+ "import torch\n",
88
+ "import numpy as np"
89
+ ]
90
+ },
91
+ {
92
+ "cell_type": "code",
93
+ "execution_count": null,
94
+ "metadata": {
95
+ "id": "63LNj3dHilRW"
96
+ },
97
+ "outputs": [],
98
+ "source": [
99
+ "model, alphabet = esm.pretrained.esm1b_t33_650M_UR50S()\n",
100
+ "\n",
101
+ "# run model on GPU if available\n",
102
+ "device = torch.device('cuda:0' if torch.cuda.is_available() else 'cpu')\n",
103
+ "model = model.to(device)\n",
104
+ "model = model.eval()\n",
105
+ "model.args.token_dropout = False"
106
+ ]
107
+ },
108
+ {
109
+ "cell_type": "code",
110
+ "execution_count": null,
111
+ "metadata": {
112
+ "id": "ql8K460bjQtv"
113
+ },
114
+ "outputs": [],
115
+ "source": [
116
+ "def get_bias_from_esm(seq, p=None):\n",
117
+ " '''p=None; number of calculation done in parallel (increase if you have more gpu-memory)'''\n",
118
+ "\n",
119
+ " # map esm-alphabet to standard-alphabet\n",
120
+ " tmp_a2n = {a:n for n,a in enumerate(alphabet.all_toks[4:24])}\n",
121
+ " tmp_aa_map = np.array([tmp_a2n[a] for a in \"ARNDCQEGHILKMFPSTWYV\"])\n",
122
+ "\n",
123
+ " x,ln = alphabet.get_batch_converter()([(None,seq)])[-1],len(seq)\n",
124
+ " if p is None: p = ln\n",
125
+ " with torch.no_grad():\n",
126
+ " f = lambda x: model(x)[\"logits\"][:,1:(ln+1),4:24]\n",
127
+ " logits = np.zeros((ln,20))\n",
128
+ " for n in range(0,ln,p):\n",
129
+ " m = min(n+p,ln)\n",
130
+ " x_h = torch.tile(torch.clone(x),[m-n,1])\n",
131
+ " for i in range(m-n):\n",
132
+ " x_h[i,n+i+1] = alphabet.mask_idx\n",
133
+ " fx_h = f(x_h.to(device))\n",
134
+ " for i in range(m-n):\n",
135
+ " logits[n+i] = fx_h[i,n+i].cpu().numpy()\n",
136
+ " \n",
137
+ " return logits[:,tmp_aa_map]"
138
+ ]
139
+ },
140
+ {
141
+ "cell_type": "code",
142
+ "execution_count": null,
143
+ "metadata": {
144
+ "id": "mrD1PRRMkZt3"
145
+ },
146
+ "outputs": [],
147
+ "source": [
148
+ "# get bias\n",
149
+ "seq = SEQUENCE\n",
150
+ "bias = get_bias_from_esm(seq)\n",
151
+ "np.savetxt(\"bias.txt\",bias)"
152
+ ]
153
+ },
154
+ {
155
+ "cell_type": "code",
156
+ "execution_count": null,
157
+ "metadata": {
158
+ "id": "K_8S9rXOkwZ8"
159
+ },
160
+ "outputs": [],
161
+ "source": [
162
+ "import matplotlib.pyplot as plt\n",
163
+ "plt.imshow(bias.T,cmap=\"bwr_r\",vmin=-10,vmax=10)"
164
+ ]
165
+ },
166
+ {
167
+ "cell_type": "code",
168
+ "source": [
169
+ "# clear GPU memory\n",
170
+ "del model\n",
171
+ "gc.collect()\n",
172
+ "torch.cuda.empty_cache()"
173
+ ],
174
+ "metadata": {
175
+ "id": "10_kZfNQJpsz"
176
+ },
177
+ "execution_count": null,
178
+ "outputs": []
179
+ },
180
+ {
181
+ "cell_type": "markdown",
182
+ "metadata": {
183
+ "id": "OA2k3sAYuiXe"
184
+ },
185
+ "source": [
186
+ "#AfDesign \n"
187
+ ]
188
+ },
189
+ {
190
+ "cell_type": "code",
191
+ "execution_count": null,
192
+ "metadata": {
193
+ "cellView": "form",
194
+ "id": "-AXy0s_4cKaK"
195
+ },
196
+ "outputs": [],
197
+ "source": [
198
+ "#@title setup afdesign\n",
199
+ "%%time\n",
200
+ "import os\n",
201
+ "if not os.path.isdir(\"params\"):\n",
202
+ " # get code\n",
203
+ " os.system(\"pip -q install git+https://github.com/sokrypton/ColabDesign.git@v1.1.1\")\n",
204
+ " # for debugging\n",
205
+ " os.system(\"ln -s /usr/local/lib/python3.*/dist-packages/colabdesign colabdesign\")\n",
206
+ " # download params\n",
207
+ " os.system(\"mkdir params\")\n",
208
+ " os.system(\"apt-get install aria2 -qq\")\n",
209
+ " os.system(\"aria2c -q -x 16 https://storage.googleapis.com/alphafold/alphafold_params_2022-12-06.tar\")\n",
210
+ " os.system(\"tar -xf alphafold_params_2022-12-06.tar -C params\")\n",
211
+ "\n",
212
+ "import warnings\n",
213
+ "warnings.simplefilter(action='ignore', category=FutureWarning)\n",
214
+ "\n",
215
+ "import os\n",
216
+ "from colabdesign import mk_afdesign_model, clear_mem\n",
217
+ "from colabdesign.af.alphafold.common import residue_constants\n",
218
+ "from IPython.display import HTML\n",
219
+ "import numpy as np\n",
220
+ "\n"
221
+ ]
222
+
223
+ },
224
+ {
225
+ "cell_type": "code",
226
+ "execution_count": null,
227
+ "metadata": {
228
+ "id": "qLd1DsnKzxBJ"
229
+ },
230
+ "outputs": [],
231
+ "source": [
232
+ "clear_mem()\n",
233
+ "model = mk_afdesign_model(protocol=\"fixbb\",\n",
234
+ " use_templates=False) # set True to constrain structure\n",
235
+ "model.prep_inputs(PDB_FILENAME, chain=\"A\")\n",
236
+ "print(\"length\", model._len)"
237
+ ]
238
+ },
239
+ {
240
+ "cell_type": "code",
241
+ "execution_count": null,
242
+ "metadata": {
243
+ "id": "WZGyGfMTmdXE"
244
+ },
245
+ "outputs": [],
246
+ "source": [
247
+ "import matplotlib.pyplot as plt\n",
248
+ "bias = np.loadtxt(\"bias.txt\")\n",
249
+ "plt.imshow(bias.T,cmap=\"bwr_r\",vmin=-10,vmax=10)"
250
+ ]
251
+ },
252
+ {
253
+ "cell_type": "code",
254
+ "execution_count": null,
255
+ "metadata": {
256
+ "id": "xeVuwTYWmQmp"
257
+ },
258
+ "outputs": [],
259
+ "source": [
260
+ "model.restart()\n",
261
+ "model.set_seq(bias=bias)\n",
262
+ "model.design_3stage(50,50,10)"
263
+ ]
264
+ },
265
+ {
266
+ "cell_type": "code",
267
+ "execution_count": null,
268
+ "metadata": {
269
+ "id": "cW1KQiHKJpfp"
270
+ },
271
+ "outputs": [],
272
+ "source": [
273
+ "HTML(model.animate())"
274
+ ]
275
+ },
276
+ {
277
+ "cell_type": "code",
278
+ "execution_count": null,
279
+ "metadata": {
280
+ "id": "YDrChASGVUUx"
281
+ },
282
+ "outputs": [],
283
+ "source": [
284
+ "model.get_seqs()"
285
+ ]
286
+ },
287
+ {
288
+ "cell_type": "code",
289
+ "execution_count": null,
290
+ "metadata": {
291
+ "id": "YEApO8YzBoS0"
292
+ },
293
+ "outputs": [],
294
+ "source": [
295
+ "model.save_pdb(f\"{model.protocol}.pdb\")\n",
296
+ "model.plot_pdb()"
297
+ ]
298
+ },
299
+ {
300
+ "cell_type": "code",
301
+ "source": [],
302
+ "metadata": {
303
+ "id": "0Xd7zQ-PqTly"
304
+ },
305
+ "execution_count": null,
306
+ "outputs": []
307
+ }
308
+ ],
309
+ "metadata": {
310
+ "accelerator": "GPU",
311
+ "colab": {
312
+ "collapsed_sections": [
313
+ "q4qiU9I0QHSz"
314
+ ],
315
+ "name": "use_esm_1b_bias.ipynb",
316
+ "provenance": [],
317
+ "include_colab_link": true
318
+ },
319
+ "kernelspec": {
320
+ "display_name": "Python 3",
321
+ "name": "python3"
322
+ },
323
+ "language_info": {
324
+ "name": "python"
325
+ }
326
+ },
327
+ "nbformat": 4,
328
+ "nbformat_minor": 0
329
+ }
model/PXDesignBench/ColabDesign/af_design_tutorial.ipynb ADDED
@@ -0,0 +1,43 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "nbformat": 4,
3
+ "nbformat_minor": 0,
4
+ "metadata": {
5
+ "colab": {
6
+ "provenance": [],
7
+ "authorship_tag": "ABX9TyM3Mazv53Et9F6cqnRak08f",
8
+ "include_colab_link": true
9
+ },
10
+ "kernelspec": {
11
+ "name": "python3",
12
+ "display_name": "Python 3"
13
+ },
14
+ "language_info": {
15
+ "name": "python"
16
+ }
17
+ },
18
+ "cells": [
19
+ {
20
+ "cell_type": "markdown",
21
+ "metadata": {
22
+ "id": "view-in-github",
23
+ "colab_type": "text"
24
+ },
25
+ "source": [
26
+ "<a href=\"https://colab.research.google.com/github/sokrypton/ColabDesign/blob/main/af/design.ipynb\" target=\"_parent\"><img src=\"https://colab.research.google.com/assets/colab-badge.svg\" alt=\"Open In Colab\"/></a>"
27
+ ]
28
+ },
29
+ {
30
+ "cell_type": "markdown",
31
+ "source": [
32
+ "The general tutorial has moved to:\n",
33
+ "https://colab.research.google.com/github/sokrypton/ColabDesign/blob/main/af/design.ipynb\n",
34
+ "\n",
35
+ "For peptide design tutorial see:\n",
36
+ "https://colab.research.google.com/github/sokrypton/ColabDesign/blob/main/af/examples/peptide_binder_design.ipynb"
37
+ ],
38
+ "metadata": {
39
+ "id": "IabCAgHR6Xa3"
40
+ }
41
+ }
42
+ ]
43
+ }
model/PXDesignBench/ColabDesign/colabdesign/__init__.py ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os,jax
2
+ # disable triton_gemm for jax versions > 0.3
3
+ if int(jax.__version__.split(".")[1]) > 3:
4
+ os.environ["XLA_FLAGS"] = "--xla_gpu_enable_triton_gemm=false"
5
+
6
+ import warnings
7
+ warnings.simplefilter(action='ignore', category=FutureWarning)
8
+
9
+ from colabdesign.shared.utils import clear_mem
10
+ from colabdesign.af.model import mk_af_model
11
+ from colabdesign.tr.model import mk_tr_model
12
+ from colabdesign.mpnn.model import mk_mpnn_model
13
+
14
+ # backward compatability
15
+ mk_design_model = mk_afdesign_model = mk_af_model
16
+ mk_trdesign_model = mk_tr_model
model/PXDesignBench/ColabDesign/colabdesign/af/README.md ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ - model.py - configure the model
2
+ - inputs.py - configure the inputs
3
+ - loss.py - configure the loss
4
+ - prep.py - prep features
5
+ - design.py - gradient update loop
6
+ - utils.py - various tools for saving/plotting
model/PXDesignBench/ColabDesign/colabdesign/af/__init__.py ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os,jax
2
+ # disable triton_gemm for jax versions > 0.3
3
+ if int(jax.__version__.split(".")[1]) > 3:
4
+ os.environ["XLA_FLAGS"] = "--xla_gpu_enable_triton_gemm=false"
5
+
6
+ import warnings
7
+ warnings.simplefilter(action='ignore', category=FutureWarning)
8
+
9
+ from colabdesign.shared.utils import clear_mem
10
+ from colabdesign.af.model import mk_af_model
11
+
12
+ # backward compatability
13
+ mk_design_model = mk_afdesign_model = mk_af_model
model/PXDesignBench/ColabDesign/colabdesign/af/alphafold/__init__.py ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright 2021 DeepMind Technologies Limited
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+ """An implementation of the inference pipeline of AlphaFold v2.0."""
model/PXDesignBench/ColabDesign/colabdesign/af/alphafold/common/__init__.py ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright 2021 DeepMind Technologies Limited
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+ """Common data types and constants used within Alphafold."""
model/PXDesignBench/ColabDesign/colabdesign/af/alphafold/common/confidence.py ADDED
@@ -0,0 +1,169 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright 2021 DeepMind Technologies Limited
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ """Functions for processing confidence metrics."""
16
+
17
+ import jax.numpy as jnp
18
+ import jax
19
+ import numpy as np
20
+ from colabdesign.af.alphafold.common import residue_constants
21
+ import scipy.special
22
+
23
+ def compute_tol(prev_pos, current_pos, mask, use_jnp=False):
24
+ # Early stopping criteria based on criteria used in
25
+ # AF2Complex: https://www.nature.com/articles/s41467-022-29394-2
26
+ _np = jnp if use_jnp else np
27
+ dist = lambda x:_np.sqrt(((x[:,None] - x[None,:])**2).sum(-1))
28
+ ca_idx = residue_constants.atom_order['CA']
29
+ sq_diff = _np.square(dist(prev_pos[:,ca_idx])-dist(current_pos[:,ca_idx]))
30
+ mask_2d = mask[:,None] * mask[None,:]
31
+ return _np.sqrt((sq_diff * mask_2d).sum()/mask_2d.sum() + 1e-8)
32
+
33
+
34
+ def compute_plddt(logits, use_jnp=False):
35
+ """Computes per-residue pLDDT from logits.
36
+ Args:
37
+ logits: [num_res, num_bins] output from the PredictedLDDTHead.
38
+ Returns:
39
+ plddt: [num_res] per-residue pLDDT.
40
+ """
41
+ if use_jnp:
42
+ _np, _softmax = jnp, jax.nn.softmax
43
+ else:
44
+ _np, _softmax = np, scipy.special.softmax
45
+
46
+ num_bins = logits.shape[-1]
47
+ bin_width = 1.0 / num_bins
48
+ bin_centers = _np.arange(start=0.5 * bin_width, stop=1.0, step=bin_width)
49
+ probs = _softmax(logits, axis=-1)
50
+ predicted_lddt_ca = (probs * bin_centers[None, :]).sum(-1)
51
+ return predicted_lddt_ca * 100
52
+
53
+ def _calculate_bin_centers(breaks, use_jnp=False):
54
+ """Gets the bin centers from the bin edges.
55
+ Args:
56
+ breaks: [num_bins - 1] the error bin edges.
57
+ Returns:
58
+ bin_centers: [num_bins] the error bin centers.
59
+ """
60
+ _np = jnp if use_jnp else np
61
+ step = breaks[1] - breaks[0]
62
+
63
+ # Add half-step to get the center
64
+ bin_centers = breaks + step / 2
65
+
66
+ # Add a catch-all bin at the end.
67
+ return _np.append(bin_centers, bin_centers[-1] + step)
68
+
69
+ def _calculate_expected_aligned_error(
70
+ alignment_confidence_breaks,
71
+ aligned_distance_error_probs,
72
+ use_jnp=False):
73
+ """Calculates expected aligned distance errors for every pair of residues.
74
+ Args:
75
+ alignment_confidence_breaks: [num_bins - 1] the error bin edges.
76
+ aligned_distance_error_probs: [num_res, num_res, num_bins] the predicted
77
+ probs for each error bin, for each pair of residues.
78
+ Returns:
79
+ predicted_aligned_error: [num_res, num_res] the expected aligned distance
80
+ error for each pair of residues.
81
+ max_predicted_aligned_error: The maximum predicted error possible.
82
+ """
83
+ bin_centers = _calculate_bin_centers(alignment_confidence_breaks, use_jnp=use_jnp)
84
+ # Tuple of expected aligned distance error and max possible error.
85
+ pae = (aligned_distance_error_probs * bin_centers).sum(-1)
86
+ return (pae, bin_centers[-1])
87
+
88
+ def compute_predicted_aligned_error(logits, breaks, use_jnp=False):
89
+ """Computes aligned confidence metrics from logits.
90
+ Args:
91
+ logits: [num_res, num_res, num_bins] the logits output from
92
+ PredictedAlignedErrorHead.
93
+ breaks: [num_bins - 1] the error bin edges.
94
+
95
+ Returns:
96
+ aligned_confidence_probs: [num_res, num_res, num_bins] the predicted
97
+ aligned error probabilities over bins for each residue pair.
98
+ predicted_aligned_error: [num_res, num_res] the expected aligned distance
99
+ error for each pair of residues.
100
+ max_predicted_aligned_error: The maximum predicted error possible.
101
+ """
102
+ _softmax = jax.nn.softmax if use_jnp else scipy.special.softmax
103
+ aligned_confidence_probs = _softmax(logits,axis=-1)
104
+ predicted_aligned_error, max_predicted_aligned_error = \
105
+ _calculate_expected_aligned_error(breaks, aligned_confidence_probs, use_jnp=use_jnp)
106
+
107
+ return {
108
+ 'aligned_confidence_probs': aligned_confidence_probs,
109
+ 'predicted_aligned_error': predicted_aligned_error,
110
+ 'max_predicted_aligned_error': max_predicted_aligned_error,
111
+ }
112
+
113
+ def predicted_tm_score(logits, breaks, residue_weights = None,
114
+ asym_id = None, use_jnp=False):
115
+ """Computes predicted TM alignment or predicted interface TM alignment score.
116
+
117
+ Args:
118
+ logits: [num_res, num_res, num_bins] the logits output from
119
+ PredictedAlignedErrorHead.
120
+ breaks: [num_bins] the error bins.
121
+ residue_weights: [num_res] the per residue weights to use for the
122
+ expectation.
123
+ asym_id: [num_res] the asymmetric unit ID - the chain ID. Only needed for
124
+ ipTM calculation.
125
+
126
+ Returns:
127
+ ptm_score: The predicted TM alignment or the predicted iTM score.
128
+ """
129
+ if use_jnp:
130
+ _np, _softmax = jnp, jax.nn.softmax
131
+ else:
132
+ _np, _softmax = np, scipy.special.softmax
133
+
134
+ # residue_weights has to be in [0, 1], but can be floating-point, i.e. the
135
+ # exp. resolved head's probability.
136
+ if residue_weights is None:
137
+ residue_weights = _np.ones(logits.shape[0])
138
+
139
+ bin_centers = _calculate_bin_centers(breaks, use_jnp=use_jnp)
140
+ num_res = residue_weights.shape[0]
141
+
142
+ # Clip num_res to avoid negative/undefined d0.
143
+ clipped_num_res = _np.maximum(residue_weights.sum(), 19)
144
+
145
+ # Compute d_0(num_res) as defined by TM-score, eqn. (5) in Yang & Skolnick
146
+ # "Scoring function for automated assessment of protein structure template
147
+ # quality", 2004: http://zhanglab.ccmb.med.umich.edu/papers/2004_3.pdf
148
+ d0 = 1.24 * (clipped_num_res - 15) ** (1./3) - 1.8
149
+
150
+ # Convert logits to probs.
151
+ probs = _softmax(logits, axis=-1)
152
+
153
+ # TM-Score term for every bin.
154
+ tm_per_bin = 1. / (1 + _np.square(bin_centers) / _np.square(d0))
155
+ # E_distances tm(distance).
156
+ predicted_tm_term = (probs * tm_per_bin).sum(-1)
157
+
158
+ if asym_id is None:
159
+ pair_mask = _np.full((num_res,num_res),True)
160
+ else:
161
+ pair_mask = asym_id[:, None] != asym_id[None, :]
162
+
163
+ predicted_tm_term *= pair_mask
164
+
165
+ pair_residue_weights = pair_mask * (residue_weights[None, :] * residue_weights[:, None])
166
+ normed_residue_mask = pair_residue_weights / (1e-8 + pair_residue_weights.sum(-1, keepdims=True))
167
+ per_alignment = (predicted_tm_term * normed_residue_mask).sum(-1)
168
+
169
+ return (per_alignment * residue_weights).max()
model/PXDesignBench/ColabDesign/colabdesign/af/alphafold/common/protein.py ADDED
@@ -0,0 +1,229 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright 2021 DeepMind Technologies Limited
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ """Protein data type."""
16
+ import dataclasses
17
+ import io
18
+ from typing import Any, Mapping, Optional
19
+ from colabdesign.af.alphafold.common import residue_constants
20
+ from Bio.PDB import PDBParser
21
+ import numpy as np
22
+
23
+ FeatureDict = Mapping[str, np.ndarray]
24
+ ModelOutput = Mapping[str, Any] # Is a nested dict.
25
+
26
+
27
+ @dataclasses.dataclass(frozen=True)
28
+ class Protein:
29
+ """Protein structure representation."""
30
+
31
+ # Cartesian coordinates of atoms in angstroms. The atom types correspond to
32
+ # residue_constants.atom_types, i.e. the first three are N, CA, CB.
33
+ atom_positions: np.ndarray # [num_res, num_atom_type, 3]
34
+
35
+ # Amino-acid type for each residue represented as an integer between 0 and
36
+ # 20, where 20 is 'X'.
37
+ aatype: np.ndarray # [num_res]
38
+
39
+ # Binary float mask to indicate presence of a particular atom. 1.0 if an atom
40
+ # is present and 0.0 if not. This should be used for loss masking.
41
+ atom_mask: np.ndarray # [num_res, num_atom_type]
42
+
43
+ # Residue index as used in PDB. It is not necessarily continuous or 0-indexed.
44
+ residue_index: np.ndarray # [num_res]
45
+
46
+ # B-factors, or temperature factors, of each residue (in sq. angstroms units),
47
+ # representing the displacement of the residue from its ground truth mean
48
+ # value.
49
+ b_factors: np.ndarray # [num_res, num_atom_type]
50
+
51
+
52
+ def from_pdb_string(pdb_str: str, chain_id: Optional[str] = None) -> Protein:
53
+ """Takes a PDB string and constructs a Protein object.
54
+
55
+ WARNING: All non-standard residue types will be converted into UNK. All
56
+ non-standard atoms will be ignored.
57
+
58
+ Args:
59
+ pdb_str: The contents of the pdb file
60
+ chain_id: If None, then the pdb file must contain a single chain (which
61
+ will be parsed). If chain_id is specified (e.g. A), then only that chain
62
+ is parsed.
63
+
64
+ Returns:
65
+ A new `Protein` parsed from the pdb contents.
66
+ """
67
+ pdb_fh = io.StringIO(pdb_str)
68
+ parser = PDBParser(QUIET=True)
69
+ structure = parser.get_structure('none', pdb_fh)
70
+ models = list(structure.get_models())
71
+ if len(models) != 1:
72
+ raise ValueError(
73
+ f'Only single model PDBs are supported. Found {len(models)} models.')
74
+ model = models[0]
75
+
76
+ if chain_id is not None:
77
+ chain = model[chain_id]
78
+ else:
79
+ chains = list(model.get_chains())
80
+ if len(chains) != 1:
81
+ raise ValueError(
82
+ 'Only single chain PDBs are supported when chain_id not specified. '
83
+ f'Found {len(chains)} chains.')
84
+ else:
85
+ chain = chains[0]
86
+
87
+ atom_positions = []
88
+ aatype = []
89
+ atom_mask = []
90
+ residue_index = []
91
+ b_factors = []
92
+
93
+ for res in chain:
94
+ if res.id[2] != ' ':
95
+ raise ValueError(
96
+ f'PDB contains an insertion code at chain {chain.id} and residue '
97
+ f'index {res.id[1]}. These are not supported.')
98
+ res_shortname = residue_constants.restype_3to1.get(res.resname, 'X')
99
+ restype_idx = residue_constants.restype_order.get(
100
+ res_shortname, residue_constants.restype_num)
101
+ pos = np.zeros((residue_constants.atom_type_num, 3))
102
+ mask = np.zeros((residue_constants.atom_type_num,))
103
+ res_b_factors = np.zeros((residue_constants.atom_type_num,))
104
+ for atom in res:
105
+ if atom.name not in residue_constants.atom_types:
106
+ continue
107
+ pos[residue_constants.atom_order[atom.name]] = atom.coord
108
+ mask[residue_constants.atom_order[atom.name]] = 1.
109
+ res_b_factors[residue_constants.atom_order[atom.name]] = atom.bfactor
110
+ if np.sum(mask) < 0.5:
111
+ # If no known atom positions are reported for the residue then skip it.
112
+ continue
113
+ aatype.append(restype_idx)
114
+ atom_positions.append(pos)
115
+ atom_mask.append(mask)
116
+ residue_index.append(res.id[1])
117
+ b_factors.append(res_b_factors)
118
+
119
+ return Protein(
120
+ atom_positions=np.array(atom_positions),
121
+ atom_mask=np.array(atom_mask),
122
+ aatype=np.array(aatype),
123
+ residue_index=np.array(residue_index),
124
+ b_factors=np.array(b_factors))
125
+
126
+
127
+ def to_pdb(prot: Protein) -> str:
128
+ """Converts a `Protein` instance to a PDB string.
129
+
130
+ Args:
131
+ prot: The protein to convert to PDB.
132
+
133
+ Returns:
134
+ PDB string.
135
+ """
136
+ restypes = residue_constants.restypes + ['X']
137
+ res_1to3 = lambda r: residue_constants.restype_1to3.get(restypes[r], 'UNK')
138
+ atom_types = residue_constants.atom_types
139
+
140
+ pdb_lines = []
141
+
142
+ atom_mask = prot.atom_mask
143
+ aatype = prot.aatype
144
+ atom_positions = prot.atom_positions
145
+ residue_index = prot.residue_index.astype(np.int32)
146
+ b_factors = prot.b_factors
147
+
148
+ if np.any(aatype > residue_constants.restype_num):
149
+ raise ValueError('Invalid aatypes.')
150
+
151
+ pdb_lines.append('MODEL 1')
152
+ atom_index = 1
153
+ chain_id = 'A'
154
+ # Add all atom sites.
155
+ for i in range(aatype.shape[0]):
156
+ res_name_3 = res_1to3(aatype[i])
157
+ for atom_name, pos, mask, b_factor in zip(
158
+ atom_types, atom_positions[i], atom_mask[i], b_factors[i]):
159
+ if mask < 0.5:
160
+ continue
161
+
162
+ record_type = 'ATOM'
163
+ name = atom_name if len(atom_name) == 4 else f' {atom_name}'
164
+ alt_loc = ''
165
+ insertion_code = ''
166
+ occupancy = 1.00
167
+ element = atom_name[0] # Protein supports only C, N, O, S, this works.
168
+ charge = ''
169
+ # PDB is a columnar format, every space matters here!
170
+ atom_line = (f'{record_type:<6}{atom_index:>5} {name:<4}{alt_loc:>1}'
171
+ f'{res_name_3:>3} {chain_id:>1}'
172
+ f'{residue_index[i]:>4}{insertion_code:>1} '
173
+ f'{pos[0]:>8.3f}{pos[1]:>8.3f}{pos[2]:>8.3f}'
174
+ f'{occupancy:>6.2f}{b_factor:>6.2f} '
175
+ f'{element:>2}{charge:>2}')
176
+ pdb_lines.append(atom_line)
177
+ atom_index += 1
178
+
179
+ # Close the chain.
180
+ chain_end = 'TER'
181
+ chain_termination_line = (
182
+ f'{chain_end:<6}{atom_index:>5} {res_1to3(aatype[-1]):>3} '
183
+ f'{chain_id:>1}{residue_index[-1]:>4}')
184
+ pdb_lines.append(chain_termination_line)
185
+ pdb_lines.append('ENDMDL')
186
+
187
+ pdb_lines.append('END')
188
+ pdb_lines.append('')
189
+ return '\n'.join(pdb_lines)
190
+
191
+
192
+ def ideal_atom_mask(prot: Protein) -> np.ndarray:
193
+ """Computes an ideal atom mask.
194
+
195
+ `Protein.atom_mask` typically is defined according to the atoms that are
196
+ reported in the PDB. This function computes a mask according to heavy atoms
197
+ that should be present in the given sequence of amino acids.
198
+
199
+ Args:
200
+ prot: `Protein` whose fields are `numpy.ndarray` objects.
201
+
202
+ Returns:
203
+ An ideal atom mask.
204
+ """
205
+ return residue_constants.STANDARD_ATOM_MASK[prot.aatype]
206
+
207
+
208
+ def from_prediction(features: FeatureDict, result: ModelOutput,
209
+ b_factors: Optional[np.ndarray] = None) -> Protein:
210
+ """Assembles a protein from a prediction.
211
+
212
+ Args:
213
+ features: Dictionary holding model inputs.
214
+ result: Dictionary holding model outputs.
215
+ b_factors: (Optional) B-factors to use for the protein.
216
+
217
+ Returns:
218
+ A protein instance.
219
+ """
220
+ fold_output = result['structure_module']
221
+ if b_factors is None:
222
+ b_factors = np.zeros_like(fold_output['final_atom_mask'])
223
+
224
+ return Protein(
225
+ aatype=features['aatype'][0],
226
+ atom_positions=fold_output['final_atom_positions'],
227
+ atom_mask=fold_output['final_atom_mask'],
228
+ residue_index=features['residue_index'][0] + 1,
229
+ b_factors=b_factors)
model/PXDesignBench/ColabDesign/colabdesign/af/alphafold/common/residue_constants.py ADDED
@@ -0,0 +1,911 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright 2021 DeepMind Technologies Limited
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ """Constants used in AlphaFold."""
16
+
17
+ import collections
18
+ import functools
19
+ from typing import List, Mapping, Tuple
20
+
21
+ import numpy as np
22
+ import tree
23
+
24
+ # Internal import (35fd).
25
+
26
+
27
+ # Distance from one CA to next CA [trans configuration: omega = 180].
28
+ ca_ca = 3.80209737096
29
+
30
+ # Format: The list for each AA type contains chi1, chi2, chi3, chi4 in
31
+ # this order (or a relevant subset from chi1 onwards). ALA and GLY don't have
32
+ # chi angles so their chi angle lists are empty.
33
+ chi_angles_atoms = {
34
+ 'ALA': [],
35
+ # Chi5 in arginine is always 0 +- 5 degrees, so ignore it.
36
+ 'ARG': [['N', 'CA', 'CB', 'CG'], ['CA', 'CB', 'CG', 'CD'],
37
+ ['CB', 'CG', 'CD', 'NE'], ['CG', 'CD', 'NE', 'CZ']],
38
+ 'ASN': [['N', 'CA', 'CB', 'CG'], ['CA', 'CB', 'CG', 'OD1']],
39
+ 'ASP': [['N', 'CA', 'CB', 'CG'], ['CA', 'CB', 'CG', 'OD1']],
40
+ 'CYS': [['N', 'CA', 'CB', 'SG']],
41
+ 'GLN': [['N', 'CA', 'CB', 'CG'], ['CA', 'CB', 'CG', 'CD'],
42
+ ['CB', 'CG', 'CD', 'OE1']],
43
+ 'GLU': [['N', 'CA', 'CB', 'CG'], ['CA', 'CB', 'CG', 'CD'],
44
+ ['CB', 'CG', 'CD', 'OE1']],
45
+ 'GLY': [],
46
+ 'HIS': [['N', 'CA', 'CB', 'CG'], ['CA', 'CB', 'CG', 'ND1']],
47
+ 'ILE': [['N', 'CA', 'CB', 'CG1'], ['CA', 'CB', 'CG1', 'CD1']],
48
+ 'LEU': [['N', 'CA', 'CB', 'CG'], ['CA', 'CB', 'CG', 'CD1']],
49
+ 'LYS': [['N', 'CA', 'CB', 'CG'], ['CA', 'CB', 'CG', 'CD'],
50
+ ['CB', 'CG', 'CD', 'CE'], ['CG', 'CD', 'CE', 'NZ']],
51
+ 'MET': [['N', 'CA', 'CB', 'CG'], ['CA', 'CB', 'CG', 'SD'],
52
+ ['CB', 'CG', 'SD', 'CE']],
53
+ 'PHE': [['N', 'CA', 'CB', 'CG'], ['CA', 'CB', 'CG', 'CD1']],
54
+ 'PRO': [['N', 'CA', 'CB', 'CG'], ['CA', 'CB', 'CG', 'CD']],
55
+ 'SER': [['N', 'CA', 'CB', 'OG']],
56
+ 'THR': [['N', 'CA', 'CB', 'OG1']],
57
+ 'TRP': [['N', 'CA', 'CB', 'CG'], ['CA', 'CB', 'CG', 'CD1']],
58
+ 'TYR': [['N', 'CA', 'CB', 'CG'], ['CA', 'CB', 'CG', 'CD1']],
59
+ 'VAL': [['N', 'CA', 'CB', 'CG1']],
60
+ }
61
+
62
+ # If chi angles given in fixed-length array, this matrix determines how to mask
63
+ # them for each AA type. The order is as per restype_order (see below).
64
+ chi_angles_mask = [
65
+ [0.0, 0.0, 0.0, 0.0], # ALA
66
+ [1.0, 1.0, 1.0, 1.0], # ARG
67
+ [1.0, 1.0, 0.0, 0.0], # ASN
68
+ [1.0, 1.0, 0.0, 0.0], # ASP
69
+ [1.0, 0.0, 0.0, 0.0], # CYS
70
+ [1.0, 1.0, 1.0, 0.0], # GLN
71
+ [1.0, 1.0, 1.0, 0.0], # GLU
72
+ [0.0, 0.0, 0.0, 0.0], # GLY
73
+ [1.0, 1.0, 0.0, 0.0], # HIS
74
+ [1.0, 1.0, 0.0, 0.0], # ILE
75
+ [1.0, 1.0, 0.0, 0.0], # LEU
76
+ [1.0, 1.0, 1.0, 1.0], # LYS
77
+ [1.0, 1.0, 1.0, 0.0], # MET
78
+ [1.0, 1.0, 0.0, 0.0], # PHE
79
+ [1.0, 1.0, 0.0, 0.0], # PRO
80
+ [1.0, 0.0, 0.0, 0.0], # SER
81
+ [1.0, 0.0, 0.0, 0.0], # THR
82
+ [1.0, 1.0, 0.0, 0.0], # TRP
83
+ [1.0, 1.0, 0.0, 0.0], # TYR
84
+ [1.0, 0.0, 0.0, 0.0], # VAL
85
+ ]
86
+
87
+ # The following chi angles are pi periodic: they can be rotated by a multiple
88
+ # of pi without affecting the structure.
89
+ chi_pi_periodic = [
90
+ [0.0, 0.0, 0.0, 0.0], # ALA
91
+ [0.0, 0.0, 0.0, 0.0], # ARG
92
+ [0.0, 0.0, 0.0, 0.0], # ASN
93
+ [0.0, 1.0, 0.0, 0.0], # ASP
94
+ [0.0, 0.0, 0.0, 0.0], # CYS
95
+ [0.0, 0.0, 0.0, 0.0], # GLN
96
+ [0.0, 0.0, 1.0, 0.0], # GLU
97
+ [0.0, 0.0, 0.0, 0.0], # GLY
98
+ [0.0, 0.0, 0.0, 0.0], # HIS
99
+ [0.0, 0.0, 0.0, 0.0], # ILE
100
+ [0.0, 0.0, 0.0, 0.0], # LEU
101
+ [0.0, 0.0, 0.0, 0.0], # LYS
102
+ [0.0, 0.0, 0.0, 0.0], # MET
103
+ [0.0, 1.0, 0.0, 0.0], # PHE
104
+ [0.0, 0.0, 0.0, 0.0], # PRO
105
+ [0.0, 0.0, 0.0, 0.0], # SER
106
+ [0.0, 0.0, 0.0, 0.0], # THR
107
+ [0.0, 0.0, 0.0, 0.0], # TRP
108
+ [0.0, 1.0, 0.0, 0.0], # TYR
109
+ [0.0, 0.0, 0.0, 0.0], # VAL
110
+ [0.0, 0.0, 0.0, 0.0], # UNK
111
+ ]
112
+
113
+ # Atoms positions relative to the 8 rigid groups, defined by the pre-omega, phi,
114
+ # psi and chi angles:
115
+ # 0: 'backbone group',
116
+ # 1: 'pre-omega-group', (empty)
117
+ # 2: 'phi-group', (currently empty, because it defines only hydrogens)
118
+ # 3: 'psi-group',
119
+ # 4,5,6,7: 'chi1,2,3,4-group'
120
+ # The atom positions are relative to the axis-end-atom of the corresponding
121
+ # rotation axis. The x-axis is in direction of the rotation axis, and the y-axis
122
+ # is defined such that the dihedral-angle-definiting atom (the last entry in
123
+ # chi_angles_atoms above) is in the xy-plane (with a positive y-coordinate).
124
+ # format: [atomname, group_idx, rel_position]
125
+ rigid_group_atom_positions = {
126
+ 'ALA': [
127
+ ['N', 0, (-0.525, 1.363, 0.000)],
128
+ ['CA', 0, (0.000, 0.000, 0.000)],
129
+ ['C', 0, (1.526, -0.000, -0.000)],
130
+ ['CB', 0, (-0.529, -0.774, -1.205)],
131
+ ['O', 3, (0.627, 1.062, 0.000)],
132
+ ],
133
+ 'ARG': [
134
+ ['N', 0, (-0.524, 1.362, -0.000)],
135
+ ['CA', 0, (0.000, 0.000, 0.000)],
136
+ ['C', 0, (1.525, -0.000, -0.000)],
137
+ ['CB', 0, (-0.524, -0.778, -1.209)],
138
+ ['O', 3, (0.626, 1.062, 0.000)],
139
+ ['CG', 4, (0.616, 1.390, -0.000)],
140
+ ['CD', 5, (0.564, 1.414, 0.000)],
141
+ ['NE', 6, (0.539, 1.357, -0.000)],
142
+ ['NH1', 7, (0.206, 2.301, 0.000)],
143
+ ['NH2', 7, (2.078, 0.978, -0.000)],
144
+ ['CZ', 7, (0.758, 1.093, -0.000)],
145
+ ],
146
+ 'ASN': [
147
+ ['N', 0, (-0.536, 1.357, 0.000)],
148
+ ['CA', 0, (0.000, 0.000, 0.000)],
149
+ ['C', 0, (1.526, -0.000, -0.000)],
150
+ ['CB', 0, (-0.531, -0.787, -1.200)],
151
+ ['O', 3, (0.625, 1.062, 0.000)],
152
+ ['CG', 4, (0.584, 1.399, 0.000)],
153
+ ['ND2', 5, (0.593, -1.188, 0.001)],
154
+ ['OD1', 5, (0.633, 1.059, 0.000)],
155
+ ],
156
+ 'ASP': [
157
+ ['N', 0, (-0.525, 1.362, -0.000)],
158
+ ['CA', 0, (0.000, 0.000, 0.000)],
159
+ ['C', 0, (1.527, 0.000, -0.000)],
160
+ ['CB', 0, (-0.526, -0.778, -1.208)],
161
+ ['O', 3, (0.626, 1.062, -0.000)],
162
+ ['CG', 4, (0.593, 1.398, -0.000)],
163
+ ['OD1', 5, (0.610, 1.091, 0.000)],
164
+ ['OD2', 5, (0.592, -1.101, -0.003)],
165
+ ],
166
+ 'CYS': [
167
+ ['N', 0, (-0.522, 1.362, -0.000)],
168
+ ['CA', 0, (0.000, 0.000, 0.000)],
169
+ ['C', 0, (1.524, 0.000, 0.000)],
170
+ ['CB', 0, (-0.519, -0.773, -1.212)],
171
+ ['O', 3, (0.625, 1.062, -0.000)],
172
+ ['SG', 4, (0.728, 1.653, 0.000)],
173
+ ],
174
+ 'GLN': [
175
+ ['N', 0, (-0.526, 1.361, -0.000)],
176
+ ['CA', 0, (0.000, 0.000, 0.000)],
177
+ ['C', 0, (1.526, 0.000, 0.000)],
178
+ ['CB', 0, (-0.525, -0.779, -1.207)],
179
+ ['O', 3, (0.626, 1.062, -0.000)],
180
+ ['CG', 4, (0.615, 1.393, 0.000)],
181
+ ['CD', 5, (0.587, 1.399, -0.000)],
182
+ ['NE2', 6, (0.593, -1.189, -0.001)],
183
+ ['OE1', 6, (0.634, 1.060, 0.000)],
184
+ ],
185
+ 'GLU': [
186
+ ['N', 0, (-0.528, 1.361, 0.000)],
187
+ ['CA', 0, (0.000, 0.000, 0.000)],
188
+ ['C', 0, (1.526, -0.000, -0.000)],
189
+ ['CB', 0, (-0.526, -0.781, -1.207)],
190
+ ['O', 3, (0.626, 1.062, 0.000)],
191
+ ['CG', 4, (0.615, 1.392, 0.000)],
192
+ ['CD', 5, (0.600, 1.397, 0.000)],
193
+ ['OE1', 6, (0.607, 1.095, -0.000)],
194
+ ['OE2', 6, (0.589, -1.104, -0.001)],
195
+ ],
196
+ 'GLY': [
197
+ ['N', 0, (-0.572, 1.337, 0.000)],
198
+ ['CA', 0, (0.000, 0.000, 0.000)],
199
+ ['C', 0, (1.517, -0.000, -0.000)],
200
+ ['O', 3, (0.626, 1.062, -0.000)],
201
+ ],
202
+ 'HIS': [
203
+ ['N', 0, (-0.527, 1.360, 0.000)],
204
+ ['CA', 0, (0.000, 0.000, 0.000)],
205
+ ['C', 0, (1.525, 0.000, 0.000)],
206
+ ['CB', 0, (-0.525, -0.778, -1.208)],
207
+ ['O', 3, (0.625, 1.063, 0.000)],
208
+ ['CG', 4, (0.600, 1.370, -0.000)],
209
+ ['CD2', 5, (0.889, -1.021, 0.003)],
210
+ ['ND1', 5, (0.744, 1.160, -0.000)],
211
+ ['CE1', 5, (2.030, 0.851, 0.002)],
212
+ ['NE2', 5, (2.145, -0.466, 0.004)],
213
+ ],
214
+ 'ILE': [
215
+ ['N', 0, (-0.493, 1.373, -0.000)],
216
+ ['CA', 0, (0.000, 0.000, 0.000)],
217
+ ['C', 0, (1.527, -0.000, -0.000)],
218
+ ['CB', 0, (-0.536, -0.793, -1.213)],
219
+ ['O', 3, (0.627, 1.062, -0.000)],
220
+ ['CG1', 4, (0.534, 1.437, -0.000)],
221
+ ['CG2', 4, (0.540, -0.785, -1.199)],
222
+ ['CD1', 5, (0.619, 1.391, 0.000)],
223
+ ],
224
+ 'LEU': [
225
+ ['N', 0, (-0.520, 1.363, 0.000)],
226
+ ['CA', 0, (0.000, 0.000, 0.000)],
227
+ ['C', 0, (1.525, -0.000, -0.000)],
228
+ ['CB', 0, (-0.522, -0.773, -1.214)],
229
+ ['O', 3, (0.625, 1.063, -0.000)],
230
+ ['CG', 4, (0.678, 1.371, 0.000)],
231
+ ['CD1', 5, (0.530, 1.430, -0.000)],
232
+ ['CD2', 5, (0.535, -0.774, 1.200)],
233
+ ],
234
+ 'LYS': [
235
+ ['N', 0, (-0.526, 1.362, -0.000)],
236
+ ['CA', 0, (0.000, 0.000, 0.000)],
237
+ ['C', 0, (1.526, 0.000, 0.000)],
238
+ ['CB', 0, (-0.524, -0.778, -1.208)],
239
+ ['O', 3, (0.626, 1.062, -0.000)],
240
+ ['CG', 4, (0.619, 1.390, 0.000)],
241
+ ['CD', 5, (0.559, 1.417, 0.000)],
242
+ ['CE', 6, (0.560, 1.416, 0.000)],
243
+ ['NZ', 7, (0.554, 1.387, 0.000)],
244
+ ],
245
+ 'MET': [
246
+ ['N', 0, (-0.521, 1.364, -0.000)],
247
+ ['CA', 0, (0.000, 0.000, 0.000)],
248
+ ['C', 0, (1.525, 0.000, 0.000)],
249
+ ['CB', 0, (-0.523, -0.776, -1.210)],
250
+ ['O', 3, (0.625, 1.062, -0.000)],
251
+ ['CG', 4, (0.613, 1.391, -0.000)],
252
+ ['SD', 5, (0.703, 1.695, 0.000)],
253
+ ['CE', 6, (0.320, 1.786, -0.000)],
254
+ ],
255
+ 'PHE': [
256
+ ['N', 0, (-0.518, 1.363, 0.000)],
257
+ ['CA', 0, (0.000, 0.000, 0.000)],
258
+ ['C', 0, (1.524, 0.000, -0.000)],
259
+ ['CB', 0, (-0.525, -0.776, -1.212)],
260
+ ['O', 3, (0.626, 1.062, -0.000)],
261
+ ['CG', 4, (0.607, 1.377, 0.000)],
262
+ ['CD1', 5, (0.709, 1.195, -0.000)],
263
+ ['CD2', 5, (0.706, -1.196, 0.000)],
264
+ ['CE1', 5, (2.102, 1.198, -0.000)],
265
+ ['CE2', 5, (2.098, -1.201, -0.000)],
266
+ ['CZ', 5, (2.794, -0.003, -0.001)],
267
+ ],
268
+ 'PRO': [
269
+ ['N', 0, (-0.566, 1.351, -0.000)],
270
+ ['CA', 0, (0.000, 0.000, 0.000)],
271
+ ['C', 0, (1.527, -0.000, 0.000)],
272
+ ['CB', 0, (-0.546, -0.611, -1.293)],
273
+ ['O', 3, (0.621, 1.066, 0.000)],
274
+ ['CG', 4, (0.382, 1.445, 0.0)],
275
+ # ['CD', 5, (0.427, 1.440, 0.0)],
276
+ ['CD', 5, (0.477, 1.424, 0.0)], # manually made angle 2 degrees larger
277
+ ],
278
+ 'SER': [
279
+ ['N', 0, (-0.529, 1.360, -0.000)],
280
+ ['CA', 0, (0.000, 0.000, 0.000)],
281
+ ['C', 0, (1.525, -0.000, -0.000)],
282
+ ['CB', 0, (-0.518, -0.777, -1.211)],
283
+ ['O', 3, (0.626, 1.062, -0.000)],
284
+ ['OG', 4, (0.503, 1.325, 0.000)],
285
+ ],
286
+ 'THR': [
287
+ ['N', 0, (-0.517, 1.364, 0.000)],
288
+ ['CA', 0, (0.000, 0.000, 0.000)],
289
+ ['C', 0, (1.526, 0.000, -0.000)],
290
+ ['CB', 0, (-0.516, -0.793, -1.215)],
291
+ ['O', 3, (0.626, 1.062, 0.000)],
292
+ ['CG2', 4, (0.550, -0.718, -1.228)],
293
+ ['OG1', 4, (0.472, 1.353, 0.000)],
294
+ ],
295
+ 'TRP': [
296
+ ['N', 0, (-0.521, 1.363, 0.000)],
297
+ ['CA', 0, (0.000, 0.000, 0.000)],
298
+ ['C', 0, (1.525, -0.000, 0.000)],
299
+ ['CB', 0, (-0.523, -0.776, -1.212)],
300
+ ['O', 3, (0.627, 1.062, 0.000)],
301
+ ['CG', 4, (0.609, 1.370, -0.000)],
302
+ ['CD1', 5, (0.824, 1.091, 0.000)],
303
+ ['CD2', 5, (0.854, -1.148, -0.005)],
304
+ ['CE2', 5, (2.186, -0.678, -0.007)],
305
+ ['CE3', 5, (0.622, -2.530, -0.007)],
306
+ ['NE1', 5, (2.140, 0.690, -0.004)],
307
+ ['CH2', 5, (3.028, -2.890, -0.013)],
308
+ ['CZ2', 5, (3.283, -1.543, -0.011)],
309
+ ['CZ3', 5, (1.715, -3.389, -0.011)],
310
+ ],
311
+ 'TYR': [
312
+ ['N', 0, (-0.522, 1.362, 0.000)],
313
+ ['CA', 0, (0.000, 0.000, 0.000)],
314
+ ['C', 0, (1.524, -0.000, -0.000)],
315
+ ['CB', 0, (-0.522, -0.776, -1.213)],
316
+ ['O', 3, (0.627, 1.062, -0.000)],
317
+ ['CG', 4, (0.607, 1.382, -0.000)],
318
+ ['CD1', 5, (0.716, 1.195, -0.000)],
319
+ ['CD2', 5, (0.713, -1.194, -0.001)],
320
+ ['CE1', 5, (2.107, 1.200, -0.002)],
321
+ ['CE2', 5, (2.104, -1.201, -0.003)],
322
+ ['OH', 5, (4.168, -0.002, -0.005)],
323
+ ['CZ', 5, (2.791, -0.001, -0.003)],
324
+ ],
325
+ 'VAL': [
326
+ ['N', 0, (-0.494, 1.373, -0.000)],
327
+ ['CA', 0, (0.000, 0.000, 0.000)],
328
+ ['C', 0, (1.527, -0.000, -0.000)],
329
+ ['CB', 0, (-0.533, -0.795, -1.213)],
330
+ ['O', 3, (0.627, 1.062, -0.000)],
331
+ ['CG1', 4, (0.540, 1.429, -0.000)],
332
+ ['CG2', 4, (0.533, -0.776, 1.203)],
333
+ ],
334
+ }
335
+
336
+ # A list of atoms (excluding hydrogen) for each AA type. PDB naming convention.
337
+ residue_atoms = {
338
+ 'ALA': ['C', 'CA', 'CB', 'N', 'O'],
339
+ 'ARG': ['C', 'CA', 'CB', 'CG', 'CD', 'CZ', 'N', 'NE', 'O', 'NH1', 'NH2'],
340
+ 'ASP': ['C', 'CA', 'CB', 'CG', 'N', 'O', 'OD1', 'OD2'],
341
+ 'ASN': ['C', 'CA', 'CB', 'CG', 'N', 'ND2', 'O', 'OD1'],
342
+ 'CYS': ['C', 'CA', 'CB', 'N', 'O', 'SG'],
343
+ 'GLU': ['C', 'CA', 'CB', 'CG', 'CD', 'N', 'O', 'OE1', 'OE2'],
344
+ 'GLN': ['C', 'CA', 'CB', 'CG', 'CD', 'N', 'NE2', 'O', 'OE1'],
345
+ 'GLY': ['C', 'CA', 'N', 'O'],
346
+ 'HIS': ['C', 'CA', 'CB', 'CG', 'CD2', 'CE1', 'N', 'ND1', 'NE2', 'O'],
347
+ 'ILE': ['C', 'CA', 'CB', 'CG1', 'CG2', 'CD1', 'N', 'O'],
348
+ 'LEU': ['C', 'CA', 'CB', 'CG', 'CD1', 'CD2', 'N', 'O'],
349
+ 'LYS': ['C', 'CA', 'CB', 'CG', 'CD', 'CE', 'N', 'NZ', 'O'],
350
+ 'MET': ['C', 'CA', 'CB', 'CG', 'CE', 'N', 'O', 'SD'],
351
+ 'PHE': ['C', 'CA', 'CB', 'CG', 'CD1', 'CD2', 'CE1', 'CE2', 'CZ', 'N', 'O'],
352
+ 'PRO': ['C', 'CA', 'CB', 'CG', 'CD', 'N', 'O'],
353
+ 'SER': ['C', 'CA', 'CB', 'N', 'O', 'OG'],
354
+ 'THR': ['C', 'CA', 'CB', 'CG2', 'N', 'O', 'OG1'],
355
+ 'TRP': ['C', 'CA', 'CB', 'CG', 'CD1', 'CD2', 'CE2', 'CE3', 'CZ2', 'CZ3',
356
+ 'CH2', 'N', 'NE1', 'O'],
357
+ 'TYR': ['C', 'CA', 'CB', 'CG', 'CD1', 'CD2', 'CE1', 'CE2', 'CZ', 'N', 'O',
358
+ 'OH'],
359
+ 'VAL': ['C', 'CA', 'CB', 'CG1', 'CG2', 'N', 'O']
360
+ }
361
+
362
+ # Naming swaps for ambiguous atom names.
363
+ # Due to symmetries in the amino acids the naming of atoms is ambiguous in
364
+ # 4 of the 20 amino acids.
365
+ # (The LDDT paper lists 7 amino acids as ambiguous, but the naming ambiguities
366
+ # in LEU, VAL and ARG can be resolved by using the 3d constellations of
367
+ # the 'ambiguous' atoms and their neighbours)
368
+ residue_atom_renaming_swaps = {
369
+ 'ASP': {'OD1': 'OD2'},
370
+ 'GLU': {'OE1': 'OE2'},
371
+ 'PHE': {'CD1': 'CD2', 'CE1': 'CE2'},
372
+ 'TYR': {'CD1': 'CD2', 'CE1': 'CE2'},
373
+ }
374
+
375
+ # Van der Waals radii [Angstroem] of the atoms (from Wikipedia)
376
+ van_der_waals_radius = {
377
+ 'C': 1.7,
378
+ 'N': 1.55,
379
+ 'O': 1.52,
380
+ 'S': 1.8,
381
+ }
382
+
383
+ Bond = collections.namedtuple(
384
+ 'Bond', ['atom1_name', 'atom2_name', 'length', 'stddev'])
385
+ BondAngle = collections.namedtuple(
386
+ 'BondAngle',
387
+ ['atom1_name', 'atom2_name', 'atom3name', 'angle_rad', 'stddev'])
388
+
389
+
390
+ @functools.lru_cache(maxsize=None)
391
+ def load_stereo_chemical_props() -> Tuple[Mapping[str, List[Bond]],
392
+ Mapping[str, List[Bond]],
393
+ Mapping[str, List[BondAngle]]]:
394
+ """Load stereo_chemical_props.txt into a nice structure.
395
+
396
+ Load literature values for bond lengths and bond angles and translate
397
+ bond angles into the length of the opposite edge of the triangle
398
+ ("residue_virtual_bonds").
399
+
400
+ Returns:
401
+ residue_bonds: dict that maps resname --> list of Bond tuples
402
+ residue_virtual_bonds: dict that maps resname --> list of Bond tuples
403
+ residue_bond_angles: dict that maps resname --> list of BondAngle tuples
404
+ """
405
+ stereo_chemical_props_path = (
406
+ 'alphafold/common/stereo_chemical_props.txt')
407
+ with open(stereo_chemical_props_path, 'rt') as f:
408
+ stereo_chemical_props = f.read()
409
+ lines_iter = iter(stereo_chemical_props.splitlines())
410
+ # Load bond lengths.
411
+ residue_bonds = {}
412
+ next(lines_iter) # Skip header line.
413
+ for line in lines_iter:
414
+ if line.strip() == '-':
415
+ break
416
+ bond, resname, length, stddev = line.split()
417
+ atom1, atom2 = bond.split('-')
418
+ if resname not in residue_bonds:
419
+ residue_bonds[resname] = []
420
+ residue_bonds[resname].append(
421
+ Bond(atom1, atom2, float(length), float(stddev)))
422
+ residue_bonds['UNK'] = []
423
+
424
+ # Load bond angles.
425
+ residue_bond_angles = {}
426
+ next(lines_iter) # Skip empty line.
427
+ next(lines_iter) # Skip header line.
428
+ for line in lines_iter:
429
+ if line.strip() == '-':
430
+ break
431
+ bond, resname, angle_degree, stddev_degree = line.split()
432
+ atom1, atom2, atom3 = bond.split('-')
433
+ if resname not in residue_bond_angles:
434
+ residue_bond_angles[resname] = []
435
+ residue_bond_angles[resname].append(
436
+ BondAngle(atom1, atom2, atom3,
437
+ float(angle_degree) / 180. * np.pi,
438
+ float(stddev_degree) / 180. * np.pi))
439
+ residue_bond_angles['UNK'] = []
440
+
441
+ def make_bond_key(atom1_name, atom2_name):
442
+ """Unique key to lookup bonds."""
443
+ return '-'.join(sorted([atom1_name, atom2_name]))
444
+
445
+ # Translate bond angles into distances ("virtual bonds").
446
+ residue_virtual_bonds = {}
447
+ for resname, bond_angles in residue_bond_angles.items():
448
+ # Create a fast lookup dict for bond lengths.
449
+ bond_cache = {}
450
+ for b in residue_bonds[resname]:
451
+ bond_cache[make_bond_key(b.atom1_name, b.atom2_name)] = b
452
+ residue_virtual_bonds[resname] = []
453
+ for ba in bond_angles:
454
+ bond1 = bond_cache[make_bond_key(ba.atom1_name, ba.atom2_name)]
455
+ bond2 = bond_cache[make_bond_key(ba.atom2_name, ba.atom3name)]
456
+
457
+ # Compute distance between atom1 and atom3 using the law of cosines
458
+ # c^2 = a^2 + b^2 - 2ab*cos(gamma).
459
+ gamma = ba.angle_rad
460
+ length = np.sqrt(bond1.length**2 + bond2.length**2
461
+ - 2 * bond1.length * bond2.length * np.cos(gamma))
462
+
463
+ # Propagation of uncertainty assuming uncorrelated errors.
464
+ dl_outer = 0.5 / length
465
+ dl_dgamma = (2 * bond1.length * bond2.length * np.sin(gamma)) * dl_outer
466
+ dl_db1 = (2 * bond1.length - 2 * bond2.length * np.cos(gamma)) * dl_outer
467
+ dl_db2 = (2 * bond2.length - 2 * bond1.length * np.cos(gamma)) * dl_outer
468
+ stddev = np.sqrt((dl_dgamma * ba.stddev)**2 +
469
+ (dl_db1 * bond1.stddev)**2 +
470
+ (dl_db2 * bond2.stddev)**2)
471
+ residue_virtual_bonds[resname].append(
472
+ Bond(ba.atom1_name, ba.atom3name, length, stddev))
473
+
474
+ return (residue_bonds,
475
+ residue_virtual_bonds,
476
+ residue_bond_angles)
477
+
478
+
479
+ # Between-residue bond lengths for general bonds (first element) and for Proline
480
+ # (second element).
481
+ between_res_bond_length_c_n = [1.329, 1.341]
482
+ between_res_bond_length_stddev_c_n = [0.014, 0.016]
483
+
484
+ # Between-residue cos_angles.
485
+ between_res_cos_angles_c_n_ca = [-0.5203, 0.0353] # degrees: 121.352 +- 2.315
486
+ between_res_cos_angles_ca_c_n = [-0.4473, 0.0311] # degrees: 116.568 +- 1.995
487
+
488
+ # This mapping is used when we need to store atom data in a format that requires
489
+ # fixed atom data size for every residue (e.g. a numpy array).
490
+ atom_types = [
491
+ 'N', 'CA', 'C', 'CB', 'O', 'CG', 'CG1', 'CG2', 'OG', 'OG1', 'SG', 'CD',
492
+ 'CD1', 'CD2', 'ND1', 'ND2', 'OD1', 'OD2', 'SD', 'CE', 'CE1', 'CE2', 'CE3',
493
+ 'NE', 'NE1', 'NE2', 'OE1', 'OE2', 'CH2', 'NH1', 'NH2', 'OH', 'CZ', 'CZ2',
494
+ 'CZ3', 'NZ', 'OXT'
495
+ ]
496
+ atom_order = {atom_type: i for i, atom_type in enumerate(atom_types)}
497
+ atom_type_num = len(atom_types) # := 37.
498
+
499
+ # A compact atom encoding with 14 columns
500
+ # pylint: disable=line-too-long
501
+ # pylint: disable=bad-whitespace
502
+ restype_name_to_atom14_names = {
503
+ 'ALA': ['N', 'CA', 'C', 'O', 'CB', '', '', '', '', '', '', '', '', ''],
504
+ 'ARG': ['N', 'CA', 'C', 'O', 'CB', 'CG', 'CD', 'NE', 'CZ', 'NH1', 'NH2', '', '', ''],
505
+ 'ASN': ['N', 'CA', 'C', 'O', 'CB', 'CG', 'OD1', 'ND2', '', '', '', '', '', ''],
506
+ 'ASP': ['N', 'CA', 'C', 'O', 'CB', 'CG', 'OD1', 'OD2', '', '', '', '', '', ''],
507
+ 'CYS': ['N', 'CA', 'C', 'O', 'CB', 'SG', '', '', '', '', '', '', '', ''],
508
+ 'GLN': ['N', 'CA', 'C', 'O', 'CB', 'CG', 'CD', 'OE1', 'NE2', '', '', '', '', ''],
509
+ 'GLU': ['N', 'CA', 'C', 'O', 'CB', 'CG', 'CD', 'OE1', 'OE2', '', '', '', '', ''],
510
+ 'GLY': ['N', 'CA', 'C', 'O', '', '', '', '', '', '', '', '', '', ''],
511
+ 'HIS': ['N', 'CA', 'C', 'O', 'CB', 'CG', 'ND1', 'CD2', 'CE1', 'NE2', '', '', '', ''],
512
+ 'ILE': ['N', 'CA', 'C', 'O', 'CB', 'CG1', 'CG2', 'CD1', '', '', '', '', '', ''],
513
+ 'LEU': ['N', 'CA', 'C', 'O', 'CB', 'CG', 'CD1', 'CD2', '', '', '', '', '', ''],
514
+ 'LYS': ['N', 'CA', 'C', 'O', 'CB', 'CG', 'CD', 'CE', 'NZ', '', '', '', '', ''],
515
+ 'MET': ['N', 'CA', 'C', 'O', 'CB', 'CG', 'SD', 'CE', '', '', '', '', '', ''],
516
+ 'PHE': ['N', 'CA', 'C', 'O', 'CB', 'CG', 'CD1', 'CD2', 'CE1', 'CE2', 'CZ', '', '', ''],
517
+ 'PRO': ['N', 'CA', 'C', 'O', 'CB', 'CG', 'CD', '', '', '', '', '', '', ''],
518
+ 'SER': ['N', 'CA', 'C', 'O', 'CB', 'OG', '', '', '', '', '', '', '', ''],
519
+ 'THR': ['N', 'CA', 'C', 'O', 'CB', 'OG1', 'CG2', '', '', '', '', '', '', ''],
520
+ 'TRP': ['N', 'CA', 'C', 'O', 'CB', 'CG', 'CD1', 'CD2', 'NE1', 'CE2', 'CE3', 'CZ2', 'CZ3', 'CH2'],
521
+ 'TYR': ['N', 'CA', 'C', 'O', 'CB', 'CG', 'CD1', 'CD2', 'CE1', 'CE2', 'CZ', 'OH', '', ''],
522
+ 'VAL': ['N', 'CA', 'C', 'O', 'CB', 'CG1', 'CG2', '', '', '', '', '', '', ''],
523
+ 'UNK': ['', '', '', '', '', '', '', '', '', '', '', '', '', ''],
524
+
525
+ }
526
+ # pylint: enable=line-too-long
527
+ # pylint: enable=bad-whitespace
528
+
529
+
530
+ # This is the standard residue order when coding AA type as a number.
531
+ # Reproduce it by taking 3-letter AA codes and sorting them alphabetically.
532
+ restypes = [
533
+ 'A', 'R', 'N', 'D', 'C', 'Q', 'E', 'G', 'H', 'I', 'L', 'K', 'M', 'F', 'P',
534
+ 'S', 'T', 'W', 'Y', 'V'
535
+ ]
536
+ restype_order = {restype: i for i, restype in enumerate(restypes)}
537
+ restype_num = len(restypes) # := 20.
538
+ unk_restype_index = restype_num # Catch-all index for unknown restypes.
539
+
540
+ restypes_with_x = restypes + ['X']
541
+ restype_order_with_x = {restype: i for i, restype in enumerate(restypes_with_x)}
542
+
543
+
544
+ def sequence_to_onehot(
545
+ sequence: str,
546
+ mapping: Mapping[str, int],
547
+ map_unknown_to_x: bool = False) -> np.ndarray:
548
+ """Maps the given sequence into a one-hot encoded matrix.
549
+
550
+ Args:
551
+ sequence: An amino acid sequence.
552
+ mapping: A dictionary mapping amino acids to integers.
553
+ map_unknown_to_x: If True, any amino acid that is not in the mapping will be
554
+ mapped to the unknown amino acid 'X'. If the mapping doesn't contain
555
+ amino acid 'X', an error will be thrown. If False, any amino acid not in
556
+ the mapping will throw an error.
557
+
558
+ Returns:
559
+ A numpy array of shape (seq_len, num_unique_aas) with one-hot encoding of
560
+ the sequence.
561
+
562
+ Raises:
563
+ ValueError: If the mapping doesn't contain values from 0 to
564
+ num_unique_aas - 1 without any gaps.
565
+ """
566
+ num_entries = max(mapping.values()) + 1
567
+
568
+ if sorted(set(mapping.values())) != list(range(num_entries)):
569
+ raise ValueError('The mapping must have values from 0 to num_unique_aas-1 '
570
+ 'without any gaps. Got: %s' % sorted(mapping.values()))
571
+
572
+ one_hot_arr = np.zeros((len(sequence), num_entries), dtype=np.int32)
573
+
574
+ for aa_index, aa_type in enumerate(sequence):
575
+ if map_unknown_to_x:
576
+ if aa_type.isalpha() and aa_type.isupper():
577
+ aa_id = mapping.get(aa_type, mapping['X'])
578
+ else:
579
+ raise ValueError(f'Invalid character in the sequence: {aa_type}')
580
+ else:
581
+ aa_id = mapping[aa_type]
582
+ one_hot_arr[aa_index, aa_id] = 1
583
+
584
+ return one_hot_arr
585
+
586
+
587
+ restype_1to3 = {
588
+ 'A': 'ALA',
589
+ 'R': 'ARG',
590
+ 'N': 'ASN',
591
+ 'D': 'ASP',
592
+ 'C': 'CYS',
593
+ 'Q': 'GLN',
594
+ 'E': 'GLU',
595
+ 'G': 'GLY',
596
+ 'H': 'HIS',
597
+ 'I': 'ILE',
598
+ 'L': 'LEU',
599
+ 'K': 'LYS',
600
+ 'M': 'MET',
601
+ 'F': 'PHE',
602
+ 'P': 'PRO',
603
+ 'S': 'SER',
604
+ 'T': 'THR',
605
+ 'W': 'TRP',
606
+ 'Y': 'TYR',
607
+ 'V': 'VAL',
608
+ }
609
+
610
+
611
+ # NB: restype_3to1 differs from Bio.PDB.protein_letters_3to1 by being a simple
612
+ # 1-to-1 mapping of 3 letter names to one letter names. The latter contains
613
+ # many more, and less common, three letter names as keys and maps many of these
614
+ # to the same one letter name (including 'X' and 'U' which we don't use here).
615
+ restype_3to1 = {v: k for k, v in restype_1to3.items()}
616
+
617
+ # Define a restype name for all unknown residues.
618
+ unk_restype = 'UNK'
619
+
620
+ resnames = [restype_1to3[r] for r in restypes] + [unk_restype]
621
+ resname_to_idx = {resname: i for i, resname in enumerate(resnames)}
622
+
623
+
624
+ # The mapping here uses hhblits convention, so that B is mapped to D, J and O
625
+ # are mapped to X, U is mapped to C, and Z is mapped to E. Other than that the
626
+ # remaining 20 amino acids are kept in alphabetical order.
627
+ # There are 2 non-amino acid codes, X (representing any amino acid) and
628
+ # "-" representing a missing amino acid in an alignment. The id for these
629
+ # codes is put at the end (20 and 21) so that they can easily be ignored if
630
+ # desired.
631
+ HHBLITS_AA_TO_ID = {
632
+ 'A': 0,
633
+ 'B': 2,
634
+ 'C': 1,
635
+ 'D': 2,
636
+ 'E': 3,
637
+ 'F': 4,
638
+ 'G': 5,
639
+ 'H': 6,
640
+ 'I': 7,
641
+ 'J': 20,
642
+ 'K': 8,
643
+ 'L': 9,
644
+ 'M': 10,
645
+ 'N': 11,
646
+ 'O': 20,
647
+ 'P': 12,
648
+ 'Q': 13,
649
+ 'R': 14,
650
+ 'S': 15,
651
+ 'T': 16,
652
+ 'U': 1,
653
+ 'V': 17,
654
+ 'W': 18,
655
+ 'X': 20,
656
+ 'Y': 19,
657
+ 'Z': 3,
658
+ '-': 21,
659
+ }
660
+
661
+ # Partial inversion of HHBLITS_AA_TO_ID.
662
+ ID_TO_HHBLITS_AA = {
663
+ 0: 'A',
664
+ 1: 'C', # Also U.
665
+ 2: 'D', # Also B.
666
+ 3: 'E', # Also Z.
667
+ 4: 'F',
668
+ 5: 'G',
669
+ 6: 'H',
670
+ 7: 'I',
671
+ 8: 'K',
672
+ 9: 'L',
673
+ 10: 'M',
674
+ 11: 'N',
675
+ 12: 'P',
676
+ 13: 'Q',
677
+ 14: 'R',
678
+ 15: 'S',
679
+ 16: 'T',
680
+ 17: 'V',
681
+ 18: 'W',
682
+ 19: 'Y',
683
+ 20: 'X', # Includes J and O.
684
+ 21: '-',
685
+ }
686
+
687
+ restypes_with_x_and_gap = restypes + ['X', '-']
688
+ MAP_HHBLITS_AATYPE_TO_OUR_AATYPE = tuple(
689
+ restypes_with_x_and_gap.index(ID_TO_HHBLITS_AA[i])
690
+ for i in range(len(restypes_with_x_and_gap)))
691
+
692
+
693
+ def _make_standard_atom_mask() -> np.ndarray:
694
+ """Returns [num_res_types, num_atom_types] mask array."""
695
+ # +1 to account for unknown (all 0s).
696
+ mask = np.zeros([restype_num + 1, atom_type_num], dtype=np.int32)
697
+ for restype, restype_letter in enumerate(restypes):
698
+ restype_name = restype_1to3[restype_letter]
699
+ atom_names = residue_atoms[restype_name]
700
+ for atom_name in atom_names:
701
+ atom_type = atom_order[atom_name]
702
+ mask[restype, atom_type] = 1
703
+ return mask
704
+
705
+
706
+ STANDARD_ATOM_MASK = _make_standard_atom_mask()
707
+
708
+
709
+ # A one hot representation for the first and second atoms defining the axis
710
+ # of rotation for each chi-angle in each residue.
711
+ def chi_angle_atom(atom_index: int) -> np.ndarray:
712
+ """Define chi-angle rigid groups via one-hot representations."""
713
+ chi_angles_index = {}
714
+ one_hots = []
715
+
716
+ for k, v in chi_angles_atoms.items():
717
+ indices = [atom_types.index(s[atom_index]) for s in v]
718
+ indices.extend([-1]*(4-len(indices)))
719
+ chi_angles_index[k] = indices
720
+
721
+ for r in restypes:
722
+ res3 = restype_1to3[r]
723
+ one_hot = np.eye(atom_type_num)[chi_angles_index[res3]]
724
+ one_hots.append(one_hot)
725
+
726
+ one_hots.append(np.zeros([4, atom_type_num])) # Add zeros for residue `X`.
727
+ one_hot = np.stack(one_hots, axis=0)
728
+ one_hot = np.transpose(one_hot, [0, 2, 1])
729
+
730
+ return one_hot
731
+
732
+ chi_atom_1_one_hot = chi_angle_atom(1)
733
+ chi_atom_2_one_hot = chi_angle_atom(2)
734
+
735
+ # An array like chi_angles_atoms but using indices rather than names.
736
+ chi_angles_atom_indices = [chi_angles_atoms[restype_1to3[r]] for r in restypes]
737
+ chi_angles_atom_indices = tree.map_structure(
738
+ lambda atom_name: atom_order[atom_name], chi_angles_atom_indices)
739
+ chi_angles_atom_indices = np.array([
740
+ chi_atoms + ([[0, 0, 0, 0]] * (4 - len(chi_atoms)))
741
+ for chi_atoms in chi_angles_atom_indices])
742
+
743
+ # Mapping from (res_name, atom_name) pairs to the atom's chi group index
744
+ # and atom index within that group.
745
+ chi_groups_for_atom = collections.defaultdict(list)
746
+ for res_name, chi_angle_atoms_for_res in chi_angles_atoms.items():
747
+ for chi_group_i, chi_group in enumerate(chi_angle_atoms_for_res):
748
+ for atom_i, atom in enumerate(chi_group):
749
+ chi_groups_for_atom[(res_name, atom)].append((chi_group_i, atom_i))
750
+ chi_groups_for_atom = dict(chi_groups_for_atom)
751
+
752
+
753
+ def _make_rigid_transformation_4x4(ex, ey, translation):
754
+ """Create a rigid 4x4 transformation matrix from two axes and transl."""
755
+ # Normalize ex.
756
+ ex_normalized = ex / np.linalg.norm(ex)
757
+
758
+ # make ey perpendicular to ex
759
+ ey_normalized = ey - np.dot(ey, ex_normalized) * ex_normalized
760
+ ey_normalized /= np.linalg.norm(ey_normalized)
761
+
762
+ # compute ez as cross product
763
+ eznorm = np.cross(ex_normalized, ey_normalized)
764
+ m = np.stack([ex_normalized, ey_normalized, eznorm, translation]).transpose()
765
+ m = np.concatenate([m, [[0., 0., 0., 1.]]], axis=0)
766
+ return m
767
+
768
+
769
+ # create an array with (restype, atomtype) --> rigid_group_idx
770
+ # and an array with (restype, atomtype, coord) for the atom positions
771
+ # and compute affine transformation matrices (4,4) from one rigid group to the
772
+ # previous group
773
+ restype_atom37_to_rigid_group = np.zeros([21, 37], dtype=np.int32)
774
+ restype_atom37_mask = np.zeros([21, 37], dtype=np.float32)
775
+ restype_atom37_rigid_group_positions = np.zeros([21, 37, 3], dtype=np.float32)
776
+ restype_atom14_to_rigid_group = np.zeros([21, 14], dtype=np.int32)
777
+ restype_atom14_mask = np.zeros([21, 14], dtype=np.float32)
778
+ restype_atom14_rigid_group_positions = np.zeros([21, 14, 3], dtype=np.float32)
779
+ restype_rigid_group_default_frame = np.zeros([21, 8, 4, 4], dtype=np.float32)
780
+
781
+ ###############################################
782
+ restype_atom14_to_atom37 = []
783
+ restype_atom37_to_atom14 = []
784
+ for rt in restypes:
785
+ atom_names = restype_name_to_atom14_names[restype_1to3[rt]]
786
+ restype_atom14_to_atom37.append([(atom_order[name] if name else 0) for name in atom_names])
787
+ atom_name_to_idx14 = {name: i for i, name in enumerate(atom_names)}
788
+ restype_atom37_to_atom14.append([(atom_name_to_idx14[name] if name in atom_name_to_idx14 else 0) for name in atom_types])
789
+ restype_atom14_to_atom37.append([0] * 14)
790
+ restype_atom37_to_atom14.append([0] * 37)
791
+ restype_atom14_to_atom37 = np.array(restype_atom14_to_atom37, dtype=np.int32)
792
+ restype_atom37_to_atom14 = np.array(restype_atom37_to_atom14, dtype=np.int32)
793
+ ################################################
794
+
795
+ def _make_rigid_group_constants():
796
+ """Fill the arrays above."""
797
+
798
+
799
+ for restype, restype_letter in enumerate(restypes):
800
+ resname = restype_1to3[restype_letter]
801
+ for atomname, group_idx, atom_position in rigid_group_atom_positions[resname]:
802
+ atomtype = atom_order[atomname]
803
+ restype_atom37_to_rigid_group[restype, atomtype] = group_idx
804
+ restype_atom37_mask[restype, atomtype] = 1
805
+ restype_atom37_rigid_group_positions[restype, atomtype, :] = atom_position
806
+
807
+ atom14idx = restype_name_to_atom14_names[resname].index(atomname)
808
+ restype_atom14_to_rigid_group[restype, atom14idx] = group_idx
809
+ restype_atom14_mask[restype, atom14idx] = 1
810
+ restype_atom14_rigid_group_positions[restype, atom14idx, :] = atom_position
811
+
812
+ atom_names = residue_atoms[resname]
813
+ atom_name_to_idx14 = {name: i for i, name in enumerate(atom_names)}
814
+
815
+ for restype, restype_letter in enumerate(restypes):
816
+ resname = restype_1to3[restype_letter]
817
+ atom_positions = {name: np.array(pos) for name, _, pos
818
+ in rigid_group_atom_positions[resname]}
819
+
820
+ # backbone to backbone is the identity transform
821
+ restype_rigid_group_default_frame[restype, 0, :, :] = np.eye(4)
822
+
823
+ # pre-omega-frame to backbone (currently dummy identity matrix)
824
+ restype_rigid_group_default_frame[restype, 1, :, :] = np.eye(4)
825
+
826
+ # phi-frame to backbone
827
+ mat = _make_rigid_transformation_4x4(
828
+ ex=atom_positions['N'] - atom_positions['CA'],
829
+ ey=np.array([1., 0., 0.]),
830
+ translation=atom_positions['N'])
831
+ restype_rigid_group_default_frame[restype, 2, :, :] = mat
832
+
833
+ # psi-frame to backbone
834
+ mat = _make_rigid_transformation_4x4(
835
+ ex=atom_positions['C'] - atom_positions['CA'],
836
+ ey=atom_positions['CA'] - atom_positions['N'],
837
+ translation=atom_positions['C'])
838
+ restype_rigid_group_default_frame[restype, 3, :, :] = mat
839
+
840
+ # chi1-frame to backbone
841
+ if chi_angles_mask[restype][0]:
842
+ base_atom_names = chi_angles_atoms[resname][0]
843
+ base_atom_positions = [atom_positions[name] for name in base_atom_names]
844
+ mat = _make_rigid_transformation_4x4(
845
+ ex=base_atom_positions[2] - base_atom_positions[1],
846
+ ey=base_atom_positions[0] - base_atom_positions[1],
847
+ translation=base_atom_positions[2])
848
+ restype_rigid_group_default_frame[restype, 4, :, :] = mat
849
+
850
+ # chi2-frame to chi1-frame
851
+ # chi3-frame to chi2-frame
852
+ # chi4-frame to chi3-frame
853
+ # luckily all rotation axes for the next frame start at (0,0,0) of the
854
+ # previous frame
855
+ for chi_idx in range(1, 4):
856
+ if chi_angles_mask[restype][chi_idx]:
857
+ axis_end_atom_name = chi_angles_atoms[resname][chi_idx][2]
858
+ axis_end_atom_position = atom_positions[axis_end_atom_name]
859
+ mat = _make_rigid_transformation_4x4(
860
+ ex=axis_end_atom_position,
861
+ ey=np.array([-1., 0., 0.]),
862
+ translation=axis_end_atom_position)
863
+ restype_rigid_group_default_frame[restype, 4 + chi_idx, :, :] = mat
864
+
865
+
866
+ _make_rigid_group_constants()
867
+
868
+
869
+ def make_atom14_dists_bounds(overlap_tolerance=1.5,
870
+ bond_length_tolerance_factor=15):
871
+ """compute upper and lower bounds for bonds to assess violations."""
872
+ restype_atom14_bond_lower_bound = np.zeros([21, 14, 14], np.float32)
873
+ restype_atom14_bond_upper_bound = np.zeros([21, 14, 14], np.float32)
874
+ restype_atom14_bond_stddev = np.zeros([21, 14, 14], np.float32)
875
+ residue_bonds, residue_virtual_bonds, _ = load_stereo_chemical_props()
876
+ for restype, restype_letter in enumerate(restypes):
877
+ resname = restype_1to3[restype_letter]
878
+ atom_list = restype_name_to_atom14_names[resname]
879
+
880
+ # create lower and upper bounds for clashes
881
+ for atom1_idx, atom1_name in enumerate(atom_list):
882
+ if not atom1_name:
883
+ continue
884
+ atom1_radius = van_der_waals_radius[atom1_name[0]]
885
+ for atom2_idx, atom2_name in enumerate(atom_list):
886
+ if (not atom2_name) or atom1_idx == atom2_idx:
887
+ continue
888
+ atom2_radius = van_der_waals_radius[atom2_name[0]]
889
+ lower = atom1_radius + atom2_radius - overlap_tolerance
890
+ upper = 1e10
891
+ restype_atom14_bond_lower_bound[restype, atom1_idx, atom2_idx] = lower
892
+ restype_atom14_bond_lower_bound[restype, atom2_idx, atom1_idx] = lower
893
+ restype_atom14_bond_upper_bound[restype, atom1_idx, atom2_idx] = upper
894
+ restype_atom14_bond_upper_bound[restype, atom2_idx, atom1_idx] = upper
895
+
896
+ # overwrite lower and upper bounds for bonds and angles
897
+ for b in residue_bonds[resname] + residue_virtual_bonds[resname]:
898
+ atom1_idx = atom_list.index(b.atom1_name)
899
+ atom2_idx = atom_list.index(b.atom2_name)
900
+ lower = b.length - bond_length_tolerance_factor * b.stddev
901
+ upper = b.length + bond_length_tolerance_factor * b.stddev
902
+ restype_atom14_bond_lower_bound[restype, atom1_idx, atom2_idx] = lower
903
+ restype_atom14_bond_lower_bound[restype, atom2_idx, atom1_idx] = lower
904
+ restype_atom14_bond_upper_bound[restype, atom1_idx, atom2_idx] = upper
905
+ restype_atom14_bond_upper_bound[restype, atom2_idx, atom1_idx] = upper
906
+ restype_atom14_bond_stddev[restype, atom1_idx, atom2_idx] = b.stddev
907
+ restype_atom14_bond_stddev[restype, atom2_idx, atom1_idx] = b.stddev
908
+ return {'lower_bound': restype_atom14_bond_lower_bound, # shape (21,14,14)
909
+ 'upper_bound': restype_atom14_bond_upper_bound, # shape (21,14,14)
910
+ 'stddev': restype_atom14_bond_stddev, # shape (21,14,14)
911
+ }