OneScience commited on
Commit
48b5986
·
verified ·
1 Parent(s): 4f777c6

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 +3 -0
  2. .msc +0 -0
  3. .mv +1 -0
  4. LICENSE +21 -0
  5. README.md +283 -0
  6. configuration.json +2 -0
  7. data/fasta/few_proteins.fasta +6 -0
  8. data/fasta/some_proteins.fasta +30 -0
  9. data/inverse_folding/5YH2.cif +0 -0
  10. data/inverse_folding/5YH2.pdb +0 -0
  11. data/inverse_folding/5YH2_mutated_seqs.fasta +8 -0
  12. data/inverse_folding/example.json +0 -0
  13. data/variant_prediction/BLAT_ECOLX_Ranganathan2015.csv +0 -0
  14. data/variant_prediction/aggregated_rho.csv +17 -0
  15. data/variant_prediction/aggregated_rho_round3.csv +17 -0
  16. data/variant_prediction/rho_pp.csv +575 -0
  17. model/README.md +10 -0
  18. model/__init__.py +2 -0
  19. model/__pycache__/__init__.cpython-311.pyc +0 -0
  20. model/esm/__init__.py +13 -0
  21. model/esm/__pycache__/__init__.cpython-311.pyc +0 -0
  22. model/esm/__pycache__/esm1.cpython-311.pyc +0 -0
  23. model/esm/__pycache__/esm2.cpython-311.pyc +0 -0
  24. model/esm/__pycache__/msa_transformer.cpython-311.pyc +0 -0
  25. model/esm/__pycache__/pretrained.cpython-311.pyc +0 -0
  26. model/esm/__pycache__/version.cpython-311.pyc +0 -0
  27. model/esm/esm1.py +200 -0
  28. model/esm/esm2.py +152 -0
  29. model/esm/esmfold/__init__.py +0 -0
  30. model/esm/esmfold/v1/__init__.py +0 -0
  31. model/esm/esmfold/v1/categorical_mixture.py +43 -0
  32. model/esm/esmfold/v1/esmfold.py +364 -0
  33. model/esm/esmfold/v1/misc.py +309 -0
  34. model/esm/esmfold/v1/pretrained.py +197 -0
  35. model/esm/esmfold/v1/tri_self_attn_block.py +160 -0
  36. model/esm/esmfold/v1/trunk.py +245 -0
  37. model/esm/inverse_folding/__init__.py +8 -0
  38. model/esm/inverse_folding/features.py +352 -0
  39. model/esm/inverse_folding/gvp_encoder.py +56 -0
  40. model/esm/inverse_folding/gvp_modules.py +475 -0
  41. model/esm/inverse_folding/gvp_transformer.py +140 -0
  42. model/esm/inverse_folding/gvp_transformer_encoder.py +184 -0
  43. model/esm/inverse_folding/gvp_utils.py +68 -0
  44. model/esm/inverse_folding/multichain_util.py +152 -0
  45. model/esm/inverse_folding/transformer_decoder.py +228 -0
  46. model/esm/inverse_folding/transformer_layer.py +304 -0
  47. model/esm/inverse_folding/util.py +323 -0
  48. model/esm/msa_transformer.py +238 -0
  49. model/esm/pretrained.py +553 -0
  50. model/esm/version.py +6 -0
.gitattributes CHANGED
@@ -33,3 +33,6 @@ saved_model/**/* 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
 
 
 
 
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
36
+ weight/esm-main/examples/inverse_folding/illustration.png filter=lfs diff=lfs merge=lfs -text
37
+ weight/esm-main/examples/lm-design/utils/ngram_stats/quadgram_seg.p filter=lfs diff=lfs merge=lfs -text
38
+ weight/esm-main/examples/lm-design/utils/ngram_stats/trigram_seg.p filter=lfs diff=lfs merge=lfs -text
.msc ADDED
Binary file (46.3 kB). View file
 
.mv ADDED
@@ -0,0 +1 @@
 
 
1
+ Revision:master,CreatedAt:1784688787
LICENSE ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ MIT License
2
+
3
+ Copyright (c) Meta Platforms, Inc. and affiliates.
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
README.md ADDED
@@ -0,0 +1,283 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ license: mit
3
+ tasks:
4
+ - protein-structure-prediction
5
+ frameworks:
6
+ - pytorch
7
+ language:
8
+ - en
9
+ - zh
10
+ tags:
11
+ - OneScience
12
+ - Life Sciences
13
+ - Protein Language Model
14
+ - Protein Structure Prediction
15
+ - Variant Effect Prediction
16
+ - ESM
17
+ modelscope:
18
+ model: OneScience/ESM
19
+ data_path: data/
20
+ ---
21
+
22
+ <p align="center">
23
+ <strong>
24
+ <span style="font-size: 30px;">ESM</span>
25
+ </strong>
26
+ </p>
27
+
28
+ # Model Introduction
29
+
30
+ ESM (Evolutionary Scale Modeling) is a family of protein language models released by Meta AI / FAIR. It can be used for protein sequence representation, structure prediction, variant effect assessment, and fixed-backbone sequence design.
31
+
32
+ Paper: Evolutionary-scale prediction of atomic-level protein structure with a language model
33
+ https://www.science.org/doi/10.1126/science.ade2574
34
+
35
+ # Model Description
36
+
37
+ This model package integrates PyTorch inference capabilities for ESM-1, ESM-2, MSA Transformer, ESMFold, ESM-1v, and ESM-IF1, and provides DCU runtime adaptation. The accompanying sample data is released with the ModelScope model package `OneScience/ESM`.
38
+
39
+ # Applicable Scenarios
40
+
41
+ | Scenario | Description |
42
+ | :---: | :--- |
43
+ | Protein sequence representation extraction | Input a FASTA file and output per-token, mean, BOS, or contact representations |
44
+ | Protein structure prediction | Input one or more amino acid sequences and output the corresponding PDB structure files |
45
+ | Variant effect scoring | Input a wild-type sequence and a DMS mutation table, and output mutation impact scores |
46
+ | Fixed-backbone sequence design | Input a PDB / CIF structure and chain ID, and sample candidate sequences satisfying backbone constraints |
47
+ | Structure-conditioned sequence scoring | Input a structure and candidate sequences, and compute conditional log-likelihood |
48
+ | ModelScope / OneCode runtime | After downloading the model project, quickly verify script connectivity in a biology-domain runtime environment |
49
+
50
+
51
+ # Usage Instructions
52
+
53
+ ## 1. OneCode Usage
54
+
55
+ You can experience intelligent one-click AI4S programming through the OneCode online environment:
56
+
57
+ [Click to experience intelligent one-click AI4S programming](https://web-2069360198568017922-iaaj.ksai.scnet.cn:58043/home)
58
+
59
+ ## 2. Manual Installation and Usage
60
+
61
+ **Hardware Requirements**
62
+
63
+ - GPU or DCU runtime is recommended.
64
+ - CPU can be used for import checks and small-configuration connectivity verification, but full training and inference are slow.
65
+ - DCU users need to install DTK in advance. DTK 25.04.2 or later is recommended, or the OneScience-recommended version matching the current cluster.
66
+
67
+
68
+
69
+
70
+
71
+ **Environment Check**
72
+
73
+ - NVIDIA GPU:
74
+
75
+ ```bash
76
+ nvidia-smi
77
+ ```
78
+
79
+ - Hygon DCU:
80
+
81
+ ```bash
82
+ hy-smi
83
+ ```
84
+
85
+ ### Download the Model Package
86
+
87
+ ```bash
88
+ modelscope download --model OneScience/ESM --local_dir ./ESM
89
+ cd ESM
90
+ ```
91
+
92
+ This model package already contains a small amount of sample data that can be used directly for default workflow verification.
93
+
94
+ ### Install the Runtime Environment
95
+
96
+ **DCU Environment**
97
+
98
+ ```bash
99
+ # First activate DTK and Conda
100
+ conda create -n onescience311 python=3.11 -y
101
+ conda activate onescience311
102
+ # Supports uv installation
103
+ pip install onescience[bio-dcu] -i http://mirrors.onescience.ai:3141/pypi/simple/ --trusted-host mirrors.onescience.ai
104
+ ```
105
+
106
+ ```bash
107
+ # If libraries cannot be found, activate CUDA as shown below
108
+ source ${ROCM_PATH}/cuda/env.sh
109
+ export LD_LIBRARY_PATH="$CONDA_PREFIX/lib:$LD_LIBRARY_PATH"
110
+ export LD_LIBRARY_PATH="$CONDA_PREFIX/lib/python3.11/site-packages/fastpt/torch/lib:$LD_LIBRARY_PATH"
111
+ ```
112
+
113
+ After installation, return to the model package directory:
114
+
115
+ ```bash
116
+ cd ./ESM
117
+ ```
118
+
119
+ ### Training and Inference Data Introduction
120
+
121
+ The FASTA, PDB / CIF, and DMS data used by the ESM examples have been released with the [ModelScope model package OneScience/ESM](https://modelscope.cn/models/OneScience/ESM). After downloading the complete model package, they can be used directly from the `data/` directory. This model package does not include a training entry point; the data is used for example inference and workflow verification. You can also download only the data directory:
122
+
123
+ ```bash
124
+ modelscope download --model OneScience/ESM ESM/data --local_dir ./data
125
+ ```
126
+ ### Training Weights
127
+
128
+ The repository includes multiple ESM weights under `weight/`, which can be selected for inference as needed.
129
+
130
+ ### Prepare Weights
131
+
132
+ Place the required ESM weights in the following directory:
133
+
134
+ ```text
135
+ weight/
136
+ checkpoints/
137
+ esm2_t6_8M_UR50D.pt
138
+ esmfold_3B_v1.pt
139
+ esm1v_t33_650M_UR90S_1.pt
140
+ esm_if1_gvp4_t16_142M_UR50.pt
141
+ ...
142
+ ```
143
+
144
+ If using a shared runtime directory, you can also specify the weight location through an environment variable:
145
+
146
+ ```bash
147
+ export ESM_WEIGHT_DIR=/path/to/esm/weight
148
+ ```
149
+
150
+ The default example reads:
151
+
152
+ - `weight/checkpoints/esm2_t6_8M_UR50D.pt`
153
+
154
+ The corresponding weights must be available for the ESMFold, ESM-1v, and ESM-IF1 examples.
155
+
156
+ ### Default Example
157
+
158
+ ```bash
159
+ bash scripts/infer.sh
160
+ ```
161
+
162
+ The default example reads `data/fasta/few_proteins.fasta`, uses `esm2_t6_8M_UR50D.pt` to extract protein representations, and saves the results to `outputs/embeddings/`.
163
+
164
+ ### Sequence Representation Extraction
165
+
166
+ ```bash
167
+ python scripts/extract.py \
168
+ weight/checkpoints/esm2_t6_8M_UR50D.pt \
169
+ data/fasta/few_proteins.fasta \
170
+ outputs/embeddings \
171
+ --include mean per_tok \
172
+ --repr_layers 6
173
+ ```
174
+
175
+ ### ESMFold Structure Prediction
176
+
177
+ ```bash
178
+ python scripts/fold.py \
179
+ -i data/fasta/few_proteins.fasta \
180
+ -o outputs/pdb \
181
+ --model-dir weight \
182
+ --cpu-only
183
+ ```
184
+
185
+ The output directory will generate one or more `.pdb` files. For formal GPU / DCU inference, you can remove `--cpu-only` and set `--chunk-size` or `--max-tokens-per-batch` according to available memory.
186
+
187
+ You can also explicitly enable ESMFold through the default script:
188
+
189
+ ```bash
190
+ RUN_ESMFOLD=1 bash scripts/infer.sh
191
+ ```
192
+
193
+ ### Inverse Folding Sequence Sampling
194
+
195
+ ```bash
196
+ python scripts/inverse_folding/sample_sequences.py \
197
+ data/inverse_folding/5YH2.pdb \
198
+ --chain A \
199
+ --outpath outputs/sampled_seqs.fasta \
200
+ --num-samples 1 \
201
+ --nogpu
202
+ ```
203
+
204
+ ### Inverse Folding Sequence Scoring
205
+
206
+ ```bash
207
+ python scripts/inverse_folding/score_log_likelihoods.py \
208
+ data/inverse_folding/5YH2.pdb \
209
+ data/inverse_folding/5YH2_mutated_seqs.fasta \
210
+ --chain A \
211
+ --outpath outputs/sequence_scores.csv \
212
+ --nogpu
213
+ ```
214
+
215
+ ### Variant Effect Prediction
216
+
217
+ Variant effect prediction requires providing a wild-type sequence matching the DMS mutation column:
218
+
219
+ ```bash
220
+ python scripts/variant_prediction/predict.py \
221
+ --model-location esm1v_t33_650M_UR90S_1 \
222
+ --sequence "${ESM_VARIANT_SEQUENCE}" \
223
+ --dms-input data/variant_prediction/BLAT_ECOLX_Ranganathan2015.csv \
224
+ --mutation-col mutant \
225
+ --dms-output outputs/variant_prediction.csv \
226
+ --offset-idx 24 \
227
+ --scoring-strategy wt-marginals
228
+ ```
229
+
230
+ # Data Format
231
+
232
+ Sample data is stored under `data/` by default:
233
+
234
+ ```text
235
+ data/
236
+ fasta/
237
+ few_proteins.fasta
238
+ some_proteins.fasta
239
+ inverse_folding/
240
+ 5YH2.pdb
241
+ 5YH2.cif
242
+ 5YH2_mutated_seqs.fasta
243
+ example.json
244
+ variant_prediction/
245
+ BLAT_ECOLX_Ranganathan2015.csv
246
+ rho_pp.csv
247
+ aggregated_rho.csv
248
+ aggregated_rho_round3.csv
249
+ ```
250
+
251
+ Where:
252
+
253
+ - FASTA files are used for sequence representation extraction and structure prediction.
254
+ - PDB / CIF files are used for inverse folding sampling and structure-conditioned sequence scoring.
255
+ - The variant effect prediction CSV must contain a mutation column. The default example column name is `mutant`, and the mutation format is like `A123B`.
256
+ - Custom DMS data must ensure that the wild-type sequence provided by `--sequence` is consistent with the wild-type amino acids in the mutation column.
257
+
258
+ # Verification
259
+
260
+ Static import check:
261
+
262
+ ```bash
263
+ python scripts/check_import_boundaries.py
264
+ ```
265
+
266
+ Syntax check:
267
+
268
+ ```bash
269
+ python -B -c "import ast, pathlib; [ast.parse(p.read_text(encoding='utf-8'), filename=str(p)) for root in ['model', 'scripts', 'tests'] for p in pathlib.Path(root).rglob('*.py')]"
270
+ ```
271
+
272
+ # Official OneScience Information
273
+
274
+ | Platform | OneScience Main Repository | Skills Repository |
275
+ | --- | --- | --- |
276
+ | Gitee | https://gitee.com/onescience-ai/onescience | https://gitee.com/onescience-ai/oneskills |
277
+ | GitHub | https://github.com/onescience-ai/OneScience | https://github.com/onescience-ai/oneskills |
278
+
279
+ # Citations and License
280
+
281
+ - This repository is based on the ESM open-source model and provides DCU adaptation.
282
+ - ESM-related source code uses the MIT License; see `LICENSE`. For the terms of use for model weights and data, refer to the corresponding publisher's instructions.
283
+ - For scientific research, cite the corresponding original ESM paper according to the specific submodel. For ESM-2 / ESMFold, cite: [Evolutionary-scale prediction of atomic-level protein structure with a language model](https://www.science.org/doi/10.1126/science.ade2574).
configuration.json ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ {"framework":"Pytorch","task":"other"}
2
+
data/fasta/few_proteins.fasta ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ >UniRef50_UPI0003108055
2
+ MPADAREYLESKHATRRFDRPAEVAGVVAFLLSDDTSFVIGAGYLVDGGYTALRAARGRLGPRRQAAPAVKLLPNTDSPR
3
+ >UniRef50_A0A223SCH7
4
+ MGPPRWWKGITGLAAVVHRADPEDKADLYAKMGLYLEYHPETRIVEARIKPRLHDVCESKVSEGGLEPPCP
5
+ >UniRef50_A0A090SUK6
6
+ MKTPEDRVFRATDEYSDFVMACRYKGNEREFVIASHDKLNEAQVETLTSYLSGEWFKKTYITGIMNDSDGVLSQHEEYGDEVFCQPLDELRVDRYIMMV
data/fasta/some_proteins.fasta ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ >UniRef50_A0A1E3NP16
2
+ AVIYYRFRSQKPDHIATIKFDGTGLTVFELKRDIILANNLLHSTDVDIVLYSTEDIQDTKSWGYQNGGSSSAGERELDDDNEVVPRSTTVLVRRTMTPKKNKGNVQRYVAGKPRLQVSGTNSVNKSISLGNNVGGTMNFGDAATNGDEDDMIKKMFSVQDEQWSQQQDVMATATRVDNFRTNVNEPVPEYYICYKCGEKGKHHIKNCPKNNDPNWEGVRVRKTTGIPKSHLKAIENPEDTIRDSNSSGNTTYMVNDEGKYVVAVADTKAWEKYQKTKKGESGGYLNGDVDVDDGELKDPETGKLWKSPVRIPCCNKIFSRKIIEDKLIDSDFTCPSCGKEQIYLDTLVADEELQAKVDEYVKNLSENKNNDGNSPKRRQVNPAGATANTSQLPQIPMMPMPPINMQMPPMNIGMPPFMPFMPMPGMNP
3
+ >UniRef50_UPI000836A30F
4
+ MTLRTLLALSILALAAAATVQARPGAPPCSPLGLKYQPGACEKWKREHPDVNPDGVVQTVTIVNNSSSVLGGYVTFWHANNEHTDVDLPGVKPGETWTANGSWTVGQAPYYLLYSSFQDSYGDPVTFYAVPISKYPALAKKLPPEPDNCQSNHFRMVFGDGPQYVYEQHSGAVVTGGQTDKNTLCQILGCPTGGSTAGGLNTQNRTTSRSAPQPVYFRSCDP
5
+ >UniRef50_A0A2G8L8Y3
6
+ MAQKRYEENLSPYAELFRSKLIEDFHLLESFDEHGKSDAPKYYSKDFEDPARQDKMMLENPHGLVKFQVYSRKEPGEHFMLVLILSNSIALGLQAEVSESDDPKFAGLKLALDIFDYCSLFLFMVEIILKWIDNFWSFWSDNWNIFDFAVTVGSFVPEIINFFAGDIGGSMVRVIVRNLRVFRILRSLKMVSRFRQVRLIALAIGKAFSAITFIMLLLFTFLYIFAITGIIFFDTYTRSERQDLKYKDSFRSLPRAMITLFQLFTLDQWYKLLNDMWKVMDSMIPLGYIILWICIGSFIFRNVFVGIMVNNFQSIRNDLFEEVKEQEAARQIIQDTEKFNEELSRQEKKLNANRRGTLYQSPTVQPPKPNQPQPSQLAGLDNSETDEQSVSQEDESNTDGQTSLSGTDSYDLLGESSDSLFRRSSDGMIDKDKLSTNWEKTVHDNLTLLTSTPSETLWPRDTLFRYFQLMESLMENLQERQDLQDLAYHSLLQIFDSFDTSA
7
+ >UniRef50_A0A1D5ZRM3
8
+ MPCVAHECHPRLPAANHCRSLSCLGTPAAGWSSGDDDREEDELDTKQVILNEMRNREMRKRSSRCSVDSPTLSGAFAWSFTPLHPRSSIEKVSCTEEEKEAASDSDNESEAFFSVKSFFTRSTSRAATVASSTDMDPPATWEGLRGCEGWPFGLCP
9
+ >UniRef50_UPI0003108055
10
+ MPADAREYLESKHATRRFDRPAEVAGVVAFLLSDDTSFVIGAGYLVDGGYTALRAARGRLGPRRQAAPAVKLLPNTDSPR
11
+ >UniRef50_A0A223SCH7
12
+ MGPPRWWKGITGLAAVVHRADPEDKADLYAKMGLYLEYHPETRIVEARIKPRLHDVCESKVSEGGLEPPCP
13
+ >UniRef50_A0A090SUK6
14
+ MKTPEDRVFRATDEYSDFVMACRYKGNEREFVIASHDKLNEAQVETLTSYLSGEWFKKTYITGIMNDSDGVLSQHEEYGDEVFCQPLDELRVDRYIMMV
15
+ >UniRef50_V4AGU2
16
+ MHLGSIYLMVVLLIYFAYTDDRKERENVDVINPEENLVQDDEQYVGDSTENIEKSGSEEEEEDKEAIEEEEDEEEELNYRYIPEPAQDIVDNGKKYIQVHCSFKQDESLIRHPSNCSRYFVCSYGVVEEMPVCDDGEVFSIQVSECVKKGSENDDCDKLPFDSPPEITRGTQPSLIWHPRHKSPRSQFRQPTTLQMKVPHIELESFTCSATGKVLSHHSENCAWYYNCSAHPDAVMQTFYSGFIMECPYPQLFSTETKQCEDFEDVKCGDRYEPKSPCDYRANHCHETSHCIPCWVRYASCLELPDGLNPWSELEWKPFFVECYKERTVFQGVCDKSAVFSPLTRACETPYSIPRQHGGWRPVCDGRRDGIYADEYGRCDIYYVCKGYIFTGFFRCEKGEMFNPVISICQKPEAVPYPCGDLEMPNICESSLNGYHLDMFGRCTHYFECKDQQLEGISMCPSGIFNPELQICESSRDQPKPCGNLTNLCTHKNDGFHSDENDCTKVFQCERGLTMTSYDCSGSVRTECDVCNTPTECNDKPNGLYPNLKEGVGYYYDCVRSQIQNHYKCDKEKGGPIFNPVKQRCFYPEDLCKEVFSLKIAW
17
+ >UniRef50_R5PKX9
18
+ MQGGEQDVFEHRQVREKVIALKNHADAAAQGAAEFERLSFEQDVAALDGFETDQAAQKRGFAAARRPENHRDFFVVKREVDAVENHSVAELLYETARFQNNVIGHFYAFHFFSRALAASDTGQHARK
19
+ >UniRef50_UPI0003674933
20
+ MKKKEDILNLEHTLLPWMGRTMKVLDYFIGDFLNLKGIELTKVQWILLKKLNEQNGQPQQNLAFLTNRDKASLARLITTMEKKKLVERIPSKIDGRINHIFITKHGCEILQKSAPVIEKVVGCIQEGISPEEIETVIKVMQKVNNNINRASN
21
+ >UniRef50_E9K9Y4
22
+ MADNVLMAYHIVHDPDERAKHVLNTKKLYKWRITEKTKGTPVVGNVALVQTQFAKRTPVMIYATKEVANDLSDLQPVKVFTNNRDQETVNQTFDDLMR
23
+ >UniRef50_A0A2C9LWN7
24
+ MGKITGLLFFLFTSVRVTPSMKNTVNDIYRVRKDVLTKYRNTEEYDLGQRKGPLKQMDTRETRTPYGHFNSDTAFISPKNILKATRPLAFHLGNLKNQTSPCSTWNLTVDCSYKSLDHIESSWFPSNTTVLLLNNNKLVTLHNETFAQLTNLTRLDLSSNDIRRIDAGAFQGLHNLQELNLHMHCCNFTDHYSLESVFAPLRNLRILNAMHNSDVGVLTYSYTFLTRLPLLQSLSIDFDLDTLYCGPEFNDLKNLTFLQFSGQVMYIDDRSFQNVAQLKNLSMDHLSNINNISHNAFKPLSNLKVLTMYHVLLYVQEILSLLEPFQGRNMTEITLDTTTRTLTQVNPTRNGILTNHDTKYLMNICLESFTLIDNRIFYIKPDAVQNIYTWKKCLMHLYIASNPIQGNNFALIRLFTLDNLKSFTFINMFRACHEFQPFPQSSPPATRNVASSSISSQNNHYQKDTTSNQQQMIRHSPFSPYLDMIDENPYQLNIPNYIFISPSLQYMNFQRLVMSQSFEYHFILVGAQNVTSLDISDSGFYRFNGLMEGVSAIKTLIISGNDVSVLSVSFFDTFVSLENFAISSCKLDRDFISLNSRRIFQNHTRLQELDISSNSLNYLSQNTFSYNNRLMWLNMSGNQFKDIPFDLTNTPELQFLDIRFNSLTTIDETTAQQMDHLVTKSGKLEILLEGNVLSCSCSDLSFMRWMRMTLVTFDQNGNFTCMNTDGERKYTLDYSNLDSLWRECWGSFFLYFALIMLCLYCIGVFAVFITMRNKNFIVSFFLQLFGGFKLHSRRDYPVGVYIGYSDKDYQFPCKELRSFIESSLKLKTFLIDRDLIASVDKASGIIEALNASWRILLVCSKSFLKEDDWSMFTMRSAIYTQTPANPARVVVLVHKDCLPLLPPALLSSVNDENICAVSEWAMNYEMMQMLTTRLH
25
+ >UniRef50_Q9REE6
26
+ MSLRGRELLTSEERLELVRIPEDISEQELGRNFTLSNFDLELIKNRRRDYNRLGFAVQLCVLRFPGWSLNDAEPIPKKVLQHLARQLHVDPDCFSLYSSREA
27
+ >UniRef50_A0A226D4M8
28
+ MQKVINFPIWRRYYFSECGNCNDFRPDGVKKVHPPQEKSRTMDDEILAAPEVTIPFEPSDPSEVVVNLISSEEEDDDDVIQIVEEKSVDKAERQRRRQKKKDLWAARKLQRNKGQNVPLQTAWQRGPRPQETSSFPTPPQQSGGAQQKPLSPILISTAGSPNTSGAPTPANVSQQPTPTPSFVHTTASTSTHPEISLNINSDLALLIRLGPDGRPILTRVENVEQNNTSTSTPTTTRKLPPAPPPPKISFDTQTGESLLNGELITRPIIDITTDSPPSITHAATVSPQTSRTSGPPTLSPISPPPRTTQSNPAHPPPRYEPRKSRHPPRDPLASSSSSSSSSPSPPPTSRARHTSSANIPPPLEPLFLNTTQLIHLIKTCRKCEKSFPTRCDGVIHQKKEHNRKHCPVCFLTLSRHGNTYKDHLNMYHALEGDKEMVVCPFCAVEHSFDGLYNHIGRSHLIPVESKGESEHEVIFSVAPSPQSNGHQTRSVTQGNTPPKNDTNSPPNLEKRRPGPASKTRKTTNDPVPSTSRTGLICHKYVPDVETPPSKAGRNFESRAGRNFESRNVYPPATNRLNPPRNKSPPRNKNLPRNKSPPRNKSLPRNKTPPPSSSRSSSSRSVSNNLRRKNPTPPPPTQPPPKKVAKPDEAGINEKIQAAIKAVNARVHIERSVHHPNNRSDREIPSTSRTVTSRHKVPTSKTSGNTSVRKDPSPPPPLQTPPKTTNLELSKVQKARIVEDVRSIVRDVRITRVLDDGEVPSTSRAVEEEKKKEEKKNETRARLPRSSRVGERSSGYFQMAEGIDFSPENPTPRSKDLKAIHISKLNLIYQQLKCYPDTSVIANVAKECGVEIPVVAKWFTKKHMEYCQKTQQRKRKRKPPELR
29
+ >UniRef50_UPI000B82D8F0
30
+ MGGLHLIELRNVNIEFDKKLIEDGTIKIYDGKITAIIGESGSGKTSLLYLLGLISSNHRYLYSFDDVTLDLSNDFEMSRIRKQKIGYIFQDNNLVENLTIFENIRLSATIAGINITDKEIKSYLEFVELGYIDSNHYPRKLSGGERQRVAIACALAKQPELILADEPTSALDTVNSEIIMGIFKKIAHKDKKKIVIATHNDRIYNEADVIYEIKNNKIQLVKGESSNESSKKEPEDYDNNVKLTPRFYFDYAIKTSRKGRFAKNLMIVLSAIAIAFSSVMYNFGDTFVKEQEKLMDAISDKEIFVVNMTAPLNTILDIDENLSIQDKDAELLRNISYVDTIYPYFEFRSIGYPLINETEASEGYIVVSKGQKEEKYTFAESKDNPYDKYVIIPYYPEQNLERRLKEKLSDESSDKVYISSQLAQLLGIENLKESVSLRVLTYVPIAQHETQMTVRPEGIVYEIDIDLSKVVELDLKIEGILDESVRNRYSNSGNNAIYVPYHKMQMILTQTQNSATIDTNLEYIEWRPSAFVVFAKSYNDVGLVIERVSSINPNFRAVSEYQDIESMNAIVKNTREIGLVIVIVILIIIFLLMSIIHMNHILDRKYEISLLKANGLTKIELTKLVSVESLRHVFLVSLISSVISLVVTKVMNLLFEEIA
data/inverse_folding/5YH2.cif ADDED
The diff for this file is too large to render. See raw diff
 
data/inverse_folding/5YH2.pdb ADDED
The diff for this file is too large to render. See raw diff
 
data/inverse_folding/5YH2_mutated_seqs.fasta ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ >mut_1
2
+ SVLQSLFEHPLYRTVLPDLTEEDTLFNLNAEIRLYPKAASESYPNWLRFHIGINRYELYSRHNPVIAALLRDLLSQKISSVGMKSGGTQLKLIMSFQNYGQALFKPMKQTREQETPPDFFYFSDFERHNAEIAAFHLDRILDFRRVPPVAGRLVNMTREIRDVTRDKKLWRTFFVSPANNICFYGECSYYCSTEHALCGKPDQIEGSLAAFLPDLALAKRKTWRNPWRRSYHKRKKAEWEVDPDYCDEVKQTPPYDRGTRLLDIMDMTIFDFLMGNMDRHHYETFEKFGNDTFIIHLDNGRGFGKHSHDEMSILVPLTQCCRVKRSTYLRLQLLAKEEYKLSSLMEESLLQDRLVPVLIKPHLEALDRRLRLVLKVLSDCVEKDGFSAVVENDLD
3
+ >mut_2
4
+ DVLQSLFEHPLYRTVLPDLTEEDTLFNLNAEIRLYPKAASESYPNWLRFHIGINRYELYSRHNPVIAALLRDLLSQKISSVGMKSGGTQLKLIMSFQNYGQALFKPMKQTREQETPPDFFYFSDFERHNAEIAAFHLDRILDFRRVPPVAGRLVNMTREIRDVTRDKKLWRTFFVSPANNICFYGECSYYCSTEHALCGKPDQIEGSLAAFLPDLALAKRKTWRNPWRRSYHKRKKAEWEVDPDYCDEVKQTPPYDRGTRLLDIMDMTIFDFLMGNMDRHHYETFEKFGNDTFIIHLDNGRGFGKHSHDEMSILVPLTQCCRVKRSTYLRLQLLAKEEYKLSSLMEESLLQDRLVPVLIKPHLEALDRRLRLVLKVLSDCVEKDGFSAVVENDLD
5
+ >mut_3
6
+ EVLQSLFEHPLYRTVLPDLTEEDTLFNLNAEIRLYPKAASESYPNWLRFHIGINRYELYSRHNPVIAALLRDLLSQKISSVGMKSGGTQLKLIMSFQNYGQALFKPMKQTREQETPPDFFYFSDFERHNAEIAAFHLDRILDFRRVPPVAGRLVNMTREIRDVTRDKKLWRTFFVSPANNICFYGECSYYCSTEHALCGKPDQIEGSLAAFLPDLALAKRKTWRNPWRRSYHKRKKAEWEVDPDYCDEVKQTPPYDRGTRLLDIMDMTIFDFLMGNMDRHHYETFEKFGNDTFIIHLDNGRGFGKHSHDEMSILVPLTQCCRVKRSTYLRLQLLAKEEYKLSSLMEESLLQDRLVPVLIKPHLEALDRRLRLVLKVLSDCVEKDGFSAVVENDLD
7
+ >mut_4
8
+ VVLQSLFEHPLYRTVLPDLTEEDTLFNLNAEIRLYPKAASESYPNWLRFHIGINRYELYSRHNPVIAALLRDLLSQKISSVGMKSGGTQLKLIMSFQNYGQALFKPMKQTREQETPPDFFYFSDFERHNAEIAAFHLDRILDFRRVPPVAGRLVNMTREIRDVTRDKKLWRTFFVSPANNICFYGECSYYCSTEHALCGKPDQIEGSLAAFLPDLALAKRKTWRNPWRRSYHKRKKAEWEVDPDYCDEVKQTPPYDRGTRLLDIMDMTIFDFLMGNMDRHHYETFEKFGNDTFIIHLDNGRGFGKHSHDEMSILVPLTQCCRVKRSTYLRLQLLAKEEYKLSSLMEESLLQDRLVPVLIKPHLEALDRRLRLVLKVLSDCVEKDGFSAVVENDLD
data/inverse_folding/example.json ADDED
The diff for this file is too large to render. See raw diff
 
data/variant_prediction/BLAT_ECOLX_Ranganathan2015.csv ADDED
The diff for this file is too large to render. See raw diff
 
data/variant_prediction/aggregated_rho.csv ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ,valid,valid,valid,full,full,full,test,test,test
2
+ ,rho,rho_boot_mean,rho_boot_std,rho,rho_boot_mean,rho_boot_std,rho,rho_boot_mean,rho_boot_std
3
+ prediction_name,,,,,,,,,
4
+ DeepSequence (published),0.5602602238441781,0.5612750863332869,0.011985038405770958,0.5136039187155506,0.512778392574446,0.017143498537203965,0.4985534977063157,0.4971342978135294,0.01880751793444042
5
+ DeepSequence (published) - single,0.5430017493589612,0.5443701641109099,0.012423838414787655,0.5020580499120493,0.5011407877592315,0.017404933590781577,0.4888504049291744,0.4871958276457871,0.01901173848626349
6
+ DeepSequence (replicated),0.5635921424785667,0.5646995390005713,0.01208513622243054,0.5201346211408833,0.5192886065212002,0.01673076687983822,0.5061160658706628,0.5046399186246291,0.018229357414485857
7
+ ESM-1b,0.5666981361139574,0.5676141841913277,0.012025131590764206,0.4585307340241866,0.45722552072809847,0.019420008294609183,0.42363802367264763,0.42161627444963734,0.021805452392623693
8
+ ESM-1v (+further training),0.5979754992703865,0.5985949225433556,0.011700006848349927,0.5382829634571142,0.5368211143294155,0.01685153619316537,0.5190273067431552,0.516894079421693,0.018513319852783258
9
+ ESM-1v (zero shot),0.593067646900253,0.5941859676949833,0.012216511625608212,0.5089550689778174,0.5077512066859666,0.01778501791633543,0.48182197932541876,0.47986902571531576,0.019581310268182918
10
+ EVMutation (published),0.5490624796568302,0.5497402994229479,0.012972877244416833,0.508419480578392,0.5068193077204962,0.017724141740786323,0.49530883571437995,0.4929738265261569,0.01925680770735712
11
+ EVMutation (replicated),0.5512073418060958,0.5516069925840847,0.012682710408380227,0.5112223872556211,0.509417510409684,0.01815069563293862,0.49832401481998395,0.4958080000308451,0.019914561834409074
12
+ MSA Transformer,0.5987868160929384,0.5996093743584658,0.011619082338376548,0.5422875260142875,0.5414621273787668,0.016736474302820666,0.5240619485695612,0.5227049509337023,0.01838724590425425
13
+ PSSM,0.4633509799617207,0.46414678680632565,0.013608999290250463,0.4604575410937561,0.45896520887271747,0.018669177520973506,0.45952417371699333,0.4572937321199404,0.020301493079271263
14
+ ProtBERT-BFD,0.5166978551105863,0.5173010932587435,0.0135134115364477,0.42751993235504165,0.4278749478751994,0.020253227983813266,0.39875286049841424,0.39902780420308837,0.022427362321673118
15
+ TAPE,0.16039305189488504,0.16335386054336812,0.015534139865906533,0.17144437052454356,0.1748040435344602,0.023020918331052527,0.17500931201798176,0.1784976509509415,0.025436008158518972
16
+ UniRep,0.17009503694214162,0.1687392944334104,0.018385140300946963,0.15554362973563243,0.15406970922460442,0.022971233340804673,0.15084962741095204,0.14933758496369925,0.024450618192371674
17
+ gt,1.0,1.0,0.0,1.0,1.0,0.0,1.0,1.0,0.0
data/variant_prediction/aggregated_rho_round3.csv ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ,valid,valid,valid,full,full,full,test,test,test
2
+ ,rho,rho_boot_mean,rho_boot_std,rho,rho_boot_mean,rho_boot_std,rho,rho_boot_mean,rho_boot_std
3
+ prediction_name,,,,,,,,,
4
+ DeepSequence (published),0.56,0.561,0.012,0.514,0.513,0.017,0.499,0.497,0.019
5
+ DeepSequence (published) - single,0.543,0.544,0.012,0.502,0.501,0.017,0.489,0.487,0.019
6
+ DeepSequence (replicated),0.564,0.565,0.012,0.52,0.519,0.017,0.506,0.505,0.018
7
+ ESM-1b,0.567,0.568,0.012,0.459,0.457,0.019,0.424,0.422,0.022
8
+ ESM-1v (+further training),0.598,0.599,0.012,0.538,0.537,0.017,0.519,0.517,0.019
9
+ ESM-1v (zero shot),0.593,0.594,0.012,0.509,0.508,0.018,0.482,0.48,0.02
10
+ EVMutation (published),0.549,0.55,0.013,0.508,0.507,0.018,0.495,0.493,0.019
11
+ EVMutation (replicated),0.551,0.552,0.013,0.511,0.509,0.018,0.498,0.496,0.02
12
+ MSA Transformer,0.599,0.6,0.012,0.542,0.541,0.017,0.524,0.523,0.018
13
+ PSSM,0.463,0.464,0.014,0.46,0.459,0.019,0.46,0.457,0.02
14
+ ProtBERT-BFD,0.517,0.517,0.014,0.428,0.428,0.02,0.399,0.399,0.022
15
+ TAPE,0.16,0.163,0.016,0.171,0.175,0.023,0.175,0.178,0.025
16
+ UniRep,0.17,0.169,0.018,0.156,0.154,0.023,0.151,0.149,0.024
17
+ gt,1.0,1.0,0.0,1.0,1.0,0.0,1.0,1.0,0.0
data/variant_prediction/rho_pp.csv ADDED
@@ -0,0 +1,575 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ,protein_name,prediction_name,rho,rho_boot_mean,rho_boot_std
2
+ 112,BLAT_ECOLX_Ranganathan2015,gt,1.0,1.0,0.0
3
+ 113,BLAT_ECOLX_Ranganathan2015,MSA Transformer,0.7734667485457659,0.7738027379896001,0.005810229642357195
4
+ 114,BLAT_ECOLX_Ranganathan2015,PSSM,0.614150958806157,0.6140369220507402,0.00914005554519492
5
+ 115,BLAT_ECOLX_Ranganathan2015,EVMutation (published),0.7176707275279989,0.7184384489293669,0.005172838583114061
6
+ 116,BLAT_ECOLX_Ranganathan2015,DeepSequence (published) - single,0.755008978954388,0.7561275888133361,0.006397359248039358
7
+ 117,BLAT_ECOLX_Ranganathan2015,DeepSequence (published),0.7755001128993768,0.7754839719498734,0.0059058513297401
8
+ 118,BLAT_ECOLX_Ranganathan2015,ESM-1v (zero shot),0.7251281855227297,0.7252663698494137,0.005817208726713974
9
+ 119,BLAT_ECOLX_Ranganathan2015,ESM-1v (+further training),0.7713005999939375,0.7711664330412893,0.005154671622503008
10
+ 120,BLAT_ECOLX_Ranganathan2015,DeepSequence (replicated),0.7907734920246668,0.7896796440415632,0.004950863463811736
11
+ 121,BLAT_ECOLX_Ranganathan2015,EVMutation (replicated),0.7409416788010579,0.7414034481390834,0.004511986638702662
12
+ 122,BLAT_ECOLX_Ranganathan2015,ProtBERT-BFD,0.5066624675266317,0.5086811085713664,0.008432655997093638
13
+ 123,BLAT_ECOLX_Ranganathan2015,TAPE,0.1437575573041793,0.14718890398398213,0.00854664176422607
14
+ 124,BLAT_ECOLX_Ranganathan2015,UniRep,0.03205236543975054,0.03109080054090812,0.01290097463153492
15
+ 125,BLAT_ECOLX_Ranganathan2015,ESM-1b,0.7244733058050135,0.7244715086369378,0.0054093172279529814
16
+ 322,PABP_YEAST_Fields2013-doubles,gt,1.0,1.0,0.0
17
+ 323,PABP_YEAST_Fields2013-doubles,MSA Transformer,0.7092749798819215,0.7083666356138891,0.0028152329308467395
18
+ 324,PABP_YEAST_Fields2013-doubles,PSSM,0.5022876340276876,0.5009430131340434,0.003914000389196363
19
+ 325,PABP_YEAST_Fields2013-doubles,EVMutation (published),0.6334326213147348,0.6319953143501386,0.0031257311261953294
20
+ 326,PABP_YEAST_Fields2013-doubles,DeepSequence (published) - single,0.697950719553739,0.6969873459722575,0.002722620907521595
21
+ 327,PABP_YEAST_Fields2013-doubles,DeepSequence (published),0.7135955622146342,0.7126803646172054,0.0026005801571960326
22
+ 328,PABP_YEAST_Fields2013-doubles,ESM-1v (zero shot),0.6808954491918657,0.6802766119879265,0.003337373999951867
23
+ 329,PABP_YEAST_Fields2013-doubles,ESM-1v (+further training),0.6724484972163407,0.6715887930967597,0.003131790856684628
24
+ 330,PABP_YEAST_Fields2013-doubles,DeepSequence (replicated),0.6690002200834452,0.6682783362133506,0.002924928420789724
25
+ 331,PABP_YEAST_Fields2013-doubles,EVMutation (replicated),0.6370081500864611,0.6365136199984236,0.0033115051939607903
26
+ 332,PABP_YEAST_Fields2013-doubles,ProtBERT-BFD,0.7018606830370693,0.7013726492421438,0.0029126542395483735
27
+ 333,PABP_YEAST_Fields2013-doubles,TAPE,0.08509310570891564,0.0848841242307348,0.0055652064474624435
28
+ 334,PABP_YEAST_Fields2013-doubles,UniRep,0.25423830212504706,0.2528601717205464,0.005044020233400653
29
+ 335,PABP_YEAST_Fields2013-doubles,ESM-1b,0.6989229474973527,0.6986292605564589,0.0033935909980897867
30
+ 0,AMIE_PSEAE_Whitehead,gt,1.0,1.0,0.0
31
+ 1,AMIE_PSEAE_Whitehead,MSA Transformer,0.6078201305487886,0.6074995010322104,0.006655174664199262
32
+ 2,AMIE_PSEAE_Whitehead,PSSM,0.3851814980540226,0.3857114471207458,0.01419582618409421
33
+ 3,AMIE_PSEAE_Whitehead,EVMutation (published),0.5482672326862741,0.5494300599441264,0.009296902066198478
34
+ 4,AMIE_PSEAE_Whitehead,DeepSequence (published) - single,0.6192004998182683,0.6235042563787871,0.009786304100603813
35
+ 5,AMIE_PSEAE_Whitehead,DeepSequence (published),0.64337902253515,0.6466208891535095,0.008118407538893896
36
+ 6,AMIE_PSEAE_Whitehead,ESM-1v (zero shot),0.6666021525370552,0.6679182566255217,0.008613681679123195
37
+ 7,AMIE_PSEAE_Whitehead,ESM-1v (+further training),0.671863659978349,0.6738279065439714,0.008391215501243852
38
+ 8,AMIE_PSEAE_Whitehead,DeepSequence (replicated),0.6459861864504847,0.6488672280630794,0.007018822987447003
39
+ 9,AMIE_PSEAE_Whitehead,EVMutation (replicated),0.5609325769621947,0.561649692444916,0.008422893320380829
40
+ 10,AMIE_PSEAE_Whitehead,ProtBERT-BFD,0.6338505619537509,0.6354477176484321,0.009554450012056636
41
+ 11,AMIE_PSEAE_Whitehead,TAPE,0.10859786063312615,0.11076584881696006,0.015015379880043802
42
+ 12,AMIE_PSEAE_Whitehead,UniRep,0.07739084999605612,0.073724376050283,0.01240093912413262
43
+ 13,AMIE_PSEAE_Whitehead,ESM-1b,0.5853972837117107,0.5836827247268739,0.009689198977483172
44
+ 476,TIM_SULSO_b0,gt,1.0,1.0,0.0
45
+ 477,TIM_SULSO_b0,MSA Transformer,0.652792451949853,0.6557516749540702,0.01600526744858049
46
+ 478,TIM_SULSO_b0,PSSM,0.5593694164359105,0.566935653048683,0.01690630663394768
47
+ 479,TIM_SULSO_b0,EVMutation (published),0.586140631338893,0.5919185710638765,0.01641131140995354
48
+ 480,TIM_SULSO_b0,DeepSequence (published) - single,0.5440966818223795,0.5487337742437185,0.015747346163591917
49
+ 481,TIM_SULSO_b0,DeepSequence (published),0.5505948722659953,0.5565402351008099,0.014555638377778407
50
+ 482,TIM_SULSO_b0,ESM-1v (zero shot),0.6424600791408842,0.647621332390191,0.016028029413886244
51
+ 483,TIM_SULSO_b0,ESM-1v (+further training),0.6528241665901272,0.6555645155980578,0.015379852940306115
52
+ 484,TIM_SULSO_b0,DeepSequence (replicated),0.58320310154665,0.5889306881826475,0.015779505439458753
53
+ 485,TIM_SULSO_b0,EVMutation (replicated),0.5887928613337577,0.5940831887831108,0.016569303240529226
54
+ 486,TIM_SULSO_b0,ProtBERT-BFD,0.6317983649729998,0.6345885687258263,0.01602936969330677
55
+ 487,TIM_SULSO_b0,TAPE,0.5532247068671533,0.5587646824504885,0.019898766536311598
56
+ 488,TIM_SULSO_b0,UniRep,0.16614520326579557,0.17309558518510257,0.03137269514815842
57
+ 489,TIM_SULSO_b0,ESM-1b,0.6237553534772002,0.6315291160092146,0.015666927222771784
58
+ 266,KKA2_KLEPN_Mikkelsen2014,gt,1.0,1.0,0.0
59
+ 267,KKA2_KLEPN_Mikkelsen2014,MSA Transformer,0.6483744764229661,0.6501362354726463,0.008392887010519141
60
+ 268,KKA2_KLEPN_Mikkelsen2014,PSSM,0.33148417825671017,0.3321644636508253,0.00954461359833698
61
+ 269,KKA2_KLEPN_Mikkelsen2014,EVMutation (published),0.6040252893227205,0.6046576561680694,0.007611417821309178
62
+ 270,KKA2_KLEPN_Mikkelsen2014,DeepSequence (published) - single,0.6428015918045534,0.646183322009227,0.006466715772852643
63
+ 271,KKA2_KLEPN_Mikkelsen2014,DeepSequence (published),0.6622233077856657,0.6647874075249056,0.007006878882782913
64
+ 272,KKA2_KLEPN_Mikkelsen2014,ESM-1v (zero shot),0.627837107524989,0.6303585274093482,0.008597860670353218
65
+ 273,KKA2_KLEPN_Mikkelsen2014,ESM-1v (+further training),0.6540013975518588,0.6568513820339432,0.008249320892729436
66
+ 274,KKA2_KLEPN_Mikkelsen2014,DeepSequence (replicated),0.6708322568508106,0.6736802365189244,0.007635987315614941
67
+ 275,KKA2_KLEPN_Mikkelsen2014,EVMutation (replicated),0.6078971023630376,0.6084473779526628,0.009849549243896777
68
+ 276,KKA2_KLEPN_Mikkelsen2014,ProtBERT-BFD,0.5441498820889966,0.5461574522717653,0.011666264975033773
69
+ 277,KKA2_KLEPN_Mikkelsen2014,TAPE,0.19644765859472593,0.19660401466689767,0.013538150129702716
70
+ 278,KKA2_KLEPN_Mikkelsen2014,UniRep,0.24229449050660715,0.2442377698228683,0.014857522651962994
71
+ 279,KKA2_KLEPN_Mikkelsen2014,ESM-1b,0.5796639591499797,0.5828984127122095,0.009462666946528803
72
+ 182,DLG4_RAT_Ranganathan2012,gt,1.0,1.0,0.0
73
+ 183,DLG4_RAT_Ranganathan2012,MSA Transformer,0.5106330149144778,0.5128948633920939,0.020360553500470727
74
+ 184,DLG4_RAT_Ranganathan2012,PSSM,0.4603978833849677,0.4625263978112141,0.023120281422982173
75
+ 185,DLG4_RAT_Ranganathan2012,EVMutation (published),0.5352653453343902,0.539345546690929,0.02299279306281621
76
+ 186,DLG4_RAT_Ranganathan2012,DeepSequence (published) - single,0.5918364209116883,0.5957477584911891,0.01995659395689766
77
+ 187,DLG4_RAT_Ranganathan2012,DeepSequence (published),0.6036625648098791,0.6070883056488765,0.020478051115311577
78
+ 188,DLG4_RAT_Ranganathan2012,ESM-1v (zero shot),0.5939968225123472,0.596847197984075,0.017630058333348964
79
+ 189,DLG4_RAT_Ranganathan2012,ESM-1v (+further training),0.5682242782581113,0.5694370162367897,0.018958485435275826
80
+ 190,DLG4_RAT_Ranganathan2012,DeepSequence (replicated),0.5765783481552431,0.5780455229510647,0.020809463738300338
81
+ 191,DLG4_RAT_Ranganathan2012,EVMutation (replicated),0.5241180720329418,0.5261248836538202,0.02186178951891566
82
+ 192,DLG4_RAT_Ranganathan2012,ProtBERT-BFD,0.5595215663542064,0.5614010576594576,0.01854665905518769
83
+ 193,DLG4_RAT_Ranganathan2012,TAPE,0.013351052100670802,0.023584538183512672,0.014457178947554198
84
+ 194,DLG4_RAT_Ranganathan2012,UniRep,0.3016230099651694,0.29971140046709394,0.027613438646412317
85
+ 195,DLG4_RAT_Ranganathan2012,ESM-1b,0.5275305911412679,0.5302881928240022,0.01742943283364256
86
+ 532,UBC9_HUMAN_Roth2017,gt,1.0,1.0,0.0
87
+ 533,UBC9_HUMAN_Roth2017,MSA Transformer,0.5257424624114496,0.5264407612968436,0.016782723059713636
88
+ 534,UBC9_HUMAN_Roth2017,PSSM,0.4252037519097337,0.42647455982971144,0.01848680680775899
89
+ 535,UBC9_HUMAN_Roth2017,EVMutation (published),0.509842177492847,0.5077129136778502,0.015575205557209867
90
+ 536,UBC9_HUMAN_Roth2017,DeepSequence (published) - single,0.5301569663083602,0.5321597182510774,0.017474789730172
91
+ 537,UBC9_HUMAN_Roth2017,DeepSequence (published),0.5451981164854786,0.5458299698225401,0.01779569747351641
92
+ 538,UBC9_HUMAN_Roth2017,ESM-1v (zero shot),0.5278002974052306,0.5289273564517684,0.0174313365381068
93
+ 539,UBC9_HUMAN_Roth2017,ESM-1v (+further training),0.530438889646823,0.5308418048769536,0.016194450129423676
94
+ 540,UBC9_HUMAN_Roth2017,DeepSequence (replicated),0.564757773228155,0.566254233293921,0.01584492457358362
95
+ 541,UBC9_HUMAN_Roth2017,EVMutation (replicated),0.5197625999541963,0.5169223464706466,0.015797268774811208
96
+ 542,UBC9_HUMAN_Roth2017,ProtBERT-BFD,0.4566745629330005,0.4597664455496374,0.01695356254093292
97
+ 543,UBC9_HUMAN_Roth2017,TAPE,0.2663201366958923,0.2655109350197859,0.020940445702932447
98
+ 544,UBC9_HUMAN_Roth2017,UniRep,0.027526620911384754,0.032226022213806015,0.0170540626567071
99
+ 545,UBC9_HUMAN_Roth2017,ESM-1b,0.42880952407240114,0.4257117461019339,0.016052256587648167
100
+ 56,BG505_env_Bloom2018,gt,1.0,1.0,0.0
101
+ 57,BG505_env_Bloom2018,MSA Transformer,0.5171538292833168,0.5171496622518762,0.006910262108734762
102
+ 58,BG505_env_Bloom2018,PSSM,0.4805043665958063,0.47934729964627765,0.006403736305762083
103
+ 59,BG505_env_Bloom2018,EVMutation (published),0.4088382668800448,0.4081773036708733,0.005327774682093342
104
+ 60,BG505_env_Bloom2018,DeepSequence (published) - single,0.17427055696697,0.17391089639228693,0.007096603606133151
105
+ 61,BG505_env_Bloom2018,DeepSequence (published),0.17901824140808725,0.17897151771830583,0.007361446332203004
106
+ 62,BG505_env_Bloom2018,ESM-1v (zero shot),0.5263381402665136,0.5258084748455352,0.007358753329943184
107
+ 63,BG505_env_Bloom2018,ESM-1v (+further training),0.5320285787368926,0.5326341655547056,0.006038819273548771
108
+ 64,BG505_env_Bloom2018,DeepSequence (replicated),0.12964060496065777,0.12952804062160664,0.009474191082563171
109
+ 65,BG505_env_Bloom2018,EVMutation (replicated),0.4183486299186111,0.41871016990435506,0.006336285035457084
110
+ 66,BG505_env_Bloom2018,ProtBERT-BFD,0.325305964247549,0.32240107597741696,0.007706083919970625
111
+ 67,BG505_env_Bloom2018,TAPE,0.028456890112386356,0.03179954870869962,0.006177994317554592
112
+ 68,BG505_env_Bloom2018,UniRep,0.20075668930719107,0.20277486226220803,0.008814544928765732
113
+ 69,BG505_env_Bloom2018,ESM-1b,0.46213634322466174,0.4615123969304536,0.007864462687152629
114
+ 462,SUMO1_HUMAN_Roth2017,gt,1.0,1.0,0.0
115
+ 463,SUMO1_HUMAN_Roth2017,MSA Transformer,0.5159144148964154,0.5204033887826773,0.016144534346014247
116
+ 464,SUMO1_HUMAN_Roth2017,PSSM,0.5068653918333971,0.5116066608485563,0.014073225487584034
117
+ 465,SUMO1_HUMAN_Roth2017,EVMutation (published),0.3943527527312187,0.39862273161443174,0.0218398217088854
118
+ 466,SUMO1_HUMAN_Roth2017,DeepSequence (published) - single,0.4546171147375774,0.4563868817701918,0.018789136591575727
119
+ 467,SUMO1_HUMAN_Roth2017,DeepSequence (published),0.4817132258726107,0.48324298006415234,0.01745562156694833
120
+ 468,SUMO1_HUMAN_Roth2017,ESM-1v (zero shot),0.4891908408067041,0.4902530587936492,0.02001929801145162
121
+ 469,SUMO1_HUMAN_Roth2017,ESM-1v (+further training),0.4870961371636435,0.48754122676040595,0.017288489612331478
122
+ 470,SUMO1_HUMAN_Roth2017,DeepSequence (replicated),0.4779470243180796,0.479960524595585,0.020147523090706877
123
+ 471,SUMO1_HUMAN_Roth2017,EVMutation (replicated),0.39100280963861933,0.3956383413944518,0.022045400156456525
124
+ 472,SUMO1_HUMAN_Roth2017,ProtBERT-BFD,0.4707613294700864,0.4702076997635277,0.020510642797657852
125
+ 473,SUMO1_HUMAN_Roth2017,TAPE,0.15068074140877044,0.14631769856923166,0.02417823419968644
126
+ 474,SUMO1_HUMAN_Roth2017,UniRep,0.08697581842056104,0.06864759400267187,0.02922305952665209
127
+ 475,SUMO1_HUMAN_Roth2017,ESM-1b,0.4208939554865267,0.4235043067669399,0.019117696248176413
128
+ 196,GAL4_YEAST_Shendure2015,gt,1.0,1.0,0.0
129
+ 197,GAL4_YEAST_Shendure2015,MSA Transformer,0.5266956520744294,0.5236482827987523,0.016313958672329276
130
+ 198,GAL4_YEAST_Shendure2015,PSSM,0.368064720312814,0.36172145092245883,0.020305140527647172
131
+ 199,GAL4_YEAST_Shendure2015,EVMutation (published),0.5527897519391798,0.5471044481198163,0.02237497642639291
132
+ 200,GAL4_YEAST_Shendure2015,DeepSequence (published) - single,0.42007796271168657,0.41396009878702655,0.019800914070488684
133
+ 201,GAL4_YEAST_Shendure2015,DeepSequence (published),0.44771721216490296,0.44150522173269036,0.018572211283338934
134
+ 202,GAL4_YEAST_Shendure2015,ESM-1v (zero shot),0.45042739409421084,0.4485824906124051,0.01733151555320306
135
+ 203,GAL4_YEAST_Shendure2015,ESM-1v (+further training),0.4395287875677813,0.43649598169067916,0.018212972219452478
136
+ 204,GAL4_YEAST_Shendure2015,DeepSequence (replicated),0.5272024171674746,0.5237709355239704,0.016265152112029255
137
+ 205,GAL4_YEAST_Shendure2015,EVMutation (replicated),0.523268936970079,0.5165768570993756,0.01812112296069153
138
+ 206,GAL4_YEAST_Shendure2015,ProtBERT-BFD,0.3363931685215737,0.33298715717786215,0.022821772133688727
139
+ 207,GAL4_YEAST_Shendure2015,TAPE,0.05800080952303017,0.06811831080338804,0.02702340073359099
140
+ 208,GAL4_YEAST_Shendure2015,UniRep,0.3119470194838534,0.3090243620686157,0.024570145461742788
141
+ 209,GAL4_YEAST_Shendure2015,ESM-1b,0.615398097573459,0.6139141766482525,0.01616576617819578
142
+ 84,BLAT_ECOLX_Ostermeier2014,gt,1.0,1.0,0.0
143
+ 85,BLAT_ECOLX_Ostermeier2014,MSA Transformer,0.7774725340080285,0.7772991120484407,0.00583115239464695
144
+ 86,BLAT_ECOLX_Ostermeier2014,PSSM,0.6266355490550037,0.6249558545704365,0.010963908722361101
145
+ 87,BLAT_ECOLX_Ostermeier2014,EVMutation (published),0.7253493163946709,0.7259111779130355,0.007055247161974134
146
+ 88,BLAT_ECOLX_Ostermeier2014,DeepSequence (published) - single,0.7573575626515066,0.7574787327674316,0.0052410410467141665
147
+ 89,BLAT_ECOLX_Ostermeier2014,DeepSequence (published),0.7780042111143465,0.7782069969302521,0.004849028422585635
148
+ 90,BLAT_ECOLX_Ostermeier2014,ESM-1v (zero shot),0.7233628349192526,0.7225479424696009,0.006683971493639809
149
+ 91,BLAT_ECOLX_Ostermeier2014,ESM-1v (+further training),0.7730745420327815,0.7726874168606355,0.0065547231293585735
150
+ 92,BLAT_ECOLX_Ostermeier2014,DeepSequence (replicated),0.7927294372907648,0.7925690818705499,0.005021676073847794
151
+ 93,BLAT_ECOLX_Ostermeier2014,EVMutation (replicated),0.747447811602467,0.7485714564837528,0.0071001482782374
152
+ 94,BLAT_ECOLX_Ostermeier2014,ProtBERT-BFD,0.4821130792800116,0.47870446935550176,0.010356473470947562
153
+ 95,BLAT_ECOLX_Ostermeier2014,TAPE,0.14731886213718737,0.1477711259950593,0.015163340123327854
154
+ 96,BLAT_ECOLX_Ostermeier2014,UniRep,0.03889602482478667,0.040737324507109665,0.01611318153937308
155
+ 97,BLAT_ECOLX_Ostermeier2014,ESM-1b,0.7251755113400309,0.7251084679688187,0.007010136942265081
156
+ 126,BLAT_ECOLX_Tenaillon2013,gt,1.0,1.0,0.0
157
+ 127,BLAT_ECOLX_Tenaillon2013,MSA Transformer,0.758747218907931,0.7560608794742473,0.014270208324360757
158
+ 128,BLAT_ECOLX_Tenaillon2013,PSSM,0.5914509988018589,0.584550802834145,0.019364487874982444
159
+ 129,BLAT_ECOLX_Tenaillon2013,EVMutation (published),0.6976808741924794,0.6939730281305263,0.017209064919944853
160
+ 130,BLAT_ECOLX_Tenaillon2013,DeepSequence (published) - single,0.7351880319385844,0.734362047270455,0.014525091995200967
161
+ 131,BLAT_ECOLX_Tenaillon2013,DeepSequence (published),0.7543453371693124,0.7522080258926729,0.012721106563380765
162
+ 132,BLAT_ECOLX_Tenaillon2013,ESM-1v (zero shot),0.705631894277465,0.6997739614439058,0.019936391958892526
163
+ 133,BLAT_ECOLX_Tenaillon2013,ESM-1v (+further training),0.7468651561611359,0.7420410512131015,0.018012297742261523
164
+ 134,BLAT_ECOLX_Tenaillon2013,DeepSequence (replicated),0.7636633966742921,0.7615069456529638,0.012651819062077643
165
+ 135,BLAT_ECOLX_Tenaillon2013,EVMutation (replicated),0.7188975120768561,0.7181426689915423,0.015603675185522175
166
+ 136,BLAT_ECOLX_Tenaillon2013,ProtBERT-BFD,0.5849974717911389,0.5759011621581035,0.02142157252628116
167
+ 137,BLAT_ECOLX_Tenaillon2013,TAPE,0.12293837281461435,0.12415027252537572,0.02966599757403504
168
+ 138,BLAT_ECOLX_Tenaillon2013,UniRep,0.018139031023161226,0.026517625360817247,0.022618042553652993
169
+ 139,BLAT_ECOLX_Tenaillon2013,ESM-1b,0.7054857406191637,0.6998800269911201,0.021248434713645674
170
+ 294,MTH3_HAEAESTABILIZED_Tawfik2015,gt,1.0,1.0,0.0
171
+ 295,MTH3_HAEAESTABILIZED_Tawfik2015,MSA Transformer,0.6835339164997478,0.6812589032616372,0.015535718954003042
172
+ 296,MTH3_HAEAESTABILIZED_Tawfik2015,PSSM,0.4416134495623428,0.44246894551424826,0.020085764953621237
173
+ 297,MTH3_HAEAESTABILIZED_Tawfik2015,EVMutation (published),0.6941903664027441,0.692016316213505,0.013094374915061331
174
+ 298,MTH3_HAEAESTABILIZED_Tawfik2015,DeepSequence (published) - single,0.7101794101084092,0.7063260455653937,0.01326393690807996
175
+ 299,MTH3_HAEAESTABILIZED_Tawfik2015,DeepSequence (published),0.7267412245284101,0.7233050341503924,0.011532195128181771
176
+ 300,MTH3_HAEAESTABILIZED_Tawfik2015,ESM-1v (zero shot),0.7028328471487627,0.6988674105054747,0.01389621848758316
177
+ 301,MTH3_HAEAESTABILIZED_Tawfik2015,ESM-1v (+further training),0.710444924607402,0.7058556345404041,0.013349806491214776
178
+ 302,MTH3_HAEAESTABILIZED_Tawfik2015,DeepSequence (replicated),0.7319377341571671,0.7284289432359438,0.011025526727213455
179
+ 303,MTH3_HAEAESTABILIZED_Tawfik2015,EVMutation (replicated),0.6881944596927662,0.6851918594602512,0.014875805426091208
180
+ 304,MTH3_HAEAESTABILIZED_Tawfik2015,ProtBERT-BFD,0.6227906481890101,0.6226488635471868,0.01368447324595496
181
+ 305,MTH3_HAEAESTABILIZED_Tawfik2015,TAPE,0.28986222371790993,0.29059002837311587,0.02293939359468894
182
+ 306,MTH3_HAEAESTABILIZED_Tawfik2015,UniRep,0.21256210891011498,0.20623088209322155,0.016982274395708104
183
+ 307,MTH3_HAEAESTABILIZED_Tawfik2015,ESM-1b,0.6013150928569109,0.6001765775002926,0.016765716391031985
184
+ 336,PABP_YEAST_Fields2013-singles,gt,1.0,1.0,0.0
185
+ 337,PABP_YEAST_Fields2013-singles,MSA Transformer,0.6686627777483488,0.6635711675242917,0.016177764258807882
186
+ 338,PABP_YEAST_Fields2013-singles,PSSM,0.42896284951548524,0.4291061605053958,0.02141741884779835
187
+ 339,PABP_YEAST_Fields2013-singles,EVMutation (published),0.6013962392775869,0.5997811886851577,0.01156645100836508
188
+ 340,PABP_YEAST_Fields2013-singles,DeepSequence (published) - single,0.6812656818721897,0.6786988061064501,0.015497646686186226
189
+ 341,PABP_YEAST_Fields2013-singles,DeepSequence (published),0.6879032274975242,0.6849609026248084,0.013722212867231664
190
+ 342,PABP_YEAST_Fields2013-singles,ESM-1v (zero shot),0.6658159648503742,0.6617537305293117,0.015156538272710452
191
+ 343,PABP_YEAST_Fields2013-singles,ESM-1v (+further training),0.6465056114571746,0.6403467410293169,0.015004313697387745
192
+ 344,PABP_YEAST_Fields2013-singles,DeepSequence (replicated),0.621237612823598,0.6166697742075684,0.015117873200550663
193
+ 345,PABP_YEAST_Fields2013-singles,EVMutation (replicated),0.6004126589511687,0.5972505301682013,0.014433400233151502
194
+ 346,PABP_YEAST_Fields2013-singles,ProtBERT-BFD,0.6590004474532792,0.6522426172055227,0.01761240430158242
195
+ 347,PABP_YEAST_Fields2013-singles,TAPE,0.08173774797871515,0.07580827883401792,0.02537818685979441
196
+ 348,PABP_YEAST_Fields2013-singles,UniRep,0.3524666785583584,0.3507280735011912,0.0214696561284629
197
+ 349,PABP_YEAST_Fields2013-singles,ESM-1b,0.6826492897030101,0.6776229323965959,0.014065470938740474
198
+ 378,POL_HV1N5-CA_Ndungu2014,gt,1.0,1.0,0.0
199
+ 379,POL_HV1N5-CA_Ndungu2014,MSA Transformer,0.8910953880622985,0.8715091885859015,0.04404390170038043
200
+ 380,POL_HV1N5-CA_Ndungu2014,PSSM,0.8027669847951657,0.7648376227138198,0.07156434462986615
201
+ 381,POL_HV1N5-CA_Ndungu2014,EVMutation (published),0.814063406437493,0.770542797914026,0.07799856588047756
202
+ 382,POL_HV1N5-CA_Ndungu2014,DeepSequence (published) - single,0.8237975570016259,0.79822473995615,0.059914597251614195
203
+ 383,POL_HV1N5-CA_Ndungu2014,DeepSequence (published),0.8152651534207193,0.7889600095175417,0.06617658502045558
204
+ 384,POL_HV1N5-CA_Ndungu2014,ESM-1v (zero shot),0.6512266902103299,0.6238138829808892,0.07766375006901825
205
+ 385,POL_HV1N5-CA_Ndungu2014,ESM-1v (+further training),0.815024804024074,0.7869525208215408,0.05466301623393627
206
+ 386,POL_HV1N5-CA_Ndungu2014,DeepSequence (replicated),0.820552840146915,0.7966023557532389,0.05723243614263114
207
+ 387,POL_HV1N5-CA_Ndungu2014,EVMutation (replicated),0.8211537136385281,0.7735182879439364,0.08095098085359952
208
+ 388,POL_HV1N5-CA_Ndungu2014,ProtBERT-BFD,0.38179501657099424,0.42193301482635154,0.14774279685397848
209
+ 389,POL_HV1N5-CA_Ndungu2014,TAPE,0.3483864504373032,0.4104118824597043,0.1470038347598428
210
+ 390,POL_HV1N5-CA_Ndungu2014,UniRep,0.4639945102236729,0.40093126150106306,0.16524010823471783
211
+ 391,POL_HV1N5-CA_Ndungu2014,ESM-1b,0.5957059795852749,0.5731935627996381,0.13224460706985164
212
+ 364,POLG_HCVJF_Sun2014,gt,1.0,1.0,0.0
213
+ 365,POLG_HCVJF_Sun2014,MSA Transformer,0.6677478668298926,0.670497369164695,0.017151824473903992
214
+ 366,POLG_HCVJF_Sun2014,PSSM,0.6494520970500091,0.6472164109404976,0.01636183923822566
215
+ 367,POLG_HCVJF_Sun2014,EVMutation (published),0.5865270173010575,0.5896466823313951,0.019303754939295415
216
+ 368,POLG_HCVJF_Sun2014,DeepSequence (published) - single,0.39251206867133814,0.39508591794495096,0.020227604662347038
217
+ 369,POLG_HCVJF_Sun2014,DeepSequence (published),0.3713820411310244,0.3795469161150128,0.023014839527838928
218
+ 370,POLG_HCVJF_Sun2014,ESM-1v (zero shot),0.6340055756536588,0.6335374345199196,0.01764641035648572
219
+ 371,POLG_HCVJF_Sun2014,ESM-1v (+further training),0.5652424039602515,0.5708409099578081,0.020101066917986344
220
+ 372,POLG_HCVJF_Sun2014,DeepSequence (replicated),0.46165721811412747,0.46807649417617975,0.022195221779086654
221
+ 373,POLG_HCVJF_Sun2014,EVMutation (replicated),0.5825890447985209,0.5852998202243922,0.022749622221884737
222
+ 374,POLG_HCVJF_Sun2014,ProtBERT-BFD,0.08677957966093554,0.07770559640019087,0.018629212118296944
223
+ 375,POLG_HCVJF_Sun2014,TAPE,0.05680250795137183,0.04875383206148289,0.02707444904306108
224
+ 376,POLG_HCVJF_Sun2014,UniRep,0.023755477003752395,0.018385016483602818,0.018204300138877978
225
+ 377,POLG_HCVJF_Sun2014,ESM-1b,0.14790101977036282,0.1451007380223277,0.018527745632610403
226
+ 308,P84126_THETH_b0,gt,1.0,1.0,0.0
227
+ 309,P84126_THETH_b0,MSA Transformer,0.5799265252107147,0.5738614544298895,0.016977861401835232
228
+ 310,P84126_THETH_b0,PSSM,0.5059938805045767,0.497875302076657,0.017450898377151254
229
+ 311,P84126_THETH_b0,EVMutation (published),0.5762676414938405,0.5713927693726344,0.015545247017306097
230
+ 312,P84126_THETH_b0,DeepSequence (published) - single,0.5267205050047176,0.5248192557448691,0.018977964279615622
231
+ 313,P84126_THETH_b0,DeepSequence (published),0.5877949812163814,0.5848736179704858,0.015886804363744445
232
+ 314,P84126_THETH_b0,ESM-1v (zero shot),0.5870635090422014,0.5811455597687403,0.01549045031439649
233
+ 315,P84126_THETH_b0,ESM-1v (+further training),0.5790524141907541,0.572625780593036,0.014736663161466617
234
+ 316,P84126_THETH_b0,DeepSequence (replicated),0.6038248556337414,0.602211740801349,0.013767217833566922
235
+ 317,P84126_THETH_b0,EVMutation (replicated),0.5700921855537731,0.5640773353834833,0.016516084944527984
236
+ 318,P84126_THETH_b0,ProtBERT-BFD,0.5721041244229742,0.5675746516094956,0.016572893593986743
237
+ 319,P84126_THETH_b0,TAPE,0.530841865819399,0.524876249458913,0.02120781628171545
238
+ 320,P84126_THETH_b0,UniRep,0.2274910400298911,0.22961913248092042,0.020560804448588488
239
+ 321,P84126_THETH_b0,ESM-1b,0.5700277792841302,0.5653475783194437,0.014015440292458613
240
+ 238,HSP82_YEAST_Bolon2016,gt,1.0,1.0,0.0
241
+ 239,HSP82_YEAST_Bolon2016,MSA Transformer,0.48917822587769644,0.4911252194110343,0.010638436729624378
242
+ 240,HSP82_YEAST_Bolon2016,PSSM,0.5080494707835187,0.5081989816141457,0.011630856503356157
243
+ 241,HSP82_YEAST_Bolon2016,EVMutation (published),0.49012823437511943,0.4936437806547088,0.009824172602805919
244
+ 242,HSP82_YEAST_Bolon2016,DeepSequence (published) - single,0.5292966677834544,0.529631038805717,0.010670673995645957
245
+ 243,HSP82_YEAST_Bolon2016,DeepSequence (published),0.5345178740223454,0.5359585453318252,0.010405888846639616
246
+ 244,HSP82_YEAST_Bolon2016,ESM-1v (zero shot),0.5770032224447383,0.5794593692641861,0.011071932164493134
247
+ 245,HSP82_YEAST_Bolon2016,ESM-1v (+further training),0.5582427433705837,0.5611201932811588,0.011556274778765427
248
+ 246,HSP82_YEAST_Bolon2016,DeepSequence (replicated),0.5447815098744462,0.5468478860295007,0.009190852805604763
249
+ 247,HSP82_YEAST_Bolon2016,EVMutation (replicated),0.4813174874985635,0.4833921506539731,0.010641726788141665
250
+ 248,HSP82_YEAST_Bolon2016,ProtBERT-BFD,0.5020206378059789,0.5038884666599158,0.010495246599296015
251
+ 249,HSP82_YEAST_Bolon2016,TAPE,0.11898211650679438,0.11418591489599068,0.0095283384478768
252
+ 250,HSP82_YEAST_Bolon2016,UniRep,0.28031483895837656,0.27995048255516847,0.016433158282085403
253
+ 251,HSP82_YEAST_Bolon2016,ESM-1b,0.5364678889354202,0.5369383571750992,0.012361055325265038
254
+ 518,TPMT_HUMAN_Fowler2018,gt,1.0,1.0,0.0
255
+ 519,TPMT_HUMAN_Fowler2018,MSA Transformer,0.5424668178781977,0.540549584398611,0.0130129824539858
256
+ 520,TPMT_HUMAN_Fowler2018,PSSM,0.48146126611262924,0.4789555004656866,0.01619133485423122
257
+ 521,TPMT_HUMAN_Fowler2018,EVMutation (published),0.5243737765811296,0.5211293318961853,0.013677282837478894
258
+ 522,TPMT_HUMAN_Fowler2018,DeepSequence (published) - single,0.5616767945109112,0.5601851812367447,0.014098853189084848
259
+ 523,TPMT_HUMAN_Fowler2018,DeepSequence (published),0.57189769074549,0.5692094068525796,0.014271609738516988
260
+ 524,TPMT_HUMAN_Fowler2018,ESM-1v (zero shot),0.5746177224716744,0.5733456843246085,0.013161147755010085
261
+ 525,TPMT_HUMAN_Fowler2018,ESM-1v (+further training),0.5667144426739071,0.5643404804061067,0.012156963082272723
262
+ 526,TPMT_HUMAN_Fowler2018,DeepSequence (replicated),0.5734186713594054,0.5725136899852928,0.01380924904516693
263
+ 527,TPMT_HUMAN_Fowler2018,EVMutation (replicated),0.5415452371370989,0.5367554768824575,0.014285595575941081
264
+ 528,TPMT_HUMAN_Fowler2018,ProtBERT-BFD,0.5755683713471709,0.5740036007868525,0.011781062164033955
265
+ 529,TPMT_HUMAN_Fowler2018,TAPE,0.21528496910537398,0.2163150200476124,0.01671186684925183
266
+ 530,TPMT_HUMAN_Fowler2018,UniRep,0.24493123064838648,0.2429991773585667,0.01737637750092445
267
+ 531,TPMT_HUMAN_Fowler2018,ESM-1b,0.585864822736713,0.5831594511762555,0.012841359293495367
268
+ 252,IF1_ECOLI_Kishony,gt,1.0,1.0,0.0
269
+ 253,IF1_ECOLI_Kishony,MSA Transformer,0.5374285372059321,0.5379972559155065,0.020194737882211888
270
+ 254,IF1_ECOLI_Kishony,PSSM,0.5052167418774901,0.5069241815649538,0.021074640419288252
271
+ 255,IF1_ECOLI_Kishony,EVMutation (published),0.5003046508987051,0.5003352234717605,0.022143569265813394
272
+ 256,IF1_ECOLI_Kishony,DeepSequence (published) - single,0.5239331603676252,0.5269853910903933,0.019737341732545446
273
+ 257,IF1_ECOLI_Kishony,DeepSequence (published),0.5232098971780704,0.5263086088632558,0.019848792789945318
274
+ 258,IF1_ECOLI_Kishony,ESM-1v (zero shot),0.5489484528277484,0.5487290835018946,0.018090689195472447
275
+ 259,IF1_ECOLI_Kishony,ESM-1v (+further training),0.5619784833217806,0.5609262853368223,0.01759996229002091
276
+ 260,IF1_ECOLI_Kishony,DeepSequence (replicated),0.5371602219910716,0.5377419211137229,0.016834767452949526
277
+ 261,IF1_ECOLI_Kishony,EVMutation (replicated),0.49106963416130595,0.487364241499556,0.02231862948055046
278
+ 262,IF1_ECOLI_Kishony,ProtBERT-BFD,0.49640551530348803,0.49572596972809546,0.021526763193477596
279
+ 263,IF1_ECOLI_Kishony,TAPE,0.3330415186026132,0.3329560370901763,0.025365922197565095
280
+ 264,IF1_ECOLI_Kishony,UniRep,0.11711947357011687,0.11208310104103972,0.02358345571859419
281
+ 265,IF1_ECOLI_Kishony,ESM-1b,0.548626388294071,0.5492417382232484,0.020649586745340585
282
+ 154,BRCA1_HUMAN_RING,gt,1.0,1.0,0.0
283
+ 155,BRCA1_HUMAN_RING,MSA Transformer,0.5193005569644538,0.5203285046503858,0.041166837523028924
284
+ 156,BRCA1_HUMAN_RING,PSSM,0.5634130110253781,0.5581058154928551,0.04362682737121433
285
+ 157,BRCA1_HUMAN_RING,EVMutation (published),0.4739893403358574,0.4727346993937392,0.036203681195866866
286
+ 158,BRCA1_HUMAN_RING,DeepSequence (published) - single,0.5543323620928434,0.5511807082846618,0.039417214029845105
287
+ 159,BRCA1_HUMAN_RING,DeepSequence (published),0.5617365720006955,0.5591185452387899,0.03842959531538541
288
+ 160,BRCA1_HUMAN_RING,ESM-1v (zero shot),0.5415424138323831,0.5341119058002446,0.03653613513934021
289
+ 161,BRCA1_HUMAN_RING,ESM-1v (+further training),0.5550269189493816,0.5537267190735496,0.03937349908877672
290
+ 162,BRCA1_HUMAN_RING,DeepSequence (replicated),0.5658118851058472,0.5627698357833636,0.037505350857757684
291
+ 163,BRCA1_HUMAN_RING,EVMutation (replicated),0.46724701283596226,0.46596752209015424,0.04012929367216169
292
+ 164,BRCA1_HUMAN_RING,ProtBERT-BFD,0.47507688987212,0.4713003309113355,0.03734723419650255
293
+ 165,BRCA1_HUMAN_RING,TAPE,0.32511391092165925,0.3259918359586091,0.05215348292668556
294
+ 166,BRCA1_HUMAN_RING,UniRep,0.4574870950916383,0.466226203934293,0.029045683651907416
295
+ 167,BRCA1_HUMAN_RING,ESM-1b,0.5729860249285059,0.5672443289637067,0.030337589962057807
296
+ 98,BLAT_ECOLX_Palzkill2012,gt,1.0,1.0,0.0
297
+ 99,BLAT_ECOLX_Palzkill2012,MSA Transformer,0.5790109592895919,0.576559464262669,0.00813860157556571
298
+ 100,BLAT_ECOLX_Palzkill2012,PSSM,0.43541874109113293,0.4346912136467994,0.011525932575641511
299
+ 101,BLAT_ECOLX_Palzkill2012,EVMutation (published),0.5035045285112302,0.5015670440233889,0.011387370179059404
300
+ 102,BLAT_ECOLX_Palzkill2012,DeepSequence (published) - single,0.5387135089739988,0.5368824370193662,0.011450482383497546
301
+ 103,BLAT_ECOLX_Palzkill2012,DeepSequence (published),0.555680249906377,0.5539233663406711,0.009685510491284273
302
+ 104,BLAT_ECOLX_Palzkill2012,ESM-1v (zero shot),0.5394874702645197,0.5391023570614875,0.01072036011365782
303
+ 105,BLAT_ECOLX_Palzkill2012,ESM-1v (+further training),0.5672174721013816,0.5661011431263104,0.010297339893877539
304
+ 106,BLAT_ECOLX_Palzkill2012,DeepSequence (replicated),0.5665462527968158,0.5646253670538975,0.00957133565445041
305
+ 107,BLAT_ECOLX_Palzkill2012,EVMutation (replicated),0.5174199245259459,0.5144044189835617,0.010884656508769686
306
+ 108,BLAT_ECOLX_Palzkill2012,ProtBERT-BFD,0.413553141253597,0.4108322854585459,0.009768034882433663
307
+ 109,BLAT_ECOLX_Palzkill2012,TAPE,0.06707069584638124,0.06961505855709685,0.01069869285554942
308
+ 110,BLAT_ECOLX_Palzkill2012,UniRep,0.0166580631994596,0.02360053325843217,0.01073550650340384
309
+ 111,BLAT_ECOLX_Palzkill2012,ESM-1b,0.54626199827611,0.5450469362296847,0.010574502773225362
310
+ 210,HG_FLU_Bloom2016,gt,1.0,1.0,0.0
311
+ 211,HG_FLU_Bloom2016,MSA Transformer,0.4807847197470188,0.48133913444729065,0.007238779061281368
312
+ 212,HG_FLU_Bloom2016,PSSM,0.467255239211276,0.4658023016610004,0.007807096034181624
313
+ 213,HG_FLU_Bloom2016,EVMutation (published),0.45827659972583357,0.45804886604872685,0.008079452114456188
314
+ 214,HG_FLU_Bloom2016,DeepSequence (published) - single,0.38185154496925244,0.3815243480167388,0.009700262344961326
315
+ 215,HG_FLU_Bloom2016,DeepSequence (published),0.408559044093847,0.4088655809693629,0.007996666160114359
316
+ 216,HG_FLU_Bloom2016,ESM-1v (zero shot),0.5377581449296356,0.5381755966315286,0.00849950538034111
317
+ 217,HG_FLU_Bloom2016,ESM-1v (+further training),0.508004961821385,0.50881255466271,0.008423294599454892
318
+ 218,HG_FLU_Bloom2016,DeepSequence (replicated),0.425338497638415,0.425397348539834,0.007829596385814108
319
+ 219,HG_FLU_Bloom2016,EVMutation (replicated),0.4745801474914726,0.4740523393070549,0.00772632329264063
320
+ 220,HG_FLU_Bloom2016,ProtBERT-BFD,0.01216830054805121,0.014371682213071179,0.008595363873197908
321
+ 221,HG_FLU_Bloom2016,TAPE,0.011506602346493722,0.011595399204682536,0.006272208060584064
322
+ 222,HG_FLU_Bloom2016,UniRep,0.11238855588872076,0.11416182055768724,0.009338414613763222
323
+ 223,HG_FLU_Bloom2016,ESM-1b,0.13466161180017006,0.13615942676936274,0.010191230998347687
324
+ 224,HIS7_YEAST_Kondrashov2017,gt,1.0,1.0,0.0
325
+ 225,HIS7_YEAST_Kondrashov2017,MSA Transformer,0.30171610633916407,0.301852298319144,0.0012676098127205092
326
+ 226,HIS7_YEAST_Kondrashov2017,PSSM,0.46025981696434587,0.4602850849857719,0.0008742604182146493
327
+ 227,HIS7_YEAST_Kondrashov2017,EVMutation (published),0.5865226545066141,0.5868249726401576,0.0008233711922239475
328
+ 228,HIS7_YEAST_Kondrashov2017,DeepSequence (published) - single,0.4924067186635951,0.49266995692585214,0.0009319735566991191
329
+ 229,HIS7_YEAST_Kondrashov2017,DeepSequence (published),0.539985999849893,0.540227447923642,0.0008648831057151851
330
+ 230,HIS7_YEAST_Kondrashov2017,ESM-1v (zero shot),0.529358182381123,0.5295580913555231,0.0007957702421518582
331
+ 231,HIS7_YEAST_Kondrashov2017,ESM-1v (+further training),0.5600853174526501,0.5602849321317114,0.0008034030458959766
332
+ 232,HIS7_YEAST_Kondrashov2017,DeepSequence (replicated),0.5771729957674867,0.5774905109783149,0.0007170541729409019
333
+ 233,HIS7_YEAST_Kondrashov2017,EVMutation (replicated),0.5839282060088532,0.5842957417091784,0.0008208185316044222
334
+ 234,HIS7_YEAST_Kondrashov2017,ProtBERT-BFD,0.5529258544618092,0.5529676964174914,0.0007360080980740549
335
+ 235,HIS7_YEAST_Kondrashov2017,TAPE,0.1014260339205887,0.101752697842131,0.0014218010200125605
336
+ 236,HIS7_YEAST_Kondrashov2017,UniRep,0.1815849109979771,0.18158251774490938,0.0014496180282351032
337
+ 237,HIS7_YEAST_Kondrashov2017,ESM-1b,0.5000466702129686,0.5002672548811231,0.0008300778727114249
338
+ 70,BG_STRSQ_hmmerbit,gt,1.0,1.0,0.0
339
+ 71,BG_STRSQ_hmmerbit,MSA Transformer,0.6555958579973886,0.659326801766521,0.00913574784080978
340
+ 72,BG_STRSQ_hmmerbit,PSSM,0.5431285035494208,0.5491891696554254,0.01382628634556949
341
+ 73,BG_STRSQ_hmmerbit,EVMutation (published),0.6297133475442988,0.6326270443670063,0.006525349201880503
342
+ 74,BG_STRSQ_hmmerbit,DeepSequence (published) - single,0.6663981684713202,0.667051777591926,0.008814659279799686
343
+ 75,BG_STRSQ_hmmerbit,DeepSequence (published),0.671353366524517,0.6721885348190513,0.009076474761061238
344
+ 76,BG_STRSQ_hmmerbit,ESM-1v (zero shot),0.528482255049547,0.5356316829302887,0.013445455516506805
345
+ 77,BG_STRSQ_hmmerbit,ESM-1v (+further training),0.6516055107633002,0.6555062061803748,0.009214695345811378
346
+ 78,BG_STRSQ_hmmerbit,DeepSequence (replicated),0.6751486915624705,0.6760984429469532,0.009352478062896172
347
+ 79,BG_STRSQ_hmmerbit,EVMutation (replicated),0.6403197196758124,0.6434637152906157,0.007241339119188467
348
+ 80,BG_STRSQ_hmmerbit,ProtBERT-BFD,0.6365069784319516,0.6396483776091306,0.007811080769658407
349
+ 81,BG_STRSQ_hmmerbit,TAPE,0.43294588799591494,0.44008364687109375,0.01682011773736568
350
+ 82,BG_STRSQ_hmmerbit,UniRep,0.19989240659304872,0.20517404401460504,0.014963964273707563
351
+ 83,BG_STRSQ_hmmerbit,ESM-1b,0.6009580023829318,0.6080513205167206,0.013233900564372743
352
+ 546,UBE4B_MOUSE_Klevit2013-singles,gt,1.0,1.0,0.0
353
+ 547,UBE4B_MOUSE_Klevit2013-singles,MSA Transformer,0.49832943520981005,0.49905990983648263,0.03105986611446269
354
+ 548,UBE4B_MOUSE_Klevit2013-singles,PSSM,0.48860473816872396,0.49337529571134364,0.031233090528237636
355
+ 549,UBE4B_MOUSE_Klevit2013-singles,EVMutation (published),0.4906841388190489,0.49199509841786193,0.03340124290266937
356
+ 550,UBE4B_MOUSE_Klevit2013-singles,DeepSequence (published) - single,0.5312205433544338,0.5329703058977546,0.029417950250717785
357
+ 551,UBE4B_MOUSE_Klevit2013-singles,DeepSequence (published),0.5395815016518124,0.5430445683834082,0.02805620658685915
358
+ 552,UBE4B_MOUSE_Klevit2013-singles,ESM-1v (zero shot),0.5220724759142595,0.5231561587068752,0.024550717856015463
359
+ 553,UBE4B_MOUSE_Klevit2013-singles,ESM-1v (+further training),0.5218576853965179,0.5198018293944963,0.029197148702440747
360
+ 554,UBE4B_MOUSE_Klevit2013-singles,DeepSequence (replicated),0.5223215278319518,0.5271163507848048,0.02943995962728437
361
+ 555,UBE4B_MOUSE_Klevit2013-singles,EVMutation (replicated),0.4846034274372467,0.48559313231244233,0.035130463278636635
362
+ 556,UBE4B_MOUSE_Klevit2013-singles,ProtBERT-BFD,0.5185431412393127,0.5236656965174686,0.028751086492193833
363
+ 557,UBE4B_MOUSE_Klevit2013-singles,TAPE,0.01730835573288986,0.03524679123603523,0.02987730394986271
364
+ 558,UBE4B_MOUSE_Klevit2013-singles,UniRep,0.10151869130428068,0.09383999274532392,0.03556604553816262
365
+ 559,UBE4B_MOUSE_Klevit2013-singles,ESM-1b,0.4877718340726251,0.48675329873590983,0.03538514294193213
366
+ 14,B3VI55_LIPSTSTABLE,gt,1.0,1.0,0.0
367
+ 15,B3VI55_LIPSTSTABLE,MSA Transformer,0.5251005167937696,0.5275545723143799,0.009041770337910218
368
+ 16,B3VI55_LIPSTSTABLE,PSSM,0.33176316087515695,0.3329724203391258,0.011406640278605069
369
+ 17,B3VI55_LIPSTSTABLE,EVMutation (published),0.43366434910484786,0.43528511611104986,0.010773070057405095
370
+ 18,B3VI55_LIPSTSTABLE,DeepSequence (published) - single,0.4747977554498681,0.4764432728845286,0.00955452160837742
371
+ 19,B3VI55_LIPSTSTABLE,DeepSequence (published),0.48780043789141697,0.489281157459712,0.008995219832666802
372
+ 20,B3VI55_LIPSTSTABLE,ESM-1v (zero shot),0.5144594346026741,0.516476518473857,0.009568231035205155
373
+ 21,B3VI55_LIPSTSTABLE,ESM-1v (+further training),0.5408988777571562,0.5429418957469877,0.008374931117004644
374
+ 22,B3VI55_LIPSTSTABLE,DeepSequence (replicated),0.5108241872870117,0.511210509948324,0.008885420291063774
375
+ 23,B3VI55_LIPSTSTABLE,EVMutation (replicated),0.45220927299548147,0.45292929103074864,0.01073069192782447
376
+ 24,B3VI55_LIPSTSTABLE,ProtBERT-BFD,0.3909053736573994,0.39106874014118553,0.010538767559809602
377
+ 25,B3VI55_LIPSTSTABLE,TAPE,0.1114444287805763,0.1120507952365121,0.012548143306758398
378
+ 26,B3VI55_LIPSTSTABLE,UniRep,0.1050036846541006,0.10502881984575867,0.013417162356959514
379
+ 27,B3VI55_LIPSTSTABLE,ESM-1b,0.4153440056253525,0.4178700751301828,0.011532303943529923
380
+ 42,BF520_env_Bloom2018,gt,1.0,1.0,0.0
381
+ 43,BF520_env_Bloom2018,MSA Transformer,0.53045503362033,0.528360683768996,0.007312684938262093
382
+ 44,BF520_env_Bloom2018,PSSM,0.48128944926535605,0.47846350663914833,0.007277527859925501
383
+ 45,BF520_env_Bloom2018,EVMutation (published),0.3961853129701546,0.3926921454653422,0.00906487418575762
384
+ 46,BF520_env_Bloom2018,DeepSequence (published) - single,0.0033350478364570987,0.009194378034284379,0.008689823275268422
385
+ 47,BF520_env_Bloom2018,DeepSequence (published),0.0029335219050744344,0.008967370879028378,0.005401668464782235
386
+ 48,BF520_env_Bloom2018,ESM-1v (zero shot),0.5137302974636209,0.5110743977804137,0.006968499056122589
387
+ 49,BF520_env_Bloom2018,ESM-1v (+further training),0.5260276733897689,0.524307610096477,0.006318717908534139
388
+ 50,BF520_env_Bloom2018,DeepSequence (replicated),0.03940344835961486,0.03571128763490593,0.010040975563315926
389
+ 51,BF520_env_Bloom2018,EVMutation (replicated),0.41701008243014626,0.4131323889976084,0.009699036294956902
390
+ 52,BF520_env_Bloom2018,ProtBERT-BFD,0.35920295750142894,0.356294565641996,0.008888654031775356
391
+ 53,BF520_env_Bloom2018,TAPE,0.03296454518403542,0.03347884384026924,0.010604055757164086
392
+ 54,BF520_env_Bloom2018,UniRep,0.19509435241603182,0.19534025730349494,0.008044823411980718
393
+ 55,BF520_env_Bloom2018,ESM-1b,0.4644044299599039,0.4621942590259476,0.0072479072681551
394
+ 490,TIM_THEMA_b0,gt,1.0,1.0,0.0
395
+ 491,TIM_THEMA_b0,MSA Transformer,0.476641570693168,0.4772084109762894,0.021262538481700146
396
+ 492,TIM_THEMA_b0,PSSM,0.3987702061334132,0.39949709692713725,0.022351322419246027
397
+ 493,TIM_THEMA_b0,EVMutation (published),0.43189426495468003,0.4320501737162544,0.023786620230565422
398
+ 494,TIM_THEMA_b0,DeepSequence (published) - single,0.4429769169797119,0.4459763974635589,0.023367347171715933
399
+ 495,TIM_THEMA_b0,DeepSequence (published),0.43793312514525096,0.43932643176681746,0.02400129226573652
400
+ 496,TIM_THEMA_b0,ESM-1v (zero shot),0.5026024874119385,0.5028606317050863,0.0196194686907316
401
+ 497,TIM_THEMA_b0,ESM-1v (+further training),0.49669513157740486,0.49715001129465347,0.021252079717001313
402
+ 498,TIM_THEMA_b0,DeepSequence (replicated),0.4065555906798227,0.4088509392059708,0.02383945792859995
403
+ 499,TIM_THEMA_b0,EVMutation (replicated),0.4372508700326144,0.43818153131258974,0.022249944638541977
404
+ 500,TIM_THEMA_b0,ProtBERT-BFD,0.5030640016728883,0.505061273209954,0.02004593130312488
405
+ 501,TIM_THEMA_b0,TAPE,0.426213240694561,0.42842760017164616,0.025447870266352153
406
+ 502,TIM_THEMA_b0,UniRep,0.15476155586059467,0.14652965312897737,0.02996974334997726
407
+ 503,TIM_THEMA_b0,ESM-1b,0.45916689313021203,0.45909489666370673,0.021672817044030984
408
+ 560,YAP1_HUMAN_Fields2012-singles,gt,1.0,1.0,0.0
409
+ 561,YAP1_HUMAN_Fields2012-singles,MSA Transformer,0.5887070642875368,0.5706519861099527,0.040386258549904866
410
+ 562,YAP1_HUMAN_Fields2012-singles,PSSM,0.5690684565019047,0.5451477752262303,0.04238593338136975
411
+ 563,YAP1_HUMAN_Fields2012-singles,EVMutation (published),0.5844091425595583,0.5694702589374069,0.03313034558652812
412
+ 564,YAP1_HUMAN_Fields2012-singles,DeepSequence (published) - single,0.6529398136915281,0.6360722049001328,0.032593234109222484
413
+ 565,YAP1_HUMAN_Fields2012-singles,DeepSequence (published),0.6456339137145388,0.6294381645066613,0.03481028251531764
414
+ 566,YAP1_HUMAN_Fields2012-singles,ESM-1v (zero shot),0.493433729941941,0.48010349687654763,0.03994836553901359
415
+ 567,YAP1_HUMAN_Fields2012-singles,ESM-1v (+further training),0.6376365184641369,0.623715503200643,0.03529100768352496
416
+ 568,YAP1_HUMAN_Fields2012-singles,DeepSequence (replicated),0.6447076152922595,0.6272717205426198,0.033734031749303436
417
+ 569,YAP1_HUMAN_Fields2012-singles,EVMutation (replicated),0.557456385066247,0.543521991089175,0.035472281995781466
418
+ 570,YAP1_HUMAN_Fields2012-singles,ProtBERT-BFD,0.5482997903990557,0.5417356076069597,0.03807717806310085
419
+ 571,YAP1_HUMAN_Fields2012-singles,TAPE,0.14957625858401177,0.1801038227952158,0.05696901517750361
420
+ 572,YAP1_HUMAN_Fields2012-singles,UniRep,0.029127721955503238,0.05432100409858017,0.03754188708662973
421
+ 573,YAP1_HUMAN_Fields2012-singles,ESM-1b,0.49074132050160213,0.47904274853673057,0.033063480562130175
422
+ 140,BRCA1_HUMAN_BRCT,gt,1.0,1.0,0.0
423
+ 141,BRCA1_HUMAN_BRCT,MSA Transformer,0.5928951868322753,0.5960239232158157,0.024771243739877567
424
+ 142,BRCA1_HUMAN_BRCT,PSSM,0.45174214496735526,0.4661431870435194,0.02242218107567778
425
+ 143,BRCA1_HUMAN_BRCT,EVMutation (published),0.575430631741363,0.5736725403805653,0.02241134787829384
426
+ 144,BRCA1_HUMAN_BRCT,DeepSequence (published) - single,0.56817101100728,0.5677360233280984,0.023388317280203356
427
+ 145,BRCA1_HUMAN_BRCT,DeepSequence (published),0.5887397586618573,0.5891289275127845,0.025473578386602996
428
+ 146,BRCA1_HUMAN_BRCT,ESM-1v (zero shot),0.43099744949022667,0.43820237951190066,0.026042969300316396
429
+ 147,BRCA1_HUMAN_BRCT,ESM-1v (+further training),0.5902839735003296,0.5924129041526023,0.022139044593609002
430
+ 148,BRCA1_HUMAN_BRCT,DeepSequence (replicated),0.6048855640279864,0.6073185827311438,0.022386535818213062
431
+ 149,BRCA1_HUMAN_BRCT,EVMutation (replicated),0.5943999321364778,0.5914745443226089,0.021113952368322746
432
+ 150,BRCA1_HUMAN_BRCT,ProtBERT-BFD,0.3807653003587669,0.38891615029062426,0.025074152619186402
433
+ 151,BRCA1_HUMAN_BRCT,TAPE,0.05185305485548559,0.06300777252497933,0.028006890598497248
434
+ 152,BRCA1_HUMAN_BRCT,UniRep,0.001009857244270908,0.024731061663019048,0.015154925933309927
435
+ 153,BRCA1_HUMAN_BRCT,ESM-1b,0.5015315617812091,0.5064634555923619,0.023953542534915467
436
+ 392,PTEN_HUMAN_Fowler2018,gt,1.0,1.0,0.0
437
+ 393,PTEN_HUMAN_Fowler2018,MSA Transformer,0.47723620402030725,0.4753707747929236,0.02041283060478458
438
+ 394,PTEN_HUMAN_Fowler2018,PSSM,0.4856705789707024,0.48540163299274086,0.01456452062108191
439
+ 395,PTEN_HUMAN_Fowler2018,EVMutation (published),0.4719118285668927,0.471271072166362,0.0171946566182038
440
+ 396,PTEN_HUMAN_Fowler2018,DeepSequence (published) - single,0.3920133344336003,0.38858890670495655,0.021275758912234644
441
+ 397,PTEN_HUMAN_Fowler2018,DeepSequence (published),0.41987506342546416,0.4166267407337688,0.02048001735899819
442
+ 398,PTEN_HUMAN_Fowler2018,ESM-1v (zero shot),0.4229117460619157,0.4216791615081128,0.022889108923404226
443
+ 399,PTEN_HUMAN_Fowler2018,ESM-1v (+further training),0.39745119841802773,0.3945916752986646,0.021297362107723237
444
+ 400,PTEN_HUMAN_Fowler2018,DeepSequence (replicated),0.4305140142957644,0.4275242282868633,0.019725711174546957
445
+ 401,PTEN_HUMAN_Fowler2018,EVMutation (replicated),0.4562780374489617,0.4570343049276496,0.017322527192949605
446
+ 402,PTEN_HUMAN_Fowler2018,ProtBERT-BFD,0.33431387346212144,0.33179215244793264,0.020748503501032432
447
+ 403,PTEN_HUMAN_Fowler2018,TAPE,0.0815737781117076,0.07995492505287519,0.010503276183057134
448
+ 404,PTEN_HUMAN_Fowler2018,UniRep,0.12983006902884325,0.12588348859114926,0.014127656261654718
449
+ 405,PTEN_HUMAN_Fowler2018,ESM-1b,0.4531834407900847,0.4504022413646627,0.019849910120253392
450
+ 406,RASH_HUMAN_Kuriyan,gt,1.0,1.0,0.0
451
+ 407,RASH_HUMAN_Kuriyan,MSA Transformer,0.4803453272496495,0.47796060028078263,0.017296002593559925
452
+ 408,RASH_HUMAN_Kuriyan,PSSM,0.45403466334542103,0.45183098094027907,0.01787397783493158
453
+ 409,RASH_HUMAN_Kuriyan,EVMutation (published),0.426341747437809,0.4229653964620471,0.01796419071897713
454
+ 410,RASH_HUMAN_Kuriyan,DeepSequence (published) - single,0.4728843219749578,0.468646862737559,0.01795985229559378
455
+ 411,RASH_HUMAN_Kuriyan,DeepSequence (published),0.46630499110930534,0.4614459892414701,0.01844189066007253
456
+ 412,RASH_HUMAN_Kuriyan,ESM-1v (zero shot),0.40727875438677086,0.40514547710795606,0.019133507919327063
457
+ 413,RASH_HUMAN_Kuriyan,ESM-1v (+further training),0.4147935141888191,0.4135324566538796,0.019219555375441195
458
+ 414,RASH_HUMAN_Kuriyan,DeepSequence (replicated),0.4718463706052156,0.4693887363231767,0.01665373741632862
459
+ 415,RASH_HUMAN_Kuriyan,EVMutation (replicated),0.41905311471869217,0.4152533339275954,0.0186456211620091
460
+ 416,RASH_HUMAN_Kuriyan,ProtBERT-BFD,0.3754077679946978,0.37224319469530265,0.020828472200020876
461
+ 417,RASH_HUMAN_Kuriyan,TAPE,0.3410037149796282,0.33821305583243977,0.02006172500654845
462
+ 418,RASH_HUMAN_Kuriyan,UniRep,0.28316890117187576,0.2804521504745546,0.016931648162857683
463
+ 419,RASH_HUMAN_Kuriyan,ESM-1b,0.34359820576597994,0.3393198546702645,0.02233342505800977
464
+ 420,RL401_YEAST_Bolon2013,gt,1.0,1.0,0.0
465
+ 421,RL401_YEAST_Bolon2013,MSA Transformer,0.5393318004129806,0.539097206955352,0.021107284547232343
466
+ 422,RL401_YEAST_Bolon2013,PSSM,0.4115446821389685,0.4029967757216066,0.02694607790699914
467
+ 423,RL401_YEAST_Bolon2013,EVMutation (published),0.45052851516991577,0.44375165687449697,0.020730159359455567
468
+ 424,RL401_YEAST_Bolon2013,DeepSequence (published) - single,0.4749118165434772,0.4687082939023236,0.02394781384346245
469
+ 425,RL401_YEAST_Bolon2013,DeepSequence (published),0.4891069305943915,0.4832628867355531,0.020837235335480923
470
+ 426,RL401_YEAST_Bolon2013,ESM-1v (zero shot),0.3780305382545389,0.3758572950839938,0.024438101597142162
471
+ 427,RL401_YEAST_Bolon2013,ESM-1v (+further training),0.36982341765304827,0.36644542392899027,0.02407282307497699
472
+ 428,RL401_YEAST_Bolon2013,DeepSequence (replicated),0.4875479135136087,0.48185494209379953,0.0224889402600134
473
+ 429,RL401_YEAST_Bolon2013,EVMutation (replicated),0.4649054471564614,0.45886647149033805,0.023302945044134975
474
+ 430,RL401_YEAST_Bolon2013,ProtBERT-BFD,0.39888508524198757,0.39548316549478596,0.024888924809883948
475
+ 431,RL401_YEAST_Bolon2013,TAPE,0.14136362276356793,0.1330418322501083,0.03239530659402373
476
+ 432,RL401_YEAST_Bolon2013,UniRep,0.11132107785812106,0.10371964011546289,0.027489697230632073
477
+ 433,RL401_YEAST_Bolon2013,ESM-1b,0.24192958338903614,0.24085320243486236,0.026555927080409752
478
+ 504,TPK1_HUMAN_Roth2017,gt,1.0,1.0,0.0
479
+ 505,TPK1_HUMAN_Roth2017,MSA Transformer,0.3415408511396077,0.33848473630002246,0.021212292675018753
480
+ 506,TPK1_HUMAN_Roth2017,PSSM,0.22072657020579714,0.2217644870830699,0.02369863818079656
481
+ 507,TPK1_HUMAN_Roth2017,EVMutation (published),0.2469522178641623,0.24730841435573284,0.01871959166700927
482
+ 508,TPK1_HUMAN_Roth2017,DeepSequence (published) - single,0.2575167904390149,0.2558063144550207,0.02055476962559519
483
+ 509,TPK1_HUMAN_Roth2017,DeepSequence (published),0.25614519361128574,0.2543757481978049,0.021967216506252808
484
+ 510,TPK1_HUMAN_Roth2017,ESM-1v (zero shot),0.33312805710397364,0.327155968484034,0.019777338079982523
485
+ 511,TPK1_HUMAN_Roth2017,ESM-1v (+further training),0.3317814621900089,0.3260704249321161,0.020979034647608977
486
+ 512,TPK1_HUMAN_Roth2017,DeepSequence (replicated),0.254473186445843,0.2514295290110877,0.02177016005083741
487
+ 513,TPK1_HUMAN_Roth2017,EVMutation (replicated),0.23867041174072273,0.23850268855356252,0.019193703578397097
488
+ 514,TPK1_HUMAN_Roth2017,ProtBERT-BFD,0.24102052288064413,0.2413615342747228,0.021738163307345192
489
+ 515,TPK1_HUMAN_Roth2017,TAPE,0.08255844412157543,0.08001237804591124,0.014507842152561057
490
+ 516,TPK1_HUMAN_Roth2017,UniRep,0.03311972123416161,0.03305706490328286,0.021578991252520243
491
+ 517,TPK1_HUMAN_Roth2017,ESM-1b,0.31345297835126973,0.3093139122995233,0.01991362706272715
492
+ 448,RL401_YEAST_Fraser2016,gt,1.0,1.0,0.0
493
+ 449,RL401_YEAST_Fraser2016,MSA Transformer,0.47482528061086265,0.4755124342582121,0.022569966034399314
494
+ 450,RL401_YEAST_Fraser2016,PSSM,0.3774016009912691,0.3773571687306486,0.015993333803246766
495
+ 451,RL401_YEAST_Fraser2016,EVMutation (published),0.40924774479083326,0.414388594923377,0.023024753763437884
496
+ 452,RL401_YEAST_Fraser2016,DeepSequence (published) - single,0.4318166476420829,0.4331294439053056,0.01910722980495821
497
+ 453,RL401_YEAST_Fraser2016,DeepSequence (published),0.4461365210878178,0.44899827665090486,0.019914780607228476
498
+ 454,RL401_YEAST_Fraser2016,ESM-1v (zero shot),0.32760495384990906,0.3291822704728004,0.02640133685107885
499
+ 455,RL401_YEAST_Fraser2016,ESM-1v (+further training),0.32990765588855403,0.3301471135676151,0.027322775648250797
500
+ 456,RL401_YEAST_Fraser2016,DeepSequence (replicated),0.4347770704966268,0.44167537164330406,0.017646832557385868
501
+ 457,RL401_YEAST_Fraser2016,EVMutation (replicated),0.4137359503211986,0.42342848446020753,0.023604416626258205
502
+ 458,RL401_YEAST_Fraser2016,ProtBERT-BFD,0.352256182908315,0.35488121411289225,0.026464030488060585
503
+ 459,RL401_YEAST_Fraser2016,TAPE,0.11246047580054895,0.11267381281460156,0.029451868723884767
504
+ 460,RL401_YEAST_Fraser2016,UniRep,0.09228239837675453,0.0855139650342207,0.02787982622396566
505
+ 461,RL401_YEAST_Fraser2016,ESM-1b,0.20980461592629226,0.21406696973008782,0.028067024964270798
506
+ 168,CALM1_HUMAN_Roth2017,gt,1.0,1.0,0.0
507
+ 169,CALM1_HUMAN_Roth2017,MSA Transformer,0.23711821254687918,0.23943485564742276,0.03113662255833698
508
+ 170,CALM1_HUMAN_Roth2017,PSSM,0.1940025702015548,0.19913438415655305,0.02630867989950736
509
+ 171,CALM1_HUMAN_Roth2017,EVMutation (published),0.23244288732891077,0.23757839644300488,0.02612586314740137
510
+ 172,CALM1_HUMAN_Roth2017,DeepSequence (published) - single,0.22492618953594645,0.22906576202846649,0.030735041631348013
511
+ 173,CALM1_HUMAN_Roth2017,DeepSequence (published),0.22789905079105036,0.22969671581656934,0.029946806999461846
512
+ 174,CALM1_HUMAN_Roth2017,ESM-1v (zero shot),0.2617141623664426,0.2652270689648074,0.025228781176764935
513
+ 175,CALM1_HUMAN_Roth2017,ESM-1v (+further training),0.2721918164887156,0.2732936184582442,0.027420080243011954
514
+ 176,CALM1_HUMAN_Roth2017,DeepSequence (replicated),0.23307246773532486,0.23633457440270692,0.029771707595051294
515
+ 177,CALM1_HUMAN_Roth2017,EVMutation (replicated),0.23487698274177318,0.24137564501443426,0.02702788568104191
516
+ 178,CALM1_HUMAN_Roth2017,ProtBERT-BFD,0.29084218774026066,0.2918048272665779,0.027753008367247246
517
+ 179,CALM1_HUMAN_Roth2017,TAPE,0.12219793057831531,0.12415304964391952,0.019957547541863924
518
+ 180,CALM1_HUMAN_Roth2017,UniRep,0.07689880828775296,0.08034276883486069,0.028587576009811506
519
+ 181,CALM1_HUMAN_Roth2017,ESM-1b,0.24496865240057522,0.2451996389337371,0.02464309631183189
520
+ 434,RL401_YEAST_Bolon2014,gt,1.0,1.0,0.0
521
+ 435,RL401_YEAST_Bolon2014,MSA Transformer,0.473016586760016,0.4787538735227928,0.01635240282545988
522
+ 436,RL401_YEAST_Bolon2014,PSSM,0.4689225734723619,0.4737125791144366,0.018513489042818982
523
+ 437,RL401_YEAST_Bolon2014,EVMutation (published),0.39726026462632547,0.40239056557397346,0.0228080866519743
524
+ 438,RL401_YEAST_Bolon2014,DeepSequence (published) - single,0.4295635873940029,0.4359091171923386,0.020125832508895207
525
+ 439,RL401_YEAST_Bolon2014,DeepSequence (published),0.4226902253289641,0.4296887661396075,0.02042130768745852
526
+ 440,RL401_YEAST_Bolon2014,ESM-1v (zero shot),0.2555902509515176,0.26273723347289263,0.023433435512064758
527
+ 441,RL401_YEAST_Bolon2014,ESM-1v (+further training),0.30819485583382966,0.3149369605358795,0.022303272256952115
528
+ 442,RL401_YEAST_Bolon2014,DeepSequence (replicated),0.4208601802656798,0.427057708121087,0.022928982939476122
529
+ 443,RL401_YEAST_Bolon2014,EVMutation (replicated),0.3795164863252923,0.38353041172591634,0.022737389271498636
530
+ 444,RL401_YEAST_Bolon2014,ProtBERT-BFD,0.3305475177656725,0.33333306438483723,0.024066951141161263
531
+ 445,RL401_YEAST_Bolon2014,TAPE,0.27031483697506303,0.2748860791185031,0.023958009305355937
532
+ 446,RL401_YEAST_Bolon2014,UniRep,0.16611039235432376,0.16134631003484823,0.029548951247265007
533
+ 447,RL401_YEAST_Bolon2014,ESM-1b,0.18258453677698241,0.18424186541936532,0.02190939840845001
534
+ 28,B3VI55_LIPST_Whitehead2015,gt,1.0,1.0,0.0
535
+ 29,B3VI55_LIPST_Whitehead2015,MSA Transformer,0.25670663558953755,0.2568287164790948,0.014303617378529112
536
+ 30,B3VI55_LIPST_Whitehead2015,PSSM,0.17356487805783094,0.17229178651491212,0.014476649812023814
537
+ 31,B3VI55_LIPST_Whitehead2015,EVMutation (published),0.22415909454397737,0.22201195664151258,0.015151263735652506
538
+ 32,B3VI55_LIPST_Whitehead2015,DeepSequence (published) - single,0.2314762900256378,0.23010900979180499,0.015350637015825532
539
+ 33,B3VI55_LIPST_Whitehead2015,DeepSequence (published),0.2314408826509719,0.23018066970458023,0.015030815308284325
540
+ 34,B3VI55_LIPST_Whitehead2015,ESM-1v (zero shot),0.2361417829414803,0.235599751959246,0.01380734986895981
541
+ 35,B3VI55_LIPST_Whitehead2015,ESM-1v (+further training),0.2424504346933426,0.24107272979662708,0.013833009304666605
542
+ 36,B3VI55_LIPST_Whitehead2015,DeepSequence (replicated),0.24479443697061962,0.2433108240939475,0.015917153531149808
543
+ 37,B3VI55_LIPST_Whitehead2015,EVMutation (replicated),0.2251732484740546,0.2236926065862732,0.015150897486335867
544
+ 38,B3VI55_LIPST_Whitehead2015,ProtBERT-BFD,0.22029752268681757,0.22189350964142437,0.012296008345577645
545
+ 39,B3VI55_LIPST_Whitehead2015,TAPE,0.03217727698102332,0.033398754623545045,0.014930614521878988
546
+ 40,B3VI55_LIPST_Whitehead2015,UniRep,0.052410727620420754,0.051318677282283995,0.012063912744717856
547
+ 41,B3VI55_LIPST_Whitehead2015,ESM-1b,0.21414102345131894,0.21411325444647447,0.01376144270479094
548
+ 280,MK01_HUMAN_Johannessen,gt,1.0,1.0,0.0
549
+ 281,MK01_HUMAN_Johannessen,MSA Transformer,0.21600719562316348,0.21324362844208555,0.010869477909858859
550
+ 282,MK01_HUMAN_Johannessen,PSSM,0.24003601283569995,0.23781768411144993,0.012873462567914572
551
+ 283,MK01_HUMAN_Johannessen,EVMutation (published),0.2411806504637287,0.23555029839403527,0.014919109500043859
552
+ 284,MK01_HUMAN_Johannessen,DeepSequence (published) - single,0.21622583201496393,0.2118857875656635,0.01330985778159382
553
+ 285,MK01_HUMAN_Johannessen,DeepSequence (published),0.2262833888426422,0.2222242751773241,0.013845563303298817
554
+ 286,MK01_HUMAN_Johannessen,ESM-1v (zero shot),0.18610638097061274,0.1807887324699657,0.011421581908870595
555
+ 287,MK01_HUMAN_Johannessen,ESM-1v (+further training),0.1711612951379414,0.1656998628430867,0.011097399419126037
556
+ 288,MK01_HUMAN_Johannessen,DeepSequence (replicated),0.2262833888426422,0.2222242751773241,0.013845563303298817
557
+ 289,MK01_HUMAN_Johannessen,EVMutation (replicated),0.2411806504637287,0.23555029839403527,0.014919109500043859
558
+ 290,MK01_HUMAN_Johannessen,ProtBERT-BFD,0.03761357865712906,0.032009850323277314,0.013532258402167076
559
+ 291,MK01_HUMAN_Johannessen,TAPE,0.24566726233768266,0.2425196910807727,0.014722071012130074
560
+ 292,MK01_HUMAN_Johannessen,UniRep,0.16466166691457634,0.15865978272069822,0.012603347408739064
561
+ 293,MK01_HUMAN_Johannessen,ESM-1b,0.020968477238634434,0.014843912213619878,0.011595884022987897
562
+ 350,PA_FLU_Sun2015,gt,1.0,1.0,0.0
563
+ 351,PA_FLU_Sun2015,MSA Transformer,0.40499549570010246,0.4071708283839041,0.020127599355418007
564
+ 352,PA_FLU_Sun2015,PSSM,0.4870284991956425,0.48503558622411713,0.017254863079323307
565
+ 353,PA_FLU_Sun2015,EVMutation (published),0.4799931222249091,0.47963201439188896,0.017318908492685997
566
+ 354,PA_FLU_Sun2015,DeepSequence (published) - single,0.47395691140007384,0.47172219190050396,0.017516562617318692
567
+ 355,PA_FLU_Sun2015,DeepSequence (published),0.4782770520849889,0.4776150037730753,0.01692698104707
568
+ 356,PA_FLU_Sun2015,ESM-1v (zero shot),0.10354167707274801,0.10113956150869738,0.014997098538970815
569
+ 357,PA_FLU_Sun2015,ESM-1v (+further training),0.5736052915722709,0.5754278729569327,0.011947354137920797
570
+ 358,PA_FLU_Sun2015,DeepSequence (replicated),0.49574925840401,0.49600755923376527,0.014212454786638254
571
+ 359,PA_FLU_Sun2015,EVMutation (replicated),0.5055094042813111,0.5062333117389017,0.014772450707935335
572
+ 360,PA_FLU_Sun2015,ProtBERT-BFD,0.025567814891833348,0.028868599359005404,0.017475521452476987
573
+ 361,PA_FLU_Sun2015,TAPE,0.023351679974442957,0.02740069503679209,0.01716926448528921
574
+ 362,PA_FLU_Sun2015,UniRep,0.03233737793643953,0.030453300705534824,0.023348423732335796
575
+ 363,PA_FLU_Sun2015,ESM-1b,0.0350533539652243,0.03379222480788328,0.01958723862748923
model/README.md ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ # Local Model Source
2
+
3
+ This directory contains OneScience `models` sources that ESM imports directly.
4
+
5
+ - `esm/`: local copy of `onescience.models.esm`
6
+ - `openfold/`: local copy of `onescience.models.openfold`, required by ESMFold
7
+ - `protenix/layer_norm/`: optional fused layer norm dependency used by OpenFold when `LAYERNORM_TYPE=fast_layernorm`
8
+
9
+ Other OneScience namespaces such as `onescience.datapipes`, `onescience.modules`, and `onescience.utils` are intentionally imported from the installed OneScience environment.
10
+
model/__init__.py ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ """Local model packages copied from OneScience for the standalone ESM project."""
2
+
model/__pycache__/__init__.cpython-311.pyc ADDED
Binary file (269 Bytes). View file
 
model/esm/__init__.py ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright (c) Facebook, Inc. and its affiliates.
2
+ #
3
+ # This source code is licensed under the MIT license found in the
4
+ # LICENSE file in the root directory of this source tree.
5
+
6
+ from onescience.datapipes import esm as data # noqa
7
+ from onescience.datapipes.esm import Alphabet, BatchConverter, FastaBatchedDataset # noqa
8
+
9
+ from .version import version as __version__ # noqa
10
+ from .esm1 import ProteinBertModel # noqa
11
+ from .esm2 import ESM2 # noqa
12
+ from .msa_transformer import MSATransformer #noqa
13
+ from . import pretrained # noqa
model/esm/__pycache__/__init__.cpython-311.pyc ADDED
Binary file (689 Bytes). View file
 
model/esm/__pycache__/esm1.cpython-311.pyc ADDED
Binary file (10.1 kB). View file
 
model/esm/__pycache__/esm2.cpython-311.pyc ADDED
Binary file (6.71 kB). View file
 
model/esm/__pycache__/msa_transformer.cpython-311.pyc ADDED
Binary file (10.3 kB). View file
 
model/esm/__pycache__/pretrained.cpython-311.pyc ADDED
Binary file (29.9 kB). View file
 
model/esm/__pycache__/version.cpython-311.pyc ADDED
Binary file (201 Bytes). View file
 
model/esm/esm1.py ADDED
@@ -0,0 +1,200 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright (c) Meta Platforms, Inc. and affiliates.
2
+ #
3
+ # This source code is licensed under the MIT license found in the
4
+ # LICENSE file in the root directory of this source tree.
5
+
6
+ import math
7
+
8
+ import torch
9
+ import torch.nn as nn
10
+ import torch.nn.functional as F
11
+
12
+ from onescience.modules.esm import (
13
+ TransformerLayer,
14
+ LearnedPositionalEmbedding,
15
+ SinusoidalPositionalEmbedding,
16
+ RobertaLMHead,
17
+ ESM1bLayerNorm,
18
+ ContactPredictionHead,
19
+ )
20
+
21
+
22
+ class ProteinBertModel(nn.Module):
23
+ @classmethod
24
+ def add_args(cls, parser):
25
+ parser.add_argument(
26
+ "--num_layers", default=36, type=int, metavar="N", help="number of layers"
27
+ )
28
+ parser.add_argument(
29
+ "--embed_dim", default=1280, type=int, metavar="N", help="embedding dimension"
30
+ )
31
+ parser.add_argument(
32
+ "--logit_bias", action="store_true", help="whether to apply bias to logits"
33
+ )
34
+ parser.add_argument(
35
+ "--ffn_embed_dim",
36
+ default=5120,
37
+ type=int,
38
+ metavar="N",
39
+ help="embedding dimension for FFN",
40
+ )
41
+ parser.add_argument(
42
+ "--attention_heads",
43
+ default=20,
44
+ type=int,
45
+ metavar="N",
46
+ help="number of attention heads",
47
+ )
48
+
49
+ def __init__(self, args, alphabet):
50
+ super().__init__()
51
+ self.args = args
52
+ self.alphabet_size = len(alphabet)
53
+ self.padding_idx = alphabet.padding_idx
54
+ self.mask_idx = alphabet.mask_idx
55
+ self.cls_idx = alphabet.cls_idx
56
+ self.eos_idx = alphabet.eos_idx
57
+ self.prepend_bos = alphabet.prepend_bos
58
+ self.append_eos = alphabet.append_eos
59
+ self.emb_layer_norm_before = getattr(self.args, "emb_layer_norm_before", False)
60
+ if self.args.arch == "roberta_large":
61
+ self.model_version = "ESM-1b"
62
+ self._init_submodules_esm1b()
63
+ else:
64
+ self.model_version = "ESM-1"
65
+ self._init_submodules_esm1()
66
+
67
+ def _init_submodules_common(self):
68
+ self.embed_tokens = nn.Embedding(
69
+ self.alphabet_size, self.args.embed_dim, padding_idx=self.padding_idx
70
+ )
71
+ self.layers = nn.ModuleList(
72
+ [
73
+ TransformerLayer(
74
+ self.args.embed_dim,
75
+ self.args.ffn_embed_dim,
76
+ self.args.attention_heads,
77
+ add_bias_kv=(self.model_version != "ESM-1b"),
78
+ use_esm1b_layer_norm=(self.model_version == "ESM-1b"),
79
+ )
80
+ for _ in range(self.args.layers)
81
+ ]
82
+ )
83
+
84
+ self.contact_head = ContactPredictionHead(
85
+ self.args.layers * self.args.attention_heads,
86
+ self.prepend_bos,
87
+ self.append_eos,
88
+ eos_idx=self.eos_idx,
89
+ )
90
+
91
+ def _init_submodules_esm1b(self):
92
+ self._init_submodules_common()
93
+ self.embed_scale = 1
94
+ self.embed_positions = LearnedPositionalEmbedding(
95
+ self.args.max_positions, self.args.embed_dim, self.padding_idx
96
+ )
97
+ self.emb_layer_norm_before = (
98
+ ESM1bLayerNorm(self.args.embed_dim) if self.emb_layer_norm_before else None
99
+ )
100
+ self.emb_layer_norm_after = ESM1bLayerNorm(self.args.embed_dim)
101
+ self.lm_head = RobertaLMHead(
102
+ embed_dim=self.args.embed_dim,
103
+ output_dim=self.alphabet_size,
104
+ weight=self.embed_tokens.weight,
105
+ )
106
+
107
+ def _init_submodules_esm1(self):
108
+ self._init_submodules_common()
109
+ self.embed_scale = math.sqrt(self.args.embed_dim)
110
+ self.embed_positions = SinusoidalPositionalEmbedding(self.args.embed_dim, self.padding_idx)
111
+ self.embed_out = nn.Parameter(torch.zeros((self.alphabet_size, self.args.embed_dim)))
112
+ self.embed_out_bias = None
113
+ if self.args.final_bias:
114
+ self.embed_out_bias = nn.Parameter(torch.zeros(self.alphabet_size))
115
+
116
+ def forward(self, tokens, repr_layers=[], need_head_weights=False, return_contacts=False):
117
+ if return_contacts:
118
+ need_head_weights = True
119
+
120
+ assert tokens.ndim == 2
121
+ padding_mask = tokens.eq(self.padding_idx) # B, T
122
+
123
+ x = self.embed_scale * self.embed_tokens(tokens)
124
+
125
+ if getattr(self.args, "token_dropout", False):
126
+ x.masked_fill_((tokens == self.mask_idx).unsqueeze(-1), 0.0)
127
+ # x: B x T x C
128
+ mask_ratio_train = 0.15 * 0.8
129
+ src_lengths = (~padding_mask).sum(-1)
130
+ mask_ratio_observed = (tokens == self.mask_idx).sum(-1).float() / src_lengths
131
+ x = x * (1 - mask_ratio_train) / (1 - mask_ratio_observed)[:, None, None]
132
+
133
+ x = x + self.embed_positions(tokens)
134
+
135
+ if self.model_version == "ESM-1b":
136
+ if self.emb_layer_norm_before:
137
+ x = self.emb_layer_norm_before(x)
138
+ if padding_mask is not None:
139
+ x = x * (1 - padding_mask.unsqueeze(-1).type_as(x))
140
+
141
+ repr_layers = set(repr_layers)
142
+ hidden_representations = {}
143
+ if 0 in repr_layers:
144
+ hidden_representations[0] = x
145
+
146
+ if need_head_weights:
147
+ attn_weights = []
148
+
149
+ # (B, T, E) => (T, B, E)
150
+ x = x.transpose(0, 1)
151
+
152
+ if not padding_mask.any():
153
+ padding_mask = None
154
+
155
+ for layer_idx, layer in enumerate(self.layers):
156
+ x, attn = layer(
157
+ x, self_attn_padding_mask=padding_mask, need_head_weights=need_head_weights
158
+ )
159
+ if (layer_idx + 1) in repr_layers:
160
+ hidden_representations[layer_idx + 1] = x.transpose(0, 1)
161
+ if need_head_weights:
162
+ # (H, B, T, T) => (B, H, T, T)
163
+ attn_weights.append(attn.transpose(1, 0))
164
+
165
+ if self.model_version == "ESM-1b":
166
+ x = self.emb_layer_norm_after(x)
167
+ x = x.transpose(0, 1) # (T, B, E) => (B, T, E)
168
+
169
+ # last hidden representation should have layer norm applied
170
+ if (layer_idx + 1) in repr_layers:
171
+ hidden_representations[layer_idx + 1] = x
172
+ x = self.lm_head(x)
173
+ else:
174
+ x = F.linear(x, self.embed_out, bias=self.embed_out_bias)
175
+ x = x.transpose(0, 1) # (T, B, E) => (B, T, E)
176
+
177
+ result = {"logits": x, "representations": hidden_representations}
178
+ if need_head_weights:
179
+ # attentions: B x L x H x T x T
180
+ attentions = torch.stack(attn_weights, 1)
181
+ if self.model_version == "ESM-1":
182
+ # ESM-1 models have an additional null-token for attention, which we remove
183
+ attentions = attentions[..., :-1]
184
+ if padding_mask is not None:
185
+ attention_mask = 1 - padding_mask.type_as(attentions)
186
+ attention_mask = attention_mask.unsqueeze(1) * attention_mask.unsqueeze(2)
187
+ attentions = attentions * attention_mask[:, None, None, :, :]
188
+ result["attentions"] = attentions
189
+ if return_contacts:
190
+ contacts = self.contact_head(tokens, attentions)
191
+ result["contacts"] = contacts
192
+
193
+ return result
194
+
195
+ def predict_contacts(self, tokens):
196
+ return self(tokens, return_contacts=True)["contacts"]
197
+
198
+ @property
199
+ def num_layers(self):
200
+ return self.args.layers
model/esm/esm2.py ADDED
@@ -0,0 +1,152 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright (c) Meta Platforms, Inc. and affiliates.
2
+ #
3
+ # This source code is licensed under the MIT license found in the
4
+ # LICENSE file in the root directory of this source tree.
5
+
6
+ from typing import Union
7
+ import torch
8
+ import torch.nn as nn
9
+
10
+ from onescience.datapipes.esm import Alphabet
11
+ from onescience.modules.esm import (
12
+ ContactPredictionHead,
13
+ ESM1bLayerNorm,
14
+ RobertaLMHead,
15
+ TransformerLayer,
16
+ )
17
+
18
+
19
+ class ESM2(nn.Module):
20
+ def __init__(
21
+ self,
22
+ num_layers: int = 33,
23
+ embed_dim: int = 1280,
24
+ attention_heads: int = 20,
25
+ alphabet: Union[Alphabet, str] = "ESM-1b",
26
+ token_dropout: bool = True,
27
+ ):
28
+ super().__init__()
29
+ self.num_layers = num_layers
30
+ self.embed_dim = embed_dim
31
+ self.attention_heads = attention_heads
32
+ if not isinstance(alphabet, Alphabet):
33
+ alphabet = Alphabet.from_architecture(alphabet)
34
+ self.alphabet = alphabet
35
+ self.alphabet_size = len(alphabet)
36
+ self.padding_idx = alphabet.padding_idx
37
+ self.mask_idx = alphabet.mask_idx
38
+ self.cls_idx = alphabet.cls_idx
39
+ self.eos_idx = alphabet.eos_idx
40
+ self.prepend_bos = alphabet.prepend_bos
41
+ self.append_eos = alphabet.append_eos
42
+ self.token_dropout = token_dropout
43
+
44
+ self._init_submodules()
45
+
46
+ def _init_submodules(self):
47
+ self.embed_scale = 1
48
+ self.embed_tokens = nn.Embedding(
49
+ self.alphabet_size,
50
+ self.embed_dim,
51
+ padding_idx=self.padding_idx,
52
+ )
53
+
54
+ self.layers = nn.ModuleList(
55
+ [
56
+ TransformerLayer(
57
+ self.embed_dim,
58
+ 4 * self.embed_dim,
59
+ self.attention_heads,
60
+ add_bias_kv=False,
61
+ use_esm1b_layer_norm=True,
62
+ use_rotary_embeddings=True,
63
+ )
64
+ for _ in range(self.num_layers)
65
+ ]
66
+ )
67
+
68
+ self.contact_head = ContactPredictionHead(
69
+ self.num_layers * self.attention_heads,
70
+ self.prepend_bos,
71
+ self.append_eos,
72
+ eos_idx=self.eos_idx,
73
+ )
74
+ self.emb_layer_norm_after = ESM1bLayerNorm(self.embed_dim)
75
+
76
+ self.lm_head = RobertaLMHead(
77
+ embed_dim=self.embed_dim,
78
+ output_dim=self.alphabet_size,
79
+ weight=self.embed_tokens.weight,
80
+ )
81
+
82
+ def forward(self, tokens, repr_layers=[], need_head_weights=False, return_contacts=False):
83
+ if return_contacts:
84
+ need_head_weights = True
85
+
86
+ assert tokens.ndim == 2
87
+ padding_mask = tokens.eq(self.padding_idx) # B, T
88
+
89
+ x = self.embed_scale * self.embed_tokens(tokens)
90
+
91
+ if self.token_dropout:
92
+ x.masked_fill_((tokens == self.mask_idx).unsqueeze(-1), 0.0)
93
+ # x: B x T x C
94
+ mask_ratio_train = 0.15 * 0.8
95
+ src_lengths = (~padding_mask).sum(-1)
96
+ mask_ratio_observed = (tokens == self.mask_idx).sum(-1).to(x.dtype) / src_lengths
97
+ x = x * (1 - mask_ratio_train) / (1 - mask_ratio_observed)[:, None, None]
98
+
99
+ if padding_mask is not None:
100
+ x = x * (1 - padding_mask.unsqueeze(-1).type_as(x))
101
+
102
+ repr_layers = set(repr_layers)
103
+ hidden_representations = {}
104
+ if 0 in repr_layers:
105
+ hidden_representations[0] = x
106
+
107
+ if need_head_weights:
108
+ attn_weights = []
109
+
110
+ # (B, T, E) => (T, B, E)
111
+ x = x.transpose(0, 1)
112
+
113
+ if not padding_mask.any():
114
+ padding_mask = None
115
+
116
+ for layer_idx, layer in enumerate(self.layers):
117
+ x, attn = layer(
118
+ x,
119
+ self_attn_padding_mask=padding_mask,
120
+ need_head_weights=need_head_weights,
121
+ )
122
+ if (layer_idx + 1) in repr_layers:
123
+ hidden_representations[layer_idx + 1] = x.transpose(0, 1)
124
+ if need_head_weights:
125
+ # (H, B, T, T) => (B, H, T, T)
126
+ attn_weights.append(attn.transpose(1, 0))
127
+
128
+ x = self.emb_layer_norm_after(x)
129
+ x = x.transpose(0, 1) # (T, B, E) => (B, T, E)
130
+
131
+ # last hidden representation should have layer norm applied
132
+ if (layer_idx + 1) in repr_layers:
133
+ hidden_representations[layer_idx + 1] = x
134
+ x = self.lm_head(x)
135
+
136
+ result = {"logits": x, "representations": hidden_representations}
137
+ if need_head_weights:
138
+ # attentions: B x L x H x T x T
139
+ attentions = torch.stack(attn_weights, 1)
140
+ if padding_mask is not None:
141
+ attention_mask = 1 - padding_mask.type_as(attentions)
142
+ attention_mask = attention_mask.unsqueeze(1) * attention_mask.unsqueeze(2)
143
+ attentions = attentions * attention_mask[:, None, None, :, :]
144
+ result["attentions"] = attentions
145
+ if return_contacts:
146
+ contacts = self.contact_head(tokens, attentions)
147
+ result["contacts"] = contacts
148
+
149
+ return result
150
+
151
+ def predict_contacts(self, tokens):
152
+ return self(tokens, return_contacts=True)["contacts"]
model/esm/esmfold/__init__.py ADDED
File without changes
model/esm/esmfold/v1/__init__.py ADDED
File without changes
model/esm/esmfold/v1/categorical_mixture.py ADDED
@@ -0,0 +1,43 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright (c) Meta Platforms, Inc. and affiliates.
2
+ #
3
+ # This source code is licensed under the MIT license found in the
4
+ # LICENSE file in the root directory of this source tree.
5
+ import torch
6
+
7
+
8
+ class CategoricalMixture:
9
+ def __init__(self, param, bins=50, start=0, end=1):
10
+ # All tensors are of shape ..., bins.
11
+ self.logits = param
12
+ bins = torch.linspace(
13
+ start, end, bins + 1, device=self.logits.device, dtype=self.logits.dtype
14
+ )
15
+ self.v_bins = (bins[:-1] + bins[1:]) / 2
16
+
17
+ def log_prob(self, true):
18
+ # Shapes are:
19
+ # self.probs: ... x bins
20
+ # true : ...
21
+ true_index = (
22
+ (
23
+ true.unsqueeze(-1)
24
+ - self.v_bins[
25
+ [
26
+ None,
27
+ ]
28
+ * true.ndim
29
+ ]
30
+ )
31
+ .abs()
32
+ .argmin(-1)
33
+ )
34
+ nll = self.logits.log_softmax(-1)
35
+ return torch.take_along_dim(nll, true_index.unsqueeze(-1), dim=-1).squeeze(-1)
36
+
37
+ def mean(self):
38
+ return (self.logits.softmax(-1) @ self.v_bins.unsqueeze(1)).squeeze(-1)
39
+
40
+
41
+ def categorical_lddt(logits, bins=50):
42
+ # Logits are ..., 37, bins.
43
+ return CategoricalMixture(logits, bins=bins).mean()
model/esm/esmfold/v1/esmfold.py ADDED
@@ -0,0 +1,364 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright (c) Meta Platforms, Inc. and affiliates.
2
+ #
3
+ # This source code is licensed under the MIT license found in the
4
+ # LICENSE file in the root directory of this source tree.
5
+ import typing as T
6
+ from dataclasses import dataclass, field
7
+ from functools import partial
8
+
9
+ import torch
10
+ import torch.nn as nn
11
+ from torch import nn
12
+ from torch.nn import LayerNorm
13
+
14
+ import model.esm as esm
15
+ from model.esm import Alphabet
16
+ from model.esm.esmfold.v1.categorical_mixture import categorical_lddt
17
+ from model.esm.esmfold.v1.misc import (
18
+ batch_encode_sequences,
19
+ collate_dense_tensors,
20
+ output_to_pdb,
21
+ )
22
+ from model.esm.esmfold.v1.trunk import FoldingTrunk, FoldingTrunkConfig
23
+ from onescience.datapipes.openfold.data_transforms import make_atom14_masks
24
+ from onescience.utils.openfold.np import residue_constants
25
+ from onescience.utils.openfold.loss import compute_predicted_aligned_error, compute_tm
26
+
27
+
28
+ @dataclass
29
+ class ESMFoldConfig:
30
+ trunk: T.Any = field(default_factory=FoldingTrunkConfig)
31
+ lddt_head_hid_dim: int = 128
32
+
33
+
34
+ load_fn = esm.pretrained.load_model_and_alphabet
35
+ esm_registry = {
36
+ "esm2_8M": partial(load_fn, "esm2_t6_8M_UR50D_500K"),
37
+ "esm2_8M_270K": esm.pretrained.esm2_t6_8M_UR50D,
38
+ "esm2_35M": partial(load_fn, "esm2_t12_35M_UR50D_500K"),
39
+ "esm2_35M_270K": esm.pretrained.esm2_t12_35M_UR50D,
40
+ "esm2_150M": partial(load_fn, "esm2_t30_150M_UR50D_500K"),
41
+ "esm2_150M_270K": partial(load_fn, "esm2_t30_150M_UR50D_270K"),
42
+ "esm2_650M": esm.pretrained.esm2_t33_650M_UR50D,
43
+ "esm2_650M_270K": partial(load_fn, "esm2_t33_650M_270K_UR50D"),
44
+ "esm2_3B": esm.pretrained.esm2_t36_3B_UR50D,
45
+ "esm2_3B_270K": partial(load_fn, "esm2_t36_3B_UR50D_500K"),
46
+ "esm2_15B": esm.pretrained.esm2_t48_15B_UR50D,
47
+ }
48
+
49
+
50
+ class ESMFold(nn.Module):
51
+ def __init__(self, esmfold_config=None, **kwargs):
52
+ super().__init__()
53
+
54
+ self.cfg = esmfold_config if esmfold_config else ESMFoldConfig(**kwargs)
55
+ cfg = self.cfg
56
+
57
+ self.distogram_bins = 64
58
+
59
+ self.esm, self.esm_dict = esm_registry.get(cfg.esm_type)()
60
+
61
+ self.esm.requires_grad_(False)
62
+ self.esm.half()
63
+
64
+ self.esm_feats = self.esm.embed_dim
65
+ self.esm_attns = self.esm.num_layers * self.esm.attention_heads
66
+ self.register_buffer("af2_to_esm", ESMFold._af2_to_esm(self.esm_dict))
67
+ self.esm_s_combine = nn.Parameter(torch.zeros(self.esm.num_layers + 1))
68
+
69
+ c_s = cfg.trunk.sequence_state_dim
70
+ c_z = cfg.trunk.pairwise_state_dim
71
+
72
+ self.esm_s_mlp = nn.Sequential(
73
+ LayerNorm(self.esm_feats),
74
+ nn.Linear(self.esm_feats, c_s),
75
+ nn.ReLU(),
76
+ nn.Linear(c_s, c_s),
77
+ )
78
+ if cfg.use_esm_attn_map:
79
+ self.esm_z_mlp = nn.Sequential(
80
+ LayerNorm(self.esm_attns),
81
+ nn.Linear(self.esm_attns, c_z),
82
+ nn.ReLU(),
83
+ nn.Linear(c_z, c_z),
84
+ )
85
+
86
+ # 0 is padding, N is unknown residues, N + 1 is mask.
87
+ self.n_tokens_embed = residue_constants.restype_num + 3
88
+ self.pad_idx = 0
89
+ self.unk_idx = self.n_tokens_embed - 2
90
+ self.mask_idx = self.n_tokens_embed - 1
91
+ self.embedding = nn.Embedding(self.n_tokens_embed, c_s, padding_idx=0)
92
+
93
+ self.trunk = FoldingTrunk(**cfg.trunk)
94
+
95
+ self.distogram_head = nn.Linear(c_z, self.distogram_bins)
96
+ self.ptm_head = nn.Linear(c_z, self.distogram_bins)
97
+ self.lm_head = nn.Linear(c_s, self.n_tokens_embed)
98
+ self.lddt_bins = 50
99
+ self.lddt_head = nn.Sequential(
100
+ nn.LayerNorm(cfg.trunk.structure_module.c_s),
101
+ nn.Linear(cfg.trunk.structure_module.c_s, cfg.lddt_head_hid_dim),
102
+ nn.Linear(cfg.lddt_head_hid_dim, cfg.lddt_head_hid_dim),
103
+ nn.Linear(cfg.lddt_head_hid_dim, 37 * self.lddt_bins),
104
+ )
105
+
106
+ @staticmethod
107
+ def _af2_to_esm(d: Alphabet):
108
+ # Remember that t is shifted from residue_constants by 1 (0 is padding).
109
+ esm_reorder = [d.padding_idx] + [
110
+ d.get_idx(v) for v in residue_constants.restypes_with_x
111
+ ]
112
+ return torch.tensor(esm_reorder)
113
+
114
+ def _af2_idx_to_esm_idx(self, aa, mask):
115
+ aa = (aa + 1).masked_fill(mask != 1, 0)
116
+ return self.af2_to_esm[aa]
117
+
118
+ def _compute_language_model_representations(
119
+ self, esmaa: torch.Tensor
120
+ ) -> torch.Tensor:
121
+ """Adds bos/eos tokens for the language model, since the structure module doesn't use these."""
122
+ batch_size = esmaa.size(0)
123
+
124
+ bosi, eosi = self.esm_dict.cls_idx, self.esm_dict.eos_idx
125
+ bos = esmaa.new_full((batch_size, 1), bosi)
126
+ eos = esmaa.new_full((batch_size, 1), self.esm_dict.padding_idx)
127
+ esmaa = torch.cat([bos, esmaa, eos], dim=1)
128
+ # Use the first padding index as eos during inference.
129
+ esmaa[range(batch_size), (esmaa != 1).sum(1)] = eosi
130
+
131
+ res = self.esm(
132
+ esmaa,
133
+ repr_layers=range(self.esm.num_layers + 1),
134
+ need_head_weights=self.cfg.use_esm_attn_map,
135
+ )
136
+ esm_s = torch.stack(
137
+ [v for _, v in sorted(res["representations"].items())], dim=2
138
+ )
139
+ esm_s = esm_s[:, 1:-1] # B, L, nLayers, C
140
+ esm_z = (
141
+ res["attentions"].permute(0, 4, 3, 1, 2).flatten(3, 4)[:, 1:-1, 1:-1, :]
142
+ if self.cfg.use_esm_attn_map
143
+ else None
144
+ )
145
+ return esm_s, esm_z
146
+
147
+ def _mask_inputs_to_esm(self, esmaa, pattern):
148
+ new_esmaa = esmaa.clone()
149
+ new_esmaa[pattern == 1] = self.esm_dict.mask_idx
150
+ return new_esmaa
151
+
152
+ def forward(
153
+ self,
154
+ aa: torch.Tensor,
155
+ mask: T.Optional[torch.Tensor] = None,
156
+ residx: T.Optional[torch.Tensor] = None,
157
+ masking_pattern: T.Optional[torch.Tensor] = None,
158
+ num_recycles: T.Optional[int] = None,
159
+ ):
160
+ """Runs a forward pass given input tokens. Use `model.infer` to
161
+ run inference from a sequence.
162
+
163
+ Args:
164
+ aa (torch.Tensor): Tensor containing indices corresponding to amino acids. Indices match
165
+ onescience.utils.openfold.np.residue_constants.restype_order_with_x.
166
+ mask (torch.Tensor): Binary tensor with 1 meaning position is unmasked and 0 meaning position is masked.
167
+ residx (torch.Tensor): Residue indices of amino acids. Will assume contiguous if not provided.
168
+ masking_pattern (torch.Tensor): Optional masking to pass to the input. Binary tensor of the same size
169
+ as `aa`. Positions with 1 will be masked. ESMFold sometimes produces different samples when
170
+ different masks are provided.
171
+ num_recycles (int): How many recycle iterations to perform. If None, defaults to training max
172
+ recycles, which is 3.
173
+ """
174
+
175
+ if mask is None:
176
+ mask = torch.ones_like(aa)
177
+
178
+ B = aa.shape[0]
179
+ L = aa.shape[1]
180
+ device = aa.device
181
+
182
+ if residx is None:
183
+ residx = torch.arange(L, device=device).expand_as(aa)
184
+
185
+ # === ESM ===
186
+ esmaa = self._af2_idx_to_esm_idx(aa, mask)
187
+
188
+ if masking_pattern is not None:
189
+ esmaa = self._mask_inputs_to_esm(esmaa, masking_pattern)
190
+
191
+ esm_s, esm_z = self._compute_language_model_representations(esmaa)
192
+
193
+ # Convert esm_s to the precision used by the trunk and
194
+ # the structure module. These tensors may be a lower precision if, for example,
195
+ # we're running the language model in fp16 precision.
196
+ esm_s = esm_s.to(self.esm_s_combine.dtype)
197
+ esm_s = esm_s.detach()
198
+
199
+ # === preprocessing ===
200
+ esm_s = (self.esm_s_combine.softmax(0).unsqueeze(0) @ esm_s).squeeze(2)
201
+
202
+ s_s_0 = self.esm_s_mlp(esm_s)
203
+ if self.cfg.use_esm_attn_map:
204
+ esm_z = esm_z.to(self.esm_s_combine.dtype)
205
+ esm_z = esm_z.detach()
206
+ s_z_0 = self.esm_z_mlp(esm_z)
207
+ else:
208
+ s_z_0 = s_s_0.new_zeros(B, L, L, self.cfg.trunk.pairwise_state_dim)
209
+
210
+ s_s_0 += self.embedding(aa)
211
+
212
+ structure: dict = self.trunk(
213
+ s_s_0, s_z_0, aa, residx, mask, no_recycles=num_recycles
214
+ )
215
+ # Documenting what we expect:
216
+ structure = {
217
+ k: v
218
+ for k, v in structure.items()
219
+ if k
220
+ in [
221
+ "s_z",
222
+ "s_s",
223
+ "frames",
224
+ "sidechain_frames",
225
+ "unnormalized_angles",
226
+ "angles",
227
+ "positions",
228
+ "states",
229
+ ]
230
+ }
231
+
232
+ disto_logits = self.distogram_head(structure["s_z"])
233
+ disto_logits = (disto_logits + disto_logits.transpose(1, 2)) / 2
234
+ structure["distogram_logits"] = disto_logits
235
+
236
+ lm_logits = self.lm_head(structure["s_s"])
237
+ structure["lm_logits"] = lm_logits
238
+
239
+ structure["aatype"] = aa
240
+ make_atom14_masks(structure)
241
+
242
+ for k in [
243
+ "atom14_atom_exists",
244
+ "atom37_atom_exists",
245
+ ]:
246
+ structure[k] *= mask.unsqueeze(-1)
247
+ structure["residue_index"] = residx
248
+
249
+ lddt_head = self.lddt_head(structure["states"]).reshape(
250
+ structure["states"].shape[0], B, L, -1, self.lddt_bins
251
+ )
252
+ structure["lddt_head"] = lddt_head
253
+ plddt = categorical_lddt(lddt_head[-1], bins=self.lddt_bins)
254
+ structure["plddt"] = (
255
+ 100 * plddt
256
+ ) # we predict plDDT between 0 and 1, scale to be between 0 and 100.
257
+
258
+ ptm_logits = self.ptm_head(structure["s_z"])
259
+
260
+ seqlen = mask.type(torch.int64).sum(1)
261
+ structure["ptm_logits"] = ptm_logits
262
+ structure["ptm"] = torch.stack(
263
+ [
264
+ compute_tm(
265
+ batch_ptm_logits[None, :sl, :sl],
266
+ max_bins=31,
267
+ no_bins=self.distogram_bins,
268
+ )
269
+ for batch_ptm_logits, sl in zip(ptm_logits, seqlen)
270
+ ]
271
+ )
272
+ structure.update(
273
+ compute_predicted_aligned_error(
274
+ ptm_logits, max_bin=31, no_bins=self.distogram_bins
275
+ )
276
+ )
277
+
278
+ return structure
279
+
280
+ @torch.no_grad()
281
+ def infer(
282
+ self,
283
+ sequences: T.Union[str, T.List[str]],
284
+ residx=None,
285
+ masking_pattern: T.Optional[torch.Tensor] = None,
286
+ num_recycles: T.Optional[int] = None,
287
+ residue_index_offset: T.Optional[int] = 512,
288
+ chain_linker: T.Optional[str] = "G" * 25,
289
+ ):
290
+ """Runs a forward pass given input sequences.
291
+
292
+ Args:
293
+ sequences (Union[str, List[str]]): A list of sequences to make predictions for. Multimers can also be passed in,
294
+ each chain should be separated by a ':' token (e.g. "<chain1>:<chain2>:<chain3>").
295
+ residx (torch.Tensor): Residue indices of amino acids. Will assume contiguous if not provided.
296
+ masking_pattern (torch.Tensor): Optional masking to pass to the input. Binary tensor of the same size
297
+ as `aa`. Positions with 1 will be masked. ESMFold sometimes produces different samples when
298
+ different masks are provided.
299
+ num_recycles (int): How many recycle iterations to perform. If None, defaults to training max
300
+ recycles (cfg.trunk.max_recycles), which is 4.
301
+ residue_index_offset (int): Residue index separation between chains if predicting a multimer. Has no effect on
302
+ single chain predictions. Default: 512.
303
+ chain_linker (str): Linker to use between chains if predicting a multimer. Has no effect on single chain
304
+ predictions. Default: length-25 poly-G ("G" * 25).
305
+ """
306
+ if isinstance(sequences, str):
307
+ sequences = [sequences]
308
+
309
+ aatype, mask, _residx, linker_mask, chain_index = batch_encode_sequences(
310
+ sequences, residue_index_offset, chain_linker
311
+ )
312
+
313
+ if residx is None:
314
+ residx = _residx
315
+ elif not isinstance(residx, torch.Tensor):
316
+ residx = collate_dense_tensors(residx)
317
+
318
+ aatype, mask, residx, linker_mask = map(
319
+ lambda x: x.to(self.device), (aatype, mask, residx, linker_mask)
320
+ )
321
+
322
+ output = self.forward(
323
+ aatype,
324
+ mask=mask,
325
+ residx=residx,
326
+ masking_pattern=masking_pattern,
327
+ num_recycles=num_recycles,
328
+ )
329
+
330
+ output["atom37_atom_exists"] = output[
331
+ "atom37_atom_exists"
332
+ ] * linker_mask.unsqueeze(2)
333
+
334
+ output["mean_plddt"] = (output["plddt"] * output["atom37_atom_exists"]).sum(
335
+ dim=(1, 2)
336
+ ) / output["atom37_atom_exists"].sum(dim=(1, 2))
337
+ output["chain_index"] = chain_index
338
+
339
+ return output
340
+
341
+ def output_to_pdb(self, output: T.Dict) -> T.List[str]:
342
+ """Returns the pbd (file) string from the model given the model output."""
343
+ return output_to_pdb(output)
344
+
345
+ def infer_pdbs(self, seqs: T.List[str], *args, **kwargs) -> T.List[str]:
346
+ """Returns list of pdb (files) strings from the model given a list of input sequences."""
347
+ output = self.infer(seqs, *args, **kwargs)
348
+ return self.output_to_pdb(output)
349
+
350
+ def infer_pdb(self, sequence: str, *args, **kwargs) -> str:
351
+ """Returns the pdb (file) string from the model given an input sequence."""
352
+ return self.infer_pdbs([sequence], *args, **kwargs)[0]
353
+
354
+ def set_chunk_size(self, chunk_size: T.Optional[int]):
355
+ # This parameter means the axial attention will be computed
356
+ # in a chunked manner. This should make the memory used more or less O(L) instead of O(L^2).
357
+ # It's equivalent to running a for loop over chunks of the dimension we're iterative over,
358
+ # where the chunk_size is the size of the chunks, so 128 would mean to parse 128-lengthed chunks.
359
+ # Setting the value to None will return to default behavior, disable chunking.
360
+ self.trunk.set_chunk_size(chunk_size)
361
+
362
+ @property
363
+ def device(self):
364
+ return self.esm_s_combine.device
model/esm/esmfold/v1/misc.py ADDED
@@ -0,0 +1,309 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright (c) Meta Platforms, Inc. and affiliates.
2
+ #
3
+ # This source code is licensed under the MIT license found in the
4
+ # LICENSE file in the root directory of this source tree.
5
+ import typing as T
6
+
7
+ import numpy as np
8
+ import torch
9
+ import torch.nn.functional as F
10
+ from einops import rearrange, repeat
11
+ from torch import nn
12
+ from onescience.utils.openfold.np import residue_constants
13
+ from onescience.utils.openfold.np.protein import Protein as OFProtein
14
+ from onescience.utils.openfold.np.protein import to_pdb
15
+ from onescience.utils.openfold.feats import atom14_to_atom37
16
+
17
+
18
+ def encode_sequence(
19
+ seq: str,
20
+ residue_index_offset: T.Optional[int] = 512,
21
+ chain_linker: T.Optional[str] = "G" * 25,
22
+ ) -> T.Tuple[torch.Tensor, torch.Tensor, torch.Tensor, torch.Tensor]:
23
+ if chain_linker is None:
24
+ chain_linker = ""
25
+ if residue_index_offset is None:
26
+ residue_index_offset = 0
27
+
28
+ chains = seq.split(":")
29
+ seq = chain_linker.join(chains)
30
+
31
+ unk_idx = residue_constants.restype_order_with_x["X"]
32
+ encoded = torch.tensor(
33
+ [residue_constants.restype_order_with_x.get(aa, unk_idx) for aa in seq]
34
+ )
35
+ residx = torch.arange(len(encoded))
36
+
37
+ if residue_index_offset > 0:
38
+ start = 0
39
+ for i, chain in enumerate(chains):
40
+ residx[start : start + len(chain) + len(chain_linker)] += (
41
+ i * residue_index_offset
42
+ )
43
+ start += len(chain) + len(chain_linker)
44
+
45
+ linker_mask = torch.ones_like(encoded, dtype=torch.float32)
46
+ chain_index = []
47
+ offset = 0
48
+ for i, chain in enumerate(chains):
49
+ if i > 0:
50
+ chain_index.extend([i - 1] * len(chain_linker))
51
+ chain_index.extend([i] * len(chain))
52
+ offset += len(chain)
53
+ linker_mask[offset : offset + len(chain_linker)] = 0
54
+ offset += len(chain_linker)
55
+
56
+ chain_index = torch.tensor(chain_index, dtype=torch.int64)
57
+
58
+ return encoded, residx, linker_mask, chain_index
59
+
60
+
61
+ def batch_encode_sequences(
62
+ sequences: T.Sequence[str],
63
+ residue_index_offset: T.Optional[int] = 512,
64
+ chain_linker: T.Optional[str] = "G" * 25,
65
+ ) -> T.Tuple[torch.Tensor, torch.Tensor, torch.Tensor, torch.Tensor, torch.Tensor]:
66
+
67
+ aatype_list = []
68
+ residx_list = []
69
+ linker_mask_list = []
70
+ chain_index_list = []
71
+ for seq in sequences:
72
+ aatype_seq, residx_seq, linker_mask_seq, chain_index_seq = encode_sequence(
73
+ seq,
74
+ residue_index_offset=residue_index_offset,
75
+ chain_linker=chain_linker,
76
+ )
77
+ aatype_list.append(aatype_seq)
78
+ residx_list.append(residx_seq)
79
+ linker_mask_list.append(linker_mask_seq)
80
+ chain_index_list.append(chain_index_seq)
81
+
82
+ aatype = collate_dense_tensors(aatype_list)
83
+ mask = collate_dense_tensors(
84
+ [aatype.new_ones(len(aatype_seq)) for aatype_seq in aatype_list]
85
+ )
86
+ residx = collate_dense_tensors(residx_list)
87
+ linker_mask = collate_dense_tensors(linker_mask_list)
88
+ chain_index_list = collate_dense_tensors(chain_index_list, -1)
89
+
90
+ return aatype, mask, residx, linker_mask, chain_index_list
91
+
92
+
93
+ def output_to_pdb(output: T.Dict) -> T.List[str]:
94
+ """Returns the pbd (file) string from the model given the model output."""
95
+ # atom14_to_atom37 must be called first, as it fails on latest numpy if the
96
+ # input is a numpy array. It will work if the input is a torch tensor.
97
+ final_atom_positions = atom14_to_atom37(output["positions"][-1], output)
98
+ output = {k: v.to("cpu").numpy() for k, v in output.items()}
99
+ final_atom_positions = final_atom_positions.cpu().numpy()
100
+ final_atom_mask = output["atom37_atom_exists"]
101
+ pdbs = []
102
+ for i in range(output["aatype"].shape[0]):
103
+ aa = output["aatype"][i]
104
+ pred_pos = final_atom_positions[i]
105
+ mask = final_atom_mask[i]
106
+ resid = output["residue_index"][i] + 1
107
+ pred = OFProtein(
108
+ aatype=aa,
109
+ atom_positions=pred_pos,
110
+ atom_mask=mask,
111
+ residue_index=resid,
112
+ b_factors=output["plddt"][i],
113
+ chain_index=output["chain_index"][i] if "chain_index" in output else None,
114
+ )
115
+ pdbs.append(to_pdb(pred))
116
+ return pdbs
117
+
118
+
119
+ def collate_dense_tensors(
120
+ samples: T.List[torch.Tensor], pad_v: float = 0
121
+ ) -> torch.Tensor:
122
+ """
123
+ Takes a list of tensors with the following dimensions:
124
+ [(d_11, ..., d_1K),
125
+ (d_21, ..., d_2K),
126
+ ...,
127
+ (d_N1, ..., d_NK)]
128
+ and stack + pads them into a single tensor of:
129
+ (N, max_i=1,N { d_i1 }, ..., max_i=1,N {diK})
130
+ """
131
+ if len(samples) == 0:
132
+ return torch.Tensor()
133
+ if len(set(x.dim() for x in samples)) != 1:
134
+ raise RuntimeError(
135
+ f"Samples has varying dimensions: {[x.dim() for x in samples]}"
136
+ )
137
+ (device,) = tuple(set(x.device for x in samples)) # assumes all on same device
138
+ max_shape = [max(lst) for lst in zip(*[x.shape for x in samples])]
139
+ result = torch.empty(
140
+ len(samples), *max_shape, dtype=samples[0].dtype, device=device
141
+ )
142
+ result.fill_(pad_v)
143
+ for i in range(len(samples)):
144
+ result_i = result[i]
145
+ t = samples[i]
146
+ result_i[tuple(slice(0, k) for k in t.shape)] = t
147
+ return result
148
+
149
+
150
+ class Attention(nn.Module):
151
+ def __init__(self, embed_dim, num_heads, head_width, gated=False):
152
+ super().__init__()
153
+ assert embed_dim == num_heads * head_width
154
+
155
+ self.embed_dim = embed_dim
156
+ self.num_heads = num_heads
157
+ self.head_width = head_width
158
+
159
+ self.proj = nn.Linear(embed_dim, embed_dim * 3, bias=False)
160
+ self.o_proj = nn.Linear(embed_dim, embed_dim, bias=True)
161
+ self.gated = gated
162
+ if gated:
163
+ self.g_proj = nn.Linear(embed_dim, embed_dim)
164
+ torch.nn.init.zeros_(self.g_proj.weight)
165
+ torch.nn.init.ones_(self.g_proj.bias)
166
+
167
+ self.rescale_factor = self.head_width**-0.5
168
+
169
+ torch.nn.init.zeros_(self.o_proj.bias)
170
+
171
+ def forward(self, x, mask=None, bias=None, indices=None):
172
+ """
173
+ Basic self attention with optional mask and external pairwise bias.
174
+ To handle sequences of different lengths, use mask.
175
+
176
+ Inputs:
177
+ x: batch of input sequneces (.. x L x C)
178
+ mask: batch of boolean masks where 1=valid, 0=padding position (.. x L_k). optional.
179
+ bias: batch of scalar pairwise attention biases (.. x Lq x Lk x num_heads). optional.
180
+
181
+ Outputs:
182
+ sequence projection (B x L x embed_dim), attention maps (B x L x L x num_heads)
183
+ """
184
+
185
+ t = rearrange(self.proj(x), "... l (h c) -> ... h l c", h=self.num_heads)
186
+ q, k, v = t.chunk(3, dim=-1)
187
+
188
+ q = self.rescale_factor * q
189
+ a = torch.einsum("...qc,...kc->...qk", q, k)
190
+
191
+ # Add external attention bias.
192
+ if bias is not None:
193
+ a = a + rearrange(bias, "... lq lk h -> ... h lq lk")
194
+
195
+ # Do not attend to padding tokens.
196
+ if mask is not None:
197
+ mask = repeat(
198
+ mask, "... lk -> ... h lq lk", h=self.num_heads, lq=q.shape[-2]
199
+ )
200
+ a = a.masked_fill(mask == False, -np.inf)
201
+
202
+ a = F.softmax(a, dim=-1)
203
+
204
+ y = torch.einsum("...hqk,...hkc->...qhc", a, v)
205
+ y = rearrange(y, "... h c -> ... (h c)", h=self.num_heads)
206
+
207
+ if self.gated:
208
+ y = self.g_proj(x).sigmoid() * y
209
+ y = self.o_proj(y)
210
+
211
+ return y, rearrange(a, "... lq lk h -> ... h lq lk")
212
+
213
+
214
+ class Dropout(nn.Module):
215
+ """
216
+ Implementation of dropout with the ability to share the dropout mask
217
+ along a particular dimension.
218
+ """
219
+
220
+ def __init__(self, r: float, batch_dim: T.Union[int, T.List[int]]):
221
+ super(Dropout, self).__init__()
222
+
223
+ self.r = r
224
+ if type(batch_dim) == int:
225
+ batch_dim = [batch_dim]
226
+ self.batch_dim = batch_dim
227
+ self.dropout = nn.Dropout(self.r)
228
+
229
+ def forward(self, x: torch.Tensor) -> torch.Tensor:
230
+ shape = list(x.shape)
231
+ if self.batch_dim is not None:
232
+ for bd in self.batch_dim:
233
+ shape[bd] = 1
234
+ return x * self.dropout(x.new_ones(shape))
235
+
236
+
237
+ class SequenceToPair(nn.Module):
238
+ def __init__(self, sequence_state_dim, inner_dim, pairwise_state_dim):
239
+ super().__init__()
240
+
241
+ self.layernorm = nn.LayerNorm(sequence_state_dim)
242
+ self.proj = nn.Linear(sequence_state_dim, inner_dim * 2, bias=True)
243
+ self.o_proj = nn.Linear(2 * inner_dim, pairwise_state_dim, bias=True)
244
+
245
+ torch.nn.init.zeros_(self.proj.bias)
246
+ torch.nn.init.zeros_(self.o_proj.bias)
247
+
248
+ def forward(self, sequence_state):
249
+ """
250
+ Inputs:
251
+ sequence_state: B x L x sequence_state_dim
252
+
253
+ Output:
254
+ pairwise_state: B x L x L x pairwise_state_dim
255
+
256
+ Intermediate state:
257
+ B x L x L x 2*inner_dim
258
+ """
259
+
260
+ assert len(sequence_state.shape) == 3
261
+
262
+ s = self.layernorm(sequence_state)
263
+ s = self.proj(s)
264
+ q, k = s.chunk(2, dim=-1)
265
+
266
+ prod = q[:, None, :, :] * k[:, :, None, :]
267
+ diff = q[:, None, :, :] - k[:, :, None, :]
268
+
269
+ x = torch.cat([prod, diff], dim=-1)
270
+ x = self.o_proj(x)
271
+
272
+ return x
273
+
274
+
275
+ class PairToSequence(nn.Module):
276
+ def __init__(self, pairwise_state_dim, num_heads):
277
+ super().__init__()
278
+
279
+ self.layernorm = nn.LayerNorm(pairwise_state_dim)
280
+ self.linear = nn.Linear(pairwise_state_dim, num_heads, bias=False)
281
+
282
+ def forward(self, pairwise_state):
283
+ """
284
+ Inputs:
285
+ pairwise_state: B x L x L x pairwise_state_dim
286
+
287
+ Output:
288
+ pairwise_bias: B x L x L x num_heads
289
+ """
290
+ assert len(pairwise_state.shape) == 4
291
+ z = self.layernorm(pairwise_state)
292
+ pairwise_bias = self.linear(z)
293
+ return pairwise_bias
294
+
295
+
296
+ class ResidueMLP(nn.Module):
297
+ def __init__(self, embed_dim, inner_dim, norm=nn.LayerNorm, dropout=0):
298
+ super().__init__()
299
+
300
+ self.mlp = nn.Sequential(
301
+ norm(embed_dim),
302
+ nn.Linear(embed_dim, inner_dim),
303
+ nn.ReLU(),
304
+ nn.Linear(inner_dim, embed_dim),
305
+ nn.Dropout(dropout),
306
+ )
307
+
308
+ def forward(self, x):
309
+ return x + self.mlp(x)
model/esm/esmfold/v1/pretrained.py ADDED
@@ -0,0 +1,197 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ # This source code is licensed under the MIT license found in the
4
+ # LICENSE file in the root directory of this source tree.
5
+
6
+ from pathlib import Path
7
+
8
+ import torch
9
+
10
+ from model.esm.esmfold.v1.esmfold import ESMFold
11
+
12
+ def _upgrade_state_dict(model_state):
13
+ """Map legacy ESMFold checkpoint keys to the current OpenFold modules."""
14
+ point_projection_prefixes = (
15
+ "trunk.structure_module.ipa.linear_q_points",
16
+ "trunk.structure_module.ipa.linear_kv_points",
17
+ "trunk.structure_module.ipa.linear_k_points",
18
+ "trunk.structure_module.ipa.linear_v_points",
19
+ )
20
+ for prefix in point_projection_prefixes:
21
+ for suffix in ("weight", "bias"):
22
+ old_key = f"{prefix}.{suffix}"
23
+ new_key = f"{prefix}.linear.{suffix}"
24
+ if old_key in model_state and new_key not in model_state:
25
+ model_state[new_key] = model_state.pop(old_key)
26
+ return model_state
27
+
28
+ def _load_model(model_name):
29
+ if model_name.endswith(".pt"): # local, treat as filepath
30
+ model_path = Path(model_name)
31
+ model_data = torch.load(str(model_path), map_location="cpu")
32
+ else: # load from hub
33
+ url = f"https://dl.fbaipublicfiles.com/fair-esm/models/{model_name}.pt"
34
+ model_data = torch.hub.load_state_dict_from_url(url, progress=False, map_location="cpu")
35
+
36
+ cfg = model_data["cfg"]["model"]
37
+ model_state = _upgrade_state_dict(model_data["model"])
38
+ # model_state = model_data["model"]
39
+ model = ESMFold(esmfold_config=cfg)
40
+
41
+ expected_keys = set(model.state_dict().keys())
42
+ found_keys = set(model_state.keys())
43
+
44
+ missing_essential_keys = []
45
+ for missing_key in expected_keys - found_keys:
46
+ if not missing_key.startswith("esm."):
47
+ missing_essential_keys.append(missing_key)
48
+
49
+ if missing_essential_keys:
50
+ raise RuntimeError(f"Keys '{', '.join(missing_essential_keys)}' are missing.")
51
+
52
+ model.load_state_dict(model_state, strict=False)
53
+
54
+ return model
55
+
56
+
57
+ def esmfold_v0():
58
+ """
59
+ ESMFold v0 model with 3B ESM-2, 48 folding blocks.
60
+ This version was used for the paper (Lin et al, 2022). It was trained
61
+ on all PDB chains until 2020-05, to ensure temporal holdout with CASP14
62
+ and the CAMEO validation and test set reported there.
63
+ """
64
+ return _load_model("esmfold_3B_v0")
65
+
66
+
67
+ def esmfold_v1():
68
+ """
69
+ ESMFold v1 model using 3B ESM-2, 48 folding blocks.
70
+ ESMFold provides fast high accuracy atomic level structure prediction
71
+ directly from the individual sequence of a protein. ESMFold uses the ESM2
72
+ protein language model to extract meaningful representations from the
73
+ protein sequence.
74
+ """
75
+ return _load_model("esmfold_3B_v1")
76
+
77
+
78
+ def esmfold_structure_module_only_8M():
79
+ """
80
+ ESMFold baseline model using 8M ESM-2, 0 folding blocks.
81
+ ESM-2 here is trained out to 500K updates.
82
+ This is a model designed to test the capabilities of the language model
83
+ when ablated for number of parameters in the language model.
84
+ See table S1 in (Lin et al, 2022).
85
+ """
86
+ return _load_model("esmfold_structure_module_only_8M")
87
+
88
+
89
+ def esmfold_structure_module_only_8M_270K():
90
+ """
91
+ ESMFold baseline model using 8M ESM-2, 0 folding blocks.
92
+ ESM-2 here is trained out to 270K updates.
93
+ This is a model designed to test the capabilities of the language model
94
+ when ablated for number of parameters in the language model.
95
+ See table S1 in (Lin et al, 2022).
96
+ """
97
+ return _load_model("esmfold_structure_module_only_8M_270K")
98
+
99
+
100
+ def esmfold_structure_module_only_35M():
101
+ """
102
+ ESMFold baseline model using 35M ESM-2, 0 folding blocks.
103
+ ESM-2 here is trained out to 500K updates.
104
+ This is a model designed to test the capabilities of the language model
105
+ when ablated for number of parameters in the language model.
106
+ See table S1 in (Lin et al, 2022).
107
+ """
108
+ return _load_model("esmfold_structure_module_only_35M")
109
+
110
+
111
+ def esmfold_structure_module_only_35M_270K():
112
+ """
113
+ ESMFold baseline model using 35M ESM-2, 0 folding blocks.
114
+ ESM-2 here is trained out to 270K updates.
115
+ This is a model designed to test the capabilities of the language model
116
+ when ablated for number of parameters in the language model.
117
+ See table S1 in (Lin et al, 2022).
118
+ """
119
+ return _load_model("esmfold_structure_module_only_35M_270K")
120
+
121
+
122
+ def esmfold_structure_module_only_150M():
123
+ """
124
+ ESMFold baseline model using 150M ESM-2, 0 folding blocks.
125
+ ESM-2 here is trained out to 500K updates.
126
+ This is a model designed to test the capabilities of the language model
127
+ when ablated for number of parameters in the language model.
128
+ See table S1 in (Lin et al, 2022).
129
+ """
130
+ return _load_model("esmfold_structure_module_only_150M")
131
+
132
+
133
+ def esmfold_structure_module_only_150M_270K():
134
+ """
135
+ ESMFold baseline model using 150M ESM-2, 0 folding blocks.
136
+ ESM-2 here is trained out to 270K updates.
137
+ This is a model designed to test the capabilities of the language model
138
+ when ablated for number of parameters in the language model.
139
+ See table S1 in (Lin et al, 2022).
140
+ """
141
+ return _load_model("esmfold_structure_module_only_150M_270K")
142
+
143
+
144
+ def esmfold_structure_module_only_650M():
145
+ """
146
+ ESMFold baseline model using 650M ESM-2, 0 folding blocks.
147
+ ESM-2 here is trained out to 500K updates.
148
+ This is a model designed to test the capabilities of the language model
149
+ when ablated for number of parameters in the language model.
150
+ See table S1 in (Lin et al, 2022).
151
+ """
152
+ return _load_model("esmfold_structure_module_only_650M")
153
+
154
+
155
+ def esmfold_structure_module_only_650M_270K():
156
+ """
157
+ ESMFold baseline model using 650M ESM-2, 0 folding blocks.
158
+ ESM-2 here is trained out to 270K updates.
159
+ This is a model designed to test the capabilities of the language model
160
+ when ablated for number of parameters in the language model.
161
+ See table S1 in (Lin et al, 2022).
162
+ """
163
+ return _load_model("esmfold_structure_module_only_650M_270K")
164
+
165
+
166
+ def esmfold_structure_module_only_3B():
167
+ """
168
+ ESMFold baseline model using 3B ESM-2, 0 folding blocks.
169
+ ESM-2 here is trained out to 500K updates.
170
+ This is a model designed to test the capabilities of the language model
171
+ when ablated for number of parameters in the language model.
172
+ See table S1 in (Lin et al, 2022).
173
+ """
174
+ return _load_model("esmfold_structure_module_only_3B")
175
+
176
+
177
+ def esmfold_structure_module_only_3B_270K():
178
+ """
179
+ ESMFold baseline model using 3B ESM-2, 0 folding blocks.
180
+ ESM-2 here is trained out to 270K updates.
181
+ This is a model designed to test the capabilities of the language model
182
+ when ablated for number of parameters in the language model.
183
+ See table S1 in (Lin et al, 2022).
184
+ """
185
+ return _load_model("esmfold_structure_module_only_3B_270K")
186
+
187
+
188
+ def esmfold_structure_module_only_15B():
189
+ """
190
+ ESMFold baseline model using 15B ESM-2, 0 folding blocks.
191
+ ESM-2 here is trained out to 270K updates.
192
+ The 15B parameter ESM-2 was not trained out to 500K updates
193
+ This is a model designed to test the capabilities of the language model
194
+ when ablated for number of parameters in the language model.
195
+ See table S1 in (Lin et al, 2022).
196
+ """
197
+ return _load_model("esmfold_structure_module_only_15B")
model/esm/esmfold/v1/tri_self_attn_block.py ADDED
@@ -0,0 +1,160 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright (c) Meta Platforms, Inc. and affiliates.
2
+ #
3
+ # This source code is licensed under the MIT license found in the
4
+ # LICENSE file in the root directory of this source tree.
5
+ import torch
6
+ from model.openfold.triangular_attention import (
7
+ TriangleAttentionEndingNode,
8
+ TriangleAttentionStartingNode,
9
+ )
10
+ from model.openfold.triangular_multiplicative_update import (
11
+ TriangleMultiplicationIncoming,
12
+ TriangleMultiplicationOutgoing,
13
+ )
14
+ from torch import nn
15
+
16
+ from model.esm.esmfold.v1.misc import (
17
+ Attention,
18
+ Dropout,
19
+ PairToSequence,
20
+ ResidueMLP,
21
+ SequenceToPair,
22
+ )
23
+
24
+
25
+ class TriangularSelfAttentionBlock(nn.Module):
26
+ def __init__(
27
+ self,
28
+ sequence_state_dim,
29
+ pairwise_state_dim,
30
+ sequence_head_width,
31
+ pairwise_head_width,
32
+ dropout=0,
33
+ **__kwargs,
34
+ ):
35
+ super().__init__()
36
+
37
+ assert sequence_state_dim % sequence_head_width == 0
38
+ assert pairwise_state_dim % pairwise_head_width == 0
39
+ sequence_num_heads = sequence_state_dim // sequence_head_width
40
+ pairwise_num_heads = pairwise_state_dim // pairwise_head_width
41
+ assert sequence_state_dim == sequence_num_heads * sequence_head_width
42
+ assert pairwise_state_dim == pairwise_num_heads * pairwise_head_width
43
+ assert pairwise_state_dim % 2 == 0
44
+
45
+ self.sequence_state_dim = sequence_state_dim
46
+ self.pairwise_state_dim = pairwise_state_dim
47
+
48
+ self.layernorm_1 = nn.LayerNorm(sequence_state_dim)
49
+
50
+ self.sequence_to_pair = SequenceToPair(
51
+ sequence_state_dim, pairwise_state_dim // 2, pairwise_state_dim
52
+ )
53
+ self.pair_to_sequence = PairToSequence(pairwise_state_dim, sequence_num_heads)
54
+
55
+ self.seq_attention = Attention(
56
+ sequence_state_dim, sequence_num_heads, sequence_head_width, gated=True
57
+ )
58
+ self.tri_mul_out = TriangleMultiplicationOutgoing(
59
+ pairwise_state_dim,
60
+ pairwise_state_dim,
61
+ )
62
+ self.tri_mul_in = TriangleMultiplicationIncoming(
63
+ pairwise_state_dim,
64
+ pairwise_state_dim,
65
+ )
66
+ self.tri_att_start = TriangleAttentionStartingNode(
67
+ pairwise_state_dim,
68
+ pairwise_head_width,
69
+ pairwise_num_heads,
70
+ inf=1e9,
71
+ ) # type: ignore
72
+ self.tri_att_end = TriangleAttentionEndingNode(
73
+ pairwise_state_dim,
74
+ pairwise_head_width,
75
+ pairwise_num_heads,
76
+ inf=1e9,
77
+ ) # type: ignore
78
+
79
+ self.mlp_seq = ResidueMLP(sequence_state_dim, 4 * sequence_state_dim, dropout=dropout)
80
+ self.mlp_pair = ResidueMLP(pairwise_state_dim, 4 * pairwise_state_dim, dropout=dropout)
81
+
82
+ assert dropout < 0.4
83
+ self.drop = nn.Dropout(dropout)
84
+ self.row_drop = Dropout(dropout * 2, 2)
85
+ self.col_drop = Dropout(dropout * 2, 1)
86
+
87
+ torch.nn.init.zeros_(self.tri_mul_in.linear_z.weight)
88
+ torch.nn.init.zeros_(self.tri_mul_in.linear_z.bias)
89
+ torch.nn.init.zeros_(self.tri_mul_out.linear_z.weight)
90
+ torch.nn.init.zeros_(self.tri_mul_out.linear_z.bias)
91
+ torch.nn.init.zeros_(self.tri_att_start.mha.linear_o.weight)
92
+ torch.nn.init.zeros_(self.tri_att_start.mha.linear_o.bias)
93
+ torch.nn.init.zeros_(self.tri_att_end.mha.linear_o.weight)
94
+ torch.nn.init.zeros_(self.tri_att_end.mha.linear_o.bias)
95
+
96
+ torch.nn.init.zeros_(self.sequence_to_pair.o_proj.weight)
97
+ torch.nn.init.zeros_(self.sequence_to_pair.o_proj.bias)
98
+ torch.nn.init.zeros_(self.pair_to_sequence.linear.weight)
99
+ torch.nn.init.zeros_(self.seq_attention.o_proj.weight)
100
+ torch.nn.init.zeros_(self.seq_attention.o_proj.bias)
101
+ torch.nn.init.zeros_(self.mlp_seq.mlp[-2].weight)
102
+ torch.nn.init.zeros_(self.mlp_seq.mlp[-2].bias)
103
+ torch.nn.init.zeros_(self.mlp_pair.mlp[-2].weight)
104
+ torch.nn.init.zeros_(self.mlp_pair.mlp[-2].bias)
105
+
106
+ def forward(self, sequence_state, pairwise_state, mask=None, chunk_size=None, **__kwargs):
107
+ """
108
+ Inputs:
109
+ sequence_state: B x L x sequence_state_dim
110
+ pairwise_state: B x L x L x pairwise_state_dim
111
+ mask: B x L boolean tensor of valid positions
112
+
113
+ Output:
114
+ sequence_state: B x L x sequence_state_dim
115
+ pairwise_state: B x L x L x pairwise_state_dim
116
+ """
117
+ assert len(sequence_state.shape) == 3
118
+ assert len(pairwise_state.shape) == 4
119
+ if mask is not None:
120
+ assert len(mask.shape) == 2
121
+
122
+ batch_dim, seq_dim, sequence_state_dim = sequence_state.shape
123
+ pairwise_state_dim = pairwise_state.shape[3]
124
+ assert sequence_state_dim == self.sequence_state_dim
125
+ assert pairwise_state_dim == self.pairwise_state_dim
126
+ assert batch_dim == pairwise_state.shape[0]
127
+ assert seq_dim == pairwise_state.shape[1]
128
+ assert seq_dim == pairwise_state.shape[2]
129
+
130
+ # Update sequence state
131
+ bias = self.pair_to_sequence(pairwise_state)
132
+
133
+ # Self attention with bias + mlp.
134
+ y = self.layernorm_1(sequence_state)
135
+ y, _ = self.seq_attention(y, mask=mask, bias=bias)
136
+ sequence_state = sequence_state + self.drop(y)
137
+ sequence_state = self.mlp_seq(sequence_state)
138
+
139
+ # Update pairwise state
140
+ pairwise_state = pairwise_state + self.sequence_to_pair(sequence_state)
141
+
142
+ # Axial attention with triangular bias.
143
+ tri_mask = mask.unsqueeze(2) * mask.unsqueeze(1) if mask is not None else None
144
+ pairwise_state = pairwise_state + self.row_drop(
145
+ self.tri_mul_out(pairwise_state, mask=tri_mask)
146
+ )
147
+ pairwise_state = pairwise_state + self.col_drop(
148
+ self.tri_mul_in(pairwise_state, mask=tri_mask)
149
+ )
150
+ pairwise_state = pairwise_state + self.row_drop(
151
+ self.tri_att_start(pairwise_state, mask=tri_mask, chunk_size=chunk_size)
152
+ )
153
+ pairwise_state = pairwise_state + self.col_drop(
154
+ self.tri_att_end(pairwise_state, mask=tri_mask, chunk_size=chunk_size)
155
+ )
156
+
157
+ # MLP over pairs.
158
+ pairwise_state = self.mlp_pair(pairwise_state)
159
+
160
+ return sequence_state, pairwise_state
model/esm/esmfold/v1/trunk.py ADDED
@@ -0,0 +1,245 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright (c) Meta Platforms, Inc. and affiliates.
2
+ #
3
+ # This source code is licensed under the MIT license found in the
4
+ # LICENSE file in the root directory of this source tree.
5
+ import typing as T
6
+ from contextlib import ExitStack
7
+ # from dataclasses import dataclass
8
+ from dataclasses import dataclass, field
9
+
10
+ import torch
11
+ import torch.nn as nn
12
+ from model.openfold.structure_module import StructureModule
13
+
14
+ from model.esm.esmfold.v1.tri_self_attn_block import TriangularSelfAttentionBlock
15
+
16
+
17
+ @dataclass
18
+ class StructureModuleConfig:
19
+ c_s: int = 384
20
+ c_z: int = 128
21
+ c_ipa: int = 16
22
+ c_resnet: int = 128
23
+ no_heads_ipa: int = 12
24
+ no_qk_points: int = 4
25
+ no_v_points: int = 8
26
+ dropout_rate: float = 0.1
27
+ no_blocks: int = 8
28
+ no_transition_layers: int = 1
29
+ no_resnet_blocks: int = 2
30
+ no_angles: int = 7
31
+ trans_scale_factor: int = 10
32
+ epsilon: float = 1e-8
33
+ inf: float = 1e5
34
+
35
+
36
+ @dataclass
37
+ class FoldingTrunkConfig:
38
+ _name: str = "FoldingTrunkConfig"
39
+ num_blocks: int = 48
40
+ sequence_state_dim: int = 1024
41
+ pairwise_state_dim: int = 128
42
+ sequence_head_width: int = 32
43
+ pairwise_head_width: int = 32
44
+ position_bins: int = 32
45
+ dropout: float = 0
46
+ layer_drop: float = 0
47
+ cpu_grad_checkpoint: bool = False
48
+
49
+ max_recycles: int = 4
50
+ chunk_size: T.Optional[int] = None
51
+
52
+ # structure_module: StructureModuleConfig = StructureModuleConfig()
53
+ structure_module: StructureModuleConfig = field(default_factory=StructureModuleConfig)
54
+
55
+
56
+ def get_axial_mask(mask):
57
+ """
58
+ Helper to convert B x L mask of valid positions to axial mask used
59
+ in row column attentions.
60
+
61
+ Input:
62
+ mask: B x L tensor of booleans
63
+
64
+ Output:
65
+ mask: B x L x L tensor of booleans
66
+ """
67
+
68
+ if mask is None:
69
+ return None
70
+ assert len(mask.shape) == 2
71
+ batch_dim, seq_dim = mask.shape
72
+ m = mask.unsqueeze(1).expand(batch_dim, seq_dim, seq_dim)
73
+ m = m.reshape(batch_dim * seq_dim, seq_dim)
74
+ return m
75
+
76
+
77
+ class RelativePosition(nn.Module):
78
+ def __init__(self, bins, pairwise_state_dim):
79
+ super().__init__()
80
+ self.bins = bins
81
+
82
+ # Note an additional offset is used so that the 0th position
83
+ # is reserved for masked pairs.
84
+ self.embedding = torch.nn.Embedding(2 * bins + 2, pairwise_state_dim)
85
+
86
+ def forward(self, residue_index, mask=None):
87
+ """
88
+ Input:
89
+ residue_index: B x L tensor of indices (dytpe=torch.long)
90
+ mask: B x L tensor of booleans
91
+
92
+ Output:
93
+ pairwise_state: B x L x L x pairwise_state_dim tensor of embeddings
94
+ """
95
+
96
+ assert residue_index.dtype == torch.long
97
+ if mask is not None:
98
+ assert residue_index.shape == mask.shape
99
+
100
+ diff = residue_index[:, None, :] - residue_index[:, :, None]
101
+ diff = diff.clamp(-self.bins, self.bins)
102
+ diff = diff + self.bins + 1 # Add 1 to adjust for padding index.
103
+
104
+ if mask is not None:
105
+ mask = mask[:, None, :] * mask[:, :, None]
106
+ diff[mask == False] = 0
107
+
108
+ output = self.embedding(diff)
109
+ return output
110
+
111
+
112
+ class FoldingTrunk(nn.Module):
113
+ def __init__(self, **kwargs):
114
+ super().__init__()
115
+ self.cfg = FoldingTrunkConfig(**kwargs)
116
+ assert self.cfg.max_recycles > 0
117
+
118
+ c_s = self.cfg.sequence_state_dim
119
+ c_z = self.cfg.pairwise_state_dim
120
+
121
+ assert c_s % self.cfg.sequence_head_width == 0
122
+ assert c_z % self.cfg.pairwise_head_width == 0
123
+ block = TriangularSelfAttentionBlock
124
+
125
+ self.pairwise_positional_embedding = RelativePosition(self.cfg.position_bins, c_z)
126
+
127
+ self.blocks = nn.ModuleList(
128
+ [
129
+ block(
130
+ sequence_state_dim=c_s,
131
+ pairwise_state_dim=c_z,
132
+ sequence_head_width=self.cfg.sequence_head_width,
133
+ pairwise_head_width=self.cfg.pairwise_head_width,
134
+ dropout=self.cfg.dropout,
135
+ )
136
+ for i in range(self.cfg.num_blocks)
137
+ ]
138
+ )
139
+
140
+ self.recycle_bins = 15
141
+ self.recycle_s_norm = nn.LayerNorm(c_s)
142
+ self.recycle_z_norm = nn.LayerNorm(c_z)
143
+ self.recycle_disto = nn.Embedding(self.recycle_bins, c_z)
144
+ self.recycle_disto.weight[0].detach().zero_()
145
+
146
+ self.structure_module = StructureModule(**self.cfg.structure_module) # type: ignore
147
+ self.trunk2sm_s = nn.Linear(c_s, self.structure_module.c_s)
148
+ self.trunk2sm_z = nn.Linear(c_z, self.structure_module.c_z)
149
+
150
+ self.chunk_size = self.cfg.chunk_size
151
+
152
+ def set_chunk_size(self, chunk_size):
153
+ # This parameter means the axial attention will be computed
154
+ # in a chunked manner. This should make the memory used more or less O(L) instead of O(L^2).
155
+ # It's equivalent to running a for loop over chunks of the dimension we're iterative over,
156
+ # where the chunk_size is the size of the chunks, so 128 would mean to parse 128-lengthed chunks.
157
+ self.chunk_size = chunk_size
158
+
159
+ def forward(self, seq_feats, pair_feats, true_aa, residx, mask, no_recycles: T.Optional[int] = None):
160
+ """
161
+ Inputs:
162
+ seq_feats: B x L x C tensor of sequence features
163
+ pair_feats: B x L x L x C tensor of pair features
164
+ residx: B x L long tensor giving the position in the sequence
165
+ mask: B x L boolean tensor indicating valid residues
166
+
167
+ Output:
168
+ predicted_structure: B x L x (num_atoms_per_residue * 3) tensor wrapped in a Coordinates object
169
+ """
170
+
171
+ device = seq_feats.device
172
+ s_s_0 = seq_feats
173
+ s_z_0 = pair_feats
174
+
175
+ if no_recycles is None:
176
+ no_recycles = self.cfg.max_recycles
177
+ else:
178
+ assert no_recycles >= 0, "Number of recycles must not be negative."
179
+ no_recycles += 1 # First 'recycle' is just the standard forward pass through the model.
180
+
181
+ def trunk_iter(s, z, residx, mask):
182
+ z = z + self.pairwise_positional_embedding(residx, mask=mask)
183
+
184
+ for block in self.blocks:
185
+ s, z = block(s, z, mask=mask, residue_index=residx, chunk_size=self.chunk_size)
186
+ return s, z
187
+
188
+ s_s = s_s_0
189
+ s_z = s_z_0
190
+ recycle_s = torch.zeros_like(s_s)
191
+ recycle_z = torch.zeros_like(s_z)
192
+ recycle_bins = torch.zeros(*s_z.shape[:-1], device=device, dtype=torch.int64)
193
+
194
+ assert no_recycles > 0
195
+ for recycle_idx in range(no_recycles):
196
+ with ExitStack() if recycle_idx == no_recycles - 1 else torch.no_grad():
197
+ # === Recycling ===
198
+ recycle_s = self.recycle_s_norm(recycle_s.detach())
199
+ recycle_z = self.recycle_z_norm(recycle_z.detach())
200
+ recycle_z += self.recycle_disto(recycle_bins.detach())
201
+
202
+ s_s, s_z = trunk_iter(s_s_0 + recycle_s, s_z_0 + recycle_z, residx, mask)
203
+
204
+ # === Structure module ===
205
+ structure = self.structure_module(
206
+ {"single": self.trunk2sm_s(s_s), "pair": self.trunk2sm_z(s_z)},
207
+ true_aa,
208
+ mask.float(),
209
+ )
210
+
211
+ recycle_s = s_s
212
+ recycle_z = s_z
213
+ # Distogram needs the N, CA, C coordinates, and bin constants same as alphafold.
214
+ recycle_bins = FoldingTrunk.distogram(
215
+ structure["positions"][-1][:, :, :3],
216
+ 3.375,
217
+ 21.375,
218
+ self.recycle_bins,
219
+ )
220
+
221
+ assert isinstance(structure, dict) # type: ignore
222
+ structure["s_s"] = s_s
223
+ structure["s_z"] = s_z
224
+
225
+ return structure
226
+
227
+ @staticmethod
228
+ def distogram(coords, min_bin, max_bin, num_bins):
229
+ # Coords are [... L x 3 x 3], where it's [N, CA, C] x 3 coordinates.
230
+ boundaries = torch.linspace(
231
+ min_bin,
232
+ max_bin,
233
+ num_bins - 1,
234
+ device=coords.device,
235
+ )
236
+ boundaries = boundaries**2
237
+ N, CA, C = [x.squeeze(-2) for x in coords.chunk(3, dim=-2)]
238
+ # Infer CB coordinates.
239
+ b = CA - N
240
+ c = C - CA
241
+ a = b.cross(c, dim=-1)
242
+ CB = -0.58273431 * a + 0.56802827 * b - 0.54067466 * c + CA
243
+ dists = (CB[..., None, :, :] - CB[..., :, None, :]).pow(2).sum(dim=-1, keepdims=True)
244
+ bins = torch.sum(dists > boundaries, dim=-1) # [..., L, L]
245
+ return bins
model/esm/inverse_folding/__init__.py ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ # Copyright (c) Facebook, Inc. and its affiliates.
2
+ #
3
+ # This source code is licensed under the MIT license found in the
4
+ # LICENSE file in the root directory of this source tree.
5
+
6
+ from . import gvp_transformer
7
+ from . import util
8
+ from . import multichain_util
model/esm/inverse_folding/features.py ADDED
@@ -0,0 +1,352 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright (c) Meta Platforms, Inc. and affiliates.
2
+ #
3
+ # This source code is licensed under the MIT license found in the
4
+ # LICENSE file in the root directory of this source tree.
5
+ #
6
+ # Portions of this file were adapted from the open source code for the following
7
+ # two papers:
8
+ #
9
+ # Ingraham, J., Garg, V., Barzilay, R., & Jaakkola, T. (2019). Generative
10
+ # models for graph-based protein design. Advances in Neural Information
11
+ # Processing Systems, 32.
12
+ #
13
+ # Jing, B., Eismann, S., Suriana, P., Townshend, R. J. L., & Dror, R. (2020).
14
+ # Learning from Protein Structure with Geometric Vector Perceptrons. In
15
+ # International Conference on Learning Representations.
16
+ #
17
+ # MIT License
18
+ #
19
+ # Copyright (c) 2020 Bowen Jing, Stephan Eismann, Patricia Suriana, Raphael Townshend, Ron Dror
20
+ #
21
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
22
+ # of this software and associated documentation files (the "Software"), to deal
23
+ # in the Software without restriction, including without limitation the rights
24
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
25
+ # copies of the Software, and to permit persons to whom the Software is
26
+ # furnished to do so, subject to the following conditions:
27
+ #
28
+ # The above copyright notice and this permission notice shall be included in all
29
+ # copies or substantial portions of the Software.
30
+ #
31
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
32
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
33
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
34
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
35
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
36
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
37
+ # SOFTWARE.
38
+ #
39
+ # ================================================================
40
+ # The below license applies to the portions of the code (parts of
41
+ # src/datasets.py and src/models.py) adapted from Ingraham, et al.
42
+ # ================================================================
43
+ #
44
+ # MIT License
45
+ #
46
+ # Copyright (c) 2019 John Ingraham, Vikas Garg, Regina Barzilay, Tommi Jaakkola
47
+ #
48
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
49
+ # of this software and associated documentation files (the "Software"), to deal
50
+ # in the Software without restriction, including without limitation the rights
51
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
52
+ # copies of the Software, and to permit persons to whom the Software is
53
+ # furnished to do so, subject to the following conditions:
54
+ #
55
+ # The above copyright notice and this permission notice shall be included in all
56
+ # copies or substantial portions of the Software.
57
+ #
58
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
59
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
60
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
61
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
62
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
63
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
64
+ # SOFTWARE.
65
+
66
+ import math
67
+ import numpy as np
68
+ import torch
69
+ import torch.nn as nn
70
+ import torch.nn.functional as F
71
+
72
+ from .gvp_utils import flatten_graph
73
+ from .gvp_modules import GVP, LayerNorm
74
+ from .util import normalize, norm, nan_to_num, rbf
75
+
76
+
77
+ class GVPInputFeaturizer(nn.Module):
78
+
79
+ @staticmethod
80
+ def get_node_features(coords, coord_mask, with_coord_mask=True):
81
+ # scalar features
82
+ node_scalar_features = GVPInputFeaturizer._dihedrals(coords)
83
+ if with_coord_mask:
84
+ node_scalar_features = torch.cat([
85
+ node_scalar_features,
86
+ coord_mask.float().unsqueeze(-1)
87
+ ], dim=-1)
88
+ # vector features
89
+ X_ca = coords[:, :, 1]
90
+ orientations = GVPInputFeaturizer._orientations(X_ca)
91
+ sidechains = GVPInputFeaturizer._sidechains(coords)
92
+ node_vector_features = torch.cat([orientations, sidechains.unsqueeze(-2)], dim=-2)
93
+ return node_scalar_features, node_vector_features
94
+
95
+ @staticmethod
96
+ def _orientations(X):
97
+ forward = normalize(X[:, 1:] - X[:, :-1])
98
+ backward = normalize(X[:, :-1] - X[:, 1:])
99
+ forward = F.pad(forward, [0, 0, 0, 1])
100
+ backward = F.pad(backward, [0, 0, 1, 0])
101
+ return torch.cat([forward.unsqueeze(-2), backward.unsqueeze(-2)], -2)
102
+
103
+ @staticmethod
104
+ def _sidechains(X):
105
+ n, origin, c = X[:, :, 0], X[:, :, 1], X[:, :, 2]
106
+ c, n = normalize(c - origin), normalize(n - origin)
107
+ bisector = normalize(c + n)
108
+ perp = normalize(torch.cross(c, n, dim=-1))
109
+ vec = -bisector * math.sqrt(1 / 3) - perp * math.sqrt(2 / 3)
110
+ return vec
111
+
112
+ @staticmethod
113
+ def _dihedrals(X, eps=1e-7):
114
+ X = torch.flatten(X[:, :, :3], 1, 2)
115
+ bsz = X.shape[0]
116
+ dX = X[:, 1:] - X[:, :-1]
117
+ U = normalize(dX, dim=-1)
118
+ u_2 = U[:, :-2]
119
+ u_1 = U[:, 1:-1]
120
+ u_0 = U[:, 2:]
121
+
122
+ # Backbone normals
123
+ n_2 = normalize(torch.cross(u_2, u_1, dim=-1), dim=-1)
124
+ n_1 = normalize(torch.cross(u_1, u_0, dim=-1), dim=-1)
125
+
126
+ # Angle between normals
127
+ cosD = torch.sum(n_2 * n_1, -1)
128
+ cosD = torch.clamp(cosD, -1 + eps, 1 - eps)
129
+ D = torch.sign(torch.sum(u_2 * n_1, -1)) * torch.acos(cosD)
130
+
131
+ # This scheme will remove phi[0], psi[-1], omega[-1]
132
+ D = F.pad(D, [1, 2])
133
+ D = torch.reshape(D, [bsz, -1, 3])
134
+ # Lift angle representations to the circle
135
+ D_features = torch.cat([torch.cos(D), torch.sin(D)], -1)
136
+ return D_features
137
+
138
+ @staticmethod
139
+ def _positional_embeddings(edge_index,
140
+ num_embeddings=None,
141
+ num_positional_embeddings=16,
142
+ period_range=[2, 1000]):
143
+ # From https://github.com/jingraham/neurips19-graph-protein-design
144
+ num_embeddings = num_embeddings or num_positional_embeddings
145
+ d = edge_index[0] - edge_index[1]
146
+
147
+ frequency = torch.exp(
148
+ torch.arange(0, num_embeddings, 2, dtype=torch.float32,
149
+ device=edge_index.device)
150
+ * -(np.log(10000.0) / num_embeddings)
151
+ )
152
+ angles = d.unsqueeze(-1) * frequency
153
+ E = torch.cat((torch.cos(angles), torch.sin(angles)), -1)
154
+ return E
155
+
156
+ @staticmethod
157
+ def _dist(X, coord_mask, padding_mask, top_k_neighbors, eps=1e-8):
158
+ """ Pairwise euclidean distances """
159
+ bsz, maxlen = X.size(0), X.size(1)
160
+ coord_mask_2D = torch.unsqueeze(coord_mask,1) * torch.unsqueeze(coord_mask,2)
161
+ residue_mask = ~padding_mask
162
+ residue_mask_2D = torch.unsqueeze(residue_mask,1) * torch.unsqueeze(residue_mask,2)
163
+ dX = torch.unsqueeze(X,1) - torch.unsqueeze(X,2)
164
+ D = coord_mask_2D * norm(dX, dim=-1)
165
+
166
+ # sorting preference: first those with coords, then among the residues that
167
+ # exist but are masked use distance in sequence as tie breaker, and then the
168
+ # residues that came from padding are last
169
+ seqpos = torch.arange(maxlen, device=X.device)
170
+ Dseq = torch.abs(seqpos.unsqueeze(1) - seqpos.unsqueeze(0)).repeat(bsz, 1, 1)
171
+ D_adjust = nan_to_num(D) + (~coord_mask_2D) * (1e8 + Dseq*1e6) + (
172
+ ~residue_mask_2D) * (1e10)
173
+
174
+ if top_k_neighbors == -1:
175
+ D_neighbors = D_adjust
176
+ E_idx = seqpos.repeat(
177
+ *D_neighbors.shape[:-1], 1)
178
+ else:
179
+ # Identify k nearest neighbors (including self)
180
+ k = min(top_k_neighbors, X.size(1))
181
+ D_neighbors, E_idx = torch.topk(D_adjust, k, dim=-1, largest=False)
182
+
183
+ coord_mask_neighbors = (D_neighbors < 5e7)
184
+ residue_mask_neighbors = (D_neighbors < 5e9)
185
+ return D_neighbors, E_idx, coord_mask_neighbors, residue_mask_neighbors
186
+
187
+
188
+ class Normalize(nn.Module):
189
+ def __init__(self, features, epsilon=1e-6):
190
+ super(Normalize, self).__init__()
191
+ self.gain = nn.Parameter(torch.ones(features))
192
+ self.bias = nn.Parameter(torch.zeros(features))
193
+ self.epsilon = epsilon
194
+
195
+ def forward(self, x, dim=-1):
196
+ mu = x.mean(dim, keepdim=True)
197
+ sigma = torch.sqrt(x.var(dim, keepdim=True) + self.epsilon)
198
+ gain = self.gain
199
+ bias = self.bias
200
+ # Reshape
201
+ if dim != -1:
202
+ shape = [1] * len(mu.size())
203
+ shape[dim] = self.gain.size()[0]
204
+ gain = gain.view(shape)
205
+ bias = bias.view(shape)
206
+ return gain * (x - mu) / (sigma + self.epsilon) + bias
207
+
208
+
209
+ class DihedralFeatures(nn.Module):
210
+ def __init__(self, node_embed_dim):
211
+ """ Embed dihedral angle features. """
212
+ super(DihedralFeatures, self).__init__()
213
+ # 3 dihedral angles; sin and cos of each angle
214
+ node_in = 6
215
+ # Normalization and embedding
216
+ self.node_embedding = nn.Linear(node_in, node_embed_dim, bias=True)
217
+ self.norm_nodes = Normalize(node_embed_dim)
218
+
219
+ def forward(self, X):
220
+ """ Featurize coordinates as an attributed graph """
221
+ V = self._dihedrals(X)
222
+ V = self.node_embedding(V)
223
+ V = self.norm_nodes(V)
224
+ return V
225
+
226
+ @staticmethod
227
+ def _dihedrals(X, eps=1e-7, return_angles=False):
228
+ # First 3 coordinates are N, CA, C
229
+ X = X[:,:,:3,:].reshape(X.shape[0], 3*X.shape[1], 3)
230
+
231
+ # Shifted slices of unit vectors
232
+ dX = X[:,1:,:] - X[:,:-1,:]
233
+ U = F.normalize(dX, dim=-1)
234
+ u_2 = U[:,:-2,:]
235
+ u_1 = U[:,1:-1,:]
236
+ u_0 = U[:,2:,:]
237
+ # Backbone normals
238
+ n_2 = F.normalize(torch.cross(u_2, u_1, dim=-1), dim=-1)
239
+ n_1 = F.normalize(torch.cross(u_1, u_0, dim=-1), dim=-1)
240
+
241
+ # Angle between normals
242
+ cosD = (n_2 * n_1).sum(-1)
243
+ cosD = torch.clamp(cosD, -1+eps, 1-eps)
244
+ D = torch.sign((u_2 * n_1).sum(-1)) * torch.acos(cosD)
245
+
246
+ # This scheme will remove phi[0], psi[-1], omega[-1]
247
+ D = F.pad(D, (1,2), 'constant', 0)
248
+ D = D.view((D.size(0), int(D.size(1)/3), 3))
249
+ phi, psi, omega = torch.unbind(D,-1)
250
+
251
+ if return_angles:
252
+ return phi, psi, omega
253
+
254
+ # Lift angle representations to the circle
255
+ D_features = torch.cat((torch.cos(D), torch.sin(D)), 2)
256
+ return D_features
257
+
258
+
259
+ class GVPGraphEmbedding(GVPInputFeaturizer):
260
+
261
+ def __init__(self, args):
262
+ super().__init__()
263
+ self.top_k_neighbors = args.top_k_neighbors
264
+ self.num_positional_embeddings = 16
265
+ self.remove_edges_without_coords = True
266
+ node_input_dim = (7, 3)
267
+ edge_input_dim = (34, 1)
268
+ node_hidden_dim = (args.node_hidden_dim_scalar,
269
+ args.node_hidden_dim_vector)
270
+ edge_hidden_dim = (args.edge_hidden_dim_scalar,
271
+ args.edge_hidden_dim_vector)
272
+ self.embed_node = nn.Sequential(
273
+ GVP(node_input_dim, node_hidden_dim, activations=(None, None)),
274
+ LayerNorm(node_hidden_dim, eps=1e-4)
275
+ )
276
+ self.embed_edge = nn.Sequential(
277
+ GVP(edge_input_dim, edge_hidden_dim, activations=(None, None)),
278
+ LayerNorm(edge_hidden_dim, eps=1e-4)
279
+ )
280
+ self.embed_confidence = nn.Linear(16, args.node_hidden_dim_scalar)
281
+
282
+ def forward(self, coords, coord_mask, padding_mask, confidence):
283
+ with torch.no_grad():
284
+ node_features = self.get_node_features(coords, coord_mask)
285
+ edge_features, edge_index = self.get_edge_features(
286
+ coords, coord_mask, padding_mask)
287
+ node_embeddings_scalar, node_embeddings_vector = self.embed_node(node_features)
288
+ edge_embeddings = self.embed_edge(edge_features)
289
+
290
+ rbf_rep = rbf(confidence, 0., 1.)
291
+ node_embeddings = (
292
+ node_embeddings_scalar + self.embed_confidence(rbf_rep),
293
+ node_embeddings_vector
294
+ )
295
+
296
+ node_embeddings, edge_embeddings, edge_index = flatten_graph(
297
+ node_embeddings, edge_embeddings, edge_index)
298
+ return node_embeddings, edge_embeddings, edge_index
299
+
300
+ def get_edge_features(self, coords, coord_mask, padding_mask):
301
+ X_ca = coords[:, :, 1]
302
+ # Get distances to the top k neighbors
303
+ E_dist, E_idx, E_coord_mask, E_residue_mask = GVPInputFeaturizer._dist(
304
+ X_ca, coord_mask, padding_mask, self.top_k_neighbors)
305
+ # Flatten the graph to be batch size 1 for torch_geometric package
306
+ dest = E_idx
307
+ B, L, k = E_idx.shape[:3]
308
+ src = torch.arange(L, device=E_idx.device).view([1, L, 1]).expand(B, L, k)
309
+ # After flattening, [2, B, E]
310
+ edge_index = torch.stack([src, dest], dim=0).flatten(2, 3)
311
+ # After flattening, [B, E]
312
+ E_dist = E_dist.flatten(1, 2)
313
+ E_coord_mask = E_coord_mask.flatten(1, 2).unsqueeze(-1)
314
+ E_residue_mask = E_residue_mask.flatten(1, 2)
315
+ # Calculate relative positional embeddings and distance RBF
316
+ pos_embeddings = GVPInputFeaturizer._positional_embeddings(
317
+ edge_index,
318
+ num_positional_embeddings=self.num_positional_embeddings,
319
+ )
320
+ D_rbf = rbf(E_dist, 0., 20.)
321
+ # Calculate relative orientation
322
+ X_src = X_ca.unsqueeze(2).expand(-1, -1, k, -1).flatten(1, 2)
323
+ X_dest = torch.gather(
324
+ X_ca,
325
+ 1,
326
+ edge_index[1, :, :].unsqueeze(-1).expand([B, L*k, 3])
327
+ )
328
+ coord_mask_src = coord_mask.unsqueeze(2).expand(-1, -1, k).flatten(1, 2)
329
+ coord_mask_dest = torch.gather(
330
+ coord_mask,
331
+ 1,
332
+ edge_index[1, :, :].expand([B, L*k])
333
+ )
334
+ E_vectors = X_src - X_dest
335
+ # For the ones without coordinates, substitute in the average vector
336
+ E_vector_mean = torch.sum(E_vectors * E_coord_mask, dim=1,
337
+ keepdims=True) / torch.sum(E_coord_mask, dim=1, keepdims=True)
338
+ E_vectors = E_vectors * E_coord_mask + E_vector_mean * ~(E_coord_mask)
339
+ # Normalize and remove nans
340
+ edge_s = torch.cat([D_rbf, pos_embeddings], dim=-1)
341
+ edge_v = normalize(E_vectors).unsqueeze(-2)
342
+ edge_s, edge_v = map(nan_to_num, (edge_s, edge_v))
343
+ # Also add indications of whether the coordinates are present
344
+ edge_s = torch.cat([
345
+ edge_s,
346
+ (~coord_mask_src).float().unsqueeze(-1),
347
+ (~coord_mask_dest).float().unsqueeze(-1),
348
+ ], dim=-1)
349
+ edge_index[:, ~E_residue_mask] = -1
350
+ if self.remove_edges_without_coords:
351
+ edge_index[:, ~E_coord_mask.squeeze(-1)] = -1
352
+ return (edge_s, edge_v), edge_index.transpose(0, 1)
model/esm/inverse_folding/gvp_encoder.py ADDED
@@ -0,0 +1,56 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright (c) Meta Platforms, Inc. and affiliates.
2
+ #
3
+ # This source code is licensed under the MIT license found in the
4
+ # LICENSE file in the root directory of this source tree.
5
+
6
+ from argparse import Namespace
7
+
8
+ import torch
9
+ import torch.nn as nn
10
+ import torch.nn.functional as F
11
+
12
+ from .features import GVPGraphEmbedding
13
+ from .gvp_modules import GVPConvLayer, LayerNorm
14
+ from .gvp_utils import unflatten_graph
15
+
16
+
17
+
18
+ class GVPEncoder(nn.Module):
19
+
20
+ def __init__(self, args):
21
+ super().__init__()
22
+ self.args = args
23
+ self.embed_graph = GVPGraphEmbedding(args)
24
+
25
+ node_hidden_dim = (args.node_hidden_dim_scalar,
26
+ args.node_hidden_dim_vector)
27
+ edge_hidden_dim = (args.edge_hidden_dim_scalar,
28
+ args.edge_hidden_dim_vector)
29
+
30
+ conv_activations = (F.relu, torch.sigmoid)
31
+ self.encoder_layers = nn.ModuleList(
32
+ GVPConvLayer(
33
+ node_hidden_dim,
34
+ edge_hidden_dim,
35
+ drop_rate=args.dropout,
36
+ vector_gate=True,
37
+ attention_heads=0,
38
+ n_message=3,
39
+ conv_activations=conv_activations,
40
+ n_edge_gvps=0,
41
+ eps=1e-4,
42
+ layernorm=True,
43
+ )
44
+ for i in range(args.num_encoder_layers)
45
+ )
46
+
47
+ def forward(self, coords, coord_mask, padding_mask, confidence):
48
+ node_embeddings, edge_embeddings, edge_index = self.embed_graph(
49
+ coords, coord_mask, padding_mask, confidence)
50
+
51
+ for i, layer in enumerate(self.encoder_layers):
52
+ node_embeddings, edge_embeddings = layer(node_embeddings,
53
+ edge_index, edge_embeddings)
54
+
55
+ node_embeddings = unflatten_graph(node_embeddings, coords.shape[0])
56
+ return node_embeddings
model/esm/inverse_folding/gvp_modules.py ADDED
@@ -0,0 +1,475 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Contents of this file are from the open source code for
2
+ #
3
+ # Jing, B., Eismann, S., Suriana, P., Townshend, R. J. L., & Dror, R. (2020).
4
+ # Learning from Protein Structure with Geometric Vector Perceptrons. In
5
+ # International Conference on Learning Representations.
6
+ #
7
+ # MIT License
8
+ #
9
+ # Copyright (c) 2020 Bowen Jing, Stephan Eismann, Patricia Suriana, Raphael Townshend, Ron Dror
10
+ #
11
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
12
+ # of this software and associated documentation files (the "Software"), to deal
13
+ # in the Software without restriction, including without limitation the rights
14
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15
+ # copies of the Software, and to permit persons to whom the Software is
16
+ # furnished to do so, subject to the following conditions:
17
+ #
18
+ # The above copyright notice and this permission notice shall be included in all
19
+ # copies or substantial portions of the Software.
20
+ #
21
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27
+ # SOFTWARE.
28
+
29
+ import typing as T
30
+ import torch
31
+ from torch import nn
32
+ import torch.nn.functional as F
33
+ from torch_geometric.nn import MessagePassing
34
+
35
+ def tuple_size(tp):
36
+ return tuple([0 if a is None else a.size() for a in tp])
37
+
38
+ def tuple_sum(tp1, tp2):
39
+ s1, v1 = tp1
40
+ s2, v2 = tp2
41
+ if v2 is None and v2 is None:
42
+ return (s1 + s2, None)
43
+ return (s1 + s2, v1 + v2)
44
+
45
+ def tuple_cat(*args, dim=-1):
46
+ '''
47
+ Concatenates any number of tuples (s, V) elementwise.
48
+
49
+ :param dim: dimension along which to concatenate when viewed
50
+ as the `dim` index for the scalar-channel tensors.
51
+ This means that `dim=-1` will be applied as
52
+ `dim=-2` for the vector-channel tensors.
53
+ '''
54
+ dim %= len(args[0][0].shape)
55
+ s_args, v_args = list(zip(*args))
56
+ return torch.cat(s_args, dim=dim), torch.cat(v_args, dim=dim)
57
+
58
+ def tuple_index(x, idx):
59
+ '''
60
+ Indexes into a tuple (s, V) along the first dimension.
61
+
62
+ :param idx: any object which can be used to index into a `torch.Tensor`
63
+ '''
64
+ return x[0][idx], x[1][idx]
65
+
66
+ def randn(n, dims, device="cpu"):
67
+ '''
68
+ Returns random tuples (s, V) drawn elementwise from a normal distribution.
69
+
70
+ :param n: number of data points
71
+ :param dims: tuple of dimensions (n_scalar, n_vector)
72
+
73
+ :return: (s, V) with s.shape = (n, n_scalar) and
74
+ V.shape = (n, n_vector, 3)
75
+ '''
76
+ return torch.randn(n, dims[0], device=device), \
77
+ torch.randn(n, dims[1], 3, device=device)
78
+
79
+ def _norm_no_nan(x, axis=-1, keepdims=False, eps=1e-8, sqrt=True):
80
+ '''
81
+ L2 norm of tensor clamped above a minimum value `eps`.
82
+
83
+ :param sqrt: if `False`, returns the square of the L2 norm
84
+ '''
85
+ # clamp is slow
86
+ # out = torch.clamp(torch.sum(torch.square(x), axis, keepdims), min=eps)
87
+ out = torch.sum(torch.square(x), axis, keepdims) + eps
88
+ return torch.sqrt(out) if sqrt else out
89
+
90
+ def _split(x, nv):
91
+ '''
92
+ Splits a merged representation of (s, V) back into a tuple.
93
+ Should be used only with `_merge(s, V)` and only if the tuple
94
+ representation cannot be used.
95
+
96
+ :param x: the `torch.Tensor` returned from `_merge`
97
+ :param nv: the number of vector channels in the input to `_merge`
98
+ '''
99
+ v = torch.reshape(x[..., -3*nv:], x.shape[:-1] + (nv, 3))
100
+ s = x[..., :-3*nv]
101
+ return s, v
102
+
103
+ def _merge(s, v):
104
+ '''
105
+ Merges a tuple (s, V) into a single `torch.Tensor`, where the
106
+ vector channels are flattened and appended to the scalar channels.
107
+ Should be used only if the tuple representation cannot be used.
108
+ Use `_split(x, nv)` to reverse.
109
+ '''
110
+ v = torch.reshape(v, v.shape[:-2] + (3*v.shape[-2],))
111
+ return torch.cat([s, v], -1)
112
+
113
+ class GVP(nn.Module):
114
+ '''
115
+ Geometric Vector Perceptron. See manuscript and README.md
116
+ for more details.
117
+
118
+ :param in_dims: tuple (n_scalar, n_vector)
119
+ :param out_dims: tuple (n_scalar, n_vector)
120
+ :param h_dim: intermediate number of vector channels, optional
121
+ :param activations: tuple of functions (scalar_act, vector_act)
122
+ :param tuple_io: whether to keep accepting tuple inputs and outputs when vi
123
+ or vo = 0
124
+ '''
125
+ def __init__(self, in_dims, out_dims, h_dim=None, vector_gate=False,
126
+ activations=(F.relu, torch.sigmoid), tuple_io=True,
127
+ eps=1e-8):
128
+ super(GVP, self).__init__()
129
+ self.si, self.vi = in_dims
130
+ self.so, self.vo = out_dims
131
+ self.tuple_io = tuple_io
132
+ if self.vi:
133
+ self.h_dim = h_dim or max(self.vi, self.vo)
134
+ self.wh = nn.Linear(self.vi, self.h_dim, bias=False)
135
+ self.ws = nn.Linear(self.h_dim + self.si, self.so)
136
+ if self.vo:
137
+ self.wv = nn.Linear(self.h_dim, self.vo, bias=False)
138
+ if vector_gate:
139
+ self.wg = nn.Linear(self.so, self.vo)
140
+ else:
141
+ self.ws = nn.Linear(self.si, self.so)
142
+
143
+ self.vector_gate = vector_gate
144
+ self.scalar_act, self.vector_act = activations
145
+ self.eps = eps
146
+
147
+ def forward(self, x):
148
+ '''
149
+ :param x: tuple (s, V) of `torch.Tensor`,
150
+ or (if vectors_in is 0), a single `torch.Tensor`
151
+ :return: tuple (s, V) of `torch.Tensor`,
152
+ or (if vectors_out is 0), a single `torch.Tensor`
153
+ '''
154
+ if self.vi:
155
+ s, v = x
156
+ v = torch.transpose(v, -1, -2)
157
+ vh = self.wh(v)
158
+ vn = _norm_no_nan(vh, axis=-2, eps=self.eps)
159
+ s = self.ws(torch.cat([s, vn], -1))
160
+ if self.scalar_act:
161
+ s = self.scalar_act(s)
162
+ if self.vo:
163
+ v = self.wv(vh)
164
+ v = torch.transpose(v, -1, -2)
165
+ if self.vector_gate:
166
+ g = self.wg(s).unsqueeze(-1)
167
+ else:
168
+ g = _norm_no_nan(v, axis=-1, keepdims=True, eps=self.eps)
169
+ if self.vector_act:
170
+ g = self.vector_act(g)
171
+ v = v * g
172
+ else:
173
+ if self.tuple_io:
174
+ assert x[1] is None
175
+ x = x[0]
176
+ s = self.ws(x)
177
+ if self.scalar_act:
178
+ s = self.scalar_act(s)
179
+ if self.vo:
180
+ v = torch.zeros(list(s.shape)[:-1] + [self.vo, 3],
181
+ device=s.device)
182
+
183
+ if self.vo:
184
+ return (s, v)
185
+ elif self.tuple_io:
186
+ return (s, None)
187
+ else:
188
+ return s
189
+
190
+
191
+ class _VDropout(nn.Module):
192
+ '''
193
+ Vector channel dropout where the elements of each
194
+ vector channel are dropped together.
195
+ '''
196
+ def __init__(self, drop_rate):
197
+ super(_VDropout, self).__init__()
198
+ self.drop_rate = drop_rate
199
+
200
+ def forward(self, x):
201
+ '''
202
+ :param x: `torch.Tensor` corresponding to vector channels
203
+ '''
204
+ if x is None:
205
+ return None
206
+ device = x.device
207
+ if not self.training:
208
+ return x
209
+ mask = torch.bernoulli(
210
+ (1 - self.drop_rate) * torch.ones(x.shape[:-1], device=device)
211
+ ).unsqueeze(-1)
212
+ x = mask * x / (1 - self.drop_rate)
213
+ return x
214
+
215
+ class Dropout(nn.Module):
216
+ '''
217
+ Combined dropout for tuples (s, V).
218
+ Takes tuples (s, V) as input and as output.
219
+ '''
220
+ def __init__(self, drop_rate):
221
+ super(Dropout, self).__init__()
222
+ self.sdropout = nn.Dropout(drop_rate)
223
+ self.vdropout = _VDropout(drop_rate)
224
+
225
+ def forward(self, x):
226
+ '''
227
+ :param x: tuple (s, V) of `torch.Tensor`,
228
+ or single `torch.Tensor`
229
+ (will be assumed to be scalar channels)
230
+ '''
231
+ if type(x) is torch.Tensor:
232
+ return self.sdropout(x)
233
+ s, v = x
234
+ return self.sdropout(s), self.vdropout(v)
235
+
236
+ class LayerNorm(nn.Module):
237
+ '''
238
+ Combined LayerNorm for tuples (s, V).
239
+ Takes tuples (s, V) as input and as output.
240
+ '''
241
+ def __init__(self, dims, tuple_io=True, eps=1e-8):
242
+ super(LayerNorm, self).__init__()
243
+ self.tuple_io = tuple_io
244
+ self.s, self.v = dims
245
+ self.scalar_norm = nn.LayerNorm(self.s)
246
+ self.eps = eps
247
+
248
+ def forward(self, x):
249
+ '''
250
+ :param x: tuple (s, V) of `torch.Tensor`,
251
+ or single `torch.Tensor`
252
+ (will be assumed to be scalar channels)
253
+ '''
254
+ if not self.v:
255
+ if self.tuple_io:
256
+ return self.scalar_norm(x[0]), None
257
+ return self.scalar_norm(x)
258
+ s, v = x
259
+ vn = _norm_no_nan(v, axis=-1, keepdims=True, sqrt=False, eps=self.eps)
260
+ nonzero_mask = (vn > 2 * self.eps)
261
+ vn = torch.sum(vn * nonzero_mask, dim=-2, keepdim=True
262
+ ) / (self.eps + torch.sum(nonzero_mask, dim=-2, keepdim=True))
263
+ vn = torch.sqrt(vn + self.eps)
264
+ v = nonzero_mask * (v / vn)
265
+ return self.scalar_norm(s), v
266
+
267
+ class GVPConv(MessagePassing):
268
+ '''
269
+ Graph convolution / message passing with Geometric Vector Perceptrons.
270
+ Takes in a graph with node and edge embeddings,
271
+ and returns new node embeddings.
272
+
273
+ This does NOT do residual updates and pointwise feedforward layers
274
+ ---see `GVPConvLayer`.
275
+
276
+ :param in_dims: input node embedding dimensions (n_scalar, n_vector)
277
+ :param out_dims: output node embedding dimensions (n_scalar, n_vector)
278
+ :param edge_dims: input edge embedding dimensions (n_scalar, n_vector)
279
+ :param n_layers: number of GVPs in the message function
280
+ :param module_list: preconstructed message function, overrides n_layers
281
+ :param aggr: should be "add" if some incoming edges are masked, as in
282
+ a masked autoregressive decoder architecture
283
+ '''
284
+ def __init__(self, in_dims, out_dims, edge_dims, n_layers=3,
285
+ vector_gate=False, module_list=None, aggr="mean", eps=1e-8,
286
+ activations=(F.relu, torch.sigmoid)):
287
+ super(GVPConv, self).__init__(aggr=aggr)
288
+ self.eps = eps
289
+ self.si, self.vi = in_dims
290
+ self.so, self.vo = out_dims
291
+ self.se, self.ve = edge_dims
292
+
293
+ module_list = module_list or []
294
+ if not module_list:
295
+ if n_layers == 1:
296
+ module_list.append(
297
+ GVP((2*self.si + self.se, 2*self.vi + self.ve),
298
+ (self.so, self.vo), activations=(None, None)))
299
+ else:
300
+ module_list.append(
301
+ GVP((2*self.si + self.se, 2*self.vi + self.ve), out_dims,
302
+ vector_gate=vector_gate, activations=activations)
303
+ )
304
+ for i in range(n_layers - 2):
305
+ module_list.append(GVP(out_dims, out_dims,
306
+ vector_gate=vector_gate))
307
+ module_list.append(GVP(out_dims, out_dims,
308
+ activations=(None, None)))
309
+ self.message_func = nn.Sequential(*module_list)
310
+
311
+ def forward(self, x, edge_index, edge_attr):
312
+ '''
313
+ :param x: tuple (s, V) of `torch.Tensor`
314
+ :param edge_index: array of shape [2, n_edges]
315
+ :param edge_attr: tuple (s, V) of `torch.Tensor`
316
+ '''
317
+ x_s, x_v = x
318
+ message = self.propagate(edge_index,
319
+ s=x_s, v=x_v.reshape(x_v.shape[0], 3*x_v.shape[1]),
320
+ edge_attr=edge_attr)
321
+ return _split(message, self.vo)
322
+
323
+ def message(self, s_i, v_i, s_j, v_j, edge_attr):
324
+ v_j = v_j.view(v_j.shape[0], v_j.shape[1]//3, 3)
325
+ v_i = v_i.view(v_i.shape[0], v_i.shape[1]//3, 3)
326
+ message = tuple_cat((s_j, v_j), edge_attr, (s_i, v_i))
327
+ message = self.message_func(message)
328
+ return _merge(*message)
329
+
330
+
331
+ class GVPConvLayer(nn.Module):
332
+ '''
333
+ Full graph convolution / message passing layer with
334
+ Geometric Vector Perceptrons. Residually updates node embeddings with
335
+ aggregated incoming messages, applies a pointwise feedforward
336
+ network to node embeddings, and returns updated node embeddings.
337
+
338
+ To only compute the aggregated messages, see `GVPConv`.
339
+
340
+ :param node_dims: node embedding dimensions (n_scalar, n_vector)
341
+ :param edge_dims: input edge embedding dimensions (n_scalar, n_vector)
342
+ :param n_message: number of GVPs to use in message function
343
+ :param n_feedforward: number of GVPs to use in feedforward function
344
+ :param drop_rate: drop probability in all dropout layers
345
+ :param autoregressive: if `True`, this `GVPConvLayer` will be used
346
+ with a different set of input node embeddings for messages
347
+ where src >= dst
348
+ '''
349
+ def __init__(self, node_dims, edge_dims, vector_gate=False,
350
+ n_message=3, n_feedforward=2, drop_rate=.1,
351
+ autoregressive=False, attention_heads=0,
352
+ conv_activations=(F.relu, torch.sigmoid),
353
+ n_edge_gvps=0, layernorm=True, eps=1e-8):
354
+
355
+ super(GVPConvLayer, self).__init__()
356
+ if attention_heads == 0:
357
+ self.conv = GVPConv(
358
+ node_dims, node_dims, edge_dims, n_layers=n_message,
359
+ vector_gate=vector_gate,
360
+ aggr="add" if autoregressive else "mean",
361
+ activations=conv_activations,
362
+ eps=eps,
363
+ )
364
+ else:
365
+ raise NotImplementedError
366
+ if layernorm:
367
+ self.norm = nn.ModuleList([LayerNorm(node_dims, eps=eps) for _ in range(2)])
368
+ else:
369
+ self.norm = nn.ModuleList([nn.Identity() for _ in range(2)])
370
+ self.dropout = nn.ModuleList([Dropout(drop_rate) for _ in range(2)])
371
+
372
+ ff_func = []
373
+ if n_feedforward == 1:
374
+ ff_func.append(GVP(node_dims, node_dims, activations=(None, None)))
375
+ else:
376
+ hid_dims = 4*node_dims[0], 2*node_dims[1]
377
+ ff_func.append(GVP(node_dims, hid_dims, vector_gate=vector_gate))
378
+ for i in range(n_feedforward-2):
379
+ ff_func.append(GVP(hid_dims, hid_dims, vector_gate=vector_gate))
380
+ ff_func.append(GVP(hid_dims, node_dims, activations=(None, None)))
381
+ self.ff_func = nn.Sequential(*ff_func)
382
+
383
+ self.edge_message_func = None
384
+ if n_edge_gvps > 0:
385
+ si, vi = node_dims
386
+ se, ve = edge_dims
387
+ module_list = [
388
+ GVP((2*si + se, 2*vi + ve), edge_dims, vector_gate=vector_gate)
389
+ ]
390
+ for i in range(n_edge_gvps - 2):
391
+ module_list.append(GVP(edge_dims, edge_dims,
392
+ vector_gate=vector_gate))
393
+ if n_edge_gvps > 1:
394
+ module_list.append(GVP(edge_dims, edge_dims,
395
+ activations=(None, None)))
396
+ self.edge_message_func = nn.Sequential(*module_list)
397
+ if layernorm:
398
+ self.edge_norm = LayerNorm(edge_dims, eps=eps)
399
+ else:
400
+ self.edge_norm = nn.Identity()
401
+ self.edge_dropout = Dropout(drop_rate)
402
+
403
+ def forward(self, x, edge_index, edge_attr,
404
+ autoregressive_x=None, node_mask=None):
405
+ '''
406
+ :param x: tuple (s, V) of `torch.Tensor`
407
+ :param edge_index: array of shape [2, n_edges]
408
+ :param edge_attr: tuple (s, V) of `torch.Tensor`
409
+ :param autoregressive_x: tuple (s, V) of `torch.Tensor`.
410
+ If not `None`, will be used as srcqq node embeddings
411
+ for forming messages where src >= dst. The corrent node
412
+ embeddings `x` will still be the base of the update and the
413
+ pointwise feedforward.
414
+ :param node_mask: array of type `bool` to index into the first
415
+ dim of node embeddings (s, V). If not `None`, only
416
+ these nodes will be updated.
417
+ '''
418
+ if self.edge_message_func:
419
+ src, dst = edge_index
420
+ if autoregressive_x is None:
421
+ x_src = x[0][src], x[1][src]
422
+ else:
423
+ mask = (src < dst).unsqueeze(-1)
424
+ x_src = (
425
+ torch.where(mask, x[0][src], autoregressive_x[0][src]),
426
+ torch.where(mask.unsqueeze(-1), x[1][src],
427
+ autoregressive_x[1][src])
428
+ )
429
+ x_dst = x[0][dst], x[1][dst]
430
+ x_edge = (
431
+ torch.cat([x_src[0], edge_attr[0], x_dst[0]], dim=-1),
432
+ torch.cat([x_src[1], edge_attr[1], x_dst[1]], dim=-2)
433
+ )
434
+ edge_attr_dh = self.edge_message_func(x_edge)
435
+ edge_attr = self.edge_norm(tuple_sum(edge_attr,
436
+ self.edge_dropout(edge_attr_dh)))
437
+
438
+ if autoregressive_x is not None:
439
+ # Guarding this import here to remove the dependency on torch_scatter, since this isn't used
440
+ # in ESM-IF1
441
+ from torch_scatter import scatter_add
442
+ src, dst = edge_index
443
+ mask = src < dst
444
+ edge_index_forward = edge_index[:, mask]
445
+ edge_index_backward = edge_index[:, ~mask]
446
+ edge_attr_forward = tuple_index(edge_attr, mask)
447
+ edge_attr_backward = tuple_index(edge_attr, ~mask)
448
+
449
+ dh = tuple_sum(
450
+ self.conv(x, edge_index_forward, edge_attr_forward),
451
+ self.conv(autoregressive_x, edge_index_backward, edge_attr_backward)
452
+ )
453
+
454
+ count = scatter_add(torch.ones_like(dst), dst,
455
+ dim_size=dh[0].size(0)).clamp(min=1).unsqueeze(-1)
456
+
457
+ dh = dh[0] / count, dh[1] / count.unsqueeze(-1)
458
+
459
+ else:
460
+ dh = self.conv(x, edge_index, edge_attr)
461
+
462
+ if node_mask is not None:
463
+ x_ = x
464
+ x, dh = tuple_index(x, node_mask), tuple_index(dh, node_mask)
465
+
466
+ x = self.norm[0](tuple_sum(x, self.dropout[0](dh)))
467
+
468
+ dh = self.ff_func(x)
469
+ x = self.norm[1](tuple_sum(x, self.dropout[1](dh)))
470
+
471
+ if node_mask is not None:
472
+ x_[0][node_mask], x_[1][node_mask] = x[0], x[1]
473
+ x = x_
474
+
475
+ return x, edge_attr
model/esm/inverse_folding/gvp_transformer.py ADDED
@@ -0,0 +1,140 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright (c) Meta Platforms, Inc. and affiliates.
2
+ #
3
+ # This source code is licensed under the MIT license found in the
4
+ # LICENSE file in the root directory of this source tree.
5
+
6
+ import argparse
7
+ from typing import Any, Dict, List, Optional, Tuple, NamedTuple
8
+ import torch
9
+ from torch import nn
10
+ from torch import Tensor
11
+ import torch.nn.functional as F
12
+ from scipy.spatial import transform
13
+
14
+ from onescience.datapipes.esm import Alphabet
15
+
16
+ from .features import DihedralFeatures
17
+ from .gvp_encoder import GVPEncoder
18
+ from .gvp_utils import unflatten_graph
19
+ from .gvp_transformer_encoder import GVPTransformerEncoder
20
+ from .transformer_decoder import TransformerDecoder
21
+ from .util import rotate, CoordBatchConverter
22
+
23
+
24
+ class GVPTransformerModel(nn.Module):
25
+ """
26
+ GVP-Transformer inverse folding model.
27
+
28
+ Architecture: Geometric GVP-GNN as initial layers, followed by
29
+ sequence-to-sequence Transformer encoder and decoder.
30
+ """
31
+
32
+ def __init__(self, args, alphabet):
33
+ super().__init__()
34
+ encoder_embed_tokens = self.build_embedding(
35
+ args, alphabet, args.encoder_embed_dim,
36
+ )
37
+ decoder_embed_tokens = self.build_embedding(
38
+ args, alphabet, args.decoder_embed_dim,
39
+ )
40
+ encoder = self.build_encoder(args, alphabet, encoder_embed_tokens)
41
+ decoder = self.build_decoder(args, alphabet, decoder_embed_tokens)
42
+ self.args = args
43
+ self.encoder = encoder
44
+ self.decoder = decoder
45
+
46
+ @classmethod
47
+ def build_encoder(cls, args, src_dict, embed_tokens):
48
+ encoder = GVPTransformerEncoder(args, src_dict, embed_tokens)
49
+ return encoder
50
+
51
+ @classmethod
52
+ def build_decoder(cls, args, tgt_dict, embed_tokens):
53
+ decoder = TransformerDecoder(
54
+ args,
55
+ tgt_dict,
56
+ embed_tokens,
57
+ )
58
+ return decoder
59
+
60
+ @classmethod
61
+ def build_embedding(cls, args, dictionary, embed_dim):
62
+ num_embeddings = len(dictionary)
63
+ padding_idx = dictionary.padding_idx
64
+ emb = nn.Embedding(num_embeddings, embed_dim, padding_idx)
65
+ nn.init.normal_(emb.weight, mean=0, std=embed_dim ** -0.5)
66
+ nn.init.constant_(emb.weight[padding_idx], 0)
67
+ return emb
68
+
69
+ def forward(
70
+ self,
71
+ coords,
72
+ padding_mask,
73
+ confidence,
74
+ prev_output_tokens,
75
+ return_all_hiddens: bool = False,
76
+ features_only: bool = False,
77
+ ):
78
+ encoder_out = self.encoder(coords, padding_mask, confidence,
79
+ return_all_hiddens=return_all_hiddens)
80
+ logits, extra = self.decoder(
81
+ prev_output_tokens,
82
+ encoder_out=encoder_out,
83
+ features_only=features_only,
84
+ return_all_hiddens=return_all_hiddens,
85
+ )
86
+ return logits, extra
87
+
88
+ def sample(self, coords, partial_seq=None, temperature=1.0, confidence=None, device=None):
89
+ """
90
+ Samples sequences based on multinomial sampling (no beam search).
91
+
92
+ Args:
93
+ coords: L x 3 x 3 list representing one backbone
94
+ partial_seq: Optional, partial sequence with mask tokens if part of
95
+ the sequence is known
96
+ temperature: sampling temperature, use low temperature for higher
97
+ sequence recovery and high temperature for higher diversity
98
+ confidence: optional length L list of confidence scores for coordinates
99
+ """
100
+ L = len(coords)
101
+ # Convert to batch format
102
+ batch_converter = CoordBatchConverter(self.decoder.dictionary)
103
+ batch_coords, confidence, _, _, padding_mask = (
104
+ batch_converter([(coords, confidence, None)], device=device)
105
+ )
106
+
107
+ # Start with prepend token
108
+ mask_idx = self.decoder.dictionary.get_idx('<mask>')
109
+ sampled_tokens = torch.full((1, 1+L), mask_idx, dtype=int)
110
+ sampled_tokens[0, 0] = self.decoder.dictionary.get_idx('<cath>')
111
+ if partial_seq is not None:
112
+ for i, c in enumerate(partial_seq):
113
+ sampled_tokens[0, i+1] = self.decoder.dictionary.get_idx(c)
114
+
115
+ # Save incremental states for faster sampling
116
+ incremental_state = dict()
117
+
118
+ # Run encoder only once
119
+ encoder_out = self.encoder(batch_coords, padding_mask, confidence)
120
+
121
+ # Make sure all tensors are on the same device if a GPU is present
122
+ if device:
123
+ sampled_tokens = sampled_tokens.to(device)
124
+
125
+ # Decode one token at a time
126
+ for i in range(1, L+1):
127
+ logits, _ = self.decoder(
128
+ sampled_tokens[:, :i],
129
+ encoder_out,
130
+ incremental_state=incremental_state,
131
+ )
132
+ logits = logits[0].transpose(0, 1)
133
+ logits /= temperature
134
+ probs = F.softmax(logits, dim=-1)
135
+ if sampled_tokens[0, i] == mask_idx:
136
+ sampled_tokens[:, i] = torch.multinomial(probs, 1).squeeze(-1)
137
+ sampled_seq = sampled_tokens[0, 1:]
138
+
139
+ # Convert back to string via lookup
140
+ return ''.join([self.decoder.dictionary.get_tok(a) for a in sampled_seq])
model/esm/inverse_folding/gvp_transformer_encoder.py ADDED
@@ -0,0 +1,184 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright (c) Meta Platforms, Inc. and affiliates.
2
+ #
3
+ # Contents of this file were adapted from the open source fairseq repository.
4
+ #
5
+ # This source code is licensed under the MIT license found in the
6
+ # LICENSE file in the root directory of this source tree.
7
+
8
+ import argparse
9
+ import math
10
+ from typing import Dict, List, Optional
11
+
12
+ import torch
13
+ import torch.nn as nn
14
+ from torch import Tensor
15
+
16
+ from onescience.modules.esm import SinusoidalPositionalEmbedding
17
+ from .features import GVPInputFeaturizer, DihedralFeatures
18
+ from .gvp_encoder import GVPEncoder
19
+ from .transformer_layer import TransformerEncoderLayer
20
+ from .util import nan_to_num, get_rotation_frames, rotate, rbf
21
+
22
+
23
+ class GVPTransformerEncoder(nn.Module):
24
+ """
25
+ Transformer encoder consisting of *args.encoder.layers* layers. Each layer
26
+ is a :class:`TransformerEncoderLayer`.
27
+
28
+ Args:
29
+ args (argparse.Namespace): parsed command-line arguments
30
+ dictionary (~fairseq.data.Dictionary): encoding dictionary
31
+ embed_tokens (torch.nn.Embedding): input embedding
32
+ """
33
+
34
+ def __init__(self, args, dictionary, embed_tokens):
35
+ super().__init__()
36
+ self.args = args
37
+ self.dictionary = dictionary
38
+
39
+ self.dropout_module = nn.Dropout(args.dropout)
40
+
41
+ embed_dim = embed_tokens.embedding_dim
42
+ self.padding_idx = embed_tokens.padding_idx
43
+
44
+ self.embed_tokens = embed_tokens
45
+ self.embed_scale = math.sqrt(embed_dim)
46
+ self.embed_positions = SinusoidalPositionalEmbedding(
47
+ embed_dim,
48
+ self.padding_idx,
49
+ )
50
+ self.embed_gvp_input_features = nn.Linear(15, embed_dim)
51
+ self.embed_confidence = nn.Linear(16, embed_dim)
52
+ self.embed_dihedrals = DihedralFeatures(embed_dim)
53
+
54
+ gvp_args = argparse.Namespace()
55
+ for k, v in vars(args).items():
56
+ if k.startswith("gvp_"):
57
+ setattr(gvp_args, k[4:], v)
58
+ self.gvp_encoder = GVPEncoder(gvp_args)
59
+ gvp_out_dim = gvp_args.node_hidden_dim_scalar + (3 *
60
+ gvp_args.node_hidden_dim_vector)
61
+ self.embed_gvp_output = nn.Linear(gvp_out_dim, embed_dim)
62
+
63
+ self.layers = nn.ModuleList([])
64
+ self.layers.extend(
65
+ [self.build_encoder_layer(args) for i in range(args.encoder_layers)]
66
+ )
67
+ self.num_layers = len(self.layers)
68
+ self.layer_norm = nn.LayerNorm(embed_dim)
69
+
70
+ def build_encoder_layer(self, args):
71
+ return TransformerEncoderLayer(args)
72
+
73
+ def forward_embedding(self, coords, padding_mask, confidence):
74
+ """
75
+ Args:
76
+ coords: N, CA, C backbone coordinates in shape length x 3 (atoms) x 3
77
+ padding_mask: boolean Tensor (true for padding) of shape length
78
+ confidence: confidence scores between 0 and 1 of shape length
79
+ """
80
+ components = dict()
81
+ coord_mask = torch.all(torch.all(torch.isfinite(coords), dim=-1), dim=-1)
82
+ coords = nan_to_num(coords)
83
+ mask_tokens = (
84
+ padding_mask * self.dictionary.padding_idx +
85
+ ~padding_mask * self.dictionary.get_idx("<mask>")
86
+ )
87
+ components["tokens"] = self.embed_tokens(mask_tokens) * self.embed_scale
88
+ components["diherals"] = self.embed_dihedrals(coords)
89
+
90
+ # GVP encoder
91
+ gvp_out_scalars, gvp_out_vectors = self.gvp_encoder(coords,
92
+ coord_mask, padding_mask, confidence)
93
+ R = get_rotation_frames(coords)
94
+ # Rotate to local rotation frame for rotation-invariance
95
+ gvp_out_features = torch.cat([
96
+ gvp_out_scalars,
97
+ rotate(gvp_out_vectors, R.transpose(-2, -1)).flatten(-2, -1),
98
+ ], dim=-1)
99
+ components["gvp_out"] = self.embed_gvp_output(gvp_out_features)
100
+
101
+ components["confidence"] = self.embed_confidence(
102
+ rbf(confidence, 0., 1.))
103
+
104
+ # In addition to GVP encoder outputs, also directly embed GVP input node
105
+ # features to the Transformer
106
+ scalar_features, vector_features = GVPInputFeaturizer.get_node_features(
107
+ coords, coord_mask, with_coord_mask=False)
108
+ features = torch.cat([
109
+ scalar_features,
110
+ rotate(vector_features, R.transpose(-2, -1)).flatten(-2, -1),
111
+ ], dim=-1)
112
+ components["gvp_input_features"] = self.embed_gvp_input_features(features)
113
+
114
+ embed = sum(components.values())
115
+ # for k, v in components.items():
116
+ # print(k, torch.mean(v, dim=(0,1)), torch.std(v, dim=(0,1)))
117
+
118
+ x = embed
119
+ x = x + self.embed_positions(mask_tokens)
120
+ x = self.dropout_module(x)
121
+ return x, components
122
+
123
+ def forward(
124
+ self,
125
+ coords,
126
+ encoder_padding_mask,
127
+ confidence,
128
+ return_all_hiddens: bool = False,
129
+ ):
130
+ """
131
+ Args:
132
+ coords (Tensor): backbone coordinates
133
+ shape batch_size x num_residues x num_atoms (3 for N, CA, C) x 3
134
+ encoder_padding_mask (ByteTensor): the positions of
135
+ padding elements of shape `(batch_size x num_residues)`
136
+ confidence (Tensor): the confidence score of shape (batch_size x
137
+ num_residues). The value is between 0. and 1. for each residue
138
+ coordinate, or -1. if no coordinate is given
139
+ return_all_hiddens (bool, optional): also return all of the
140
+ intermediate hidden states (default: False).
141
+
142
+ Returns:
143
+ dict:
144
+ - **encoder_out** (Tensor): the last encoder layer's output of
145
+ shape `(num_residues, batch_size, embed_dim)`
146
+ - **encoder_padding_mask** (ByteTensor): the positions of
147
+ padding elements of shape `(batch_size, num_residues)`
148
+ - **encoder_embedding** (Tensor): the (scaled) embedding lookup
149
+ of shape `(batch_size, num_residues, embed_dim)`
150
+ - **encoder_states** (List[Tensor]): all intermediate
151
+ hidden states of shape `(num_residues, batch_size, embed_dim)`.
152
+ Only populated if *return_all_hiddens* is True.
153
+ """
154
+ x, encoder_embedding = self.forward_embedding(coords,
155
+ encoder_padding_mask, confidence)
156
+ # account for padding while computing the representation
157
+ x = x * (1 - encoder_padding_mask.unsqueeze(-1).type_as(x))
158
+
159
+ # B x T x C -> T x B x C
160
+ x = x.transpose(0, 1)
161
+
162
+ encoder_states = []
163
+
164
+ if return_all_hiddens:
165
+ encoder_states.append(x)
166
+
167
+ # encoder layers
168
+ for layer in self.layers:
169
+ x = layer(
170
+ x, encoder_padding_mask=encoder_padding_mask
171
+ )
172
+ if return_all_hiddens:
173
+ assert encoder_states is not None
174
+ encoder_states.append(x)
175
+
176
+ if self.layer_norm is not None:
177
+ x = self.layer_norm(x)
178
+
179
+ return {
180
+ "encoder_out": [x], # T x B x C
181
+ "encoder_padding_mask": [encoder_padding_mask], # B x T
182
+ "encoder_embedding": [encoder_embedding], # dictionary
183
+ "encoder_states": encoder_states, # List[T x B x C]
184
+ }
model/esm/inverse_folding/gvp_utils.py ADDED
@@ -0,0 +1,68 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright (c) Meta Platforms, Inc. and affiliates.
2
+ #
3
+ # This source code is licensed under the MIT license found in the
4
+ # LICENSE file in the root directory of this source tree.
5
+
6
+ import torch
7
+
8
+
9
+ def flatten_graph(node_embeddings, edge_embeddings, edge_index):
10
+ """
11
+ Flattens the graph into a batch size one (with disconnected subgraphs for
12
+ each example) to be compatible with pytorch-geometric package.
13
+ Args:
14
+ node_embeddings: node embeddings in tuple form (scalar, vector)
15
+ - scalar: shape batch size x nodes x node_embed_dim
16
+ - vector: shape batch size x nodes x node_embed_dim x 3
17
+ edge_embeddings: edge embeddings of in tuple form (scalar, vector)
18
+ - scalar: shape batch size x edges x edge_embed_dim
19
+ - vector: shape batch size x edges x edge_embed_dim x 3
20
+ edge_index: shape batch_size x 2 (source node and target node) x edges
21
+ Returns:
22
+ node_embeddings: node embeddings in tuple form (scalar, vector)
23
+ - scalar: shape batch total_nodes x node_embed_dim
24
+ - vector: shape batch total_nodes x node_embed_dim x 3
25
+ edge_embeddings: edge embeddings of in tuple form (scalar, vector)
26
+ - scalar: shape batch total_edges x edge_embed_dim
27
+ - vector: shape batch total_edges x edge_embed_dim x 3
28
+ edge_index: shape 2 x total_edges
29
+ """
30
+ x_s, x_v = node_embeddings
31
+ e_s, e_v = edge_embeddings
32
+ batch_size, N = x_s.shape[0], x_s.shape[1]
33
+ node_embeddings = (torch.flatten(x_s, 0, 1), torch.flatten(x_v, 0, 1))
34
+ edge_embeddings = (torch.flatten(e_s, 0, 1), torch.flatten(e_v, 0, 1))
35
+
36
+ edge_mask = torch.any(edge_index != -1, dim=1)
37
+ # Re-number the nodes by adding batch_idx * N to each batch
38
+ edge_index = edge_index + (torch.arange(batch_size, device=edge_index.device) *
39
+ N).unsqueeze(-1).unsqueeze(-1)
40
+ edge_index = edge_index.permute(1, 0, 2).flatten(1, 2)
41
+ edge_mask = edge_mask.flatten()
42
+ edge_index = edge_index[:, edge_mask]
43
+ edge_embeddings = (
44
+ edge_embeddings[0][edge_mask, :],
45
+ edge_embeddings[1][edge_mask, :]
46
+ )
47
+ return node_embeddings, edge_embeddings, edge_index
48
+
49
+
50
+ def unflatten_graph(node_embeddings, batch_size):
51
+ """
52
+ Unflattens node embeddings.
53
+ Args:
54
+ node_embeddings: node embeddings in tuple form (scalar, vector)
55
+ - scalar: shape batch total_nodes x node_embed_dim
56
+ - vector: shape batch total_nodes x node_embed_dim x 3
57
+ batch_size: int
58
+ Returns:
59
+ node_embeddings: node embeddings in tuple form (scalar, vector)
60
+ - scalar: shape batch size x nodes x node_embed_dim
61
+ - vector: shape batch size x nodes x node_embed_dim x 3
62
+ """
63
+ x_s, x_v = node_embeddings
64
+ x_s = x_s.reshape(batch_size, -1, x_s.shape[1])
65
+ x_v = x_v.reshape(batch_size, -1, x_v.shape[1], x_v.shape[2])
66
+ return (x_s, x_v)
67
+
68
+
model/esm/inverse_folding/multichain_util.py ADDED
@@ -0,0 +1,152 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright (c) Meta Platforms, Inc. and affiliates.
2
+ #
3
+ # This source code is licensed under the MIT license found in the
4
+ # LICENSE file in the root directory of this source tree.
5
+
6
+ import biotite.structure
7
+ import numpy as np
8
+ import torch
9
+ from typing import Sequence, Tuple, List
10
+
11
+ from model.esm.inverse_folding.util import (
12
+ load_structure,
13
+ extract_coords_from_structure,
14
+ load_coords,
15
+ get_sequence_loss,
16
+ get_encoder_output,
17
+ )
18
+
19
+
20
+ def extract_coords_from_complex(structure: biotite.structure.AtomArray):
21
+ """
22
+ Args:
23
+ structure: biotite AtomArray
24
+ Returns:
25
+ Tuple (coords_list, seq_list)
26
+ - coords: Dictionary mapping chain ids to L x 3 x 3 array for N, CA, C
27
+ coordinates representing the backbone of each chain
28
+ - seqs: Dictionary mapping chain ids to native sequences of each chain
29
+ """
30
+ coords = {}
31
+ seqs = {}
32
+ all_chains = biotite.structure.get_chains(structure)
33
+ for chain_id in all_chains:
34
+ chain = structure[structure.chain_id == chain_id]
35
+ coords[chain_id], seqs[chain_id] = extract_coords_from_structure(chain)
36
+ return coords, seqs
37
+
38
+
39
+ def load_complex_coords(fpath, chains):
40
+ """
41
+ Args:
42
+ fpath: filepath to either pdb or cif file
43
+ chains: the chain ids (the order matters for autoregressive model)
44
+ Returns:
45
+ Tuple (coords_list, seq_list)
46
+ - coords: Dictionary mapping chain ids to L x 3 x 3 array for N, CA, C
47
+ coordinates representing the backbone of each chain
48
+ - seqs: Dictionary mapping chain ids to native sequences of each chain
49
+ """
50
+ structure = load_structure(fpath, chains)
51
+ return extract_coords_from_complex(structure)
52
+
53
+
54
+ def _concatenate_coords(coords, target_chain_id, padding_length=10):
55
+ """
56
+ Args:
57
+ coords: Dictionary mapping chain ids to L x 3 x 3 array for N, CA, C
58
+ coordinates representing the backbone of each chain
59
+ target_chain_id: The chain id to sample sequences for
60
+ padding_length: Length of padding between concatenated chains
61
+ Returns:
62
+ Tuple (coords, seq)
63
+ - coords is an L x 3 x 3 array for N, CA, C coordinates, a
64
+ concatenation of the chains with padding in between
65
+ - seq is the extracted sequence, with padding tokens inserted
66
+ between the concatenated chains
67
+ """
68
+ pad_coords = np.full((padding_length, 3, 3), np.nan, dtype=np.float32)
69
+ # For best performance, put the target chain first in concatenation.
70
+ coords_list = [coords[target_chain_id]]
71
+ for chain_id in coords:
72
+ if chain_id == target_chain_id:
73
+ continue
74
+ coords_list.append(pad_coords)
75
+ coords_list.append(coords[chain_id])
76
+ coords_concatenated = np.concatenate(coords_list, axis=0)
77
+ return coords_concatenated
78
+
79
+
80
+ def sample_sequence_in_complex(model, coords, target_chain_id, temperature=1.,
81
+ padding_length=10):
82
+ """
83
+ Samples sequence for one chain in a complex.
84
+ Args:
85
+ model: An instance of the GVPTransformer model
86
+ coords: Dictionary mapping chain ids to L x 3 x 3 array for N, CA, C
87
+ coordinates representing the backbone of each chain
88
+ target_chain_id: The chain id to sample sequences for
89
+ padding_length: padding length in between chains
90
+ Returns:
91
+ Sampled sequence for the target chain
92
+ """
93
+ target_chain_len = coords[target_chain_id].shape[0]
94
+ all_coords = _concatenate_coords(coords, target_chain_id)
95
+ device = next(model.parameters()).device
96
+
97
+ # Supply padding tokens for other chains to avoid unused sampling for speed
98
+ padding_pattern = ['<pad>'] * all_coords.shape[0]
99
+ for i in range(target_chain_len):
100
+ padding_pattern[i] = '<mask>'
101
+ sampled = model.sample(all_coords, partial_seq=padding_pattern,
102
+ temperature=temperature, device=device)
103
+ sampled = sampled[:target_chain_len]
104
+ return sampled
105
+
106
+
107
+ def score_sequence_in_complex(model, alphabet, coords, target_chain_id,
108
+ target_seq, padding_length=10):
109
+ """
110
+ Scores sequence for one chain in a complex.
111
+ Args:
112
+ model: An instance of the GVPTransformer model
113
+ alphabet: Alphabet for the model
114
+ coords: Dictionary mapping chain ids to L x 3 x 3 array for N, CA, C
115
+ coordinates representing the backbone of each chain
116
+ target_chain_id: The chain id to sample sequences for
117
+ target_seq: Target sequence for the target chain for scoring.
118
+ padding_length: padding length in between chains
119
+ Returns:
120
+ Tuple (ll_fullseq, ll_withcoord)
121
+ - ll_fullseq: Average log-likelihood over the full target chain
122
+ - ll_withcoord: Average log-likelihood in target chain excluding those
123
+ residues without coordinates
124
+ """
125
+ all_coords = _concatenate_coords(coords, target_chain_id)
126
+
127
+ loss, target_padding_mask = get_sequence_loss(model, alphabet, all_coords,
128
+ target_seq)
129
+ ll_fullseq = -np.sum(loss * ~target_padding_mask) / np.sum(
130
+ ~target_padding_mask)
131
+
132
+ # Also calculate average when excluding masked portions
133
+ coord_mask = np.all(np.isfinite(coords[target_chain_id]), axis=(-1, -2))
134
+ ll_withcoord = -np.sum(loss * coord_mask) / np.sum(coord_mask)
135
+ return ll_fullseq, ll_withcoord
136
+
137
+
138
+ def get_encoder_output_for_complex(model, alphabet, coords, target_chain_id):
139
+ """
140
+ Args:
141
+ model: An instance of the GVPTransformer model
142
+ alphabet: Alphabet for the model
143
+ coords: Dictionary mapping chain ids to L x 3 x 3 array for N, CA, C
144
+ coordinates representing the backbone of each chain
145
+ target_chain_id: The chain id to sample sequences for
146
+ Returns:
147
+ Dictionary mapping chain id to encoder output for each chain
148
+ """
149
+ all_coords = _concatenate_coords(coords, target_chain_id)
150
+ all_rep = get_encoder_output(model, alphabet, all_coords)
151
+ target_chain_len = coords[target_chain_id].shape[0]
152
+ return all_rep[:target_chain_len]
model/esm/inverse_folding/transformer_decoder.py ADDED
@@ -0,0 +1,228 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright (c) Meta Platforms, Inc. and affiliates.
2
+ #
3
+ # Contents of this file were adapted from the open source fairseq repository.
4
+ #
5
+ # This source code is licensed under the MIT license found in the
6
+ # LICENSE file in the root directory of this source tree.
7
+
8
+ import math
9
+ from typing import Any, Dict, List, Optional
10
+
11
+ import torch
12
+ import torch.nn as nn
13
+ from torch import Tensor
14
+
15
+ from onescience.modules.esm import SinusoidalPositionalEmbedding
16
+ from .transformer_layer import TransformerDecoderLayer
17
+
18
+
19
+ def fill_with_neg_inf(t):
20
+ """FP16-compatible function that fills a tensor with -inf."""
21
+ return t.float().fill_(float("-inf")).type_as(t)
22
+
23
+
24
+ class TransformerDecoder(nn.Module):
25
+ """
26
+ Transformer decoder consisting of *args.decoder.layers* layers. Each layer
27
+ is a :class:`TransformerDecoderLayer`.
28
+
29
+ Args:
30
+ args (argparse.Namespace): parsed command-line arguments
31
+ dictionary (~fairseq.data.Dictionary): decoding dictionary
32
+ embed_tokens (torch.nn.Embedding): output embedding
33
+ no_encoder_attn (bool, optional): whether to attend to encoder outputs
34
+ (default: False).
35
+ """
36
+
37
+ def __init__(
38
+ self,
39
+ args,
40
+ dictionary,
41
+ embed_tokens,
42
+ ):
43
+ super().__init__()
44
+ self.args = args
45
+ self.dictionary = dictionary
46
+ self._future_mask = torch.empty(0)
47
+
48
+ self.dropout_module = nn.Dropout(args.dropout)
49
+
50
+ input_embed_dim = embed_tokens.embedding_dim
51
+ embed_dim = args.decoder_embed_dim
52
+ self.embed_dim = embed_dim
53
+
54
+ self.padding_idx = embed_tokens.padding_idx
55
+
56
+ self.embed_tokens = embed_tokens
57
+ self.embed_scale = math.sqrt(embed_dim)
58
+
59
+ self.project_in_dim = (
60
+ nn.Linear(input_embed_dim, embed_dim, bias=False)
61
+ if embed_dim != input_embed_dim
62
+ else None
63
+ )
64
+ self.embed_positions = SinusoidalPositionalEmbedding(
65
+ embed_dim,
66
+ self.padding_idx,
67
+ )
68
+
69
+ self.layers = nn.ModuleList([])
70
+ self.layers.extend(
71
+ [
72
+ self.build_decoder_layer(args)
73
+ for _ in range(args.decoder_layers)
74
+ ]
75
+ )
76
+ self.num_layers = len(self.layers)
77
+ self.layer_norm = nn.LayerNorm(embed_dim)
78
+
79
+ self.build_output_projection(args, dictionary)
80
+
81
+ def build_output_projection(self, args, dictionary):
82
+ self.output_projection = nn.Linear(
83
+ args.decoder_embed_dim, len(dictionary), bias=False
84
+ )
85
+ nn.init.normal_(
86
+ self.output_projection.weight, mean=0, std=args.decoder_embed_dim ** -0.5
87
+ )
88
+
89
+ def build_decoder_layer(self, args):
90
+ return TransformerDecoderLayer(args)
91
+
92
+ def forward(
93
+ self,
94
+ prev_output_tokens,
95
+ encoder_out: Optional[Dict[str, List[Tensor]]] = None,
96
+ incremental_state: Optional[Dict[str, Dict[str, Optional[Tensor]]]] = None,
97
+ features_only: bool = False,
98
+ return_all_hiddens: bool = False,
99
+ ):
100
+ """
101
+ Args:
102
+ prev_output_tokens (LongTensor): previous decoder outputs of shape
103
+ `(batch, tgt_len)`, for teacher forcing
104
+ encoder_out (optional): output from the encoder, used for
105
+ encoder-side attention, should be of size T x B x C
106
+ incremental_state (dict): dictionary used for storing state during
107
+ :ref:`Incremental decoding`
108
+ features_only (bool, optional): only return features without
109
+ applying output layer (default: False).
110
+
111
+ Returns:
112
+ tuple:
113
+ - the decoder's output of shape `(batch, tgt_len, vocab)`
114
+ - a dictionary with any model-specific outputs
115
+ """
116
+
117
+ x, extra = self.extract_features(
118
+ prev_output_tokens,
119
+ encoder_out=encoder_out,
120
+ incremental_state=incremental_state,
121
+ )
122
+
123
+ if not features_only:
124
+ x = self.output_layer(x)
125
+ x = x.transpose(1, 2) # B x T x C -> B x C x T
126
+ return x, extra
127
+
128
+ def extract_features(
129
+ self,
130
+ prev_output_tokens,
131
+ encoder_out: Optional[Dict[str, List[Tensor]]],
132
+ incremental_state: Optional[Dict[str, Dict[str, Optional[Tensor]]]] = None,
133
+ ):
134
+ """
135
+ Similar to *forward* but only return features.
136
+
137
+ Includes several features from "Jointly Learning to Align and
138
+ Translate with Transformer Models" (Garg et al., EMNLP 2019).
139
+
140
+ Returns:
141
+ tuple:
142
+ - the decoder's features of shape `(batch, tgt_len, embed_dim)`
143
+ - a dictionary with any model-specific outputs
144
+ """
145
+ bs, slen = prev_output_tokens.size()
146
+
147
+ enc: Optional[Tensor] = None
148
+ padding_mask: Optional[Tensor] = None
149
+ if encoder_out is not None and len(encoder_out["encoder_out"]) > 0:
150
+ enc = encoder_out["encoder_out"][0]
151
+ assert (
152
+ enc.size()[1] == bs
153
+ ), f"Expected enc.shape == (t, {bs}, c) got {enc.shape}"
154
+ if encoder_out is not None and len(encoder_out["encoder_padding_mask"]) > 0:
155
+ padding_mask = encoder_out["encoder_padding_mask"][0]
156
+
157
+ # embed positions
158
+ positions = self.embed_positions(
159
+ prev_output_tokens
160
+ )
161
+
162
+ if incremental_state is not None:
163
+ prev_output_tokens = prev_output_tokens[:, -1:]
164
+ positions = positions[:, -1:]
165
+
166
+ # embed tokens and positions
167
+ x = self.embed_scale * self.embed_tokens(prev_output_tokens)
168
+
169
+ if self.project_in_dim is not None:
170
+ x = self.project_in_dim(x)
171
+
172
+ x += positions
173
+
174
+ x = self.dropout_module(x)
175
+
176
+ # B x T x C -> T x B x C
177
+ x = x.transpose(0, 1)
178
+
179
+ self_attn_padding_mask: Optional[Tensor] = None
180
+ if prev_output_tokens.eq(self.padding_idx).any():
181
+ self_attn_padding_mask = prev_output_tokens.eq(self.padding_idx)
182
+
183
+ # decoder layers
184
+ attn: Optional[Tensor] = None
185
+ inner_states: List[Optional[Tensor]] = [x]
186
+ for idx, layer in enumerate(self.layers):
187
+ if incremental_state is None:
188
+ self_attn_mask = self.buffered_future_mask(x)
189
+ else:
190
+ self_attn_mask = None
191
+
192
+ x, layer_attn, _ = layer(
193
+ x,
194
+ enc,
195
+ padding_mask,
196
+ incremental_state,
197
+ self_attn_mask=self_attn_mask,
198
+ self_attn_padding_mask=self_attn_padding_mask,
199
+ need_attn=False,
200
+ need_head_weights=False,
201
+ )
202
+ inner_states.append(x)
203
+
204
+ if self.layer_norm is not None:
205
+ x = self.layer_norm(x)
206
+
207
+ # T x B x C -> B x C x T
208
+ x = x.transpose(0, 1)
209
+
210
+ return x, {"inner_states": inner_states}
211
+
212
+ def output_layer(self, features):
213
+ """Project features to the vocabulary size."""
214
+ return self.output_projection(features)
215
+
216
+ def buffered_future_mask(self, tensor):
217
+ dim = tensor.size(0)
218
+ # self._future_mask.device != tensor.device is not working in TorchScript. This is a workaround.
219
+ if (
220
+ self._future_mask.size(0) == 0
221
+ or (not self._future_mask.device == tensor.device)
222
+ or self._future_mask.size(0) < dim
223
+ ):
224
+ self._future_mask = torch.triu(
225
+ fill_with_neg_inf(torch.zeros([dim, dim])), 1
226
+ )
227
+ self._future_mask = self._future_mask.to(tensor)
228
+ return self._future_mask[:dim, :dim]
model/esm/inverse_folding/transformer_layer.py ADDED
@@ -0,0 +1,304 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright (c) Meta Platforms, Inc. and affiliates.
2
+ #
3
+ # Contents of this file were adapted from the open source fairseq repository.
4
+ #
5
+ # This source code is licensed under the MIT license found in the
6
+ # LICENSE file in the root directory of this source tree.
7
+
8
+ from typing import Dict, List, Optional
9
+
10
+ import torch
11
+ import torch.nn as nn
12
+ import torch.nn.functional as F
13
+ from onescience.modules.attention import MultiheadAttention
14
+ from torch import Tensor
15
+
16
+
17
+ class TransformerEncoderLayer(nn.Module):
18
+ """Encoder layer block.
19
+ `layernorm -> dropout -> add residual`
20
+
21
+ Args:
22
+ args (argparse.Namespace): parsed command-line arguments
23
+ """
24
+
25
+ def __init__(self, args):
26
+ super().__init__()
27
+ self.args = args
28
+ self.embed_dim = args.encoder_embed_dim
29
+ self.self_attn = self.build_self_attention(self.embed_dim, args)
30
+ self.self_attn_layer_norm = torch.nn.LayerNorm(self.embed_dim)
31
+ self.dropout_module = nn.Dropout(args.dropout)
32
+ self.activation_fn = F.relu
33
+ self.fc1 = self.build_fc1(
34
+ self.embed_dim,
35
+ args.encoder_ffn_embed_dim,
36
+ )
37
+ self.fc2 = self.build_fc2(
38
+ args.encoder_ffn_embed_dim,
39
+ self.embed_dim,
40
+ )
41
+
42
+ self.final_layer_norm = nn.LayerNorm(self.embed_dim)
43
+
44
+ def build_fc1(self, input_dim, output_dim):
45
+ return nn.Linear(input_dim, output_dim)
46
+
47
+ def build_fc2(self, input_dim, output_dim):
48
+ return nn.Linear(input_dim, output_dim)
49
+
50
+ def build_self_attention(self, embed_dim, args):
51
+ return MultiheadAttention(
52
+ embed_dim,
53
+ args.encoder_attention_heads,
54
+ dropout=args.attention_dropout,
55
+ self_attention=True,
56
+ )
57
+
58
+ def residual_connection(self, x, residual):
59
+ return residual + x
60
+
61
+ def forward(
62
+ self,
63
+ x,
64
+ encoder_padding_mask: Optional[Tensor],
65
+ attn_mask: Optional[Tensor] = None,
66
+ ):
67
+ """
68
+ Args:
69
+ x (Tensor): input to the layer of shape `(seq_len, batch, embed_dim)`
70
+ encoder_padding_mask (ByteTensor): binary ByteTensor of shape
71
+ `(batch, seq_len)` where padding elements are indicated by ``1``.
72
+ attn_mask (ByteTensor): binary tensor of shape `(tgt_len, src_len)`,
73
+ where `tgt_len` is the length of output and `src_len` is the
74
+ length of input, though here both are equal to `seq_len`.
75
+ `attn_mask[tgt_i, src_j] = 1` means that when calculating the
76
+ embedding for `tgt_i`, we exclude (mask out) `src_j`. This is
77
+ useful for strided self-attention.
78
+
79
+ Returns:
80
+ encoded output of shape `(seq_len, batch, embed_dim)`
81
+ """
82
+ # anything in original attn_mask = 1, becomes -1e8
83
+ # anything in original attn_mask = 0, becomes 0
84
+ # Note that we cannot use -inf here, because at some edge cases,
85
+ # the attention weight (before softmax) for some padded element in query
86
+ # will become -inf, which results in NaN in model parameters
87
+ if attn_mask is not None:
88
+ attn_mask = attn_mask.masked_fill(
89
+ attn_mask.to(torch.bool), -1e8 if x.dtype == torch.float32 else -1e4
90
+ )
91
+
92
+ residual = x
93
+ x = self.self_attn_layer_norm(x)
94
+ x, _ = self.self_attn(
95
+ query=x,
96
+ key=x,
97
+ value=x,
98
+ key_padding_mask=encoder_padding_mask,
99
+ need_weights=False,
100
+ attn_mask=attn_mask,
101
+ )
102
+ x = self.dropout_module(x)
103
+ x = self.residual_connection(x, residual)
104
+
105
+ residual = x
106
+ x = self.final_layer_norm(x)
107
+ x = self.activation_fn(self.fc1(x))
108
+ x = self.fc2(x)
109
+ x = self.dropout_module(x)
110
+ x = self.residual_connection(x, residual)
111
+ return x
112
+
113
+
114
+ class TransformerDecoderLayer(nn.Module):
115
+ """Decoder layer block.
116
+ `layernorm -> dropout -> add residual`
117
+
118
+ Args:
119
+ args (argparse.Namespace): parsed command-line arguments
120
+ no_encoder_attn (bool, optional): whether to attend to encoder outputs
121
+ (default: False).
122
+ """
123
+
124
+ def __init__(
125
+ self, args, no_encoder_attn=False, add_bias_kv=False, add_zero_attn=False
126
+ ):
127
+ super().__init__()
128
+ self.embed_dim = args.decoder_embed_dim
129
+ self.dropout_module = nn.Dropout(args.dropout)
130
+
131
+ self.self_attn = self.build_self_attention(
132
+ self.embed_dim,
133
+ args,
134
+ add_bias_kv=add_bias_kv,
135
+ add_zero_attn=add_zero_attn,
136
+ )
137
+ self.nh = self.self_attn.num_heads
138
+ self.head_dim = self.self_attn.head_dim
139
+
140
+ self.activation_fn = F.relu
141
+
142
+ self.self_attn_layer_norm = nn.LayerNorm(self.embed_dim)
143
+
144
+ if no_encoder_attn:
145
+ self.encoder_attn = None
146
+ self.encoder_attn_layer_norm = None
147
+ else:
148
+ self.encoder_attn = self.build_encoder_attention(self.embed_dim, args)
149
+ self.encoder_attn_layer_norm = nn.LayerNorm(self.embed_dim)
150
+
151
+ self.ffn_layernorm = (
152
+ LayerNorm(args.decoder_ffn_embed_dim)
153
+ if getattr(args, "scale_fc", False)
154
+ else None
155
+ )
156
+ self.w_resid = (
157
+ nn.Parameter(
158
+ torch.ones(
159
+ self.embed_dim,
160
+ ),
161
+ requires_grad=True,
162
+ )
163
+ if getattr(args, "scale_resids", False)
164
+ else None
165
+ )
166
+
167
+ self.fc1 = self.build_fc1(
168
+ self.embed_dim,
169
+ args.decoder_ffn_embed_dim,
170
+ )
171
+ self.fc2 = self.build_fc2(
172
+ args.decoder_ffn_embed_dim,
173
+ self.embed_dim,
174
+ )
175
+
176
+ self.final_layer_norm = nn.LayerNorm(self.embed_dim)
177
+ self.need_attn = True
178
+
179
+ def build_fc1(self, input_dim, output_dim):
180
+ return nn.Linear(input_dim, output_dim)
181
+
182
+ def build_fc2(self, input_dim, output_dim):
183
+ return nn.Linear(input_dim, output_dim)
184
+
185
+ def build_self_attention(
186
+ self, embed_dim, args, add_bias_kv=False, add_zero_attn=False
187
+ ):
188
+ return MultiheadAttention(
189
+ embed_dim,
190
+ args.decoder_attention_heads,
191
+ dropout=args.attention_dropout,
192
+ add_bias_kv=add_bias_kv,
193
+ add_zero_attn=add_zero_attn,
194
+ self_attention=True,
195
+ )
196
+
197
+ def build_encoder_attention(self, embed_dim, args):
198
+ return MultiheadAttention(
199
+ embed_dim,
200
+ args.decoder_attention_heads,
201
+ kdim=args.encoder_embed_dim,
202
+ vdim=args.encoder_embed_dim,
203
+ dropout=args.attention_dropout,
204
+ encoder_decoder_attention=True,
205
+ )
206
+
207
+ def residual_connection(self, x, residual):
208
+ return residual + x
209
+
210
+ def forward(
211
+ self,
212
+ x,
213
+ encoder_out: Optional[torch.Tensor] = None,
214
+ encoder_padding_mask: Optional[torch.Tensor] = None,
215
+ incremental_state: Optional[Dict[str, Dict[str, Optional[Tensor]]]] = None,
216
+ prev_self_attn_state: Optional[List[torch.Tensor]] = None,
217
+ prev_attn_state: Optional[List[torch.Tensor]] = None,
218
+ self_attn_mask: Optional[torch.Tensor] = None,
219
+ self_attn_padding_mask: Optional[torch.Tensor] = None,
220
+ need_attn: bool = False,
221
+ need_head_weights: bool = False,
222
+ ):
223
+ """
224
+ Args:
225
+ x (Tensor): input to the layer of shape `(seq_len, batch, embed_dim)`
226
+ encoder_padding_mask (ByteTensor, optional): binary
227
+ ByteTensor of shape `(batch, src_len)` where padding
228
+ elements are indicated by ``1``.
229
+ need_attn (bool, optional): return attention weights
230
+ need_head_weights (bool, optional): return attention weights
231
+ for each head (default: return average over heads).
232
+
233
+ Returns:
234
+ encoded output of shape `(seq_len, batch, embed_dim)`
235
+ """
236
+ if need_head_weights:
237
+ need_attn = True
238
+
239
+ residual = x
240
+ x = self.self_attn_layer_norm(x)
241
+ if prev_self_attn_state is not None:
242
+ prev_key, prev_value = prev_self_attn_state[:2]
243
+ saved_state: Dict[str, Optional[Tensor]] = {
244
+ "prev_key": prev_key,
245
+ "prev_value": prev_value,
246
+ }
247
+ if len(prev_self_attn_state) >= 3:
248
+ saved_state["prev_key_padding_mask"] = prev_self_attn_state[2]
249
+ assert incremental_state is not None
250
+ self.self_attn._set_input_buffer(incremental_state, saved_state)
251
+ _self_attn_input_buffer = self.self_attn._get_input_buffer(incremental_state)
252
+ y = x
253
+
254
+ x, attn = self.self_attn(
255
+ query=x,
256
+ key=y,
257
+ value=y,
258
+ key_padding_mask=self_attn_padding_mask,
259
+ incremental_state=incremental_state,
260
+ need_weights=False,
261
+ attn_mask=self_attn_mask,
262
+ )
263
+ x = self.dropout_module(x)
264
+ x = self.residual_connection(x, residual)
265
+
266
+ if self.encoder_attn is not None and encoder_out is not None:
267
+ residual = x
268
+ x = self.encoder_attn_layer_norm(x)
269
+ if prev_attn_state is not None:
270
+ prev_key, prev_value = prev_attn_state[:2]
271
+ saved_state: Dict[str, Optional[Tensor]] = {
272
+ "prev_key": prev_key,
273
+ "prev_value": prev_value,
274
+ }
275
+ if len(prev_attn_state) >= 3:
276
+ saved_state["prev_key_padding_mask"] = prev_attn_state[2]
277
+ assert incremental_state is not None
278
+ self.encoder_attn._set_input_buffer(incremental_state, saved_state)
279
+
280
+ x, attn = self.encoder_attn(
281
+ query=x,
282
+ key=encoder_out,
283
+ value=encoder_out,
284
+ key_padding_mask=encoder_padding_mask,
285
+ incremental_state=incremental_state,
286
+ static_kv=True,
287
+ need_weights=need_attn or (not self.training and self.need_attn),
288
+ need_head_weights=need_head_weights,
289
+ )
290
+ x = self.dropout_module(x)
291
+ x = self.residual_connection(x, residual)
292
+
293
+ residual = x
294
+ x = self.final_layer_norm(x)
295
+
296
+ x = self.activation_fn(self.fc1(x))
297
+ if self.ffn_layernorm is not None:
298
+ x = self.ffn_layernorm(x)
299
+ x = self.fc2(x)
300
+ x = self.dropout_module(x)
301
+ if self.w_resid is not None:
302
+ residual = torch.mul(self.w_resid, residual)
303
+ x = self.residual_connection(x, residual)
304
+ return x, attn, None
model/esm/inverse_folding/util.py ADDED
@@ -0,0 +1,323 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright (c) Meta Platforms, Inc. and affiliates.
2
+ #
3
+ # This source code is licensed under the MIT license found in the
4
+ # LICENSE file in the root directory of this source tree.
5
+
6
+ import json
7
+ import math
8
+
9
+ import biotite.structure
10
+ from biotite.structure.io import pdbx, pdb
11
+ from biotite.structure.residues import get_residues
12
+ from biotite.structure import filter_backbone
13
+ from biotite.structure import get_chains
14
+ from biotite.sequence import ProteinSequence
15
+ import numpy as np
16
+ from scipy.spatial import transform
17
+ from scipy.stats import special_ortho_group
18
+ import torch
19
+ import torch.nn as nn
20
+ import torch.nn.functional as F
21
+ import torch.utils.data as data
22
+ from typing import Sequence, Tuple, List
23
+
24
+ from onescience.datapipes.esm import BatchConverter
25
+
26
+
27
+ def load_structure(fpath, chain=None):
28
+ """
29
+ Args:
30
+ fpath: filepath to either pdb or cif file
31
+ chain: the chain id or list of chain ids to load
32
+ Returns:
33
+ biotite.structure.AtomArray
34
+ """
35
+ if fpath.endswith('cif'):
36
+ with open(fpath) as fin:
37
+ pdbxf = pdbx.PDBxFile.read(fin)
38
+ structure = pdbx.get_structure(pdbxf, model=1)
39
+ elif fpath.endswith('pdb'):
40
+ with open(fpath) as fin:
41
+ pdbf = pdb.PDBFile.read(fin)
42
+ structure = pdb.get_structure(pdbf, model=1)
43
+ bbmask = filter_backbone(structure)
44
+ structure = structure[bbmask]
45
+ all_chains = get_chains(structure)
46
+ if len(all_chains) == 0:
47
+ raise ValueError('No chains found in the input file.')
48
+ if chain is None:
49
+ chain_ids = all_chains
50
+ elif isinstance(chain, list):
51
+ chain_ids = chain
52
+ else:
53
+ chain_ids = [chain]
54
+ for chain in chain_ids:
55
+ if chain not in all_chains:
56
+ raise ValueError(f'Chain {chain} not found in input file')
57
+ chain_filter = [a.chain_id in chain_ids for a in structure]
58
+ structure = structure[chain_filter]
59
+ return structure
60
+
61
+
62
+ def extract_coords_from_structure(structure: biotite.structure.AtomArray):
63
+ """
64
+ Args:
65
+ structure: An instance of biotite AtomArray
66
+ Returns:
67
+ Tuple (coords, seq)
68
+ - coords is an L x 3 x 3 array for N, CA, C coordinates
69
+ - seq is the extracted sequence
70
+ """
71
+ coords = get_atom_coords_residuewise(["N", "CA", "C"], structure)
72
+ residue_identities = get_residues(structure)[1]
73
+ seq = ''.join([ProteinSequence.convert_letter_3to1(r) for r in residue_identities])
74
+ return coords, seq
75
+
76
+
77
+ def load_coords(fpath, chain):
78
+ """
79
+ Args:
80
+ fpath: filepath to either pdb or cif file
81
+ chain: the chain id
82
+ Returns:
83
+ Tuple (coords, seq)
84
+ - coords is an L x 3 x 3 array for N, CA, C coordinates
85
+ - seq is the extracted sequence
86
+ """
87
+ structure = load_structure(fpath, chain)
88
+ return extract_coords_from_structure(structure)
89
+
90
+
91
+ def get_atom_coords_residuewise(atoms: List[str], struct: biotite.structure.AtomArray):
92
+ """
93
+ Example for atoms argument: ["N", "CA", "C"]
94
+ """
95
+ def filterfn(s, axis=None):
96
+ filters = np.stack([s.atom_name == name for name in atoms], axis=1)
97
+ sum = filters.sum(0)
98
+ if not np.all(sum <= np.ones(filters.shape[1])):
99
+ raise RuntimeError("structure has multiple atoms with same name")
100
+ index = filters.argmax(0)
101
+ coords = s[index].coord
102
+ coords[sum == 0] = float("nan")
103
+ return coords
104
+
105
+ return biotite.structure.apply_residue_wise(struct, struct, filterfn)
106
+
107
+
108
+ def get_sequence_loss(model, alphabet, coords, seq):
109
+ device = next(model.parameters()).device
110
+ batch_converter = CoordBatchConverter(alphabet)
111
+ batch = [(coords, None, seq)]
112
+ coords, confidence, strs, tokens, padding_mask = batch_converter(
113
+ batch, device=device)
114
+
115
+ prev_output_tokens = tokens[:, :-1].to(device)
116
+ target = tokens[:, 1:]
117
+ target_padding_mask = (target == alphabet.padding_idx)
118
+ logits, _ = model.forward(coords, padding_mask, confidence, prev_output_tokens)
119
+ loss = F.cross_entropy(logits, target, reduction='none')
120
+ loss = loss[0].cpu().detach().numpy()
121
+ target_padding_mask = target_padding_mask[0].cpu().numpy()
122
+ return loss, target_padding_mask
123
+
124
+
125
+ def score_sequence(model, alphabet, coords, seq):
126
+ loss, target_padding_mask = get_sequence_loss(model, alphabet, coords, seq)
127
+ ll_fullseq = -np.sum(loss * ~target_padding_mask) / np.sum(~target_padding_mask)
128
+ # Also calculate average when excluding masked portions
129
+ coord_mask = np.all(np.isfinite(coords), axis=(-1, -2))
130
+ ll_withcoord = -np.sum(loss * coord_mask) / np.sum(coord_mask)
131
+ return ll_fullseq, ll_withcoord
132
+
133
+
134
+ def get_encoder_output(model, alphabet, coords):
135
+ device = next(model.parameters()).device
136
+ batch_converter = CoordBatchConverter(alphabet)
137
+ batch = [(coords, None, None)]
138
+ coords, confidence, strs, tokens, padding_mask = batch_converter(
139
+ batch, device=device)
140
+ encoder_out = model.encoder.forward(coords, padding_mask, confidence,
141
+ return_all_hiddens=False)
142
+ # remove beginning and end (bos and eos tokens)
143
+ return encoder_out['encoder_out'][0][1:-1, 0]
144
+
145
+
146
+ def rotate(v, R):
147
+ """
148
+ Rotates a vector by a rotation matrix.
149
+
150
+ Args:
151
+ v: 3D vector, tensor of shape (length x batch_size x channels x 3)
152
+ R: rotation matrix, tensor of shape (length x batch_size x 3 x 3)
153
+
154
+ Returns:
155
+ Rotated version of v by rotation matrix R.
156
+ """
157
+ R = R.unsqueeze(-3)
158
+ v = v.unsqueeze(-1)
159
+ return torch.sum(v * R, dim=-2)
160
+
161
+
162
+ def get_rotation_frames(coords):
163
+ """
164
+ Returns a local rotation frame defined by N, CA, C positions.
165
+
166
+ Args:
167
+ coords: coordinates, tensor of shape (batch_size x length x 3 x 3)
168
+ where the third dimension is in order of N, CA, C
169
+
170
+ Returns:
171
+ Local relative rotation frames in shape (batch_size x length x 3 x 3)
172
+ """
173
+ v1 = coords[:, :, 2] - coords[:, :, 1]
174
+ v2 = coords[:, :, 0] - coords[:, :, 1]
175
+ e1 = normalize(v1, dim=-1)
176
+ u2 = v2 - e1 * torch.sum(e1 * v2, dim=-1, keepdim=True)
177
+ e2 = normalize(u2, dim=-1)
178
+ e3 = torch.cross(e1, e2, dim=-1)
179
+ R = torch.stack([e1, e2, e3], dim=-2)
180
+ return R
181
+
182
+
183
+ def nan_to_num(ts, val=0.0):
184
+ """
185
+ Replaces nans in tensor with a fixed value.
186
+ """
187
+ val = torch.tensor(val, dtype=ts.dtype, device=ts.device)
188
+ return torch.where(~torch.isfinite(ts), val, ts)
189
+
190
+
191
+ def rbf(values, v_min, v_max, n_bins=16):
192
+ """
193
+ Returns RBF encodings in a new dimension at the end.
194
+ """
195
+ rbf_centers = torch.linspace(v_min, v_max, n_bins, device=values.device)
196
+ rbf_centers = rbf_centers.view([1] * len(values.shape) + [-1])
197
+ rbf_std = (v_max - v_min) / n_bins
198
+ v_expand = torch.unsqueeze(values, -1)
199
+ z = (values.unsqueeze(-1) - rbf_centers) / rbf_std
200
+ return torch.exp(-z ** 2)
201
+
202
+
203
+ def norm(tensor, dim, eps=1e-8, keepdim=False):
204
+ """
205
+ Returns L2 norm along a dimension.
206
+ """
207
+ return torch.sqrt(
208
+ torch.sum(torch.square(tensor), dim=dim, keepdim=keepdim) + eps)
209
+
210
+
211
+ def normalize(tensor, dim=-1):
212
+ """
213
+ Normalizes a tensor along a dimension after removing nans.
214
+ """
215
+ return nan_to_num(
216
+ torch.div(tensor, norm(tensor, dim=dim, keepdim=True))
217
+ )
218
+
219
+
220
+ class CoordBatchConverter(BatchConverter):
221
+ def __call__(self, raw_batch: Sequence[Tuple[Sequence, str]], device=None):
222
+ """
223
+ Args:
224
+ raw_batch: List of tuples (coords, confidence, seq)
225
+ In each tuple,
226
+ coords: list of floats, shape L x 3 x 3
227
+ confidence: list of floats, shape L; or scalar float; or None
228
+ seq: string of length L
229
+ Returns:
230
+ coords: Tensor of shape batch_size x L x 3 x 3
231
+ confidence: Tensor of shape batch_size x L
232
+ strs: list of strings
233
+ tokens: LongTensor of shape batch_size x L
234
+ padding_mask: ByteTensor of shape batch_size x L
235
+ """
236
+ self.alphabet.cls_idx = self.alphabet.get_idx("<cath>")
237
+ batch = []
238
+ for coords, confidence, seq in raw_batch:
239
+ if confidence is None:
240
+ confidence = 1.
241
+ if isinstance(confidence, float) or isinstance(confidence, int):
242
+ confidence = [float(confidence)] * len(coords)
243
+ if seq is None:
244
+ seq = 'X' * len(coords)
245
+ batch.append(((coords, confidence), seq))
246
+
247
+ coords_and_confidence, strs, tokens = super().__call__(batch)
248
+
249
+ # pad beginning and end of each protein due to legacy reasons
250
+ coords = [
251
+ F.pad(torch.tensor(cd), (0, 0, 0, 0, 1, 1), value=np.inf)
252
+ for cd, _ in coords_and_confidence
253
+ ]
254
+ confidence = [
255
+ F.pad(torch.tensor(cf), (1, 1), value=-1.)
256
+ for _, cf in coords_and_confidence
257
+ ]
258
+ coords = self.collate_dense_tensors(coords, pad_v=np.nan)
259
+ confidence = self.collate_dense_tensors(confidence, pad_v=-1.)
260
+ if device is not None:
261
+ coords = coords.to(device)
262
+ confidence = confidence.to(device)
263
+ tokens = tokens.to(device)
264
+ padding_mask = torch.isnan(coords[:,:,0,0])
265
+ coord_mask = torch.isfinite(coords.sum(-2).sum(-1))
266
+ confidence = confidence * coord_mask + (-1.) * padding_mask
267
+ return coords, confidence, strs, tokens, padding_mask
268
+
269
+ def from_lists(self, coords_list, confidence_list=None, seq_list=None, device=None):
270
+ """
271
+ Args:
272
+ coords_list: list of length batch_size, each item is a list of
273
+ floats in shape L x 3 x 3 to describe a backbone
274
+ confidence_list: one of
275
+ - None, default to highest confidence
276
+ - list of length batch_size, each item is a scalar
277
+ - list of length batch_size, each item is a list of floats of
278
+ length L to describe the confidence scores for the backbone
279
+ with values between 0. and 1.
280
+ seq_list: either None or a list of strings
281
+ Returns:
282
+ coords: Tensor of shape batch_size x L x 3 x 3
283
+ confidence: Tensor of shape batch_size x L
284
+ strs: list of strings
285
+ tokens: LongTensor of shape batch_size x L
286
+ padding_mask: ByteTensor of shape batch_size x L
287
+ """
288
+ batch_size = len(coords_list)
289
+ if confidence_list is None:
290
+ confidence_list = [None] * batch_size
291
+ if seq_list is None:
292
+ seq_list = [None] * batch_size
293
+ raw_batch = zip(coords_list, confidence_list, seq_list)
294
+ return self.__call__(raw_batch, device)
295
+
296
+ @staticmethod
297
+ def collate_dense_tensors(samples, pad_v):
298
+ """
299
+ Takes a list of tensors with the following dimensions:
300
+ [(d_11, ..., d_1K),
301
+ (d_21, ..., d_2K),
302
+ ...,
303
+ (d_N1, ..., d_NK)]
304
+ and stack + pads them into a single tensor of:
305
+ (N, max_i=1,N { d_i1 }, ..., max_i=1,N {diK})
306
+ """
307
+ if len(samples) == 0:
308
+ return torch.Tensor()
309
+ if len(set(x.dim() for x in samples)) != 1:
310
+ raise RuntimeError(
311
+ f"Samples has varying dimensions: {[x.dim() for x in samples]}"
312
+ )
313
+ (device,) = tuple(set(x.device for x in samples)) # assumes all on same device
314
+ max_shape = [max(lst) for lst in zip(*[x.shape for x in samples])]
315
+ result = torch.empty(
316
+ len(samples), *max_shape, dtype=samples[0].dtype, device=device
317
+ )
318
+ result.fill_(pad_v)
319
+ for i in range(len(samples)):
320
+ result_i = result[i]
321
+ t = samples[i]
322
+ result_i[tuple(slice(0, k) for k in t.shape)] = t
323
+ return result
model/esm/msa_transformer.py ADDED
@@ -0,0 +1,238 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright (c) Meta Platforms, Inc. and affiliates.
2
+ #
3
+ # This source code is licensed under the MIT license found in the
4
+ # LICENSE file in the root directory of this source tree.
5
+
6
+ import torch
7
+ import torch.nn as nn
8
+
9
+ from onescience.modules.esm import (
10
+ AxialTransformerLayer,
11
+ LearnedPositionalEmbedding,
12
+ RobertaLMHead,
13
+ ESM1bLayerNorm,
14
+ ContactPredictionHead,
15
+ )
16
+
17
+ from onescience.modules.attention import RowSelfAttention, ColumnSelfAttention
18
+
19
+
20
+
21
+ class MSATransformer(nn.Module):
22
+ @classmethod
23
+ def add_args(cls, parser):
24
+ # fmt: off
25
+ parser.add_argument(
26
+ "--num_layers",
27
+ default=12,
28
+ type=int,
29
+ metavar="N",
30
+ help="number of layers"
31
+ )
32
+ parser.add_argument(
33
+ "--embed_dim",
34
+ default=768,
35
+ type=int,
36
+ metavar="N",
37
+ help="embedding dimension"
38
+ )
39
+ parser.add_argument(
40
+ "--logit_bias",
41
+ action="store_true",
42
+ help="whether to apply bias to logits"
43
+ )
44
+ parser.add_argument(
45
+ "--ffn_embed_dim",
46
+ default=3072,
47
+ type=int,
48
+ metavar="N",
49
+ help="embedding dimension for FFN",
50
+ )
51
+ parser.add_argument(
52
+ "--attention_heads",
53
+ default=12,
54
+ type=int,
55
+ metavar="N",
56
+ help="number of attention heads",
57
+ )
58
+ parser.add_argument(
59
+ "--dropout",
60
+ default=0.1,
61
+ type=float,
62
+ help="Dropout to apply."
63
+ )
64
+ parser.add_argument(
65
+ "--attention_dropout",
66
+ default=0.1,
67
+ type=float,
68
+ help="Dropout to apply."
69
+ )
70
+ parser.add_argument(
71
+ "--activation_dropout",
72
+ default=0.1,
73
+ type=float,
74
+ help="Dropout to apply."
75
+ )
76
+ parser.add_argument(
77
+ "--max_tokens_per_msa",
78
+ default=2 ** 14,
79
+ type=int,
80
+ help=(
81
+ "Used during inference to batch attention computations in a single "
82
+ "forward pass. This allows increased input sizes with less memory."
83
+ ),
84
+ )
85
+ # fmt: on
86
+
87
+ def __init__(self, args, alphabet):
88
+ super().__init__()
89
+ self.args = args
90
+ self.alphabet_size = len(alphabet)
91
+ self.padding_idx = alphabet.padding_idx
92
+ self.mask_idx = alphabet.mask_idx
93
+ self.cls_idx = alphabet.cls_idx
94
+ self.eos_idx = alphabet.eos_idx
95
+ self.prepend_bos = alphabet.prepend_bos
96
+ self.append_eos = alphabet.append_eos
97
+
98
+ self.embed_tokens = nn.Embedding(
99
+ self.alphabet_size, self.args.embed_dim, padding_idx=self.padding_idx
100
+ )
101
+
102
+ if getattr(self.args, "embed_positions_msa", False):
103
+ emb_dim = getattr(self.args, "embed_positions_msa_dim", self.args.embed_dim)
104
+ self.msa_position_embedding = nn.Parameter(
105
+ 0.01 * torch.randn(1, 1024, 1, emb_dim),
106
+ requires_grad=True,
107
+ )
108
+ else:
109
+ self.register_parameter("msa_position_embedding", None)
110
+
111
+ self.dropout_module = nn.Dropout(self.args.dropout)
112
+ self.layers = nn.ModuleList(
113
+ [
114
+ AxialTransformerLayer(
115
+ self.args.embed_dim,
116
+ self.args.ffn_embed_dim,
117
+ self.args.attention_heads,
118
+ self.args.dropout,
119
+ self.args.attention_dropout,
120
+ self.args.activation_dropout,
121
+ getattr(self.args, "max_tokens_per_msa", self.args.max_tokens),
122
+ )
123
+ for _ in range(self.args.layers)
124
+ ]
125
+ )
126
+
127
+ self.contact_head = ContactPredictionHead(
128
+ self.args.layers * self.args.attention_heads,
129
+ self.prepend_bos,
130
+ self.append_eos,
131
+ eos_idx=self.eos_idx,
132
+ )
133
+ self.embed_positions = LearnedPositionalEmbedding(
134
+ self.args.max_positions,
135
+ self.args.embed_dim,
136
+ self.padding_idx,
137
+ )
138
+ self.emb_layer_norm_before = ESM1bLayerNorm(self.args.embed_dim)
139
+ self.emb_layer_norm_after = ESM1bLayerNorm(self.args.embed_dim)
140
+ self.lm_head = RobertaLMHead(
141
+ embed_dim=self.args.embed_dim,
142
+ output_dim=self.alphabet_size,
143
+ weight=self.embed_tokens.weight,
144
+ )
145
+
146
+ def forward(self, tokens, repr_layers=[], need_head_weights=False, return_contacts=False):
147
+ if return_contacts:
148
+ need_head_weights = True
149
+
150
+ assert tokens.ndim == 3
151
+ batch_size, num_alignments, seqlen = tokens.size()
152
+ padding_mask = tokens.eq(self.padding_idx) # B, R, C
153
+ if not padding_mask.any():
154
+ padding_mask = None
155
+
156
+ x = self.embed_tokens(tokens)
157
+ x += self.embed_positions(tokens.view(batch_size * num_alignments, seqlen)).view(x.size())
158
+ if self.msa_position_embedding is not None:
159
+ if x.size(1) > 1024:
160
+ raise RuntimeError(
161
+ "Using model with MSA position embedding trained on maximum MSA "
162
+ f"depth of 1024, but received {x.size(1)} alignments."
163
+ )
164
+ x += self.msa_position_embedding[:, :num_alignments]
165
+
166
+ x = self.emb_layer_norm_before(x)
167
+
168
+ x = self.dropout_module(x)
169
+
170
+ if padding_mask is not None:
171
+ x = x * (1 - padding_mask.unsqueeze(-1).type_as(x))
172
+
173
+ repr_layers = set(repr_layers)
174
+ hidden_representations = {}
175
+ if 0 in repr_layers:
176
+ hidden_representations[0] = x
177
+
178
+ if need_head_weights:
179
+ row_attn_weights = []
180
+ col_attn_weights = []
181
+
182
+ # B x R x C x D -> R x C x B x D
183
+ x = x.permute(1, 2, 0, 3)
184
+
185
+ for layer_idx, layer in enumerate(self.layers):
186
+ x = layer(
187
+ x,
188
+ self_attn_padding_mask=padding_mask,
189
+ need_head_weights=need_head_weights,
190
+ )
191
+ if need_head_weights:
192
+ x, col_attn, row_attn = x
193
+ # H x C x B x R x R -> B x H x C x R x R
194
+ col_attn_weights.append(col_attn.permute(2, 0, 1, 3, 4))
195
+ # H x B x C x C -> B x H x C x C
196
+ row_attn_weights.append(row_attn.permute(1, 0, 2, 3))
197
+ if (layer_idx + 1) in repr_layers:
198
+ hidden_representations[layer_idx + 1] = x.permute(2, 0, 1, 3)
199
+
200
+ x = self.emb_layer_norm_after(x)
201
+ x = x.permute(2, 0, 1, 3) # R x C x B x D -> B x R x C x D
202
+
203
+ # last hidden representation should have layer norm applied
204
+ if (layer_idx + 1) in repr_layers:
205
+ hidden_representations[layer_idx + 1] = x
206
+ x = self.lm_head(x)
207
+
208
+ result = {"logits": x, "representations": hidden_representations}
209
+ if need_head_weights:
210
+ # col_attentions: B x L x H x C x R x R
211
+ col_attentions = torch.stack(col_attn_weights, 1)
212
+ # row_attentions: B x L x H x C x C
213
+ row_attentions = torch.stack(row_attn_weights, 1)
214
+ result["col_attentions"] = col_attentions
215
+ result["row_attentions"] = row_attentions
216
+ if return_contacts:
217
+ contacts = self.contact_head(tokens, row_attentions)
218
+ result["contacts"] = contacts
219
+
220
+ return result
221
+
222
+ def predict_contacts(self, tokens):
223
+ return self(tokens, return_contacts=True)["contacts"]
224
+
225
+ @property
226
+ def num_layers(self):
227
+ return self.args.layers
228
+
229
+ def max_tokens_per_msa_(self, value: int) -> None:
230
+ """The MSA Transformer automatically batches attention computations when
231
+ gradients are disabled to allow you to pass in larger MSAs at test time than
232
+ you can fit in GPU memory. By default this occurs when more than 2^14 tokens
233
+ are passed in the input MSA. You can set this value to infinity to disable
234
+ this behavior.
235
+ """
236
+ for module in self.modules():
237
+ if isinstance(module, (RowSelfAttention, ColumnSelfAttention)):
238
+ module.max_tokens_per_msa = value
model/esm/pretrained.py ADDED
@@ -0,0 +1,553 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright (c) Meta Platforms, Inc. and affiliates.
2
+ #
3
+ # This source code is licensed under the MIT license found in the
4
+ # LICENSE file in the root directory of this source tree.
5
+
6
+ import re
7
+ import urllib
8
+ import warnings
9
+ from argparse import Namespace
10
+ from pathlib import Path
11
+
12
+ import torch
13
+
14
+ import model.esm as esm
15
+ from onescience.datapipes.esm import Alphabet
16
+ from model.esm.esm2 import ESM2
17
+
18
+
19
+ def _has_regression_weights(model_name):
20
+ """Return whether we expect / require regression weights;
21
+ Right now that is all models except ESM-1v, ESM-IF, and partially trained ESM2 models"""
22
+ return not ("esm1v" in model_name or "esm_if" in model_name or "270K" in model_name or "500K" in model_name)
23
+
24
+
25
+ def load_model_and_alphabet(model_name):
26
+ if model_name.endswith(".pt"): # treat as filepath
27
+ return load_model_and_alphabet_local(model_name)
28
+ else:
29
+ return load_model_and_alphabet_hub(model_name)
30
+
31
+
32
+ def load_hub_workaround(url):
33
+ try:
34
+ data = torch.hub.load_state_dict_from_url(url, progress=False, map_location="cpu")
35
+ except RuntimeError:
36
+ # Pytorch version issue - see https://github.com/pytorch/pytorch/issues/43106
37
+ fn = Path(url).name
38
+ data = torch.load(
39
+ f"{torch.hub.get_dir()}/checkpoints/{fn}",
40
+ map_location="cpu",
41
+ )
42
+ except urllib.error.HTTPError as e:
43
+ raise Exception(f"Could not load {url}, check if you specified a correct model name?")
44
+ return data
45
+
46
+
47
+ def load_regression_hub(model_name):
48
+ url = f"https://dl.fbaipublicfiles.com/fair-esm/regression/{model_name}-contact-regression.pt"
49
+ regression_data = load_hub_workaround(url)
50
+ return regression_data
51
+
52
+
53
+ def _download_model_and_regression_data(model_name):
54
+ url = f"https://dl.fbaipublicfiles.com/fair-esm/models/{model_name}.pt"
55
+ model_data = load_hub_workaround(url)
56
+ if _has_regression_weights(model_name):
57
+ regression_data = load_regression_hub(model_name)
58
+ else:
59
+ regression_data = None
60
+ return model_data, regression_data
61
+
62
+
63
+ def load_model_and_alphabet_hub(model_name):
64
+ model_data, regression_data = _download_model_and_regression_data(model_name)
65
+ return load_model_and_alphabet_core(model_name, model_data, regression_data)
66
+
67
+
68
+ def load_model_and_alphabet_local(model_location):
69
+ """Load from local path. The regression weights need to be co-located"""
70
+ model_location = Path(model_location)
71
+ model_data = torch.load(str(model_location), map_location="cpu")
72
+ model_name = model_location.stem
73
+ if _has_regression_weights(model_name):
74
+ regression_location = str(model_location.with_suffix("")) + "-contact-regression.pt"
75
+ regression_data = torch.load(regression_location, map_location="cpu")
76
+ else:
77
+ regression_data = None
78
+ return load_model_and_alphabet_core(model_name, model_data, regression_data)
79
+
80
+
81
+ def has_emb_layer_norm_before(model_state):
82
+ """Determine whether layer norm needs to be applied before the encoder"""
83
+ return any(k.startswith("emb_layer_norm_before") for k, param in model_state.items())
84
+
85
+
86
+ def _load_model_and_alphabet_core_v1(model_data):
87
+ import model.esm as esm # since esm.inverse_folding is imported below, you actually have to re-import esm here
88
+
89
+ alphabet = esm.Alphabet.from_architecture(model_data["args"].arch)
90
+
91
+ if model_data["args"].arch == "roberta_large":
92
+ # upgrade state dict
93
+ pra = lambda s: "".join(s.split("encoder_")[1:] if "encoder" in s else s)
94
+ prs1 = lambda s: "".join(s.split("encoder.")[1:] if "encoder" in s else s)
95
+ prs2 = lambda s: "".join(
96
+ s.split("sentence_encoder.")[1:] if "sentence_encoder" in s else s
97
+ )
98
+ model_args = {pra(arg[0]): arg[1] for arg in vars(model_data["args"]).items()}
99
+ model_state = {prs1(prs2(arg[0])): arg[1] for arg in model_data["model"].items()}
100
+ model_state["embed_tokens.weight"][alphabet.mask_idx].zero_() # For token drop
101
+ model_args["emb_layer_norm_before"] = has_emb_layer_norm_before(model_state)
102
+ model_type = esm.ProteinBertModel
103
+
104
+ elif model_data["args"].arch == "protein_bert_base":
105
+
106
+ # upgrade state dict
107
+ pra = lambda s: "".join(s.split("decoder_")[1:] if "decoder" in s else s)
108
+ prs = lambda s: "".join(s.split("decoder.")[1:] if "decoder" in s else s)
109
+ model_args = {pra(arg[0]): arg[1] for arg in vars(model_data["args"]).items()}
110
+ model_state = {prs(arg[0]): arg[1] for arg in model_data["model"].items()}
111
+ model_type = esm.ProteinBertModel
112
+ elif model_data["args"].arch == "msa_transformer":
113
+
114
+ # upgrade state dict
115
+ pra = lambda s: "".join(s.split("encoder_")[1:] if "encoder" in s else s)
116
+ prs1 = lambda s: "".join(s.split("encoder.")[1:] if "encoder" in s else s)
117
+ prs2 = lambda s: "".join(
118
+ s.split("sentence_encoder.")[1:] if "sentence_encoder" in s else s
119
+ )
120
+ prs3 = lambda s: s.replace("row", "column") if "row" in s else s.replace("column", "row")
121
+ model_args = {pra(arg[0]): arg[1] for arg in vars(model_data["args"]).items()}
122
+ model_state = {prs1(prs2(prs3(arg[0]))): arg[1] for arg in model_data["model"].items()}
123
+ if model_args.get("embed_positions_msa", False):
124
+ emb_dim = model_state["msa_position_embedding"].size(-1)
125
+ model_args["embed_positions_msa_dim"] = emb_dim # initial release, bug: emb_dim==1
126
+
127
+ model_type = esm.MSATransformer
128
+
129
+ elif "invariant_gvp" in model_data["args"].arch:
130
+ import model.esm.inverse_folding
131
+
132
+ model_type = esm.inverse_folding.gvp_transformer.GVPTransformerModel
133
+ model_args = vars(model_data["args"]) # convert Namespace -> dict
134
+
135
+ def update_name(s):
136
+ # Map the module names in checkpoints trained with internal code to
137
+ # the updated module names in open source code
138
+ s = s.replace("W_v", "embed_graph.embed_node")
139
+ s = s.replace("W_e", "embed_graph.embed_edge")
140
+ s = s.replace("embed_scores.0", "embed_confidence")
141
+ s = s.replace("embed_score.", "embed_graph.embed_confidence.")
142
+ s = s.replace("seq_logits_projection.", "")
143
+ s = s.replace("embed_ingraham_features", "embed_dihedrals")
144
+ s = s.replace("embed_gvp_in_local_frame.0", "embed_gvp_output")
145
+ s = s.replace("embed_features_in_local_frame.0", "embed_gvp_input_features")
146
+ return s
147
+
148
+ model_state = {
149
+ update_name(sname): svalue
150
+ for sname, svalue in model_data["model"].items()
151
+ if "version" not in sname
152
+ }
153
+
154
+ else:
155
+ raise ValueError("Unknown architecture selected")
156
+
157
+ model = model_type(
158
+ Namespace(**model_args),
159
+ alphabet,
160
+ )
161
+
162
+ return model, alphabet, model_state
163
+
164
+
165
+ def _load_model_and_alphabet_core_v2(model_data):
166
+ def upgrade_state_dict(state_dict):
167
+ """Removes prefixes 'model.encoder.sentence_encoder.' and 'model.encoder.'."""
168
+ prefixes = ["encoder.sentence_encoder.", "encoder."]
169
+ pattern = re.compile("^" + "|".join(prefixes))
170
+ state_dict = {pattern.sub("", name): param for name, param in state_dict.items()}
171
+ return state_dict
172
+
173
+ cfg = model_data["cfg"]["model"]
174
+ state_dict = model_data["model"]
175
+ state_dict = upgrade_state_dict(state_dict)
176
+ alphabet = Alphabet.from_architecture("ESM-1b")
177
+ model = ESM2(
178
+ num_layers=cfg.encoder_layers,
179
+ embed_dim=cfg.encoder_embed_dim,
180
+ attention_heads=cfg.encoder_attention_heads,
181
+ alphabet=alphabet,
182
+ token_dropout=cfg.token_dropout,
183
+ )
184
+ return model, alphabet, state_dict
185
+
186
+
187
+ def load_model_and_alphabet_core(model_name, model_data, regression_data=None):
188
+ if regression_data is not None:
189
+ model_data["model"].update(regression_data["model"])
190
+
191
+ if model_name.startswith("esm2"):
192
+ model, alphabet, model_state = _load_model_and_alphabet_core_v2(model_data)
193
+ else:
194
+ model, alphabet, model_state = _load_model_and_alphabet_core_v1(model_data)
195
+
196
+ expected_keys = set(model.state_dict().keys())
197
+ found_keys = set(model_state.keys())
198
+
199
+ if regression_data is None:
200
+ expected_missing = {"contact_head.regression.weight", "contact_head.regression.bias"}
201
+ error_msgs = []
202
+ missing = (expected_keys - found_keys) - expected_missing
203
+ if missing:
204
+ error_msgs.append(f"Missing key(s) in state_dict: {missing}.")
205
+ unexpected = found_keys - expected_keys
206
+ if unexpected:
207
+ error_msgs.append(f"Unexpected key(s) in state_dict: {unexpected}.")
208
+
209
+ if error_msgs:
210
+ raise RuntimeError(
211
+ "Error(s) in loading state_dict for {}:\n\t{}".format(
212
+ model.__class__.__name__, "\n\t".join(error_msgs)
213
+ )
214
+ )
215
+ if expected_missing - found_keys:
216
+ warnings.warn(
217
+ "Regression weights not found, predicting contacts will not produce correct results."
218
+ )
219
+
220
+ model.load_state_dict(model_state, strict=regression_data is not None)
221
+
222
+ return model, alphabet
223
+
224
+
225
+ def esm1_t34_670M_UR50S():
226
+ """34 layer transformer model with 670M params, trained on Uniref50 Sparse.
227
+
228
+ Returns a tuple of (Model, Alphabet).
229
+ """
230
+ return load_model_and_alphabet_hub("esm1_t34_670M_UR50S")
231
+
232
+
233
+ def esm1_t34_670M_UR50D():
234
+ """34 layer transformer model with 670M params, trained on Uniref50 Dense.
235
+
236
+ Returns a tuple of (Model, Alphabet).
237
+ """
238
+ return load_model_and_alphabet_hub("esm1_t34_670M_UR50D")
239
+
240
+
241
+ def esm1_t34_670M_UR100():
242
+ """34 layer transformer model with 670M params, trained on Uniref100.
243
+
244
+ Returns a tuple of (Model, Alphabet).
245
+ """
246
+ return load_model_and_alphabet_hub("esm1_t34_670M_UR100")
247
+
248
+
249
+ def esm1_t12_85M_UR50S():
250
+ """12 layer transformer model with 85M params, trained on Uniref50 Sparse.
251
+
252
+ Returns a tuple of (Model, Alphabet).
253
+ """
254
+ return load_model_and_alphabet_hub("esm1_t12_85M_UR50S")
255
+
256
+
257
+ def esm1_t6_43M_UR50S():
258
+ """6 layer transformer model with 43M params, trained on Uniref50 Sparse.
259
+
260
+ Returns a tuple of (Model, Alphabet).
261
+ """
262
+ return load_model_and_alphabet_hub("esm1_t6_43M_UR50S")
263
+
264
+
265
+ def esm1b_t33_650M_UR50S():
266
+ """33 layer transformer model with 650M params, trained on Uniref50 Sparse.
267
+ This is our best performing model, which will be described in a future publication.
268
+
269
+ Returns a tuple of (Model, Alphabet).
270
+ """
271
+ return load_model_and_alphabet_hub("esm1b_t33_650M_UR50S")
272
+
273
+
274
+ def esm_msa1_t12_100M_UR50S():
275
+ warnings.warn(
276
+ "This model had a minor bug in the positional embeddings, "
277
+ "please use ESM-MSA-1b: esm.pretrained.esm_msa1b_t12_100M_UR50S()",
278
+ )
279
+ return load_model_and_alphabet_hub("esm_msa1_t12_100M_UR50S")
280
+
281
+
282
+ def esm_msa1b_t12_100M_UR50S():
283
+ return load_model_and_alphabet_hub("esm_msa1b_t12_100M_UR50S")
284
+
285
+
286
+ def esm1v_t33_650M_UR90S():
287
+ """33 layer transformer model with 650M params, trained on Uniref90.
288
+ This is model 1 of a 5 model ensemble.
289
+
290
+ Returns a tuple of (Model, Alphabet).
291
+ """
292
+ return load_model_and_alphabet_hub("esm1v_t33_650M_UR90S_1")
293
+
294
+
295
+ def esm1v_t33_650M_UR90S_1():
296
+ """33 layer transformer model with 650M params, trained on Uniref90.
297
+ This is model 1 of a 5 model ensemble.
298
+
299
+ Returns a tuple of (Model, Alphabet).
300
+ """
301
+ return load_model_and_alphabet_hub("esm1v_t33_650M_UR90S_1")
302
+
303
+
304
+ def esm1v_t33_650M_UR90S_2():
305
+ """33 layer transformer model with 650M params, trained on Uniref90.
306
+ This is model 2 of a 5 model ensemble.
307
+
308
+ Returns a tuple of (Model, Alphabet).
309
+ """
310
+ return load_model_and_alphabet_hub("esm1v_t33_650M_UR90S_2")
311
+
312
+
313
+ def esm1v_t33_650M_UR90S_3():
314
+ """33 layer transformer model with 650M params, trained on Uniref90.
315
+ This is model 3 of a 5 model ensemble.
316
+
317
+ Returns a tuple of (Model, Alphabet).
318
+ """
319
+ return load_model_and_alphabet_hub("esm1v_t33_650M_UR90S_3")
320
+
321
+
322
+ def esm1v_t33_650M_UR90S_4():
323
+ """33 layer transformer model with 650M params, trained on Uniref90.
324
+ This is model 4 of a 5 model ensemble.
325
+
326
+ Returns a tuple of (Model, Alphabet).
327
+ """
328
+ return load_model_and_alphabet_hub("esm1v_t33_650M_UR90S_4")
329
+
330
+
331
+ def esm1v_t33_650M_UR90S_5():
332
+ """33 layer transformer model with 650M params, trained on Uniref90.
333
+ This is model 5 of a 5 model ensemble.
334
+
335
+ Returns a tuple of (Model, Alphabet).
336
+ """
337
+ return load_model_and_alphabet_hub("esm1v_t33_650M_UR90S_5")
338
+
339
+
340
+ def esm_if1_gvp4_t16_142M_UR50():
341
+ """Inverse folding model with 142M params, with 4 GVP-GNN layers, 8
342
+ Transformer encoder layers, and 8 Transformer decoder layers, trained on
343
+ CATH structures and 12 million alphafold2 predicted structures from UniRef50
344
+ sequences.
345
+
346
+ Returns a tuple of (Model, Alphabet).
347
+ """
348
+ return load_model_and_alphabet_hub("esm_if1_gvp4_t16_142M_UR50")
349
+
350
+
351
+ def esm2_t6_8M_UR50D():
352
+ """6 layer ESM-2 model with 8M params, trained on UniRef50.
353
+
354
+ Returns a tuple of (Model, Alphabet).
355
+ """
356
+ return load_model_and_alphabet_hub("esm2_t6_8M_UR50D")
357
+
358
+
359
+ def esm2_t12_35M_UR50D():
360
+ """12 layer ESM-2 model with 35M params, trained on UniRef50.
361
+
362
+ Returns a tuple of (Model, Alphabet).
363
+ """
364
+ return load_model_and_alphabet_hub("esm2_t12_35M_UR50D")
365
+
366
+
367
+ def esm2_t30_150M_UR50D():
368
+ """30 layer ESM-2 model with 150M params, trained on UniRef50.
369
+
370
+ Returns a tuple of (Model, Alphabet).
371
+ """
372
+ return load_model_and_alphabet_hub("esm2_t30_150M_UR50D")
373
+
374
+
375
+ def esm2_t33_650M_UR50D():
376
+ """33 layer ESM-2 model with 650M params, trained on UniRef50.
377
+
378
+ Returns a tuple of (Model, Alphabet).
379
+ """
380
+ return load_model_and_alphabet_hub("esm2_t33_650M_UR50D")
381
+
382
+
383
+ def esm2_t36_3B_UR50D():
384
+ """36 layer ESM-2 model with 3B params, trained on UniRef50.
385
+
386
+ Returns a tuple of (Model, Alphabet).
387
+ """
388
+ return load_model_and_alphabet_hub("esm2_t36_3B_UR50D")
389
+
390
+
391
+ def esm2_t48_15B_UR50D():
392
+ """48 layer ESM-2 model with 15B params, trained on UniRef50.
393
+ If you have OOM while loading this model, please refer to README
394
+ on how to employ FSDP and ZeRO CPU offloading
395
+
396
+ Returns a tuple of (Model, Alphabet).
397
+ """
398
+ return load_model_and_alphabet_hub("esm2_t48_15B_UR50D")
399
+
400
+
401
+ def esmfold_v0():
402
+ """
403
+ ESMFold v0 model with 3B ESM-2, 48 folding blocks.
404
+ This version was used for the paper (Lin et al, 2022). It was trained
405
+ on all PDB chains until 2020-05, to ensure temporal holdout with CASP14
406
+ and the CAMEO validation and test set reported there.
407
+ """
408
+ import model.esm.esmfold.v1.pretrained
409
+ return esm.esmfold.v1.pretrained.esmfold_v0()
410
+
411
+
412
+ def esmfold_v1():
413
+ """
414
+ ESMFold v1 model using 3B ESM-2, 48 folding blocks.
415
+ ESMFold provides fast high accuracy atomic level structure prediction
416
+ directly from the individual sequence of a protein. ESMFold uses the ESM2
417
+ protein language model to extract meaningful representations from the
418
+ protein sequence.
419
+ """
420
+ import model.esm.esmfold.v1.pretrained
421
+ return esm.esmfold.v1.pretrained.esmfold_v1()
422
+
423
+ def esmfold_structure_module_only_8M():
424
+ """
425
+ ESMFold baseline model using 8M ESM-2, 0 folding blocks.
426
+ ESM-2 here is trained out to 500K updates.
427
+ This is a model designed to test the capabilities of the language model
428
+ when ablated for number of parameters in the language model.
429
+ See table S1 in (Lin et al, 2022).
430
+ """
431
+ import model.esm.esmfold.v1.pretrained
432
+ return esm.esmfold.v1.pretrained.esmfold_structure_module_only_8M()
433
+
434
+
435
+ def esmfold_structure_module_only_8M_270K():
436
+ """
437
+ ESMFold baseline model using 8M ESM-2, 0 folding blocks.
438
+ ESM-2 here is trained out to 270K updates.
439
+ This is a model designed to test the capabilities of the language model
440
+ when ablated for number of parameters in the language model.
441
+ See table S1 in (Lin et al, 2022).
442
+ """
443
+ import model.esm.esmfold.v1.pretrained
444
+ return esm.esmfold.v1.pretrained.esmfold_structure_module_only_8M_270K()
445
+
446
+
447
+ def esmfold_structure_module_only_35M():
448
+ """
449
+ ESMFold baseline model using 35M ESM-2, 0 folding blocks.
450
+ ESM-2 here is trained out to 500K updates.
451
+ This is a model designed to test the capabilities of the language model
452
+ when ablated for number of parameters in the language model.
453
+ See table S1 in (Lin et al, 2022).
454
+ """
455
+ import model.esm.esmfold.v1.pretrained
456
+ return esm.esmfold.v1.pretrained.esmfold_structure_module_only_35M()
457
+
458
+
459
+ def esmfold_structure_module_only_35M_270K():
460
+ """
461
+ ESMFold baseline model using 35M ESM-2, 0 folding blocks.
462
+ ESM-2 here is trained out to 270K updates.
463
+ This is a model designed to test the capabilities of the language model
464
+ when ablated for number of parameters in the language model.
465
+ See table S1 in (Lin et al, 2022).
466
+ """
467
+ import model.esm.esmfold.v1.pretrained
468
+ return esm.esmfold.v1.pretrained.esmfold_structure_module_only_35M_270K()
469
+
470
+
471
+ def esmfold_structure_module_only_150M():
472
+ """
473
+ ESMFold baseline model using 150M ESM-2, 0 folding blocks.
474
+ ESM-2 here is trained out to 500K updates.
475
+ This is a model designed to test the capabilities of the language model
476
+ when ablated for number of parameters in the language model.
477
+ See table S1 in (Lin et al, 2022).
478
+ """
479
+ import model.esm.esmfold.v1.pretrained
480
+ return esm.esmfold.v1.pretrained.esmfold_structure_module_only_150M()
481
+
482
+
483
+ def esmfold_structure_module_only_150M_270K():
484
+ """
485
+ ESMFold baseline model using 150M ESM-2, 0 folding blocks.
486
+ ESM-2 here is trained out to 270K updates.
487
+ This is a model designed to test the capabilities of the language model
488
+ when ablated for number of parameters in the language model.
489
+ See table S1 in (Lin et al, 2022).
490
+ """
491
+ import model.esm.esmfold.v1.pretrained
492
+ return esm.esmfold.v1.pretrained.esmfold_structure_module_only_150M_270K()
493
+
494
+
495
+ def esmfold_structure_module_only_650M():
496
+ """
497
+ ESMFold baseline model using 650M ESM-2, 0 folding blocks.
498
+ ESM-2 here is trained out to 500K updates.
499
+ This is a model designed to test the capabilities of the language model
500
+ when ablated for number of parameters in the language model.
501
+ See table S1 in (Lin et al, 2022).
502
+ """
503
+ import model.esm.esmfold.v1.pretrained
504
+ return esm.esmfold.v1.pretrained.esmfold_structure_module_only_650M()
505
+
506
+
507
+ def esmfold_structure_module_only_650M_270K():
508
+ """
509
+ ESMFold baseline model using 650M ESM-2, 0 folding blocks.
510
+ ESM-2 here is trained out to 270K updates.
511
+ This is a model designed to test the capabilities of the language model
512
+ when ablated for number of parameters in the language model.
513
+ See table S1 in (Lin et al, 2022).
514
+ """
515
+ import model.esm.esmfold.v1.pretrained
516
+ return esm.esmfold.v1.pretrained.esmfold_structure_module_only_650M_270K()
517
+
518
+
519
+ def esmfold_structure_module_only_3B():
520
+ """
521
+ ESMFold baseline model using 3B ESM-2, 0 folding blocks.
522
+ ESM-2 here is trained out to 500K updates.
523
+ This is a model designed to test the capabilities of the language model
524
+ when ablated for number of parameters in the language model.
525
+ See table S1 in (Lin et al, 2022).
526
+ """
527
+ import model.esm.esmfold.v1.pretrained
528
+ return esm.esmfold.v1.pretrained.esmfold_structure_module_only_3B()
529
+
530
+
531
+ def esmfold_structure_module_only_3B_270K():
532
+ """
533
+ ESMFold baseline model using 3B ESM-2, 0 folding blocks.
534
+ ESM-2 here is trained out to 270K updates.
535
+ This is a model designed to test the capabilities of the language model
536
+ when ablated for number of parameters in the language model.
537
+ See table S1 in (Lin et al, 2022).
538
+ """
539
+ import model.esm.esmfold.v1.pretrained
540
+ return esm.esmfold.v1.pretrained.esmfold_structure_module_only_3B_270K()
541
+
542
+
543
+ def esmfold_structure_module_only_15B():
544
+ """
545
+ ESMFold baseline model using 15B ESM-2, 0 folding blocks.
546
+ ESM-2 here is trained out to 270K updates.
547
+ The 15B parameter ESM-2 was not trained out to 500K updates
548
+ This is a model designed to test the capabilities of the language model
549
+ when ablated for number of parameters in the language model.
550
+ See table S1 in (Lin et al, 2022).
551
+ """
552
+ import model.esm.esmfold.v1.pretrained
553
+ return esm.esmfold.v1.pretrained.esmfold_structure_module_only_15B()
model/esm/version.py ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ # Copyright (c) Meta Platforms, Inc. and affiliates.
2
+ #
3
+ # This source code is licensed under the MIT license found in the
4
+ # LICENSE file in the root directory of this source tree.
5
+
6
+ version = "2.0.1"