├── .gitignore ├── LICENSE ├── README.md ├── config └── predict │ ├── CR3022_BindDDG.yaml │ ├── CR3022_GearBind.yaml │ ├── CR3022_GearBindP.yaml │ ├── HER2_BindDDG.yaml │ ├── HER2_GearBind.yaml │ └── HER2_GearBindP.yaml ├── data ├── 1n8z.pdb ├── 6xc3_ba11.pdb ├── 6xc3_ba4.pdb ├── 6xc3_wt.pdb ├── CR3022_segments.csv ├── HER2_binders.csv └── skempi_v2_with_all_results_0415.csv ├── gearbind ├── __init__.py ├── dataset.py ├── geometry.py ├── layer.py ├── model.py ├── residue_constants.py ├── task.py └── util.py ├── results └── GearBind_HER2_1n8z_renum.pdb_HL_C.csv └── script ├── fix_pdb.py ├── predict.py └── process_skempi.py /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | __pycache__ 3 | *.pyc 4 | *.pyo 5 | *.pyd 6 | .idea 7 | .vscode -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. 10 | 11 | "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. 12 | 13 | "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. 14 | 15 | "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. 16 | 17 | "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. 18 | 19 | "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. 20 | 21 | "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). 22 | 23 | "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. 24 | 25 | "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." 26 | 27 | "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 28 | 29 | 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 30 | 31 | 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 32 | 33 | 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: 34 | 35 | You must give any other recipients of the Work or Derivative Works a copy of this License; and 36 | You must cause any modified files to carry prominent notices stating that You changed the files; and 37 | You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and 38 | If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. 39 | You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 40 | 41 | 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 42 | 43 | 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 44 | 45 | 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 46 | 47 | 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 48 | 49 | 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. 50 | 51 | END OF TERMS AND CONDITIONS -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # GearBind 2 | 3 | For the latest version of GearBind code and the link to the datasets, please refer to https://github.com/DeepGraphLearning/GearBind. 4 | 5 | ## Overview 6 | 7 | GearBind is a pretrainable geometric graph neural network for protein-protein binding affinity change (ddG_bind) prediction. 8 | It is pretrained on CATH using contrastive learning and fine-tuned on SKEMPI with a regression loss. 9 | Here we provide the inference code of GearBind. 10 | 11 | This codebase is based on PyTorch and [TorchDrug]. It supports training and inference with multiple GPUs or multiple machines. 12 | 13 | [TorchDrug]: https://github.com/DeepGraphLearning/torchdrug 14 | 15 | ## Installation 16 | 17 | You may install the dependencies via either conda or pip. Generally, GearBind works 18 | with Python 3.8/3.9 and PyTorch version >= 1.8.0. 19 | 20 | Windows, Mac OS X and Linux should all be supported. 21 | 22 | ### From Conda 23 | 24 | If internet connection is smooth, the installation should be completed within 15 minutes. 25 | [Using mamba as the conda solver](https://www.anaconda.com/blog/a-faster-conda-for-a-growing-community) can potentially speed up the installation process. 26 | 27 | ```bash 28 | conda install pyg pytorch=1.8.0 cudatoolkit=11.1 torchdrug -c pyg -c pytorch -c conda-forge 29 | conda install rdkit easydict pyyaml biopython gdown -c conda-forge 30 | ``` 31 | 32 | 33 | ## Inference on HER2 and CR3022 34 | 35 | Now we show how to use our (pre-)trained models for inference on new wild-type proteins. 36 | Here we take the HER2 and CR3022 proteins used in the paper as examples. 37 | First, you need to download the checkpoints to the `./checkpoints` directory. 38 | Note that we can not provide FoldX-generated HER2 and CR3022 mutant structures due to license restrictions. 39 | Please prepare the wild-type and mutant structures yourself. 40 | The prepared dataset should have the following file structure: 41 | 42 | - `data.csv`: a csv file with columns "pdb_id", "mutation", "chain_a", "chain_b", "wt_protein", "mt_protein", where 43 | - "pdb_id" is the stem of the protein complex structure file name 44 | - "mutation" is the comma-separated mutation list 45 | - "chain_a" and "chain_b" are interacting chains in the complex (e.g., HL and C), 46 | - "wt_protein" and "mt_protein" are the file names of the wild-type and mutant structures, respectively. 47 | - `data`: folder storing the wild-type and mutant structures. 48 | 49 | The PDB structures used to prepare the HER2 (`1n8z.pdb`) and CR3022 dataset (`6xc3_wt.pdb`) are provided in the `data` directory. 50 | `6xc3_ba4.pdb` and `6xc3_ba11.pdb` are the PDB structures of CR3022 against the RBD of BA.4 and BA.1.1 strains of SARS-CoV-2, respectively, modelled by SWISS-MODEL. 51 | 52 | ```bash 53 | # Downloading model checkpoints 54 | cd checkpoints 55 | gdown 1nFEjbjdlRWFwYz7LUNv_D6oLnEsZ5beJ 56 | unzip new-gearbind-model-weights.zip 57 | mv new-gearbind-model-weights/*.pth ./ 58 | rm -rf new-gearbind-model-weights 59 | cd .. 60 | ``` 61 | 62 | We have prepared the config file in the `./config/predict` directory. 63 | To get the prediction results of the pre-trained models on different variants, you can run the following commands. 64 | 65 | ```bash 66 | # Run GearBind-P models on CR3022 datasets 67 | python script/predict.py -c config/predict/CR3022_GearBindP.yaml 68 | 69 | # Run GearBind models on HER2 datasets 70 | python script/predict.py -c config/predict/HER2_GearBind.yaml 71 | ``` 72 | 73 | The inference should take about 2 minutes on a single A100 GPU. The expected output for HER2 binders are stored in `results/GearBind_HER2_1n8z_renum.pdb_HL_C.csv`. 74 | After finishing the prediction, you are expected to get an output file called `__.csv`. 75 | For the second case, the name of the output file is `GearBind_HER2_1n8z_renum.pdb_HL_C.csv`. 76 | You can compare this output with the results we provide in `./results`. 77 | 78 | To run the model on your own protein complexes, you need to 79 | 1. prepare the dataset with FoldX 80 | 2. write a customized dataset class following `dataset.HER2` and `dataset.CR3022` 81 | 3. add a `.yaml` file by modifying the configuration of the dataset class 82 | 83 | 84 | ## SKEMPI preprocesssing 85 | 86 | The following commands process SKEMPI from raw data, including downloading the raw data, processing the data so that it is ready for FoldX mutagenesis. 87 | 88 | ```bash 89 | python script/process_skempi.py --csv-path $SKEMPI_CSV_PATH --pdb-dir $SKEMPI_PDB_DIR --output-csv-path $PROCESSED_SKEMPI_CSV_PATH --output-pdb-dir $PROCESSED_SKEMPI_PDB_DIR --no-repair 90 | ``` 91 | 92 | where 93 | - `SKEMPI_CSV_PATH`: the path to the raw SKEMPI csv file. 94 | - `SKEMPI_PDB_DIR`: the directory containing the raw SKEMPI pdb files. 95 | - `PROCESSED_SKEMPI_CSV_PATH`: the path to the processed SKEMPI csv file. 96 | - `PROCESSED_SKEMPI_PDB_DIR`: the directory to store the processed SKEMPI pdb files. 97 | 98 | The processed SKEMPI dataset and all model predictions can be found in `data/skempi_v2_with_all_results_0415.csv`. 99 | -------------------------------------------------------------------------------- /config/predict/CR3022_BindDDG.yaml: -------------------------------------------------------------------------------- 1 | dataset: 2 | class: CR3022 3 | path: ./data/CR3022 4 | node_feature: residue_symbol 5 | residue_feature: default 6 | split: 7 | test_sets: 8 | - 6xc3_ba11_renum.pdb_C_HL 9 | - 6xc3_ba4_renum.pdb_C_HL 10 | - 6xc3_wt_renum.pdb_C_HL 11 | 12 | task: 13 | class: BindingAffinityChange 14 | model: 15 | class: DDGPredictor 16 | hidden_dim: 128 17 | pair_dim: 64 18 | max_relpos: 32 19 | num_layers: 2 20 | normalization: False 21 | task: [ddG] 22 | criterion: mse 23 | metric: ["mae", "rmse", "spearmanr", "pearsonr"] 24 | 25 | optimizer: 26 | class: Adam 27 | lr: 1.0e-4 28 | 29 | engine: 30 | gpus: [0] 31 | batch_size: 8 32 | 33 | checkpoints: 34 | - ./checkpoints/bindddg0.pth 35 | - ./checkpoints/bindddg1.pth 36 | - ./checkpoints/bindddg2.pth 37 | - ./checkpoints/bindddg3.pth 38 | - ./checkpoints/bindddg4.pth 39 | -------------------------------------------------------------------------------- /config/predict/CR3022_GearBind.yaml: -------------------------------------------------------------------------------- 1 | dataset: 2 | class: CR3022 3 | path: ./data/CR3022 4 | node_feature: residue_symbol 5 | residue_feature: default 6 | split: 7 | test_sets: 8 | - 6xc3_ba11_renum.pdb_C_HL 9 | - 6xc3_ba4_renum.pdb_C_HL 10 | - 6xc3_wt_renum.pdb_C_HL 11 | 12 | task: 13 | class: BindingAffinityChange 14 | model: 15 | class: BindModel 16 | num_mlp_layer: 2 17 | model: 18 | class: GearBind 19 | input_dim: 58 20 | hidden_dims: [128, 128, 128, 128] 21 | batch_norm: True 22 | short_cut: True 23 | concat_hidden: True 24 | num_relation: 7 25 | edge_input_dim: 59 26 | num_angle_bin: 8 27 | graph_construction_model: 28 | class: GraphConstruction 29 | node_layers: 30 | - class: InterfaceGraph 31 | cutoff: 6.0 32 | edge_layers: 33 | - class: SequentialEdge 34 | max_distance: 2 35 | - class: SpatialEdge 36 | radius: 10.0 37 | max_distance: 5 38 | - class: KNNEdge 39 | k: 10 40 | max_distance: 5 41 | edge_feature: gearnet 42 | normalization: False 43 | task: [ddG] 44 | criterion: mse 45 | metric: ["mae", "rmse", "spearmanr", "pearsonr"] 46 | 47 | optimizer: 48 | class: Adam 49 | lr: 1.0e-4 50 | 51 | engine: 52 | gpus: [0] 53 | batch_size: 8 54 | 55 | checkpoints: 56 | - ./checkpoints/gearbind0.pth 57 | - ./checkpoints/gearbind1.pth 58 | - ./checkpoints/gearbind2.pth 59 | - ./checkpoints/gearbind3.pth 60 | - ./checkpoints/gearbind4.pth 61 | -------------------------------------------------------------------------------- /config/predict/CR3022_GearBindP.yaml: -------------------------------------------------------------------------------- 1 | dataset: 2 | class: CR3022 3 | path: ./data/CR3022 4 | node_feature: residue_symbol 5 | residue_feature: default 6 | split: 7 | test_sets: 8 | - 6xc3_ba11_renum.pdb_C_HL 9 | - 6xc3_ba4_renum.pdb_C_HL 10 | - 6xc3_wt_renum.pdb_C_HL 11 | 12 | task: 13 | class: BindingAffinityChange 14 | model: 15 | class: BindModel 16 | num_mlp_layer: 2 17 | model: 18 | class: GearBind 19 | input_dim: 58 20 | hidden_dims: [128, 128, 128, 128] 21 | batch_norm: True 22 | short_cut: True 23 | concat_hidden: True 24 | num_relation: 7 25 | edge_input_dim: 59 26 | num_angle_bin: 8 27 | graph_construction_model: 28 | class: GraphConstruction 29 | node_layers: 30 | - class: InterfaceGraph 31 | cutoff: 6.0 32 | edge_layers: 33 | - class: SequentialEdge 34 | max_distance: 2 35 | - class: SpatialEdge 36 | radius: 10.0 37 | max_distance: 5 38 | - class: KNNEdge 39 | k: 10 40 | max_distance: 5 41 | edge_feature: gearnet 42 | normalization: False 43 | task: [ddG] 44 | criterion: mse 45 | metric: ["mae", "rmse", "spearmanr", "pearsonr"] 46 | 47 | optimizer: 48 | class: Adam 49 | lr: 1.0e-4 50 | 51 | engine: 52 | gpus: [0] 53 | batch_size: 8 54 | 55 | checkpoints: 56 | - ./checkpoints/gearbindP0.pth 57 | - ./checkpoints/gearbindP1.pth 58 | - ./checkpoints/gearbindP2.pth 59 | - ./checkpoints/gearbindP3.pth 60 | - ./checkpoints/gearbindP4.pth 61 | 62 | -------------------------------------------------------------------------------- /config/predict/HER2_BindDDG.yaml: -------------------------------------------------------------------------------- 1 | dataset: 2 | class: HER2 3 | path: ./data/aff_optim_1n8z_0328 4 | node_feature: residue_symbol 5 | residue_feature: default 6 | split: 7 | test_set: 1n8z_renum.pdb_HL_C 8 | 9 | task: 10 | class: BindingAffinityChange 11 | model: 12 | class: DDGPredictor 13 | hidden_dim: 128 14 | pair_dim: 64 15 | max_relpos: 32 16 | num_layers: 2 17 | normalization: False 18 | task: [ddG] 19 | criterion: mse 20 | metric: ["mae", "rmse", "spearmanr", "pearsonr"] 21 | 22 | optimizer: 23 | class: Adam 24 | lr: 1.0e-4 25 | 26 | engine: 27 | gpus: [0] 28 | batch_size: 8 29 | 30 | checkpoints: 31 | - ./checkpoints/bindddg0.pth 32 | - ./checkpoints/bindddg1.pth 33 | - ./checkpoints/bindddg2.pth 34 | - ./checkpoints/bindddg3.pth 35 | - ./checkpoints/bindddg4.pth 36 | -------------------------------------------------------------------------------- /config/predict/HER2_GearBind.yaml: -------------------------------------------------------------------------------- 1 | dataset: 2 | class: HER2 3 | path: ./data/aff_optim_1n8z_0328 4 | node_feature: residue_symbol 5 | residue_feature: default 6 | split: 7 | test_set: 1n8z_renum.pdb_HL_C 8 | 9 | task: 10 | class: BindingAffinityChange 11 | model: 12 | class: BindModel 13 | num_mlp_layer: 2 14 | model: 15 | class: GearBind 16 | input_dim: 58 17 | hidden_dims: [128, 128, 128, 128] 18 | batch_norm: True 19 | short_cut: True 20 | concat_hidden: True 21 | num_relation: 7 22 | edge_input_dim: 59 23 | num_angle_bin: 8 24 | graph_construction_model: 25 | class: GraphConstruction 26 | node_layers: 27 | - class: InterfaceGraph 28 | cutoff: 6.0 29 | edge_layers: 30 | - class: SequentialEdge 31 | max_distance: 2 32 | - class: SpatialEdge 33 | radius: 10.0 34 | max_distance: 5 35 | - class: KNNEdge 36 | k: 10 37 | max_distance: 5 38 | edge_feature: gearnet 39 | normalization: False 40 | task: [ddG] 41 | criterion: mse 42 | metric: ["mae", "rmse", "spearmanr", "pearsonr"] 43 | 44 | optimizer: 45 | class: Adam 46 | lr: 1.0e-4 47 | 48 | engine: 49 | gpus: [0] 50 | batch_size: 8 51 | 52 | checkpoints: 53 | - ./checkpoints/gearbind0.pth 54 | - ./checkpoints/gearbind1.pth 55 | - ./checkpoints/gearbind2.pth 56 | - ./checkpoints/gearbind3.pth 57 | - ./checkpoints/gearbind4.pth 58 | 59 | -------------------------------------------------------------------------------- /config/predict/HER2_GearBindP.yaml: -------------------------------------------------------------------------------- 1 | dataset: 2 | class: HER2 3 | path: ./data/aff_optim_1n8z_0328 4 | node_feature: residue_symbol 5 | residue_feature: default 6 | split: 7 | test_set: 1n8z_renum.pdb_HL_C 8 | 9 | task: 10 | class: BindingAffinityChange 11 | model: 12 | class: BindModel 13 | num_mlp_layer: 2 14 | model: 15 | class: GearBind 16 | input_dim: 58 17 | hidden_dims: [128, 128, 128, 128] 18 | batch_norm: True 19 | short_cut: True 20 | concat_hidden: True 21 | num_relation: 7 22 | edge_input_dim: 59 23 | num_angle_bin: 8 24 | graph_construction_model: 25 | class: GraphConstruction 26 | node_layers: 27 | - class: InterfaceGraph 28 | cutoff: 6.0 29 | edge_layers: 30 | - class: SequentialEdge 31 | max_distance: 2 32 | - class: SpatialEdge 33 | radius: 10.0 34 | max_distance: 5 35 | - class: KNNEdge 36 | k: 10 37 | max_distance: 5 38 | edge_feature: gearnet 39 | normalization: False 40 | task: [ddG] 41 | criterion: mse 42 | metric: ["mae", "rmse", "spearmanr", "pearsonr"] 43 | 44 | optimizer: 45 | class: Adam 46 | lr: 1.0e-4 47 | 48 | engine: 49 | gpus: [0] 50 | batch_size: 8 51 | 52 | checkpoints: 53 | - ./checkpoints/gearbindP0.pth 54 | - ./checkpoints/gearbindP1.pth 55 | - ./checkpoints/gearbindP2.pth 56 | - ./checkpoints/gearbindP3.pth 57 | - ./checkpoints/gearbindP4.pth 58 | -------------------------------------------------------------------------------- /data/CR3022_segments.csv: -------------------------------------------------------------------------------- 1 | pdb_fname,chain_a,chain_b,segments 2 | 6xc3_wt.pdb,HL,C,H26-35;H50-66;H99-108;L24-40;L56-62;L95-103 3 | 6xc3_ba11.pdb,HL,C,H26-35;H50-66;H99-108;L24-40;L56-62;L95-103 4 | 6xc3_ba4.pdb,HL,C,H26-35;H50-66;H99-108;L24-40;L56-62;L95-103 5 | -------------------------------------------------------------------------------- /data/HER2_binders.csv: -------------------------------------------------------------------------------- 1 | KD (nM),mutation,num_mutations,ddG,pdb_fname,chain_a,chain_b 2 | 0.56,"SH105A,DH110Y",2,-0.7237822258651097,1n8z.pdb,HL,A 3 | 0.87,"SH105T,GH108Y,GH109Y,DH110F,GH111I,FH112Y,AH114Y,YH117V",8,-0.4627736961914781,1n8z.pdb,HL,A 4 | 0.94,"SH105T,WH107Y,GH108F,GH109F,DH110N,FH112W,AH114Y,MH115F,YH117V",9,-0.4169258138169134,1n8z.pdb,HL,A 5 | 0.98,"SH105A,WH107Y,GH108Y,DH110Y,FH112G,AH114W,MH115F,DH116A",8,-0.3922367421662862,1n8z.pdb,HL,A 6 | 1.07,"DH110W,AH114S",2,-0.3401831076329564,1n8z.pdb,HL,A 7 | 2.02,"GH108H,DH110Y",2,0.0362839072657568,1n8z.pdb,HL,A 8 | 2.4,"SH105T,GH108L,GH109E,DH110G,GH111L,FH112S,AH114F",7,0.138405582015384,1n8z.pdb,HL,A 9 | 2.54,"SH105T,WH107Y,DH110R,FH112A,AH114Y,MH115F,YH117V",7,0.1719948508458042,1n8z.pdb,HL,A 10 | 2.64,"SH105A,GH108P,GH109F,DH110Y,FH112P,AH114N,MH115Y",7,0.1948722871117976,1n8z.pdb,HL,A 11 | 2.64,"SH105A,GH108I,GH109D,DH110G,GH111Y,FH112S,AH114F",7,0.1948722871117976,1n8z.pdb,HL,A 12 | 2.99,"SH105T,WH107Y,GH108Y,GH109Y,DH110G,FH112P,AH114Y,MH115F",8,0.2686292829736842,1n8z.pdb,HL,A 13 | 3.0,"SH105A,WH107Y,GH109L,DH110G,GH111D,FH112W,AH114Y,MH115F,DH116A",9,0.2706074216519738,1n8z.pdb,HL,A 14 | 3.39,"SH105A,WH107Y,GH108E,GH109A,DH110Y,FH112L,AH114P,MH115F,DH116G",9,0.3430155006083932,1n8z.pdb,HL,A 15 | 3.42,"SH105A,GH108L,DH110E,FH112Y,AH114N,MH115F",6,0.3482353756416518,1n8z.pdb,HL,A 16 | 3.5,DH110R,1,0.3619342977116773,1n8z.pdb,HL,A 17 | 3.99,"SH105A,RH106N,WH107D,GH108I,GH109Y,DH110I,GH111Q,FH112G,AH114D,MH115L,DH116N,YH117R",12,0.4395622517013517,1n8z.pdb,HL,A 18 | 4.09,"SH105A,GH108T,GH109A,DH110G,GH111Y,FH112T,AH114Y",7,0.4542276535676812,1n8z.pdb,HL,A 19 | 4.56,"SH105T,GH109Y,DH110Y,FH112Y",4,0.5186731901543311,1n8z.pdb,HL,A 20 | 4.67,"SH105A,GH108W,GH109Y,DH110Y,FH112Y,AH114Y,MH115F,YH117V",8,0.53279514114897,1n8z.pdb,HL,A 21 | 4.83,"SH105A,GH108P,DH110Y,FH112S,AH114Y,YH117V",6,0.5527533057267906,1n8z.pdb,HL,A 22 | 5.05,"DH110P,FH112L",2,0.5791421690541512,1n8z.pdb,HL,A 23 | 5.08,"SH105A,GH108R",2,0.5826512729976088,1n8z.pdb,HL,A 24 | 5.35,"SH105V,WH107Y,GH108Y,FH112G,AH114Y,MH115F",6,0.6133315763072389,1n8z.pdb,HL,A 25 | 5.66,"SH105A,GH108Y,GH109Y,DH110Y,FH112Y,AH114Y,MH115F,YH117V",8,0.6467028154793848,1n8z.pdb,HL,A 26 | 6.29,"SH105A,GH108Y,GH109Y,DH110L,FH112Y,AH114Y,MH115F",7,0.70922852623921,1n8z.pdb,HL,A 27 | 6.44,"SH105A,GH108W,GH109Y,DH110G,FH112Y,AH114Y,MH115F",7,0.7231911202394699,1n8z.pdb,HL,A 28 | 6.5,"SH105A,GH108L,GH109Y,DH110Y,FH112Y,AH114Y,MH115F",7,0.7286853047494919,1n8z.pdb,HL,A 29 | 6.69,"SH105A,GH108W,GH109Y,DH110G,FH112Y,AH114Y",6,0.7457548519336061,1n8z.pdb,HL,A 30 | 6.76,"SH105V,WH107Y,DH110W,YH113W,AH114Y,MH115F",6,0.7519216940611511,1n8z.pdb,HL,A 31 | 6.82,"SH105T,WH107Y,GH108Y,GH109Y,DH110Y,FH112S,AH114H,MH115F",8,0.757156944478405,1n8z.pdb,HL,A 32 | 6.93,"SH105A,GH109Y,DH110S,FH112W,AH114V",5,0.7666363784497428,1n8z.pdb,HL,A 33 | 7.03,"SH105A,GH108E,DH110I,FH112G,AH114Y,MH115F,DH116V",7,0.7751243744038518,1n8z.pdb,HL,A 34 | 7.04,"SH105A,GH108Y,GH109Y,DH110G,GH111Y,FH112Y,AH114Y,MH115F,YH117V",9,0.7759665237762814,1n8z.pdb,HL,A 35 | 7.11,"SH105A,WH107Y,GH108F,GH109Y,GH111Y,FH112Y,AH114Y,MH115F,YH117F",9,0.7818282873347258,1n8z.pdb,HL,A 36 | 7.31,"SH105A,WH107Y,GH109D,DH110G,GH111Y,FH112Y,AH114Y,MH115F,DH116A",9,0.7982635155577533,1n8z.pdb,HL,A 37 | 7.31,"SH105A,WH107Y,DH110S,GH111Y,AH114Y,MH115Y,DH116S",7,0.7982635155577533,1n8z.pdb,HL,A 38 | 7.43,"SH105A,GH108Y,DH110Y,FH112G,AH114Y,MH115F",6,0.8079101653225713,1n8z.pdb,HL,A 39 | 7.54,"SH105T,WH107N,GH108Y,GH109Y,GH111Y,FH112Y,AH114Y,MH115F",8,0.8166170312096455,1n8z.pdb,HL,A 40 | 7.69,"SH105A,GH108K,DH110Y,FH112H,AH114Y",5,0.8282875067440028,1n8z.pdb,HL,A 41 | 7.78,"SH105A,GH108Y,GH109Y,DH110G,GH111H,FH112Y,AH114Y",7,0.8351810141918765,1n8z.pdb,HL,A 42 | 7.95,"SH105A,GH109Y,GH111Y,FH112Y,AH114M,YH117V",6,0.8479872136492244,1n8z.pdb,HL,A 43 | 8.05,"SH105A,WH107Y,GH108Y,DH110Y,FH112G,AH114Y,MH115F",7,0.8553929598760597,1n8z.pdb,HL,A 44 | 8.08,"SH105A,DH110P,FH112Y,MH115F,DH116V,YH117W",6,0.8575967515693623,1n8z.pdb,HL,A 45 | 8.11,"SH105A,GH108R,GH109Q,FH112A,AH114Y,MH115L",6,0.8597923760109758,1n8z.pdb,HL,A 46 | 8.19,"SH105A,WH107Y,GH108Y,DH110Y,FH112G,AH114W,MH115Y,YH117T",8,0.8656079023015746,1n8z.pdb,HL,A 47 | 8.2,"SH105A,GH108V,GH109Y,DH110G,GH111Y,FH112Y,AH114Y,MH115F",8,0.866330845629534,1n8z.pdb,HL,A 48 | 8.29,"SH105A,GH108Y,GH109Y,DH110Y,FH112G,AH114Y,MH115F",7,0.872797941807633,1n8z.pdb,HL,A 49 | 8.41,"SH105A,WH107N,GH108Y,GH109Y,GH111L,FH112Y,AH114Y,MH115F",8,0.8813123683581381,1n8z.pdb,HL,A 50 | 8.44,"SH105A,WH107Y,GH108Y,GH109Y,GH111Y,FH112Y,AH114Y,MH115F",8,0.8834219918943376,1n8z.pdb,HL,A 51 | 8.45,"SH105A,GH109Y,DH110G,FH112A,AH114Y",5,0.8841235336977409,1n8z.pdb,HL,A 52 | 8.52,"SH105A,GH108Y,GH109Y,DH110Y,FH112Y,AH114Y,YH117V",7,0.8890112030057296,1n8z.pdb,HL,A 53 | 8.57,"SH105T,RH106S,WH107I,GH108F,GH109S,DH110G,FH112Y,AH114G,MH115L,YH117S",10,0.8924778716666424,1n8z.pdb,HL,A 54 | 8.68,"SH105A,GH108Y,GH109Y,DH110Y,FH112A,AH114Y,MH115F",7,0.9000338834442232,1n8z.pdb,HL,A 55 | 8.73,"SH105T,WH107Y,GH109S,DH110F,GH111H,FH112Y,AH114Y,MH115F,YH117V",9,0.903436833545202,1n8z.pdb,HL,A 56 | 8.78,"SH105A,DH110Y,FH112Y,AH114Y,YH117V",5,0.906820349216412,1n8z.pdb,HL,A 57 | 8.92,"SH105T,WH107F,GH108I,GH109D,DH110N,FH112P,AH114Y,MH115F",8,0.9161926664462872,1n8z.pdb,HL,A 58 | 9.08,"SH105A,WH107Y,GH108L,GH109S,DH110A,GH111V,FH112Y,AH114Y,YH117H",9,0.9267254235691488,1n8z.pdb,HL,A 59 | 9.14,"SH105T,WH107Y,GH108A,GH109S,DH110G,GH111Y,MH115F",7,0.9306274265901688,1n8z.pdb,HL,A 60 | 9.2,"SH105T,RH106L,GH109L,DH110P,GH111M,FH112M,AH114V,MH115Y,DH116F,YH117F",10,0.934503898329039,1n8z.pdb,HL,A 61 | 9.22,"SH105A,GH108L,GH109Y,DH110Y,FH112L,AH114Y,MH115F,YH117V",8,0.935790439515932,1n8z.pdb,HL,A 62 | 9.24,"SH105A,GH109E,DH110F,FH112P,AH114Y,MH115F",6,0.9370741929624238,1n8z.pdb,HL,A 63 | 9.28,"SH105A,GH108T,GH109E,DH110R,AH114S,MH115F,YH117I",7,0.9396333847766094,1n8z.pdb,HL,A 64 | 9.56,"SH105A,GH109Y,DH110Y,FH112Y,AH114Y,MH115F,YH117V",7,0.9572447192439668,1n8z.pdb,HL,A 65 | 9.91,"SH105A,WH107Y,GH108Y,DH110Y,FH112G,AH114Y",6,0.9785472908493276,1n8z.pdb,HL,A 66 | 10.12,"SH105A,RH106K,WH107F,GH108A,GH109Y,DH110Y,FH112P,AH114H,MH115F,YH117P",10,0.9909706034254544,1n8z.pdb,HL,A 67 | 10.16,"SH105A,GH108Y,DH110Y,FH112Y,AH114F,YH117V",6,0.9933076951494098,1n8z.pdb,HL,A 68 | 10.5,"SH105A,DH110G,FH112Y,AH114F",4,1.0128093275025982,1n8z.pdb,HL,A 69 | 10.69,"SH105A,GH108Y,DH110F,FH112G,AH114Y,MH115F",6,1.0234340461197142,1n8z.pdb,HL,A 70 | 10.9,"SH105A,GH108L,DH110S,FH112Y,AH114W,MH115F",6,1.0349596450458591,1n8z.pdb,HL,A 71 | 11.0,"SH105A,GH108Y,GH109Y,DH110Y,FH112R,AH114Y,MH115F",7,1.040370203049461,1n8z.pdb,HL,A 72 | 11.3,"SH105T,RH106P,WH107Y,GH108D,GH109V,DH110L,FH112S,AH114Y,MH115F,DH116R,YH117V",11,1.0563115769094669,1n8z.pdb,HL,A 73 | 11.31,"SH105T,DH110Y,FH112Y",3,1.0568356388487654,1n8z.pdb,HL,A 74 | 11.75,"WH107Y,GH108Y,GH109A,DH110G,FH112W,AH114Y,MH115F",7,1.0794471319116743,1n8z.pdb,HL,A 75 | 11.84,"SH105A,GH108Y,DH110G,FH112Y,AH114Y",5,1.0839677709319169,1n8z.pdb,HL,A 76 | 12.0,"SH105T,WH107Y,DH110Y,FH112Y,AH114Y",5,1.0919202659555776,1n8z.pdb,HL,A 77 | 12.07,"SH105T,WH107Y,GH108R,DH110P,GH111Y,FH112Y,AH114Y,MH115F,YH117P",9,1.0953661949775064,1n8z.pdb,HL,A 78 | 12.1,"SH105V,GH109V,DH110G,GH111A,FH112Y,AH114N,MH115F",7,1.0968369081458746,1n8z.pdb,HL,A 79 | 12.21,"SH105T,WH107Y,GH108D,GH109Y,GH111Y,FH112Y,AH114Y,MH115F",8,1.1021985011522393,1n8z.pdb,HL,A 80 | 12.49,"SH105A,GH108Y,GH109Y,DH110Y,FH112G,AH114Y,MH115F,YH117V",8,1.115631186316833,1n8z.pdb,HL,A 81 | 12.77,"SH105A,GH108R,GH109Y,DH110G,GH111Y,FH112Y,AH114Y",7,1.1287660517297835,1n8z.pdb,HL,A 82 | 12.84,"SH105T,GH108A,GH109F,FH112V,AH114Y",5,1.1320047664615736,1n8z.pdb,HL,A 83 | 12.94,"SH105T,WH107Y,GH108Y,GH109Y,DH110G,GH111L,FH112Y,AH114Y,YH117V",9,1.13660100350741,1n8z.pdb,HL,A 84 | 13.1,"SH105A,GH108R,FH112G,AH114Y,MH115F",5,1.143881611060614,1n8z.pdb,HL,A 85 | 13.16,"SH105V,WH107Y,GH109F,FH112S,AH114Y,MH115F,YH117P",7,1.1465889363373163,1n8z.pdb,HL,A 86 | 13.21,"SH105A,WH107Y,GH108V,DH110L,FH112G,AH114P,MH115L,DH116G",8,1.1488356283878964,1n8z.pdb,HL,A 87 | 13.33,"SH105A,GH108Y,GH109Y,DH110Y,FH112Y,YH117V",6,1.154193180952582,1n8z.pdb,HL,A 88 | 13.4,"SH105A,GH109Y,DH110Y,FH112N,AH114Y,MH115F",6,1.1572961913279671,1n8z.pdb,HL,A 89 | 13.48,"SH105V,DH110Y,FH112Y",3,1.1608227016435195,1n8z.pdb,HL,A 90 | 13.6,"SH105A,GH108R,DH110Y,FH112S,YH117V",5,1.1660734182907664,1n8z.pdb,HL,A 91 | 13.7,"SH105A,GH108W,GH109Y,DH110G,FH112Y,AH114F,MH115F",7,1.1704137452763277,1n8z.pdb,HL,A 92 | 13.9,"SH105A,WH107Y,GH109S,DH110S,GH111Y,FH112Y,AH114Y,MH115F",8,1.1790001562032035,1n8z.pdb,HL,A 93 | 13.92,"SH105A,WH107H,GH108F,DH110V,GH111A,FH112S,AH114S,MH115F",8,1.1798519924157311,1n8z.pdb,HL,A 94 | 14.0,"SH105A,WH107Y,DH110Y,FH112G,AH114Y,MH115F",6,1.183247142015281,1n8z.pdb,HL,A 95 | 14.12,"SH105A,RH106K,WH107Y,GH109A,DH110T,FH112W,AH114Y,MH115F",8,1.1883036619027791,1n8z.pdb,HL,A 96 | 14.3,"SH105A,WH107Y,GH109Y,DH110Y,FH112P,AH114Y,MH115F",7,1.19580843199771,1n8z.pdb,HL,A 97 | 14.34,"SH105T,WH107Y,GH109Y,DH110G,FH112P,AH114W,MH115F",7,1.1974633268830883,1n8z.pdb,HL,A 98 | 14.5,"SH105A,WH107Y,GH108R,DH110V,GH111W,FH112Y,AH114D,MH115F,YH117N",9,1.204037064049789,1n8z.pdb,HL,A 99 | 14.7,"SH105A,WH107Y,GH108L,GH109Q,DH110L,FH112P,AH114Y,MH115F",8,1.2121529715648336,1n8z.pdb,HL,A 100 | 14.9,"SH105A,GH108Y,GH109Y,DH110G,GH111Y,FH112Y,AH114W,MH115F,YH117V",9,1.2201592012929652,1n8z.pdb,HL,A 101 | 14.9,"SH105A,GH108W,DH110G,FH112A,AH114Y,MH115F",6,1.2201592012929652,1n8z.pdb,HL,A 102 | 14.9,"SH105A,RH106K,WH107Y,GH108L,DH110Q,GH111E,FH112A,MH115Y,DH116F,YH117S",10,1.2201592012929652,1n8z.pdb,HL,A 103 | 15.4,"SH105A,GH108D,GH109S,DH110G,FH112P,AH114Y,MH115F,YH117S",8,1.2397138471116946,1n8z.pdb,HL,A 104 | 15.7,"SH105A,WH107Y,GH109S,DH110R,GH111Y,FH112Y,AH114Y,MH115F",8,1.2511441434631898,1n8z.pdb,HL,A 105 | 15.7,"SH105A,WH107Y,GH109S,DH110G,GH111Y,FH112Y,AH114Y,MH115F",8,1.2511441434631898,1n8z.pdb,HL,A 106 | 15.74,"SH105A,GH108L,GH109A,DH110G,GH111Y,FH112N,AH114Y,MH115F,YH117V",9,1.2526516556856002,1n8z.pdb,HL,A 107 | 15.76,"SH105A,WH107Y,GH108T,GH109Y,DH110F,FH112S,YH113F,AH114D,MH115F",9,1.2534039757660531,1n8z.pdb,HL,A 108 | 15.85,"SH105A,GH108L,GH109R,DH110A,GH111L,FH112G,AH114Y",7,1.2567776437584772,1n8z.pdb,HL,A 109 | 16.01,"SH105V,GH108Y,DH110Y,FH112Y,AH114Y",5,1.2627282472930157,1n8z.pdb,HL,A 110 | 16.17,"SH105A,GH108Y,GH109Y,DH110G,GH111Y,FH112A,AH114Y",7,1.2686196766612454,1n8z.pdb,HL,A 111 | 16.48,"SH105A,WH107Y,GH108W,DH110L,FH112G,AH114Y,MH115F,YH117H",8,1.279870251493465,1n8z.pdb,HL,A 112 | 16.5,"SH105V,WH107Y,GH109F,DH110Y,FH112Y,AH114Y,MH115F",7,1.280588810688581,1n8z.pdb,HL,A 113 | 16.77,"SH105A,GH108L,GH109A,DH110F,FH112Y",5,1.2902050143226145,1n8z.pdb,HL,A 114 | 16.95,"SH105A,RH106K,WH107Y,GH108I,GH109N,DH110A,GH111Y,FH112S,MH115F,DH116F,YH117D",11,1.2965301845485868,1n8z.pdb,HL,A 115 | 17.41,"SH105A,WH107Y,GH108S,DH110Y,FH112L,AH114P,MH115Y,DH116A",8,1.3123942238937722,1n8z.pdb,HL,A 116 | 17.47,"SH105A,RH106K,WH107Y,GH108A,GH109Y,DH110Y,FH112D,YH113F,AH114W,MH115G,DH116S,YH117V",12,1.314432478141855,1n8z.pdb,HL,A 117 | 18.46,"SH105T,WH107Y,GH108E,GH109Y,DH110Q,GH111D,FH112Y,AH114H,MH115F",9,1.3470890861032476,1n8z.pdb,HL,A 118 | 18.6,"TH59S,SH105A,WH107Y,DH110S,GH111Y,FH112A,AH114Y,MH115F,DH116Y",9,1.351565269172914,1n8z.pdb,HL,A 119 | 18.64,"SH105A,GH108Y,DH110Q,GH111V",4,1.3528379914319668,1n8z.pdb,HL,A 120 | 19.0,"SH105A,WH107Y,GH108Y,DH110V,FH112P,AH114S,YH117V",7,1.3641711060919943,1n8z.pdb,HL,A 121 | 19.1,"SH105A,GH109Y,DH110G,FH112Y,AH114Y,MH115F",6,1.3672810974001397,1n8z.pdb,HL,A 122 | 19.29,"SH105A,RH106S,WH107Y,GH109L,FH112Y,AH114Y,MH115F,YH117V",8,1.3731454785416997,1n8z.pdb,HL,A 123 | 19.38,"SH105A,GH108N,GH109Y,DH110Y,FH112Y,AH114Y,MH115F",7,1.375903211917031,1n8z.pdb,HL,A 124 | 19.4,"SH105A,GH109Y,GH111Y,FH112Y",4,1.3765143022071555,1n8z.pdb,HL,A 125 | 19.42,"SH105A,WH107Y,GH108Y,GH109S,DH110Y,FH112Q,MH115F,YH117P",8,1.377124762831745,1n8z.pdb,HL,A 126 | 19.6,"SH105A,WH107Y,DH110G,FH112R,AH114Y,MH115F",6,1.3825907860775128,1n8z.pdb,HL,A 127 | 19.66,"SH105A,WH107Y,GH108W,GH109Y,DH110G,FH112Y,AH114Y,MH115F",8,1.3844016442894187,1n8z.pdb,HL,A 128 | 19.75,"SH105T,GH108L,GH109Y,DH110Y,GH111S,FH112A,AH114Y,MH115F,YH117F",9,1.3871075956332677,1n8z.pdb,HL,A 129 | 19.8,"SH105A,WH107Y,GH108A,GH109H,DH110Y,FH112P,AH114Y,MH115F,YH117F",9,1.388605578691113,1n8z.pdb,HL,A 130 | 19.87,"SH105V,WH107Y,GH109S,GH111V,FH112Y,AH114Y,MH115F,YH117I",8,1.3906964121625194,1n8z.pdb,HL,A 131 | 20.01,"SH105A,GH108L,GH109T,DH110G,GH111L,FH112S,AH114N,MH115W",8,1.3948560720649024,1n8z.pdb,HL,A 132 | 20.1,"SH105A,GH108Y,GH109Y,DH110G,FH112Y",5,1.397514798967089,1n8z.pdb,HL,A 133 | 20.18,"SH105A,WH107Y,GH108Y,DH110Y,FH112Y,AH114Y,MH115F,DH116H",8,1.399868136654245,1n8z.pdb,HL,A 134 | 20.5,"SH105A,GH109S,DH110I,FH112Y,MH115F,YH117H",6,1.4091891074179266,1n8z.pdb,HL,A 135 | 20.59,"SH105A,DH110Y,FH112G,AH114Y,MH115F",5,1.4117844232517438,1n8z.pdb,HL,A 136 | 21.0,"SH105A,WH107Y,GH109N,DH110Y,GH111Y,FH112Y,AH114Y,MH115F",8,1.4234657496544028,1n8z.pdb,HL,A 137 | 21.1,"SH105A,GH109Y,DH110G,GH111Y,FH112S,AH114Y,MH115F,YH117V",8,1.42628025368273,1n8z.pdb,HL,A 138 | 21.5,"SH105A,WH107Y,GH108T,GH109S,DH110V,FH112I,MH115F,DH116N",8,1.437406439523638,1n8z.pdb,HL,A 139 | 21.88,"SH105A,GH108P,GH109Y,DH110G,GH111Y,FH112Y,AH114Y",7,1.4477862234108088,1n8z.pdb,HL,A 140 | 21.93,"SH105T,GH108N,GH109Y,FH112A,AH114F,MH115F",6,1.4491385453486745,1n8z.pdb,HL,A 141 | 21.96,"SH105A,WH107Y,GH108R,DH110R,AH114S,MH115F",6,1.4499484593281888,1n8z.pdb,HL,A 142 | 22.0,"SH105A,GH108Y,GH109W,DH110Y,FH112A,AH114Y,MH115F",7,1.4510266252012638,1n8z.pdb,HL,A 143 | 22.15,"SH105A,GH109Y,DH110Y,FH112Y,AH114W,MH115F",6,1.4550523619849596,1n8z.pdb,HL,A 144 | 22.6,"SH105A,WH107H,GH108Y,GH109Y,DH110Y,FH112Y,AH114Y,MH115F,YH117V",9,1.4669679990612696,1n8z.pdb,HL,A 145 | 22.6,"SH105A,RH106T,WH107Y,GH108S,GH109T,DH110Y,GH111Y,FH112N,MH115F,DH116G,YH117I",11,1.4669679990612696,1n8z.pdb,HL,A 146 | 22.7,"SH105T,WH107Y,GH108L,GH109H,GH111Y,FH112Y,AH114Y,MH115F",8,1.4695836853575417,1n8z.pdb,HL,A 147 | 22.93,"SH105V,WH107Y,GH108F,GH109Y,FH112N,AH114Y,MH115F,YH117L",8,1.4755562959340305,1n8z.pdb,HL,A 148 | 22.96,"SH105A,WH107F,GH108D,DH110P,GH111F,FH112Y,MH115F,DH116A",8,1.4763309118435703,1n8z.pdb,HL,A 149 | 23.07,"SH105A,WH107Y,GH108R,DH110Y,GH111V,FH112L,AH114D,MH115F,DH116A",9,1.4791625365349272,1n8z.pdb,HL,A 150 | 23.14,"SH105A,WH107E,GH108N,GH109D,DH110G,GH111S,FH112P,YH113G,AH114S,MH115F,DH116E",11,1.4809574584385814,1n8z.pdb,HL,A 151 | 23.3,"SH105A,RH106V,WH107T,GH108D,GH109L,FH112L,YH113H,AH114S,MH115Y,DH116R",10,1.4850398310685566,1n8z.pdb,HL,A 152 | 23.87,"SH105T,WH107Y,GH108Y,GH109Y,DH110G,GH111S,FH112G,AH114F,MH115F",9,1.4993588503290294,1n8z.pdb,HL,A 153 | 23.93,"SH105A,GH108Y,DH110Y,FH112Y,YH117V",5,1.500846178266027,1n8z.pdb,HL,A 154 | 23.98,"SH105A,GH109Y,DH110G,FH112Y,AH114Y,MH115F,YH117V",7,1.5020827722940735,1n8z.pdb,HL,A 155 | 24.24,"SH105A,WH107Y,GH108D,GH109P,DH110Y,AH114H,MH115L",7,1.5084717813602868,1n8z.pdb,HL,A 156 | 25.08,"SH105V,WH107Y,GH109Y,DH110G,GH111D,FH112Y,AH114Y,MH115F",8,1.52865457919094,1n8z.pdb,HL,A 157 | 25.17,"SH105T,GH109Y,GH111Y,FH112W,AH114F,MH115F",6,1.5307767975213746,1n8z.pdb,HL,A 158 | 25.2,"SH105A,RH106K,WH107Y,DH110V,FH112Y",5,1.5314825176569329,1n8z.pdb,HL,A 159 | 25.5,"SH105A,WH107Y,GH108S,GH109A,DH110Y,FH112L,AH114D,MH115F,DH116A",9,1.5384938655664762,1n8z.pdb,HL,A 160 | 25.71,"SH105A,GH108W,DH110G,FH112Y,AH114Y,MH115F",6,1.543352901457563,1n8z.pdb,HL,A 161 | 25.9,"SH105A,WH107Y,GH108L,GH109T,DH110A,GH111Y,FH112Q,AH114F,MH115F,DH116Y",10,1.54771509426733,1n8z.pdb,HL,A 162 | 26.06,"SH105A,FH112S,AH114Y,MH115F",4,1.551363770826585,1n8z.pdb,HL,A 163 | 26.24,"SH105A,WH107Y,DH110R,FH112Y,AH114S,MH115F",6,1.5554418502965497,1n8z.pdb,HL,A 164 | 26.3,"SH105A,DH110G,FH112Y,AH114F,MH115F",5,1.5567949958800131,1n8z.pdb,HL,A 165 | 26.7,"SH105A,GH109Y,GH111Y,FH112Y,AH114Y,MH115F,YH117V",7,1.5657378371294524,1n8z.pdb,HL,A 166 | 27.0,"SH105A,RH106A,WH107T,GH108Y,DH110G,GH111L,FH112G,YH113D,AH114M,MH115S,DH116S,YH117I",12,1.572357481233821,1n8z.pdb,HL,A 167 | 27.0,"SH105A,WH107Y,GH109V,DH110Y,GH111P,AH114Y,MH115F",7,1.572357481233821,1n8z.pdb,HL,A 168 | 27.1,"RH106I,GH108E,GH109R,DH110T,FH112Q,AH114S,MH115Y,DH116T,YH117S",9,1.5745476943890555,1n8z.pdb,HL,A 169 | 27.9,"SH105A,GH108E,GH109R,DH110Y,FH112Y,AH114V,MH115L,YH117V",8,1.5917838768120358,1n8z.pdb,HL,A 170 | 27.9,"SH105A,GH109Y,DH110G,FH112Y,AH114F,MH115F",6,1.5917838768120358,1n8z.pdb,HL,A 171 | 27.97,"SH105A,WH107Y,GH109A,DH110Y,GH111S,FH112S,AH114Y,MH115F,DH116G",9,1.5932684538860578,1n8z.pdb,HL,A 172 | 28.3,"SH105A,GH109Y,DH110G,GH111W,FH112S,AH114Y,MH115F",7,1.60021749941958,1n8z.pdb,HL,A 173 | 29.2,"SH105A,GH108R,GH109D,DH110G,FH112Y,AH114Y,MH115F",7,1.6187653371696855,1n8z.pdb,HL,A 174 | 29.24,"SH105T,WH107Y,GH108Y,FH112Y,AH114D,MH115F",6,1.619576359861357,1n8z.pdb,HL,A 175 | 29.72,"SH105A,WH107Y,GH108F,GH109Y,GH111H,FH112Y,AH114Y,MH115F,YH117V",9,1.629223009626175,1n8z.pdb,HL,A 176 | 30.0,"SH105A,WH107Y,GH108Y,GH109Y,GH111Y,FH112G,AH114Y,MH115F,YH117V",9,1.634778527743972,1n8z.pdb,HL,A 177 | 30.9,"SH105A,GH109S,DH110Y,FH112Y,AH114Y,MH115F",6,1.6522906987691783,1n8z.pdb,HL,A 178 | 30.9,"SH105A,WH107Y,GH108Y,GH109Y,DH110G,GH111V,FH112Y,AH114Y,MH115F",9,1.6522906987691783,1n8z.pdb,HL,A 179 | 30.94,"SH105A,WH107H,GH108Y,GH109D,DH110Y,FH112R,AH114Y,YH117V",8,1.653057130937837,1n8z.pdb,HL,A 180 | 31.0,"SH105A,DH110F,FH112Y,AH114Y,MH115F",5,1.654204923322185,1n8z.pdb,HL,A 181 | 31.2,"DH110V,FH112K",2,1.6580149170556275,1n8z.pdb,HL,A 182 | 31.4,"SH105A,WH107Y,DH110G,GH111Y,FH112Y,AH114Y,MH115F,YH117V",8,1.6618005656149926,1n8z.pdb,HL,A 183 | 32.0,"SH105A,GH108Y,GH109Y,DH110G,GH111S,FH112Y,AH114Y,MH115F,YH117V",9,1.6730145026200614,1n8z.pdb,HL,A 184 | 32.49,"SH105A,DH110Y,FH112Y,AH114Y,MH115F,YH117V",6,1.6820176677207943,1n8z.pdb,HL,A 185 | 32.81,"SH105A,GH108Y,GH109Y,DH110G,FH112A,AH114Y,MH115F,YH117F",8,1.6878242880091443,1n8z.pdb,HL,A 186 | 32.84,"SH105A,GH109S,DH110E,GH111A,AH114W,MH115F",6,1.6883657521599336,1n8z.pdb,HL,A 187 | 33.0,"SH105A,RH106P,GH108W,GH109S,DH110G,GH111W,FH112Y,AH114F,MH115F,YH117T",10,1.6912452328403855,1n8z.pdb,HL,A 188 | 33.31,"SH105A,WH107Y,GH108P,GH109N,DH110Y,AH114M,MH115F",7,1.6967847126469895,1n8z.pdb,HL,A 189 | 33.8,"SH105A,GH108V,GH109S,DH110G,GH111A,FH112R,AH114Y,YH117V",8,1.7054363780013464,1n8z.pdb,HL,A 190 | 35.04,"SH105A,WH107F,DH110A,FH112G,AH114Y,MH115F",6,1.726782105172216,1n8z.pdb,HL,A 191 | 35.47,"SH105T,WH107Y,GH108R,DH110A,GH111H,FH112G,AH114Y,MH115F",8,1.73400824362788,1n8z.pdb,HL,A 192 | 35.77,"SH105A,GH108Y,GH109Y,DH110G,FH112S,AH114Y,MH115F",7,1.7389980427789382,1n8z.pdb,HL,A 193 | 35.82,"SH105A,WH107Y,GH109D,DH110A,GH111D,MH115F,YH117P",7,1.7398256053995258,1n8z.pdb,HL,A 194 | 36.04,"SH105A,WH107Y,GH108I,GH109F,DH110G,FH112P,AH114Y,MH115F",8,1.7434532102880151,1n8z.pdb,HL,A 195 | 36.13,"GH108E,FH112K",2,1.7449308521385856,1n8z.pdb,HL,A 196 | 36.22,"SH105A,WH107Y,GH109D,DH110Y,FH112Y,AH114Y,MH115F",7,1.746404817751312,1n8z.pdb,HL,A 197 | 36.28,"SH105V,WH107Y,GH108P,GH109E,DH110V,GH111Y,FH112G,AH114Y,MH115F",9,1.747385428155182,1n8z.pdb,HL,A 198 | 36.72,"SH105A,RH106N,WH107V,GH109S,DH110S,GH111L,FH112G,YH113I,MH115A,DH116L,YH117D",11,1.7545274015715382,1n8z.pdb,HL,A 199 | 36.76,"RH106Y,WH107P,GH108D,GH109F,DH110G,GH111Y,FH112Y,YH113V,AH114Y,MH115F,DH116A",11,1.755172422847826,1n8z.pdb,HL,A 200 | 37.82,"SH105A,RH106K,WH107Y,GH108T,GH109R,DH110G,GH111F,FH112S,AH114G,MH115F,DH116G",11,1.7720145090556727,1n8z.pdb,HL,A 201 | 37.83,"SH105A,DH110S,FH112Y",3,1.7721711387945227,1n8z.pdb,HL,A 202 | 37.95,"SH105A,GH109Y,DH110G,GH111Y,FH112Y,AH114S,MH115F",7,1.774047472852967,1n8z.pdb,HL,A 203 | 38.2,"SH105A,WH107Y,GH109R,DH110N,FH112S,AH114S,MH115Y",7,1.777937519551941,1n8z.pdb,HL,A 204 | 38.28,"SH105A,RH106K,WH107F,GH108E,GH109R,DH110G,GH111Y,FH112Y,YH113S,AH114F,MH115D,DH116F,YH117G",13,1.7791769593005355,1n8z.pdb,HL,A 205 | 38.66,"SH105A,GH108E,FH112S,AH114S",4,1.785029145013743,1n8z.pdb,HL,A 206 | 38.77,"GH109V,FH112Y",2,1.78671246574355,1n8z.pdb,HL,A 207 | 39.1,"SH105A,WH107Y,GH109Y,DH110G,GH111Y,FH112Y,AH114Y,MH115F",8,1.7917339200917386,1n8z.pdb,HL,A 208 | 39.6,"SH105A,GH108Y,DH110Y,FH112Y,AH114L,MH115F,YH117V",7,1.7992620008429157,1n8z.pdb,HL,A 209 | 39.66,"SH105A,WH107Y,GH108Y,GH109W,GH111Y,AH114Y,MH115F",7,1.8001589760085732,1n8z.pdb,HL,A 210 | 39.91,"SH105A,WH107Y,GH108P,DH110G,FH112I,AH114D,MH115F,YH117P",8,1.803881823395869,1n8z.pdb,HL,A 211 | 40.0,"SH105A,WH107Y,DH110Y,FH112Y,AH114W,MH115F",6,1.8052163422566512,1n8z.pdb,HL,A 212 | 40.11,"SH105A,GH108L,GH109R,DH110G,GH111L,FH112G,AH114Y,MH115W",8,1.8068433491014932,1n8z.pdb,HL,A 213 | 40.6,"SH105A,WH107Y,GH109D,DH110S,GH111Y,FH112Y,AH114Y,MH115F",8,1.8140371302638256,1n8z.pdb,HL,A 214 | 41.25,"SH105A,WH107Y,GH109P,DH110Y,GH111Y,FH112Y",6,1.8234470724769751,1n8z.pdb,HL,A 215 | 41.57,"SH105T,WH107Y,GH108Y,DH110G,GH111Y,FH112G,AH114Y,MH115F",8,1.828025328411325,1n8z.pdb,HL,A 216 | 41.61,"SH105A,WH107N,GH108Y,GH109Y,GH111Y,FH112Y,AH114Y,MH115L",8,1.82859513079595,1n8z.pdb,HL,A 217 | 41.63,"SH105V,GH109R,DH110Y,FH112V,AH114Y,MH115F",6,1.828879826612937,1n8z.pdb,HL,A 218 | 41.67,"GH108V,FH112S",2,1.8294488081536675,1n8z.pdb,HL,A 219 | 42.12,"SH105A,WH107Y,DH110Y,FH112N,AH114W,MH115F,YH117T",7,1.8358124781846,1n8z.pdb,HL,A 220 | 42.13,"SH105A,WH107G,GH109Y,DH110G,GH111Y,FH112Y,YH113T,AH114W,MH115F",9,1.8359531196057333,1n8z.pdb,HL,A 221 | 42.25,"SH105A,RH106G,WH107S,GH108S,GH109A,DH110S,FH112W,AH114H,MH115Y,DH116T,YH117T",11,1.837638217637936,1n8z.pdb,HL,A 222 | 42.25,"SH105A,WH107Y,GH109T,DH110G,GH111T,FH112Y,AH114Y,MH115F,DH116L,YH117H",10,1.837638217637936,1n8z.pdb,HL,A 223 | 42.45,"SH105A,GH108E,DH110Y,FH112S,AH114E,MH115F,DH116A",7,1.840436107058702,1n8z.pdb,HL,A 224 | 42.75,"SH105A,WH107Y,GH108Y,GH109Y,GH111F,FH112G,AH114Y,MH115F",8,1.844608321370238,1n8z.pdb,HL,A 225 | 42.87,"SH105A,WH107Y,DH110L,FH112G,AH114T,MH115L,DH116A",7,1.8462690147736556,1n8z.pdb,HL,A 226 | 43.05,"SH105A,RH106Q,WH107N,GH108W,GH109D,DH110R,FH112S,AH114F,MH115Y,DH116T",10,1.84875135911928,1n8z.pdb,HL,A 227 | 45.1,"SH105A,WH107Y,GH109A,DH110R,GH111S,FH112G,MH115Y,DH116E",8,1.876312234666143,1n8z.pdb,HL,A 228 | 45.51,"SH105A,WH107N,GH108Y,GH109Y,DH110Y,FH112A,AH114Y,MH115F",8,1.8816738276725076,1n8z.pdb,HL,A 229 | 46.1,"SH105A,RH106S,WH107V,GH108D,GH109L,DH110G,AH114D,MH115F,DH116R",9,1.8893051234561271,1n8z.pdb,HL,A 230 | 46.1,"SH105A,RH106I,WH107T,GH108F,GH109Y,DH110G,GH111Y,FH112T,YH113I,AH114V,MH115W,DH116E",12,1.8893051234561271,1n8z.pdb,HL,A 231 | 46.69,"SH105A,DH110Y,FH112Y,AH114W,MH115F",5,1.8968393702764068,1n8z.pdb,HL,A 232 | 47.98,"SH105A,GH108S,DH110A,GH111S",4,1.9129862038235412,1n8z.pdb,HL,A 233 | 48.33,"SH105A,GH108Q,DH110R,GH111S,FH112G,AH114Y",6,1.917292280184375,1n8z.pdb,HL,A 234 | 48.72,"SH105A,GH108L,GH109D,DH110Y,GH111F,FH112Y",6,1.9220538982663555,1n8z.pdb,HL,A 235 | 49.87,"SH105A,GH108H,GH109Y,GH111V,FH112G,YH113F,AH114Y,MH115F",8,1.9358758007700327,1n8z.pdb,HL,A 236 | 50.0,"SH105A,WH107Y,GH109Y,GH111Y,FH112Y,AH114Y,MH115F,YH117V",8,1.9374181818932428,1n8z.pdb,HL,A 237 | 50.85,"SH105A,WH107F,GH109P,DH110A,GH111Y,AH114G,MH115F,DH116Y",8,1.9474052143395113,1n8z.pdb,HL,A 238 | 50.86,"SH105A,WH107Y,GH108M,GH109R,DH110P,GH111A,AH114P,MH115F,DH116L",9,1.947521712616112,1n8z.pdb,HL,A 239 | 52.01,"SH105A,GH109S,DH110G,GH111N,FH112Y,AH114E,MH115F",7,1.9607684933249985,1n8z.pdb,HL,A 240 | 53.93,"SH105A,RH106S,WH107Y,GH109S,DH110G,GH111S,FH112Y,YH113F,AH114S,MH115F,DH116P,YH117L",12,1.9822454118693231,1n8z.pdb,HL,A 241 | 54.01,"SH105A,WH107Y,GH109Y,DH110G,GH111A,FH112Y,AH114Y,MH115F",8,1.983123606558561,1n8z.pdb,HL,A 242 | 56.27,"SH105T,WH107Y,GH108Y,GH109S,DH110G,GH111H,FH112Y,AH114S,MH115F",9,2.007409587173962,1n8z.pdb,HL,A 243 | 56.99,"SH105A,WH107Y,GH111Y,FH112Y,AH114Y,MH115Y",6,2.0149421878198854,1n8z.pdb,HL,A 244 | 57.56,"SH105A,WH107Y,DH110G,GH111Y,FH112Y,AH114Y,MH115Y",7,2.02083831035093,1n8z.pdb,HL,A 245 | 57.63,"SH105T,WH107Y,GH109S,DH110F,FH112Y,MH115L,YH117S",7,2.021558366674697,1n8z.pdb,HL,A 246 | 58.1,"SH105A,WH107Y,DH110L,GH111S,FH112Y,AH114S,MH115F,YH117L",8,2.02637049772507,1n8z.pdb,HL,A 247 | 59.06,"SH105T,WH107Y,GH108F,DH110A,GH111Y,FH112W,AH114W",7,2.0360797267058377,1n8z.pdb,HL,A 248 | 59.1,"SH105A,RH106K,WH107F,GH108H,GH109W,DH110G,GH111E,FH112D,YH113W,AH114L,MH115S,YH117N",12,2.0364808451935676,1n8z.pdb,HL,A 249 | 60.3,"SH105A,RH106G,WH107S,GH108V,GH109A,DH110E,FH112W,AH114H,MH115Y,DH116R,YH117D",11,2.0483898287580136,1n8z.pdb,HL,A 250 | 60.62,"SH105A,WH107Y,GH108Y,DH110S,GH111S,FH112S,AH114Y,MH115F,DH116A",9,2.0515255395978205,1n8z.pdb,HL,A 251 | 60.72,"SH105A,WH107S,GH109Y,DH110P,FH112Y,YH113G,AH114S,MH115F,DH116A",9,2.05250205536818,1n8z.pdb,HL,A 252 | 63.64,"SH105A,WH107T,GH108V,GH109V,DH110G,GH111W,FH112Y,YH113G,AH114R,MH115F",10,2.080328974290902,1n8z.pdb,HL,A 253 | 65.0,"SH105A,WH107N,GH108S,DH110T,FH112I,YH113W,MH115F,DH116A",8,2.09285641084149,1n8z.pdb,HL,A 254 | 65.33,"SH105A,DH110T,GH111Y,FH112Y",4,2.095856634465433,1n8z.pdb,HL,A 255 | 65.58,"SH105A,GH108P,GH109P,DH110Y,GH111Y,FH112W,YH113W,MH115F",8,2.098119458940152,1n8z.pdb,HL,A 256 | 66.61,"SH105A,GH109N,DH110V,FH112Y,AH114V,MH115L",6,2.1073521980751035,1n8z.pdb,HL,A 257 | 67.0,"SH105A,WH107A,DH110T,GH111S,FH112I,YH113S,AH114L,MH115G,DH116H,YH117G",10,2.1108108752681627,1n8z.pdb,HL,A 258 | 67.4,"SH105A,WH107Y,GH109D,DH110A,GH111F,FH112I,YH113M,AH114S,MH115F,DH116G,YH117V",11,2.114337385583715,1n8z.pdb,HL,A 259 | 67.6,"SH105A,RH106P,GH109T,DH110Y,GH111R,FH112Y,YH113G,AH114Y,MH115F,YH117H",10,2.1160928001531474,1n8z.pdb,HL,A 260 | 70.7,"SH105A,RH106V,WH107Y,GH109P,DH110Y,FH112G,YH113F,AH114S,MH115Y,YH117S",10,2.142656919208381,1n8z.pdb,HL,A 261 | 70.95,"SH105A,GH108Y,GH109Y,DH110G,GH111T,FH112S,AH114Y,MH115F,YH117V",9,2.144748174410976,1n8z.pdb,HL,A 262 | 71.04,"SH105V,RH106Y,WH107Y,GH108Y,GH109E,DH110A,FH112S,AH114Y,MH115F,YH117G",10,2.145499222874644,1n8z.pdb,HL,A 263 | 71.77,"SH105A,RH106I,GH108S,GH109M,DH110Y,GH111D,FH112V,YH113G,AH114Y,MH115Y,DH116P,YH117F",12,2.1515561336664284,1n8z.pdb,HL,A 264 | 71.8,"SH105A,WH107Y,GH109L,DH110Y,FH112S,AH114Y,MH115F,DH116R",8,2.1518037280074633,1n8z.pdb,HL,A 265 | 72.34,"SH105A,WH107Y,DH110S,GH111S,FH112Y,AH114Y,MH115Y",7,2.1562428228870054,1n8z.pdb,HL,A 266 | 72.84,"SH105A,GH108Y,GH109S,DH110G,GH111Y,FH112Y",6,2.1603236489384567,1n8z.pdb,HL,A 267 | 75.07,"SH105A,WH107Y,GH108L,GH109T,GH111A,FH112D,YH113F,AH114R,MH115L,DH116H",10,2.178189486831892,1n8z.pdb,HL,A 268 | 76.87,"SH105A,RH106Q,GH108Y,GH109D,DH110Y,FH112G,YH113T,AH114Y,MH115L",9,2.1922274421299086,1n8z.pdb,HL,A 269 | 78.14,"SH105T,GH108R,GH109W,DH110G,GH111Y,FH112G,AH114Y,MH115F,YH117F",9,2.201935601028625,1n8z.pdb,HL,A 270 | 79.05,"SH105A,WH107Y,GH108Y,DH110G,FH112G,AH114Y",6,2.2087952909356137,1n8z.pdb,HL,A 271 | 79.66,"WH107Y,GH109R,DH110G,GH111V,FH112Y,AH114Y,MH115F",7,2.21334947768708,1n8z.pdb,HL,A 272 | 80.1,"SH105T,WH107Y,GH108S,GH109R,DH110S,GH111Y,FH112Y,AH114G,MH115L,YH117P",10,2.216612866920377,1n8z.pdb,HL,A 273 | 83.25,"SH105A,WH107P,GH108S,GH109Y,GH111V,FH112G,YH113G,AH114D,DH116L,YH117F",10,2.2394650876351427,1n8z.pdb,HL,A 274 | 83.55,"SH105A,WH107Y,GH108V,GH109T,DH110A,GH111N,FH112T,AH114S,MH115Y,YH117P",10,2.2415962121767787,1n8z.pdb,HL,A 275 | 88.13,"SH105A,GH109T,DH110Y,GH111T,FH112Y,YH113G,AH114Y,MH115F",8,2.2732140368343785,1n8z.pdb,HL,A 276 | 89.59,"SH105A,GH108A,GH109R,DH110G,GH111A,FH112G,AH114Y,MH115W",8,2.2829484432708007,1n8z.pdb,HL,A 277 | 90.13,"SH105A,WH107Y,GH108P,GH109S,DH110G,GH111Y,FH112Y,AH114Y,MH115F",9,2.2865087040541745,1n8z.pdb,HL,A 278 | 97.17,"SH105A,WH107Y,DH110S,GH111S,FH112Y,AH114Y,MH115F",7,2.3310663952524795,1n8z.pdb,HL,A 279 | 97.3,"SH105A,WH107Y,GH109D,DH110G,GH111T,FH112Y,AH114F,MH115F,DH116A,YH117H",10,2.3318584842056307,1n8z.pdb,HL,A 280 | 97.71,"SH105A,RH106K,WH107Y,GH108D,GH109T,DH110A,FH112S,AH114H,MH115F,YH117V",10,2.334349696669035,1n8z.pdb,HL,A 281 | 98.42,"SH105A,RH106F,WH107A,GH108D,GH109S,DH110G,GH111A,FH112Y,YH113G,AH114I,MH115W,DH116S,YH117F",13,2.3386391245580818,1n8z.pdb,HL,A 282 | 98.95,"SH105A,WH107Y,GH108D,GH109Y,DH110Y,FH112Y,AH114Y,MH115F",8,2.341820968872103,1n8z.pdb,HL,A 283 | 102.0,"SH105A,WH107S,GH108Y,GH109A,DH110Y,GH111L,FH112Y,YH113G,AH114S,MH115W",10,2.3598067098700817,1n8z.pdb,HL,A 284 | 103.61,"SH105A,WH107D,DH110R,GH111S,FH112Y,AH114S,MH115F,DH116Y",8,2.369085122296065,1n8z.pdb,HL,A 285 | 104.06,"SH105T,WH107N,GH108V,GH109V,DH110N,GH111L,FH112Y,AH114S,MH115Y,YH117S",10,2.371652694020071,1n8z.pdb,HL,A 286 | 105.85,"SH105A,WH107Y,GH108Y,GH109S,DH110Y,FH112G,AH114Y,MH115F",8,2.381757165054818,1n8z.pdb,HL,A 287 | 108.6,"SH105A,WH107N,GH109Y,DH110Y,FH112G,MH115F",6,2.396952616391278,1n8z.pdb,HL,A 288 | 109.2,"SH105V,RH106L,WH107S,GH108R,GH109I,DH110V,GH111V,FH112S,AH114F,MH115Y",10,2.4002168229062537,1n8z.pdb,HL,A 289 | 109.22,"TH59S,SH105A,WH107Y,GH108Y,DH110G,GH111S,FH112M,AH114Y,MH115Y,DH116G",10,2.4003253206601975,1n8z.pdb,HL,A 290 | 110.57,"WH107I,GH108R,GH109R,DH110W,AH114Y,MH115F",6,2.407603360938822,1n8z.pdb,HL,A 291 | 112.0,"SH105A,WH107G,GH108F,GH109V,DH110Y,GH111A,FH112G,YH113I,AH114P,MH115F",10,2.4152164084706875,1n8z.pdb,HL,A 292 | 112.19,"SH105A,WH107Y,GH108Y,GH109S,GH111Y,FH112S,AH114T,MH115F,DH116S",9,2.416220609406164,1n8z.pdb,HL,A 293 | 116.13,"SH105A,GH108W,GH109Y,DH110G,FH112R,YH113N,AH114Y,MH115F,YH117I",9,2.436669913548658,1n8z.pdb,HL,A 294 | 119.89,"SH105T,WH107S,GH109E,DH110L,GH111Y,FH112G,AH114F,MH115H,YH117M",9,2.4555480419981386,1n8z.pdb,HL,A 295 | 121.09,"SH105A,GH108A,GH109T,DH110A,GH111L,FH112G,AH114Y,MH115W",8,2.4614485171995284,1n8z.pdb,HL,A 296 | 123.1,"SH105A,DH110Y,FH112W,AH114G,MH115F",5,2.471202031946069,1n8z.pdb,HL,A 297 | 124.16,"SH105A,WH107D,DH110G,MH115Y",4,2.4762817290259704,1n8z.pdb,HL,A 298 | 124.99,"SH105A,WH107F,GH108S,DH110Y,FH112A,AH114D,MH115Y,DH116A",8,2.480229045626988,1n8z.pdb,HL,A 299 | 126.77,"SH105A,WH107D,GH109Y,DH110P,GH111Q,FH112Y,YH113G,AH114G,MH115Y,DH116G",10,2.4886067236019382,1n8z.pdb,HL,A 300 | 127.5,"SH105A,WH107Y,GH109R,FH112S,AH114Y,MH115F",6,2.4920085495066715,1n8z.pdb,HL,A 301 | 128.1,"SH105A,RH106G,WH107Y,GH108E,DH110Y,FH112L,AH114P,MH115F,DH116A",9,2.494790019328086,1n8z.pdb,HL,A 302 | 128.37,"SH105A,RH106T,WH107Y,GH108Y,DH110P,GH111Y,FH112Y",7,2.496037433019408,1n8z.pdb,HL,A 303 | 128.79,"SH105A,WH107S,GH108N,GH109Y,DH110Y,GH111Y,FH112G,YH113S,AH114G,MH115F,DH116A",11,2.4979726488727216,1n8z.pdb,HL,A 304 | 130.61,"DH110E,FH112Y,YH113H",3,2.5062862980950236,1n8z.pdb,HL,A 305 | 131.5,"SH105V,WH107L,GH109D,DH110Y,FH112G",5,2.5103096798202085,1n8z.pdb,HL,A 306 | 133.0,"SH105A,GH108W,GH109T,DH110P,GH111A,FH112N,AH114P,MH115F,DH116L",9,2.5170294340944235,1n8z.pdb,HL,A 307 | 133.97,"YH57D,TH59A,SH105A,WH107V,DH110R,FH112Y,AH114Y,MH115Y",8,2.5213346440663305,1n8z.pdb,HL,A 308 | 134.47,"SH105A,WH107S,GH108H,GH109I,DH110G,GH111Y,FH112Y,YH113G,AH114Q,MH115V,DH116A,YH117L",12,2.523541664886201,1n8z.pdb,HL,A 309 | 135.02,"SH105A,RH106S,WH107Y,GH108Y,GH109A,DH110P,FH112S,AH114G,MH115F,YH117P",10,2.525959929337386,1n8z.pdb,HL,A 310 | 135.31,"SH105A,WH107Y,GH109L,DH110N,GH111H,FH112Y,AH114V,MH115Y,DH116P",9,2.527231050864371,1n8z.pdb,HL,A 311 | 135.37,"SH105A,WH107S,GH108Y,GH109F,DH110R,GH111F,FH112T,YH113G,AH114D,MH115F,DH116F",11,2.5274937013712933,1n8z.pdb,HL,A 312 | 139.75,"SH105A,GH108W,DH110Y,FH112Y,AH114Y,MH115F,DH116A",7,2.5463593524120824,1n8z.pdb,HL,A 313 | 141.43,"WH107Y,GH108Y,GH109D,DH110Y,GH111N,FH112Y,AH114F",7,2.553439025054127,1n8z.pdb,HL,A 314 | 146.32,"SH105A,WH107D,DH110S,GH111S,FH112S,AH114S,MH115Y,DH116S",8,2.5735771250407,1n8z.pdb,HL,A 315 | 148.77,"SH105A,WH107T,GH108T,GH109S,DH110S,GH111I,FH112P,YH113S,AH114S,MH115F",10,2.5834150776213125,1n8z.pdb,HL,A 316 | 150.36,"SH105A,WH107Y,GH108R,GH109Y,DH110G,GH111Y,FH112Y,AH114Y,YH117V",9,2.5897133929085623,1n8z.pdb,HL,A 317 | 151.1,"SH105A,WH107Y,GH109S,DH110L,GH111T,FH112Y,DH116H",7,2.592622006645403,1n8z.pdb,HL,A 318 | 152.88,"SH105A,WH107Y,GH108Y,GH109Y,DH110L,GH111D,FH112Y,AH114Y,MH115F",9,2.5995604669684873,1n8z.pdb,HL,A 319 | 153.52,"SH105A,WH107D,GH109Y,DH110P,GH111F,FH112Y,YH113S,AH114G",8,2.6020354658003075,1n8z.pdb,HL,A 320 | 154.68,"SH105A,RH106T,WH107S,GH109S,DH110V,GH111D,FH112R,AH114D,MH115Y,DH116V",10,2.606495216263438,1n8z.pdb,HL,A 321 | 155.5,"SH105A,WH107Y,GH108N,GH109P,DH110F,GH111D,FH112G,YH113F,AH114Y,MH115F,YH117V",11,2.6096276668303062,1n8z.pdb,HL,A 322 | 157.39,"SH105A,WH107S,GH108S,DH110Y,GH111Y,FH112Y,AH114G,MH115F,DH116V",9,2.616785120684554,1n8z.pdb,HL,A 323 | 160.15,"YH57D,TH59A,NH62D,SH105A,WH107E,DH110Y,FH112Y",7,2.627084350102752,1n8z.pdb,HL,A 324 | 165.5,"SH105A,WH107G,GH108Y,GH109Y,DH110Q,GH111D,FH112S,YH113Q,AH114S,MH115W,DH116G",11,2.6465525111398485,1n8z.pdb,HL,A 325 | 168.68,"SH105A,WH107V,DH110Y,FH112Y,AH114S,MH115Y",6,2.65782819596458,1n8z.pdb,HL,A 326 | 170.52,"SH105A,RH106S,WH107S,GH109R,DH110L,GH111D,FH112L,AH114D,MH115F,DH116R,YH117L",11,2.6642558041169817,1n8z.pdb,HL,A 327 | 171.22,"SH105A,RH106T,WH107G,GH108Y,DH110Y,GH111L,FH112L,AH114S,MH115D,DH116H,YH117D",11,2.666682894704172,1n8z.pdb,HL,A 328 | 181.9,"SH105A,RH106T,WH107G,GH108S,DH110G,FH112G,YH113F,AH114S,MH115Y,DH116G",10,2.7025308645253467,1n8z.pdb,HL,A 329 | 188.46,"SH105A,RH106Q,WH107Y,GH109R,DH110G,FH112Y,YH113W,AH114Y,MH115F",9,2.7235206664953893,1n8z.pdb,HL,A 330 | 188.5,"SH105A,WH107S,GH108Y,GH109A,DH110F,GH111L,FH112Y,YH113G,AH114R",9,2.7236463990900344,1n8z.pdb,HL,A 331 | 190.9,"SH105A,WH107Y,GH108S,GH109Y,DH110Y,FH112G,YH113G,MH115F",8,2.7311419379790234,1n8z.pdb,HL,A 332 | 192.08,"TH37Y,TH59S,NH62R,SH105A,WH107H,GH109S,DH110E,FH112R,AH114T,YH117V",10,2.7347927581421736,1n8z.pdb,HL,A 333 | 205.07,"SH105A,WH107D,GH108S,GH109P,DH110Y,GH111Y,FH112G,YH113S,AH114L,MH115Y,DH116L",11,2.7735624796560217,1n8z.pdb,HL,A 334 | 213.14,"TH59A,SH105A,WH107E,DH110V,FH112Y,AH114S,MH115F,DH116A",8,2.7964298480284135,1n8z.pdb,HL,A 335 | 213.8,"WH107Y,GH108S,GH109Y,DH110S,FH112G,YH113H,MH115F,DH116A",8,2.7982615743635133,1n8z.pdb,HL,A 336 | 222.67,"SH105A,GH108Y,DH110L,FH112S,AH114G,MH115L,DH116T",7,2.822344662323319,1n8z.pdb,HL,A 337 | 224.9,"IH30V,KH35S,DH36S,TH37S,TH59E,YH64S,WH107Y,GH108S,GH109Y,DH110Y,FH112G,MH115F",12,2.828248448799391,1n8z.pdb,HL,A 338 | 225.85,"SH105A,GH108E,GH109Q,DH110A,GH111S,FH112V,YH113G,AH114S,MH115F,DH116G",10,2.830745754258825,1n8z.pdb,HL,A 339 | 227.95,"SH105A,WH107S,DH110Y,GH111Y,FH112H,AH114G,MH115F,DH116V",8,2.836229042257777,1n8z.pdb,HL,A 340 | 230.09,"TH59S,SH105A,WH107S,GH108S,DH110Y,GH111Y,FH112S,AH114S,MH115Y",9,2.8417650499005216,1n8z.pdb,HL,A 341 | 230.51,"SH105A,GH108R,GH109Y,DH110G,FH112A,AH114Q,MH115F,DH116A,YH117L",9,2.8428455097448104,1n8z.pdb,HL,A 342 | 230.61,"GH109T,FH112V",2,2.8431024719208313,1n8z.pdb,HL,A 343 | 231.3,"SH105A,WH107D,DH110M,GH111Y,FH112R,AH114G,MH115L,DH116Y,YH117G",9,2.8448724798134943,1n8z.pdb,HL,A 344 | 239.28,"GH108D,FH112N",2,2.864967766870114,1n8z.pdb,HL,A 345 | 243.36,"SH105A,WH107Y,DH110G,GH111P,FH112S,AH114R,MH115L,DH116S",8,2.874984597946602,1n8z.pdb,HL,A 346 | 250.7,"SH105A,GH108S,DH110G,GH111S,FH112L,MH115L",6,2.8925894133022396,1n8z.pdb,HL,A 347 | 253.19,"WH107K,AH114G",2,2.8984447287376316,1n8z.pdb,HL,A 348 | 256.0,"SH105A,WH107G,GH108H,GH109Y,DH110S,GH111L,FH112G,AH114S,MH115F,YH117F",10,2.9049837690754696,1n8z.pdb,HL,A 349 | 256.24,"WH107R,GH111Y",2,2.905538932617965,1n8z.pdb,HL,A 350 | 257.05,"SH105A,WH107D,DH110I,GH111A,FH112Y,AH114Y,MH115F,DH116A",8,2.9074087781445996,1n8z.pdb,HL,A 351 | 257.12,"SH105A,WH107Y,DH110R,GH111S,FH112S,AH114Y,MH115F",7,2.9075700930370214,1n8z.pdb,HL,A 352 | 267.19,"WH107S,GH111Q",2,2.930330388331462,1n8z.pdb,HL,A 353 | 277.34,"YH57D,TH59E,SH105A,WH107V,DH110Y,FH112Y,AH114Y,MH115Y",8,2.952419471484241,1n8z.pdb,HL,A 354 | 277.54,"SH105A,WH107D,GH109I,DH110Y,FH112Y,YH113G,AH114G,MH115F,DH116A",9,2.952846556266106,1n8z.pdb,HL,A 355 | 277.82,"SH105A,WH107D,GH108V,GH109Y,DH110V,FH112S,YH113P,AH114V,MH115F",9,2.953443958201806,1n8z.pdb,HL,A 356 | 278.0,"SH105A,WH107S,GH108N,GH109N,DH110W,GH111Y,FH112S,AH114S,MH115F,DH116Q,YH117F",11,2.9538276844470026,1n8z.pdb,HL,A 357 | 280.77,"GH109A,YH113T",2,2.9597016771039204,1n8z.pdb,HL,A 358 | 301.0,"SH105A,RH106Y,WH107M,GH109S,DH110H,GH111T,FH112I,AH114S,MH115F,DH116E,YH117H",11,3.00092118967787,1n8z.pdb,HL,A 359 | 301.77,"GH109L,FH112V",2,3.002434829293737,1n8z.pdb,HL,A 360 | 307.53,"SH105A,WH107S,DH110G,GH111S,FH112Y,AH114Y,MH115Y",7,3.0136366185232433,1n8z.pdb,HL,A 361 | 310.88,"YH113T,AH114F",2,3.0200554460319182,1n8z.pdb,HL,A 362 | 321.95,"SH105A,RH106T,WH107S,GH109T,DH110A,GH111S,FH112W,YH113Q,AH114H,MH115Y,DH116G,YH117V",12,3.040784907478752,1n8z.pdb,HL,A 363 | 327.57,"SH105A,WH107L,GH109A,DH110S,GH111H,FH112G,AH114L,MH115Y,YH117D",9,3.051037596368211,1n8z.pdb,HL,A 364 | 329.97,"SH105A,WH107S,GH108T,DH110S,AH114S,MH115Y",6,3.055362477212835,1n8z.pdb,HL,A 365 | 337.65,"SH105A,WH107S,DH110Y,GH111Y,FH112T,AH114G,MH115F",7,3.0689936804587408,1n8z.pdb,HL,A 366 | 347.56,"TH59S,SH105A,WH107S,GH109Y,DH110Y,GH111Y,FH112S,AH114S,MH115F",9,3.0861318091211807,1n8z.pdb,HL,A 367 | 353.55,"SH105T,WH107Y,GH108S,GH109Y,DH110Y,FH112Y,YH113H",7,3.096255395240327,1n8z.pdb,HL,A 368 | 357.6,"SH105A,WH107D,GH108Y,GH109D,DH110F,FH112L,YH113S,AH114V,MH115G,DH116A,YH117V",11,3.103003497539296,1n8z.pdb,HL,A 369 | 361.85,"WH107Y,GH108S,GH109Y,DH110S,FH112G,YH113G,AH114S,MH115F",8,3.1100031506633847,1n8z.pdb,HL,A 370 | 363.6,"SH105A,WH107D,DH110G,FH112V,MH115F,DH116T",6,3.112861495091403,1n8z.pdb,HL,A 371 | 366.22,"SH105A,WH107Y,GH108S,GH111S,FH112Y,AH114Y,MH115Y",7,3.1171152312608807,1n8z.pdb,HL,A 372 | 367.0,"SH105A,WH107Y,GH108H,GH109Y,DH110R,GH111T,FH112I,YH113G,AH114S,MH115F,DH116G",11,3.118375733488433,1n8z.pdb,HL,A 373 | 368.48,"SH105A,RH106W,WH107A,GH108S,DH110Y,FH112G,AH114G",7,3.1207601086433474,1n8z.pdb,HL,A 374 | 381.22,"SH105A,WH107Y,GH108R,GH109D,DH110G,GH111Y,FH112D,AH114Y,MH115F",9,3.140897670196731,1n8z.pdb,HL,A 375 | 393.99,"YH113Q,AH114H",2,3.1604183066032387,1n8z.pdb,HL,A 376 | 394.14,"YH38W,YH57D,TH59A,SH105A,WH107V,DH110R,FH112Y,AH114Y,MH115Y",9,3.160643822187305,1n8z.pdb,HL,A 377 | 402.38,"SH105A,WH107D,DH110R,FH112R",4,3.172902091925506,1n8z.pdb,HL,A 378 | 422.65,"SH105A,WH107Y,GH108S,DH110S,GH111S,FH112Y,AH114Y,MH115Y",8,3.202019624383059,1n8z.pdb,HL,A 379 | 440.64,"SH105A,WH107Y,DH110S,GH111S,FH112N,AH114Y,MH115Y",7,3.2267152756660664,1n8z.pdb,HL,A 380 | 444.26,"SH105A,RH106T,WH107G,GH108L,GH109S,DH110P,GH111S,FH112G,YH113S,AH114N,MH115G,DH116P",12,3.2315625762539035,1n8z.pdb,HL,A 381 | 465.34,"SH105V,WH107S,GH109Y,GH111Y,FH112Y,YH113S,AH114W,MH115F,DH116A",9,3.25902766945746,1n8z.pdb,HL,A 382 | 475.78,"TH59A,SH105A,RH106S,WH107S,DH110G,GH111Y,FH112S,AH114Y,MH115Y,DH116T",10,3.2721725445901804,1n8z.pdb,HL,A 383 | 477.55,"SH105A,WH107Y,GH108S,GH109Y,DH110Y,FH112G,YH113G,AH114Y,MH115F",9,3.2743724988896883,1n8z.pdb,HL,A 384 | 494.72,"SH105A,WH107S,GH108Y,DH110S,FH112S,AH114S,MH115F",7,3.295299727398657,1n8z.pdb,HL,A 385 | 496.0,"SH105A,WH107G,GH108Y,GH109A,DH110Y,GH111Y,FH112V,YH113A,AH114G,MH115R,DH116E",11,3.296830611929394,1n8z.pdb,HL,A 386 | 497.74,"WH107Y,GH108S,GH109Y,DH110Y,FH112G,YH113G,AH114G,MH115F",8,3.2989053347044095,1n8z.pdb,HL,A 387 | 542.45,"NH62S,SH105A,RH106S,WH107D,DH110V,GH111S,FH112S,AH114S,MH115F",9,3.3498669067270743,1n8z.pdb,HL,A 388 | 553.82,"TH59A,SH105A,RH106S,WH107S,DH110S,GH111S,FH112S,AH114Y,MH115Y,DH116N",10,3.362156617482235,1n8z.pdb,HL,A 389 | 566.15,"SH105A,WH107S,GH108R,DH110S,GH111S,FH112S,AH114M",7,3.3752020171048525,1n8z.pdb,HL,A 390 | 566.77,"SH105A,WH107D,GH108R,DH110V,GH111S,FH112G,AH114Y,MH115L,DH116Y",9,3.375850465833082,1n8z.pdb,HL,A 391 | 569.89,"SH105A,WH107N,GH108Y,GH109Y,DH110G,GH111A,FH112A,AH114Y,MH115F",9,3.3791028981024116,1n8z.pdb,HL,A 392 | 590.53,"TH59S,NH62S,SH105A,RH106S,WH107S,DH110R,GH111Y,FH112Y,AH114Y,MH115Y",10,3.400180609132512,1n8z.pdb,HL,A 393 | 602.21,"SH105A,WH107T,GH108D,GH109I,DH110I,GH111Y,FH112S,YH113G,AH114H,MH115F,DH116A",11,3.4117842450877376,1n8z.pdb,HL,A 394 | 603.04,"SH105A,WH107S,DH110S,FH112Y,AH114S,MH115Y,DH116N",7,3.412600233844005,1n8z.pdb,HL,A 395 | 637.2,"SH105A,WH107F,GH108M,DH110G,FH112Y,YH113T,AH114S,MH115S",8,3.445244366892531,1n8z.pdb,HL,A 396 | 642.24,"IH30F,TH59A,SH105A,RH106S,WH107D,DH110S,GH111Y,FH112S,MH115F",9,3.449911992483541,1n8z.pdb,HL,A 397 | 667.96,"SH105A,WH107S,GH108S,DH110S,GH111S,FH112Y,AH114G,MH115F",8,3.473175345910061,1n8z.pdb,HL,A 398 | 669.18,"TH59E,NH62D,YH64S,SH105A,WH107S,DH110S,GH111S,FH112T,MH115Y",9,3.474256446798133,1n8z.pdb,HL,A 399 | 680.03,"SH105A,WH107S,DH110S,GH111S,AH114G",5,3.483785345333928,1n8z.pdb,HL,A 400 | 712.8,"SH105A,WH107G,GH108Y,GH109Y,GH111T,FH112S,YH113Q,AH114S,MH115H,DH116A",10,3.5116684825765656,1n8z.pdb,HL,A 401 | 809.63,"PH58S,TH59S,NH62D,SH105A,WH107S,DH110S,GH111S,FH112Y,AH114Y,MH115Y",10,3.587132929073423,1n8z.pdb,HL,A 402 | 863.55,"SH105A,WH107Y,GH108S,DH110S,FH112G,YH113N,MH115F,DH116A",8,3.625330942866942,1n8z.pdb,HL,A 403 | 901.24,"SH105A,WH107T,DH110S,GH111S,FH112Y,MH115Y",6,3.650640369003076,1n8z.pdb,HL,A 404 | 906.53,"TH59S,SH105A,WH107Y,GH108R,DH110S,GH111S,FH112S,AH114Y,MH115F",9,3.654107712680352,1n8z.pdb,HL,A 405 | 959.35,"SH105A,WH107H,GH108Y,GH109Y,DH110G,GH111W,FH112S,YH113S,AH114G,MH115Y",10,3.687659363275268,1n8z.pdb,HL,A 406 | 994.32,"SH105A,WH107S,GH108A,DH110I,FH112Y",5,3.7088709895640193,1n8z.pdb,HL,A 407 | 1052.08,"WH107Y,GH109Y,DH110S,FH112Y,YH113G,MH115F",6,3.742323997945441,1n8z.pdb,HL,A 408 | 1065.31,"SH105A,WH107S,DH110S,GH111Y,FH112S,AH114S,MH115F,YH117V",8,3.749727680544879,1n8z.pdb,HL,A 409 | 1067.07,"SH105A,WH107S,DH110S,GH111S,FH112Y,AH114Y,MH115Y",7,3.750705663576209,1n8z.pdb,HL,A 410 | 1322.98,"KH35S,TH37Y,TH59S,NH62S,SH105A,WH107D,DH110V,FH112S,AH114S,YH117V",10,3.878065180980748,1n8z.pdb,HL,A 411 | 1407.65,"SH105A,WH107S,DH110R,GH111Y,FH112T,AH114G,MH115F",7,3.9148178683598855,1n8z.pdb,HL,A 412 | 1588.0,"SH105A,RH106S,WH107S,DH110S,GH111S,FH112S,AH114S,MH115Y,DH116S",9,3.9862401562770753,1n8z.pdb,HL,A 413 | 1672.63,"TH59A,NH62D,SH105A,RH106S,WH107S,DH110S,GH111S,FH112Y,AH114Y,MH115Y",10,4.01700137419585,1n8z.pdb,HL,A 414 | 1698.5,"IH30V,TH59S,NH62D,SH105A,RH106S,WH107S,DH110S,GH111S,FH112Y,AH114Y,MH115Y",11,4.02609448759946,1n8z.pdb,HL,A 415 | 1724.82,"SH105A,RH106S,WH107S,DH110S,GH111S,FH112S,AH114S,MH115Y,DH116Y",9,4.035204733486509,1n8z.pdb,HL,A 416 | 1830.41,"SH105A,WH107S,DH110S,FH112Y,AH114Y,MH115Y",6,4.0704066237865355,1n8z.pdb,HL,A 417 | 1986.37,"SH105A,WH107Y,GH108S,GH109S,DH110S,FH112G,YH113S,MH115F",8,4.1188507512046275,1n8z.pdb,HL,A 418 | 2286.4,"SH105A,WH107V,DH110R,FH112Y,MH115Y",5,4.20219077968194,1n8z.pdb,HL,A 419 | 2421.18,"SH105A,RH106V,WH107S,DH110S,GH111S,FH112S,AH114S,MH115Y,DH116Q",9,4.236124353620554,1n8z.pdb,HL,A 420 | 2523.9,"SH105A,WH107D,DH110S,FH112Y,MH115Y",5,4.260740911048753,1n8z.pdb,HL,A 421 | -------------------------------------------------------------------------------- /gearbind/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DeepGraphLearning/GearBind/34f14272f2bd9ee7181c0a6675e6439e72e81d45/gearbind/__init__.py -------------------------------------------------------------------------------- /gearbind/dataset.py: -------------------------------------------------------------------------------- 1 | import os 2 | import csv 3 | import glob 4 | import pickle 5 | from tqdm import tqdm 6 | 7 | import numpy as np 8 | import pandas as pd 9 | 10 | from copy import deepcopy 11 | 12 | from Bio.PDB import PDBParser 13 | 14 | import torch 15 | from torch.nn import functional as F 16 | from torch.utils import data as torch_data 17 | 18 | from torchdrug import core, data, datasets, utils 19 | from torchdrug.layers import functional 20 | from torchdrug.core import Registry as R 21 | 22 | from gearbind import residue_constants 23 | 24 | 25 | def bio_load_pdb(pdb): 26 | parser = PDBParser(QUIET=True) 27 | protein = parser.get_structure(0, pdb) 28 | residues = [residue for residue in protein.get_residues()] 29 | residue_type = [data.Protein.residue2id.get(residue.get_resname(), 0) for residue in residues] 30 | chain_id = [data.Protein.alphabet2id.get(residue.get_parent().id, 0) for residue in residues] 31 | insertion_code = [data.Protein.alphabet2id.get(residue.full_id[3][2], -1) for residue in residues] 32 | residue_number = [residue.full_id[3][1] for residue in residues] 33 | id2residue = {residue.full_id: i for i, residue in enumerate(residues)} 34 | # residue_feature = functional.one_hot(torch.as_tensor(residue_type), len(data.Protein.residue2id)+1) 35 | 36 | atoms = [atom for atom in protein.get_atoms()] 37 | atoms = [atom for atom in atoms if atom.get_name() in data.Protein.atom_name2id] 38 | occupancy = [atom.get_occupancy() for atom in atoms] 39 | b_factor = [atom.get_bfactor() for atom in atoms] 40 | atom_type = [data.feature.atom_vocab.get(atom.get_name()[0], 0) for atom in atoms] 41 | atom_name = [data.Protein.atom_name2id.get(atom.get_name(), 37) for atom in atoms] 42 | node_position = np.stack([atom.get_coord() for atom in atoms], axis=0) 43 | node_position = torch.as_tensor(node_position) 44 | atom2residue = [id2residue[atom.get_parent().full_id] for atom in atoms] 45 | 46 | edge_list = [[0, 0, 0]] 47 | bond_type = [0] 48 | 49 | return data.Protein(edge_list, atom_type=atom_type, bond_type=bond_type, residue_type=residue_type, 50 | num_node=len(atoms), num_residue=len(residues), atom_name=atom_name, 51 | atom2residue=atom2residue, occupancy=occupancy, b_factor=b_factor, chain_id=chain_id, 52 | residue_number=residue_number, node_position=node_position, insertion_code=insertion_code, # residue_feature=residue_feature 53 | ), "".join([data.Protein.id2residue_symbol[res] for res in residue_type]) 54 | 55 | 56 | @R.register("datasets.SKEMPI") 57 | class SKEMPI(data.ProteinDataset): 58 | 59 | fname = "SKEMPI.zip" 60 | md5 = "2c54e2ae7cda20cc5dfb2f5ab2adb8af" 61 | processed_file = "skempi.pkl.gz" 62 | splits = ["split_0", "split_1", "split_2", "split_3", "split_4"] 63 | 64 | def __init__(self, path, verbose=1, **kwargs): 65 | path = os.path.expanduser(path) 66 | if not os.path.exists(path): 67 | os.makedirs(path) 68 | self.path = path 69 | 70 | zip_file = os.path.join(path, self.fname) 71 | path = os.path.join(utils.extract(zip_file), "SKEMPI") 72 | pkl_file = os.path.join(path, self.processed_file) 73 | 74 | if os.path.exists(pkl_file): 75 | self.load_pickle(pkl_file, verbose=verbose, **kwargs) 76 | else: 77 | pdb_files = [] 78 | csv_files = [] 79 | for split in self.splits: 80 | split_path = utils.extract(os.path.join(path, "%s.zip" % split)) 81 | pdb_files += sorted(glob.glob(os.path.join(split_path, split, "*.pdb"))) 82 | csv_files.append(os.path.join(path, "%s.csv" % split)) 83 | self.load_pdbs(pdb_files, verbose=verbose, **kwargs) 84 | self.load_annotation(csv_files) 85 | self.save_pickle(pkl_file, verbose=verbose) 86 | 87 | pdb_splits = [os.path.basename(os.path.dirname(pdb_file)) for pdb_file in self.pdb_files] 88 | self.num_samples = [pdb_splits.count(split) for split in self.splits] 89 | 90 | def load_pdbs(self, pdb_files, transform=None, lazy=False, verbose=0, **kwargs): 91 | """ 92 | Load the dataset from pdb files. 93 | 94 | Parameters: 95 | pdb_files (list of str): pdb file names 96 | transform (Callable, optional): protein sequence transformation function 97 | lazy (bool, optional): if lazy mode is used, the proteins are processed in the dataloader. 98 | This may slow down the data loading process, but save a lot of CPU memory and dataset loading time. 99 | verbose (int, optional): output verbose level 100 | **kwargs 101 | """ 102 | num_sample = len(pdb_files) 103 | 104 | self.transform = transform 105 | self.lazy = lazy 106 | self.kwargs = kwargs 107 | self.data = [] 108 | self.pdb_files = [] 109 | self.sequences = [] 110 | 111 | if verbose: 112 | pdb_files = tqdm(pdb_files, "Constructing proteins from pdbs") 113 | for i, pdb_file in enumerate(pdb_files): 114 | if not lazy or i == 0: 115 | protein, sequence = bio_load_pdb(pdb_file) 116 | else: 117 | protein, sequence = None, None 118 | self.data.append(protein) 119 | self.pdb_files.append(pdb_file) 120 | self.sequences.append(sequence) 121 | 122 | def load_annotation(self, csv_files): 123 | data_dict = { 124 | os.path.basename(pdb_file): (protein, pdb_file, sequence) \ 125 | for pdb_file, protein, sequence in zip(self.pdb_files, self.data, self.sequences) 126 | } 127 | self.data = [] 128 | self.pdb_files = [] 129 | self.sequences = [] 130 | 131 | for fname in csv_files: 132 | csv_file = open(fname, "r") 133 | reader = csv.reader(csv_file, delimiter=',') 134 | header = next(reader) 135 | mutation_id, chain_a_id, chain_b_id, wt_protein_id, mt_protein_id = \ 136 | map(header.index, ["mutation", "chain_a", "chain_b", "wt_protein", "mt_protein"]) 137 | ddG_id = header.index("ddG") if "ddG" in header else None 138 | 139 | for line in reader: 140 | mutations, chain_a, chain_b, _wild_type, _mutant = \ 141 | map(lambda i: line[i], [mutation_id, chain_a_id, chain_b_id, wt_protein_id, mt_protein_id]) 142 | ddG = line[ddG_id] if ddG_id is not None else 0.0 143 | mutations = mutations.split(",") 144 | 145 | if _wild_type not in data_dict: continue 146 | wild_type = data_dict[_wild_type][0] 147 | with wild_type.node(): 148 | entity_a = torch.zeros(wild_type.num_residue, dtype=torch.bool) 149 | for a in chain_a: 150 | entity_a |= wild_type.chain_id == wild_type.alphabet2id[a] 151 | wild_type.entity_a = entity_a[wild_type.atom2residue] 152 | 153 | entity_b = torch.zeros(wild_type.num_residue, dtype=torch.bool) 154 | for b in chain_b: 155 | entity_b |= wild_type.chain_id == wild_type.alphabet2id[b] 156 | wild_type.entity_b = entity_b[wild_type.atom2residue] 157 | 158 | is_mutation = torch.zeros(wild_type.num_residue, dtype=torch.bool) 159 | for m in mutations: 160 | if m[-2].isalpha(): 161 | is_mutation |= \ 162 | (wild_type.chain_id == wild_type.alphabet2id[m[1]]) & \ 163 | (wild_type.residue_number == int(m[2:-2])) & \ 164 | (wild_type.insertion_code == wild_type.alphabet2id[m[-2]]) 165 | else: 166 | is_mutation |= \ 167 | (wild_type.chain_id == wild_type.alphabet2id[m[1]]) & \ 168 | (wild_type.residue_number == int(m[2:-1])) 169 | wild_type.is_mutation = is_mutation[wild_type.atom2residue] 170 | wild_type = wild_type.subgraph(wild_type.entity_a | wild_type.entity_b) 171 | if hasattr(wild_type, "node_feature"): 172 | with wild_type.node(): 173 | wild_type.node_feature = wild_type.node_feature.to_sparse() 174 | 175 | if _mutant not in data_dict: continue 176 | mutant = data_dict[_mutant][0] 177 | with mutant.node(): 178 | entity_a = torch.zeros(mutant.num_residue, dtype=torch.bool) 179 | for a in chain_a: 180 | entity_a |= mutant.chain_id == mutant.alphabet2id[a] 181 | mutant.entity_a = entity_a[mutant.atom2residue] 182 | 183 | entity_b = torch.zeros(mutant.num_residue, dtype=torch.bool) 184 | for b in chain_b: 185 | entity_b |= mutant.chain_id == mutant.alphabet2id[b] 186 | mutant.entity_b = entity_b[mutant.atom2residue] 187 | 188 | is_mutation = torch.zeros(mutant.num_residue, dtype=torch.bool) 189 | for m in mutations: 190 | if m[-2].isalpha(): 191 | is_mutation |= \ 192 | (mutant.chain_id == mutant.alphabet2id[m[1]]) & \ 193 | (mutant.residue_number == int(m[2:-2])) & \ 194 | (mutant.insertion_code == mutant.alphabet2id[m[-2]]) 195 | else: 196 | is_mutation |= \ 197 | (mutant.chain_id == mutant.alphabet2id[m[1]]) & \ 198 | (mutant.residue_number == int(m[2:-1])) 199 | mutant.is_mutation = is_mutation[mutant.atom2residue] 200 | mutant = mutant.subgraph(mutant.entity_a | mutant.entity_b) 201 | if hasattr(mutant, "node_feature"): 202 | with mutant.node(): 203 | mutant.node_feature = mutant.node_feature.to_sparse() 204 | 205 | self.data.append((wild_type, mutant, float(ddG), mutations, fname.split(".")[0])) 206 | self.pdb_files.append(data_dict[_mutant][1]) 207 | self.sequences.append((data_dict[_wild_type][2], data_dict[_mutant][2])) 208 | 209 | def split(self, test_set="split_0", valid_ratio=0.1): 210 | indices = list(range(len(self))) 211 | train_indices = [] 212 | offset = 0 213 | for split, num_samples in zip(self.splits, self.num_samples): 214 | if split != test_set: 215 | train_indices += indices[offset: offset + num_samples] 216 | offset += num_samples 217 | 218 | idx = self.splits.index(test_set) 219 | num_samples = self.num_samples[idx] 220 | offset = sum(self.num_samples[:idx]) 221 | test_indices = indices[offset: offset + num_samples] 222 | 223 | num_val_samples = int(len(train_indices) * valid_ratio) 224 | valid_indices = np.random.choice(train_indices, num_val_samples, replace=False) 225 | train_indices = [idx for idx in train_indices if idx not in valid_indices] 226 | 227 | return [ 228 | torch_data.Subset(self, train_indices), 229 | torch_data.Subset(self, valid_indices), 230 | torch_data.Subset(self, test_indices) 231 | ] 232 | 233 | def get_item(self, index): 234 | if getattr(self, "lazy", False): 235 | mutant = data.Protein.from_pdb(self.pdb_files[index], self.kwargs) 236 | wild_type = data.Protein.from_pdb( 237 | os.path.join(os.path.dirname(self.pdb_files[index]), "WT_" + os.path.basename(self.pdb_files[index])), 238 | self.kwargs 239 | ) 240 | else: 241 | wild_type = self.data[index][0].clone() 242 | mutant = self.data[index][1].clone() 243 | 244 | wt_residue_feature = F.one_hot(wild_type.residue_type, len(data.Protein.residue2id)+1) 245 | # wt_atom_feature = F.one_hot(wild_type.atom_name, len(data.Protein.atom_name2id)+1) 246 | wt_atom_feature = torch.cat([ 247 | F.one_hot(wild_type.atom_name, residue_constants.atom_type_num), 248 | wt_residue_feature[wild_type.atom2residue] 249 | ], dim=-1) 250 | with wild_type.node(): 251 | wild_type.node_feature = wt_atom_feature 252 | with wild_type.residue(): 253 | wild_type.residue_feature = wt_residue_feature 254 | 255 | mt_residue_feature = F.one_hot(mutant.residue_type, len(data.Protein.residue2id)+1) 256 | # mt_atom_feature = F.one_hot(mutant.atom_name, len(data.Protein.atom_name2id)+1) 257 | mt_atom_feature = torch.cat([ 258 | F.one_hot(mutant.atom_name, residue_constants.atom_type_num), 259 | mt_residue_feature[mutant.atom2residue] 260 | ], dim=-1) 261 | with mutant.node(): 262 | mutant.node_feature = mt_atom_feature 263 | with mutant.residue(): 264 | mutant.residue_feature = mt_residue_feature 265 | # if hasattr(wild_type, "node_feature"): 266 | # with wild_type.node(): 267 | # wild_type.node_feature = wild_type.node_feature.to_dense() 268 | # if hasattr(wild_type, "residue_feature"): 269 | # with wild_type.residue(): 270 | # wild_type.residue_feature = wild_type.residue_feature.to_dense() 271 | # if hasattr(mutant, "node_feature"): 272 | # with mutant.node(): 273 | # mutant.node_feature = mutant.node_feature.to_dense() 274 | # if hasattr(mutant, "residue_feature"): 275 | # with mutant.residue(): 276 | # mutant.residue_feature = mutant.residue_feature.to_dense() 277 | item = {"wild_type": wild_type, "mutant": mutant} 278 | if self.transform: 279 | item = self.transform(item) 280 | item["ddG"] = self.data[index][2] 281 | return item 282 | 283 | def __repr__(self): 284 | lines = [ 285 | "#sample: %d" % len(self), 286 | "#task: ddG", 287 | ] 288 | return "%s(\n %s\n)" % (self.__class__.__name__, "\n ".join(lines)) 289 | 290 | 291 | @R.register("datasets.HER2") 292 | class HER2(SKEMPI): 293 | 294 | processed_file = "1n8z_0328.pkl.gz" 295 | splits = ["1n8z_renum.pdb_HL_C"] 296 | 297 | def __init__(self, path, verbose=1, **kwargs): 298 | path = os.path.expanduser(path) 299 | if not os.path.exists(path): 300 | os.makedirs(path) 301 | self.path = path 302 | 303 | pkl_file = os.path.join(path, self.processed_file) 304 | 305 | if os.path.exists(pkl_file): 306 | self.load_pickle(pkl_file, verbose=verbose, **kwargs) 307 | else: 308 | pdb_files = [] 309 | csv_files = [] 310 | for split in self.splits: 311 | split_path = os.path.join(path, split) 312 | pdb_files += sorted(glob.glob(os.path.join(split_path, "data", "*.pdb"))) 313 | csv_files.append(os.path.join(split_path, "data.csv")) 314 | self.load_pdbs(pdb_files, verbose=verbose, **kwargs) 315 | self.load_annotation(csv_files) 316 | pdb_files = [] 317 | for pdb_file in self.pdb_files: 318 | pdb_dir, pdb_name = os.path.split(pdb_file) 319 | split = os.path.basename(os.path.dirname(pdb_dir)) 320 | pdb_file = os.path.join(split, pdb_name) 321 | pdb_files.append(pdb_file) 322 | self.pdb_files = pdb_files 323 | self.save_pickle(pkl_file, verbose=verbose) 324 | 325 | pdb_splits = [os.path.basename(os.path.dirname(pdb_file)) for pdb_file in self.pdb_files] 326 | self.num_samples = [pdb_splits.count(split) for split in self.splits] 327 | 328 | def split(self, **kwargs): 329 | indices = list(range(len(self))) 330 | subset = torch_data.Subset(self, indices) 331 | 332 | return [ 333 | subset, 334 | subset, 335 | subset 336 | ] 337 | 338 | 339 | @R.register("datasets.CR3022") 340 | class CR3022(HER2): 341 | 342 | processed_file = "CR3022.pkl.gz" 343 | splits = ["6xc3_ba11_renum.pdb_C_HL", "6xc3_ba4_renum.pdb_C_HL", "6xc3_wt_renum.pdb_C_HL"] 344 | 345 | 346 | atom_type_mapping = torch.tensor([data.feature.atom_vocab[n[0]] for n in residue_constants.atom_order]) # (37, ) 347 | atom_name_mapping = torch.tensor([data.Protein.atom_name2id[n] for n in residue_constants.atom_order]) # (37, ) 348 | inv_atom_name_mapping = torch.zeros((len(data.Protein.atom_name2id)), dtype=torch.long) 349 | inv_atom_name_mapping[atom_name_mapping] = torch.arange(residue_constants.atom_type_num, dtype=torch.long) # (37, ) 350 | residue_type_mapping = torch.tensor([data.Protein.residue_symbol2id.get(n, 0) for n in residue_constants.restypes_with_x]) # (21, ) 351 | 352 | 353 | def load_protein(data_dict): 354 | atom_mask = torch.tensor(data_dict['atom_mask']).bool() 355 | atom_type = atom_type_mapping[None, :] 356 | atom_type = atom_type.expand_as(atom_mask)[atom_mask] 357 | atom_name = atom_name_mapping[None, :] 358 | atom_name = atom_name.expand_as(atom_mask)[atom_mask] 359 | node_position = torch.tensor(data_dict['atom_positions'])[atom_mask] 360 | residue_type = torch.tensor(data_dict['aatype']) 361 | residue_type = residue_type_mapping[residue_type] 362 | residue_number = torch.tensor(data_dict['residue_index']) 363 | b_factor = torch.tensor(data_dict['b_factors'])[atom_mask] 364 | chain_id = torch.tensor(data_dict['chain_index']) 365 | num_residue = residue_type.shape[0] 366 | num_atom = atom_name.shape[0] 367 | 368 | atom2residue = torch.arange(num_residue)[:, None] 369 | atom2residue = atom2residue.expand_as(atom_mask)[atom_mask] 370 | 371 | edge_list = torch.zeros((1, 3), dtype=torch.long) 372 | bond_type = torch.zeros((1,), dtype=torch.long) 373 | 374 | residue_feature = F.one_hot(residue_type, len(residue_constants.restypes_with_x)) 375 | atom_feature = torch.cat([ 376 | F.one_hot(atom_name, residue_constants.atom_type_num), 377 | residue_feature[atom2residue] 378 | ], dim=-1) 379 | 380 | protein = data.Protein(edge_list=edge_list, atom_type=atom_type, bond_type=bond_type, 381 | residue_type=residue_type, atom_name=atom_name, atom2residue=atom2residue, 382 | residue_feature=residue_feature, atom_feature=atom_feature, bond_feature=None, 383 | residue_number=residue_number, b_factor=b_factor, chain_id=chain_id, 384 | node_position=node_position, num_node=num_atom, num_residue=num_residue, 385 | ) 386 | return protein 387 | -------------------------------------------------------------------------------- /gearbind/geometry.py: -------------------------------------------------------------------------------- 1 | import functools 2 | import math 3 | import torch 4 | from torch import nn 5 | from torch.nn import functional as F 6 | from torch.utils import checkpoint 7 | from torch_scatter import scatter_mean, scatter_add, scatter_max, scatter_min, scatter_sum 8 | from torch_cluster import knn, nearest 9 | 10 | from torchdrug import core, data, layers, utils 11 | from torchdrug.layers import functional 12 | from torchdrug.core import Registry as R 13 | 14 | 15 | @R.register("layers.InterfaceGraph") 16 | class InterfaceGraph(nn.Module, core.Configurable): 17 | 18 | def __init__(self, entity_level='node', cutoff=10.0): 19 | super(InterfaceGraph, self).__init__() 20 | self.entity_level = entity_level 21 | self.cutoff = cutoff 22 | 23 | def get_interface(self, a, b): 24 | nearest_b_indices = nearest(a.node_position, b.node_position, a.node2graph, b.node2graph) 25 | nearest_distance = (a.node_position - b.node_position[nearest_b_indices]).norm(dim=-1) 26 | is_interface_atom = nearest_distance < self.cutoff 27 | 28 | is_interface_resiude = scatter_max(is_interface_atom.long(), a.atom2residue)[0] 29 | is_interface_atom = is_interface_resiude[a.atom2residue].bool() 30 | return is_interface_atom 31 | 32 | def forward(self, graph): 33 | entity_a = graph.subgraph(graph.entity_a) 34 | entity_b = graph.subgraph(graph.entity_b) 35 | interface_mask_a = self.get_interface(entity_a, entity_b) 36 | interface_mask_b = self.get_interface(entity_b, entity_a) 37 | mask = torch.zeros(graph.num_node, dtype=torch.bool, device=graph.device) 38 | mask[graph.entity_a] = interface_mask_a 39 | mask[graph.entity_b] = interface_mask_b 40 | mask[graph.is_mutation] = 1 41 | 42 | if self.entity_level in ["node", "atom"]: 43 | graph = graph.subgraph(mask) 44 | else: 45 | graph = graph.subresidue(mask) 46 | 47 | return graph 48 | 49 | 50 | @R.register("layers.AtomPositionGather") 51 | class AtomPositionGather(nn.Module, core.Configurable): 52 | 53 | def from_3_points(self, p_x_axis, origin, p_xy_plane, eps=1e-10): 54 | """ 55 | Adpated from torchfold 56 | Implements algorithm 21. Constructs transformations from sets of 3 57 | points using the Gram-Schmidt algorithm. 58 | Args: 59 | x_axis: [*, 3] coordinates 60 | origin: [*, 3] coordinates used as frame origins 61 | p_xy_plane: [*, 3] coordinates 62 | eps: Small epsilon value 63 | Returns: 64 | A transformation object of shape [*] 65 | """ 66 | p_x_axis = torch.unbind(p_x_axis, dim=-1) 67 | origin = torch.unbind(origin, dim=-1) 68 | p_xy_plane = torch.unbind(p_xy_plane, dim=-1) 69 | 70 | e0 = [c1 - c2 for c1, c2 in zip(p_x_axis, origin)] 71 | e1 = [c1 - c2 for c1, c2 in zip(p_xy_plane, origin)] 72 | 73 | denom = torch.sqrt(sum((c * c for c in e0)) + eps) 74 | e0 = [c / denom for c in e0] 75 | dot = sum((c1 * c2 for c1, c2 in zip(e0, e1))) 76 | e1 = [c2 - c1 * dot for c1, c2 in zip(e0, e1)] 77 | denom = torch.sqrt(sum((c * c for c in e1)) + eps) 78 | e1 = [c / denom for c in e1] 79 | e2 = [ 80 | e0[1] * e1[2] - e0[2] * e1[1], 81 | e0[2] * e1[0] - e0[0] * e1[2], 82 | e0[0] * e1[1] - e0[1] * e1[0], 83 | ] 84 | 85 | rots = torch.stack([c for tup in zip(e0, e1, e2) for c in tup], dim=-1) 86 | rots = rots.reshape(rots.shape[:-1] + (3, 3)) 87 | 88 | return rots 89 | 90 | def forward(self, graph): 91 | residue_mask = \ 92 | scatter_add((graph.atom_name == graph.atom_name2id["N"]).float(), graph.atom2residue, dim_size=graph.num_residue) + \ 93 | scatter_add((graph.atom_name == graph.atom_name2id["CA"]).float(), graph.atom2residue, dim_size=graph.num_residue) + \ 94 | scatter_add((graph.atom_name == graph.atom_name2id["C"]).float(), graph.atom2residue, dim_size=graph.num_residue) 95 | residue_mask = (residue_mask == 3) 96 | atom_mask = residue_mask[graph.atom2residue] & (graph.atom_name == graph.atom_name2id["CA"]) 97 | graph = graph.subresidue(residue_mask) 98 | 99 | atom_pos = torch.full((graph.num_residue, len(graph.atom_name2id), 3), float("inf"), dtype=torch.float, device=graph.device) 100 | atom_pos[graph.atom2residue, graph.atom_name] = graph.node_position 101 | atom_pos_mask = torch.zeros((graph.num_residue, len(graph.atom_name2id)), dtype=torch.bool, device=graph.device) 102 | atom_pos_mask[graph.atom2residue, graph.atom_name] = 1 103 | 104 | graph = graph.subgraph(graph.atom_name == graph.atom_name2id["CA"]) 105 | frame = self.from_3_points( 106 | atom_pos[:, graph.atom_name2id["N"]], 107 | atom_pos[:, graph.atom_name2id["CA"]], 108 | atom_pos[:, graph.atom_name2id["C"]] 109 | ).transpose(-1, -2) 110 | 111 | graph.view = 'residue' 112 | with graph.residue(): 113 | graph.atom_pos = atom_pos 114 | graph.atom_pos_mask = atom_pos_mask 115 | graph.frame = frame 116 | 117 | return graph, atom_mask 118 | 119 | 120 | @R.register("layers.geometry.BackboneNode") 121 | class BackboneNode(nn.Module, core.Configurable): 122 | """ 123 | Construct only alpha carbon atoms. 124 | """ 125 | 126 | def forward(self, graph): 127 | """ 128 | Return a subgraph that only consists of alpha carbon nodes. 129 | 130 | Parameters: 131 | graph (Graph): :math:`n` graph(s) 132 | """ 133 | mask = ((graph.atom_name == data.Protein.atom_name2id["N"]) | 134 | (graph.atom_name == data.Protein.atom_name2id["CA"]) | 135 | (graph.atom_name == data.Protein.atom_name2id["C"]) ) & (graph.atom2residue != -1) 136 | residue2num_atom = graph.atom2residue[mask].bincount(minlength=graph.num_residue) 137 | residue_mask = residue2num_atom > 0 138 | mask = mask & residue_mask[graph.atom2residue] 139 | graph = graph.subgraph(mask).subresidue(residue_mask) 140 | 141 | return graph 142 | 143 | 144 | @R.register("layers.KNNMutationSite") 145 | class KNNMutationSite(nn.Module, core.Configurable): 146 | 147 | def __init__(self, k=64): 148 | super(KNNMutationSite, self).__init__() 149 | self.k = k 150 | 151 | def forward(self, graph): 152 | # Construct mutation site graphs 153 | mutation_mask = graph.is_mutation.to(torch.bool) & (graph.atom_name == graph.atom_name2id["CA"]) 154 | 155 | center_position = graph.node_position[mutation_mask] 156 | mut2graph = graph.node2graph[mutation_mask] 157 | # Calculate distance to center position in each graph 158 | center_indices = nearest(graph.node_position, center_position, graph.node2graph, mut2graph) 159 | dist_to_center = ((graph.node_position - center_position[center_indices])**2).sum(-1) 160 | dist_to_center[mutation_mask] = 0.0 161 | _, selected_index = functional.variadic_topk(dist_to_center, graph.num_nodes, self.k, largest=False) 162 | start = graph.num_cum_nodes - graph.num_nodes 163 | selected_index += start.view(-1, 1) 164 | selected_index = selected_index.view(-1) 165 | node_mask = torch.zeros(graph.num_node, dtype=torch.bool, device=graph.device) 166 | node_mask[selected_index] = 1 167 | # graph = graph.subgraph(node_mask) 168 | return node_mask 169 | -------------------------------------------------------------------------------- /gearbind/layer.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | 3 | import torch 4 | from torch import nn 5 | from torch.nn import functional as F 6 | 7 | from torch_scatter import scatter_add, scatter_mean, scatter_max, scatter_min 8 | 9 | from torchdrug import layers, data 10 | from torchdrug.layers import functional 11 | 12 | 13 | class DDGAttention(nn.Module): 14 | 15 | def __init__(self, input_dim, output_dim, value_dim=16, query_key_dim=16, num_heads=12): 16 | super(DDGAttention, self).__init__() 17 | self.input_dim = input_dim 18 | self.output_dim = output_dim 19 | self.value_dim = value_dim 20 | self.query_key_dim = query_key_dim 21 | self.num_heads = num_heads 22 | 23 | self.query = nn.Linear(input_dim, query_key_dim*num_heads, bias=False) 24 | self.key = nn.Linear(input_dim, query_key_dim*num_heads, bias=False) 25 | self.value = nn.Linear(input_dim, value_dim*num_heads, bias=False) 26 | 27 | self.out_transform = nn.Linear( 28 | in_features = (num_heads*value_dim) + (num_heads*(3+3+1)), 29 | out_features = output_dim, 30 | ) 31 | self.layer_norm = nn.LayerNorm(output_dim) 32 | 33 | def _alpha_from_logits(self, logits, mask, inf=1e5): 34 | """ 35 | Args: 36 | logits: Logit matrices, (N, L_i, L_j, num_heads). 37 | mask: Masks, (N, L). 38 | Returns: 39 | alpha: Attention weights. 40 | """ 41 | N, L, _, _ = logits.size() 42 | mask_row = mask.view(N, L, 1, 1).expand_as(logits) # (N, L, *, *) 43 | mask_pair = mask_row * mask_row.permute(0, 2, 1, 3) # (N, L, L, *) 44 | 45 | logits = torch.where(mask_pair, logits, logits-inf) 46 | alpha = torch.softmax(logits, dim=2) # (N, L, L, num_heads) 47 | alpha = torch.where(mask_row, alpha, torch.zeros_like(alpha)) 48 | return alpha 49 | 50 | def _heads(self, x, n_heads, n_ch): 51 | """ 52 | Args: 53 | x: (..., num_heads * num_channels) 54 | Returns: 55 | (..., num_heads, num_channels) 56 | """ 57 | s = list(x.size())[:-1] + [n_heads, n_ch] 58 | return x.view(*s) 59 | 60 | def forward(self, x, pos_CA, pos_CB, frame, mask): 61 | # Attention logits 62 | query = self._heads(self.query(x), self.num_heads, self.query_key_dim) # (N, L, n_heads, head_size) 63 | key = self._heads(self.key(x), self.num_heads, self.query_key_dim) # (N, L, n_heads, head_size) 64 | logits_node = torch.einsum('blhd, bkhd->blkh', query, key) 65 | alpha = self._alpha_from_logits(logits_node, mask) # (N, L, L, n_heads) 66 | 67 | value = self._heads(self.value(x), self.num_heads, self.value_dim) # (N, L, n_heads, head_size) 68 | feat_node = torch.einsum('blkh, bkhd->blhd', alpha, value).flatten(-2) 69 | 70 | rel_pos = pos_CB.unsqueeze(1) - pos_CA.unsqueeze(2) # (N, L, L, 3) 71 | atom_pos_bias = torch.einsum('blkh, blkd->blhd', alpha, rel_pos) # (N, L, n_heads, 3) 72 | feat_distance = atom_pos_bias.norm(dim=-1) 73 | feat_points = torch.einsum('blij, blhj->blhi', frame, atom_pos_bias) # (N, L, n_heads, 3) 74 | feat_direction = feat_points / (feat_points.norm(dim=-1, keepdim=True) + 1e-10) 75 | feat_spatial = torch.cat([ 76 | feat_points.flatten(-2), 77 | feat_distance, 78 | feat_direction.flatten(-2), 79 | ], dim=-1) 80 | 81 | feat_all = torch.cat([feat_node, feat_spatial], dim=-1) 82 | 83 | feat_all = self.out_transform(feat_all) # (N, L, F) 84 | feat_all = torch.where(mask.unsqueeze(-1), feat_all, torch.zeros_like(feat_all)) 85 | if x.shape[-1] == feat_all.shape[-1]: 86 | x_updated = self.layer_norm(x + feat_all) 87 | else: 88 | x_updated = self.layer_norm(feat_all) 89 | 90 | return x_updated 91 | 92 | 93 | class GeometricAttention(nn.Module): 94 | 95 | def __init__(self, node_feat_dim, pair_feat_dim, value_dim=16, query_key_dim=16, 96 | num_query_points=8, num_value_points=8, num_heads=12, activation=None): 97 | super().__init__() 98 | self.node_feat_dim = node_feat_dim 99 | self.pair_feat_dim = pair_feat_dim 100 | self.value_dim = value_dim 101 | self.query_key_dim = query_key_dim 102 | self.num_query_points = num_query_points 103 | self.num_value_points = num_value_points 104 | self.num_heads = num_heads 105 | 106 | # Node 107 | self.proj_query = nn.Linear(node_feat_dim, query_key_dim*num_heads, bias=False) 108 | self.proj_key = nn.Linear(node_feat_dim, query_key_dim*num_heads, bias=False) 109 | self.proj_value = nn.Linear(node_feat_dim, value_dim*num_heads, bias=False) 110 | 111 | # Pair 112 | self.proj_pair_bias = nn.Linear(pair_feat_dim, num_heads, bias=False) 113 | 114 | self.spatial_coef = nn.Parameter(torch.full([1, 1, 1, self.num_heads], fill_value=np.log(np.exp(1.) - 1.)), requires_grad=True) 115 | 116 | # Output 117 | self.out_transform = nn.Linear( 118 | in_features = (num_heads*pair_feat_dim) + (num_heads*value_dim) + (num_heads*(3+3+1)), 119 | out_features = node_feat_dim, 120 | ) 121 | self.layer_norm = nn.LayerNorm(node_feat_dim) 122 | 123 | if isinstance(activation, str): 124 | self.activation = getattr(F, activation) 125 | else: 126 | self.activation = activation 127 | 128 | def _alpha_from_logits(self, logits, mask, inf=1e5): 129 | """ 130 | Args: 131 | logits: Logit matrices, (N, L_i, L_j, num_heads). 132 | mask: Masks, (N, L). 133 | Returns: 134 | alpha: Attention weights. 135 | """ 136 | N, L, _, _ = logits.size() 137 | mask_row = mask.view(N, L, 1, 1).expand_as(logits) # (N, L, *, *) 138 | mask_pair = mask_row * mask_row.permute(0, 2, 1, 3) # (N, L, L, *) 139 | 140 | logits = torch.where(mask_pair, logits, logits-inf) 141 | alpha = torch.softmax(logits, dim=2) # (N, L, L, num_heads) 142 | alpha = torch.where(mask_row, alpha, torch.zeros_like(alpha)) 143 | return alpha 144 | 145 | def _heads(self, x, n_heads, n_ch): 146 | """ 147 | Args: 148 | x: (..., num_heads * num_channels) 149 | Returns: 150 | (..., num_heads, num_channels) 151 | """ 152 | s = list(x.size())[:-1] + [n_heads, n_ch] 153 | return x.view(*s) 154 | 155 | def _normalize_vector(self, v, dim, eps=1e-6): 156 | return v / (torch.linalg.norm(v, ord=2, dim=dim, keepdim=True) + eps) 157 | 158 | def _node_logits(self, x): 159 | query_l = self._heads(self.proj_query(x), self.num_heads, self.query_key_dim) # (N, L, n_heads, qk_ch) 160 | key_l = self._heads(self.proj_key(x), self.num_heads, self.query_key_dim) # (N, L, n_heads, qk_ch) 161 | 162 | query_l = query_l.permute(0, 2, 1, 3) # (N,L1,H,C) -> (N,H,L1,C) 163 | key_l = key_l.permute(0, 2, 3, 1) # (N,L2,H,C) -> (N,H,C,L2) 164 | 165 | logits = torch.matmul(query_l, key_l) # (N,H,L1,L2) 166 | logits = logits.permute(0, 2, 3, 1) # (N,L1,L2,H) 167 | 168 | return logits 169 | 170 | def _pair_logits(self, z): 171 | logits_pair = self.proj_pair_bias(z) 172 | return logits_pair 173 | 174 | def _beta_logits(self, p_CB): 175 | qk = p_CB[:, :, None, :].expand(-1, -1, self.num_heads, -1) 176 | sum_sq_dist = ((qk.unsqueeze(2) - qk.unsqueeze(1)) ** 2).sum(-1) # (N, L, L, n_heads) 177 | gamma = F.softplus(self.spatial_coef) 178 | logtis_beta = sum_sq_dist * ((-1 * gamma * np.sqrt(2 / 9)) / 2) 179 | return logtis_beta 180 | 181 | def _pair_aggregation(self, alpha, z): 182 | N, L = z.shape[:2] 183 | feat_p2n = torch.einsum("blkh, blkc->blhc", alpha, z) 184 | return feat_p2n.reshape(N, L, -1) 185 | 186 | def _node_aggregation(self, alpha, x): 187 | N, L = x.shape[:2] 188 | value_l = self._heads(self.proj_value(x), self.num_heads, self.query_key_dim) # (N, L, n_heads, v_ch) 189 | feat_node = torch.einsum("blkh, bkhc->blhc", alpha, value_l) 190 | return feat_node.reshape(N, L, -1) 191 | 192 | def _beta_aggregation(self, alpha, graph, p_CB): 193 | N, L = p_CB.size()[:2] 194 | v = p_CB[:, :, None, :].expand(N, L, self.num_heads, 3) # (N, L, n_heads, 3) 195 | aggr = torch.einsum('blkh, bkhd->blhd', alpha, v) 196 | 197 | atom_pos, _ = functional.variadic_to_padded(graph.atom_pos, graph.num_nodes) 198 | frame, _ = functional.variadic_to_padded(graph.frame, graph.num_nodes) 199 | feat_points = (aggr - atom_pos[:, :, None, graph.atom_name2id["CA"]]) 200 | feat_points = torch.einsum('blij, blhj->blhi', frame, feat_points) # (N, L, n_heads, 3) 201 | feat_distance = feat_points.norm(dim=-1) 202 | feat_direction = self._normalize_vector(feat_points, dim=-1, eps=1e-4) 203 | 204 | feat_spatial = torch.cat([ 205 | feat_points.reshape(N, L, -1), 206 | feat_distance.reshape(N, L, -1), 207 | feat_direction.reshape(N, L, -1), 208 | ], dim=-1) 209 | 210 | return feat_spatial 211 | 212 | def forward(self, graph, x, z, mask): 213 | pos_CB = torch.where( 214 | graph.atom_pos_mask[:, graph.atom_name2id["CB"], None].expand(-1, 3).bool(), 215 | graph.atom_pos[:, graph.atom_name2id["CB"]], 216 | graph.atom_pos[:, graph.atom_name2id["CA"]], 217 | ) 218 | pos_CB, _ = functional.variadic_to_padded(pos_CB, graph.num_nodes) 219 | 220 | # Attention logits 221 | logits_node = self._node_logits(x) 222 | logits_pair = self._pair_logits(z) 223 | logits_spatial = self._beta_logits(pos_CB) 224 | # Summing logits up and apply `softmax`. 225 | logits_sum = logits_node + logits_pair + logits_spatial 226 | alpha = self._alpha_from_logits(logits_sum * np.sqrt(1 / 3), mask) # (N, L, L, n_heads) 227 | 228 | # Aggregate features 229 | feat_p2n = self._pair_aggregation(alpha, z) 230 | feat_node = self._node_aggregation(alpha, x) 231 | feat_spatial = self._beta_aggregation(alpha, graph, pos_CB) 232 | 233 | # Finally 234 | feat_all = self.out_transform(torch.cat([feat_p2n, feat_node, feat_spatial], dim=-1)) # (N, L, F) 235 | feat_all = torch.where(mask.unsqueeze(-1), feat_all, torch.zeros_like(feat_all)) 236 | if self.activation: 237 | feat_all = self.activation(feat_all) 238 | x_updated = self.layer_norm(x + feat_all) 239 | return x_updated 240 | 241 | 242 | class PerResidueEncoder(nn.Module): 243 | 244 | num_residue_type = len(data.Protein.residue2id) 245 | num_atom_names = len(data.Protein.atom_name2id) 246 | 247 | def __init__(self, hidden_dim): 248 | super(PerResidueEncoder, self).__init__() 249 | self.aatype_embed = nn.Embedding(self.num_residue_type, hidden_dim) 250 | self.mlp = nn.Sequential( 251 | nn.Linear(self.num_residue_type * self.num_atom_names * 3 + hidden_dim, hidden_dim * 2), nn.ReLU(), 252 | nn.Linear(hidden_dim * 2, hidden_dim), nn.ReLU(), 253 | nn.Linear(hidden_dim, hidden_dim), nn.ReLU(), 254 | nn.Linear(hidden_dim, hidden_dim) 255 | ) 256 | 257 | def forward(self, graph): 258 | crd14 = (graph.atom_pos - graph.atom_pos[:, None, graph.atom_name2id["CA"]]) 259 | crd14 = torch.einsum('bij, bkj->bki', graph.frame, crd14) # (*, 14, 3) 260 | crd14_mask = graph.atom_pos_mask.unsqueeze(-1).expand_as(crd14).bool() 261 | crd14 = torch.where(crd14_mask, crd14, torch.zeros_like(crd14)) 262 | 263 | residue_type = graph.residue_type 264 | residue_type[residue_type == -1] = self.num_residue_type - 1 265 | aa_expand = residue_type[:, None, None, None].expand(-1, self.num_residue_type, self.num_atom_names, 3) 266 | rng_expand = torch.arange(0, self.num_residue_type)[None, :, None, None] 267 | rng_expand = rng_expand.expand(graph.num_node, -1, self.num_atom_names, 3).to(aa_expand) 268 | place_mask = (aa_expand == rng_expand) 269 | crd_expand = crd14[:, None, :, :].expand(-1, self.num_residue_type, self.num_atom_names, 3) 270 | crd_expand = torch.where(place_mask, crd_expand, torch.zeros_like(crd_expand)) 271 | crd_feat = crd_expand.reshape(-1, self.num_residue_type * self.num_atom_names * 3) 272 | 273 | aa_feat = self.aatype_embed(residue_type) # (*, hidden_dim) 274 | 275 | out_feat = self.mlp(torch.cat([crd_feat, aa_feat], dim=-1)) 276 | return out_feat 277 | -------------------------------------------------------------------------------- /gearbind/model.py: -------------------------------------------------------------------------------- 1 | from collections.abc import Sequence 2 | 3 | import torch 4 | from torch import nn 5 | from torch import autograd 6 | 7 | from torch_scatter import scatter_add 8 | 9 | from torchdrug import core, layers, utils 10 | from torchdrug.layers import functional 11 | from torchdrug.core import Registry as R 12 | 13 | from . import layer, geometry 14 | 15 | 16 | @R.register("models.BindModel") 17 | class BindModel(nn.Module, core.Configurable): 18 | 19 | def __init__(self, model, num_mlp_layer=2): 20 | super(BindModel, self).__init__() 21 | self.model = model 22 | self.num_mlp_layer = num_mlp_layer 23 | 24 | hidden_dims = [model.output_dim] * (num_mlp_layer - 1) 25 | self.mlp = layers.MLP(model.output_dim * 2, hidden_dims + [1]) 26 | 27 | def forward(self, batch, all_loss=None, metric=None): 28 | mutant = batch["mutant"] 29 | mutant_output = self.model(mutant, mutant.node_feature.float(), all_loss=all_loss, metric=metric) 30 | 31 | wild_type = batch["wild_type"] 32 | wild_type_output = self.model(wild_type, wild_type.node_feature.float(), all_loss=all_loss, metric=metric) 33 | 34 | wild_type_output = wild_type_output["graph_feature"] 35 | mutant_output = mutant_output["graph_feature"] 36 | 37 | outputs = torch.cat([mutant_output, wild_type_output], dim=-1) 38 | pred = self.mlp(outputs) 39 | outputs = torch.cat([wild_type_output, mutant_output], dim=-1) 40 | pred = pred - self.mlp(outputs) 41 | 42 | return { 43 | 'ddG': pred, 44 | 'wild_type_feature': wild_type_output, 45 | 'mutant_feature': mutant_output 46 | } 47 | 48 | 49 | @R.register("models.GearBind") 50 | class GearBind(nn.Module, core.Configurable): 51 | 52 | def __init__(self, input_dim, hidden_dims, num_relation, edge_input_dim=None, num_angle_bin=None, 53 | short_cut=False, batch_norm=False, activation="relu", concat_hidden=False, readout="sum", 54 | use_attn=True): 55 | super(GearBind, self).__init__() 56 | if not isinstance(hidden_dims, Sequence): 57 | hidden_dims = [hidden_dims] 58 | self.input_dim = input_dim 59 | self.output_dim = sum(hidden_dims) if concat_hidden else hidden_dims[-1] 60 | self.dims = [input_dim] + list(hidden_dims) 61 | self.edge_dims = [edge_input_dim] + self.dims[:-1] 62 | self.num_relation = num_relation 63 | self.num_angle_bin = num_angle_bin 64 | self.short_cut = short_cut 65 | self.concat_hidden = concat_hidden 66 | self.batch_norm = batch_norm 67 | self.use_attn = use_attn 68 | 69 | self.layers = nn.ModuleList() 70 | for i in range(len(self.dims) - 1): 71 | self.layers.append(layers.GeometricRelationalGraphConv(self.dims[i], self.dims[i + 1], num_relation, 72 | None, batch_norm, activation)) 73 | self.atom_position_gather = geometry.AtomPositionGather() 74 | if use_attn: 75 | self.attn_layers = nn.ModuleList() 76 | for i in range(len(self.dims) - 1): 77 | self.attn_layers.append(layer.DDGAttention(self.dims[i+1], self.dims[i+1])) 78 | if num_angle_bin: 79 | self.spatial_line_graph = layers.SpatialLineGraph(num_angle_bin) 80 | self.edge_layers = nn.ModuleList() 81 | for i in range(len(self.edge_dims) - 1): 82 | self.edge_layers.append(layers.GeometricRelationalGraphConv( 83 | self.edge_dims[i], self.edge_dims[i + 1], num_angle_bin, None, batch_norm, activation)) 84 | 85 | if batch_norm: 86 | self.batch_norm_layers = nn.ModuleList() 87 | for i in range(len(self.dims) - 1): 88 | self.batch_norm_layers.append(nn.BatchNorm1d(self.dims[i + 1])) 89 | 90 | if readout == "sum": 91 | self.readout = layers.SumReadout() 92 | elif readout == "mean": 93 | self.readout = layers.MeanReadout() 94 | else: 95 | raise ValueError("Unknown readout `%s`" % readout) 96 | 97 | def forward(self, graph, input, all_loss=None, metric=None): 98 | residue_graph, node_mask = self.atom_position_gather(graph) 99 | pos_CA, _ = functional.variadic_to_padded(residue_graph.node_position, residue_graph.num_nodes, value=0) 100 | pos_CB = torch.where( 101 | residue_graph.atom_pos_mask[:, residue_graph.atom_name2id["CB"], None].expand(-1, 3), 102 | residue_graph.atom_pos[:, residue_graph.atom_name2id["CB"]], 103 | residue_graph.atom_pos[:, residue_graph.atom_name2id["CA"]] 104 | ) 105 | pos_CB, _ = functional.variadic_to_padded(pos_CB, residue_graph.num_nodes, value=0) 106 | frame, _ = functional.variadic_to_padded(residue_graph.frame, residue_graph.num_nodes, value=0) 107 | 108 | if self.num_angle_bin: 109 | line_graph = self.spatial_line_graph(graph) 110 | edge_input = line_graph.node_feature.float() 111 | 112 | hiddens = [] 113 | layer_input = input 114 | for i in range(len(self.layers)): 115 | hidden = self.layers[i](graph, layer_input) 116 | if self.short_cut and hidden.shape == layer_input.shape: 117 | hidden = hidden + layer_input 118 | if self.num_angle_bin: 119 | edge_hidden = self.edge_layers[i](line_graph, edge_input) 120 | node_out = graph.edge_list[:, 1] * self.num_relation + graph.edge_list[:, 2] 121 | update = scatter_add(edge_hidden * graph.edge_weight.unsqueeze(-1), node_out, dim=0, dim_size=graph.num_node * self.num_relation) 122 | update = update.view(graph.num_node, self.num_relation * edge_hidden.shape[1]) 123 | update = self.layers[i].linear(update) 124 | update = self.layers[i].activation(update) 125 | hidden = hidden + update 126 | edge_input = edge_hidden 127 | if self.batch_norm: 128 | hidden = self.batch_norm_layers[i](hidden) 129 | 130 | if self.use_attn: 131 | x, mask = functional.variadic_to_padded(hidden[node_mask], residue_graph.num_nodes, value=0) 132 | residue_hidden = self.attn_layers[i](x, pos_CA, pos_CB, frame, mask.bool()) 133 | residue_hidden = functional.padded_to_variadic(residue_hidden, residue_graph.num_nodes) 134 | hidden[node_mask] += residue_hidden 135 | 136 | hiddens.append(hidden) 137 | layer_input = hidden 138 | 139 | if self.concat_hidden: 140 | node_feature = torch.cat(hiddens, dim=-1) 141 | else: 142 | node_feature = hiddens[-1] 143 | graph_feature = self.readout(residue_graph, node_feature[node_mask]) 144 | 145 | return { 146 | "graph_feature": graph_feature, 147 | "node_feature": node_feature 148 | } 149 | 150 | 151 | @R.register("models.DDGPredictor") 152 | class DDGPredictor(nn.Module, core.Configurable): 153 | 154 | def __init__(self, hidden_dim=512, num_layers=4, pair_dim=128, max_relpos=100, 155 | num_neighbors=128, num_heads=12, activation=None): 156 | super(DDGPredictor, self).__init__() 157 | self.hidden_dim = hidden_dim 158 | self.pair_dim = pair_dim 159 | self.max_relpos = max_relpos 160 | self.num_layers = num_layers 161 | self.output_dim = 2 162 | self.atom_position_gather = geometry.AtomPositionGather() 163 | self.mutation_site_graph = geometry.KNNMutationSite(k=num_neighbors) 164 | 165 | self.relpos_embedding = nn.Embedding(max_relpos*2+2, pair_dim) 166 | self.residue_encoder = layer.PerResidueEncoder(hidden_dim) 167 | 168 | self.blocks = nn.ModuleList([ 169 | layer.GeometricAttention(hidden_dim, pair_dim, num_heads=num_heads, activation=activation) for _ in range(num_layers) 170 | ]) 171 | 172 | # Readout 173 | self.mlp = nn.Sequential( 174 | nn.Linear(hidden_dim*2, hidden_dim), nn.ReLU(), 175 | nn.Linear(hidden_dim, hidden_dim), nn.ReLU(), 176 | nn.Linear(hidden_dim, hidden_dim), nn.ReLU(), 177 | nn.Linear(hidden_dim, hidden_dim) 178 | ) 179 | 180 | self.project = nn.Linear(hidden_dim, 1, bias=False) 181 | 182 | def encode(self, graph): 183 | chain_id = graph.entity_a.long() * 2 + graph.entity_b.long() 184 | chain_id, _ = functional.variadic_to_padded(chain_id, graph.num_nodes) # batch_size * num_nodes * 1 185 | same_chain = (chain_id.unsqueeze(1) == chain_id.unsqueeze(2)) 186 | 187 | seqpos, _ = functional.variadic_to_padded(graph.residue_number, graph.num_nodes) # batch_size * num_nodes * 1 188 | relpos = seqpos.unsqueeze(1) - seqpos.unsqueeze(2) 189 | relpos = relpos.clamp(min=-self.max_relpos, max=self.max_relpos) + self.max_relpos 190 | relpos = torch.where(same_chain, relpos, torch.full_like(relpos, fill_value=self.max_relpos*2+1)) 191 | pair_input = self.relpos_embedding(relpos) 192 | 193 | # Residue encoder 194 | input = self.residue_encoder(graph) 195 | x, mask = functional.variadic_to_padded(input, graph.num_nodes) 196 | 197 | for block in self.blocks: 198 | x = block(graph, x, pair_input, mask.bool()) 199 | return x, mask 200 | 201 | def forward(self, batch, all_loss=None, metric=None): 202 | wild_type, _ = self.atom_position_gather(batch["wild_type"]) 203 | mutant, _ = self.atom_position_gather(batch["mutant"]) 204 | assert (wild_type.num_nodes == mutant.num_nodes).all() 205 | assert (wild_type.num_nodes == wild_type.num_residues).all() 206 | 207 | is_valid = (wild_type.num_nodes > 0) & (scatter_add(wild_type.is_mutation.float(), wild_type.node2graph, dim=0, dim_size=wild_type.batch_size) > 0) 208 | wild_type = wild_type[is_valid] 209 | mutant = mutant[is_valid] 210 | node_mask = self.mutation_site_graph(wild_type) 211 | wild_type = wild_type.subresidue(node_mask) 212 | mutant = mutant.subresidue(node_mask) 213 | 214 | output_wt, mask = self.encode(wild_type) 215 | output_mt, mask = self.encode(mutant) 216 | 217 | feat_wm = torch.cat([output_wt, output_mt], dim=-1) 218 | feat_mw = torch.cat([output_mt, output_wt], dim=-1) 219 | feat_diff = self.mlp(feat_wm) - self.mlp(feat_mw) # (N, L, F) 220 | 221 | per_residue_ddg = (self.project(feat_diff) * mask.float().unsqueeze(-1)).squeeze(-1) # (N, L) 222 | ddG = per_residue_ddg.sum(dim=1, keepdim=True) # (N,) 223 | 224 | result = torch.zeros((batch["wild_type"].batch_size, 1), dtype=torch.float, device=wild_type.device) 225 | result[is_valid] = ddG 226 | feat_wt = output_wt.sum(dim=1) 227 | feat_mt = output_mt.sum(dim=1) 228 | _feat_wt = torch.zeros((batch["wild_type"].batch_size, feat_wt.shape[1]), dtype=torch.float, device=wild_type.device) 229 | _feat_mt = torch.zeros((batch["mutant"].batch_size, feat_wt.shape[1]), dtype=torch.float, device=mutant.device) 230 | _feat_wt[is_valid] = feat_wt 231 | _feat_mt[is_valid] = feat_mt 232 | 233 | return { 234 | 'ddG': result, 235 | 'wild_type_feature': _feat_wt, 236 | 'mutant_feature': _feat_mt, 237 | } 238 | -------------------------------------------------------------------------------- /gearbind/residue_constants.py: -------------------------------------------------------------------------------- 1 | # Copyright 2021 DeepMind Technologies Limited 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | """Constants used in AlphaFold.""" 16 | 17 | import collections 18 | import functools 19 | import os 20 | from typing import List, Mapping, Tuple 21 | 22 | import numpy as np 23 | import tree 24 | 25 | # Internal import (35fd). 26 | 27 | 28 | # Distance from one CA to next CA [trans configuration: omega = 180]. 29 | ca_ca = 3.80209737096 30 | 31 | # Format: The list for each AA type contains chi1, chi2, chi3, chi4 in 32 | # this order (or a relevant subset from chi1 onwards). ALA and GLY don't have 33 | # chi angles so their chi angle lists are empty. 34 | chi_angles_atoms = { 35 | 'ALA': [], 36 | # Chi5 in arginine is always 0 +- 5 degrees, so ignore it. 37 | 'ARG': [['N', 'CA', 'CB', 'CG'], ['CA', 'CB', 'CG', 'CD'], 38 | ['CB', 'CG', 'CD', 'NE'], ['CG', 'CD', 'NE', 'CZ']], 39 | 'ASN': [['N', 'CA', 'CB', 'CG'], ['CA', 'CB', 'CG', 'OD1']], 40 | 'ASP': [['N', 'CA', 'CB', 'CG'], ['CA', 'CB', 'CG', 'OD1']], 41 | 'CYS': [['N', 'CA', 'CB', 'SG']], 42 | 'GLN': [['N', 'CA', 'CB', 'CG'], ['CA', 'CB', 'CG', 'CD'], 43 | ['CB', 'CG', 'CD', 'OE1']], 44 | 'GLU': [['N', 'CA', 'CB', 'CG'], ['CA', 'CB', 'CG', 'CD'], 45 | ['CB', 'CG', 'CD', 'OE1']], 46 | 'GLY': [], 47 | 'HIS': [['N', 'CA', 'CB', 'CG'], ['CA', 'CB', 'CG', 'ND1']], 48 | 'ILE': [['N', 'CA', 'CB', 'CG1'], ['CA', 'CB', 'CG1', 'CD1']], 49 | 'LEU': [['N', 'CA', 'CB', 'CG'], ['CA', 'CB', 'CG', 'CD1']], 50 | 'LYS': [['N', 'CA', 'CB', 'CG'], ['CA', 'CB', 'CG', 'CD'], 51 | ['CB', 'CG', 'CD', 'CE'], ['CG', 'CD', 'CE', 'NZ']], 52 | 'MET': [['N', 'CA', 'CB', 'CG'], ['CA', 'CB', 'CG', 'SD'], 53 | ['CB', 'CG', 'SD', 'CE']], 54 | 'PHE': [['N', 'CA', 'CB', 'CG'], ['CA', 'CB', 'CG', 'CD1']], 55 | 'PRO': [['N', 'CA', 'CB', 'CG'], ['CA', 'CB', 'CG', 'CD']], 56 | 'SER': [['N', 'CA', 'CB', 'OG']], 57 | 'THR': [['N', 'CA', 'CB', 'OG1']], 58 | 'TRP': [['N', 'CA', 'CB', 'CG'], ['CA', 'CB', 'CG', 'CD1']], 59 | 'TYR': [['N', 'CA', 'CB', 'CG'], ['CA', 'CB', 'CG', 'CD1']], 60 | 'VAL': [['N', 'CA', 'CB', 'CG1']], 61 | } 62 | 63 | # If chi angles given in fixed-length array, this matrix determines how to mask 64 | # them for each AA type. The order is as per restype_order (see below). 65 | chi_angles_mask = [ 66 | [0.0, 0.0, 0.0, 0.0], # ALA 67 | [1.0, 1.0, 1.0, 1.0], # ARG 68 | [1.0, 1.0, 0.0, 0.0], # ASN 69 | [1.0, 1.0, 0.0, 0.0], # ASP 70 | [1.0, 0.0, 0.0, 0.0], # CYS 71 | [1.0, 1.0, 1.0, 0.0], # GLN 72 | [1.0, 1.0, 1.0, 0.0], # GLU 73 | [0.0, 0.0, 0.0, 0.0], # GLY 74 | [1.0, 1.0, 0.0, 0.0], # HIS 75 | [1.0, 1.0, 0.0, 0.0], # ILE 76 | [1.0, 1.0, 0.0, 0.0], # LEU 77 | [1.0, 1.0, 1.0, 1.0], # LYS 78 | [1.0, 1.0, 1.0, 0.0], # MET 79 | [1.0, 1.0, 0.0, 0.0], # PHE 80 | [1.0, 1.0, 0.0, 0.0], # PRO 81 | [1.0, 0.0, 0.0, 0.0], # SER 82 | [1.0, 0.0, 0.0, 0.0], # THR 83 | [1.0, 1.0, 0.0, 0.0], # TRP 84 | [1.0, 1.0, 0.0, 0.0], # TYR 85 | [1.0, 0.0, 0.0, 0.0], # VAL 86 | ] 87 | 88 | # The following chi angles are pi periodic: they can be rotated by a multiple 89 | # of pi without affecting the structure. 90 | chi_pi_periodic = [ 91 | [0.0, 0.0, 0.0, 0.0], # ALA 92 | [0.0, 0.0, 0.0, 0.0], # ARG 93 | [0.0, 0.0, 0.0, 0.0], # ASN 94 | [0.0, 1.0, 0.0, 0.0], # ASP 95 | [0.0, 0.0, 0.0, 0.0], # CYS 96 | [0.0, 0.0, 0.0, 0.0], # GLN 97 | [0.0, 0.0, 1.0, 0.0], # GLU 98 | [0.0, 0.0, 0.0, 0.0], # GLY 99 | [0.0, 0.0, 0.0, 0.0], # HIS 100 | [0.0, 0.0, 0.0, 0.0], # ILE 101 | [0.0, 0.0, 0.0, 0.0], # LEU 102 | [0.0, 0.0, 0.0, 0.0], # LYS 103 | [0.0, 0.0, 0.0, 0.0], # MET 104 | [0.0, 1.0, 0.0, 0.0], # PHE 105 | [0.0, 0.0, 0.0, 0.0], # PRO 106 | [0.0, 0.0, 0.0, 0.0], # SER 107 | [0.0, 0.0, 0.0, 0.0], # THR 108 | [0.0, 0.0, 0.0, 0.0], # TRP 109 | [0.0, 1.0, 0.0, 0.0], # TYR 110 | [0.0, 0.0, 0.0, 0.0], # VAL 111 | [0.0, 0.0, 0.0, 0.0], # UNK 112 | ] 113 | 114 | # Atoms positions relative to the 8 rigid groups, defined by the pre-omega, phi, 115 | # psi and chi angles: 116 | # 0: 'backbone group', 117 | # 1: 'pre-omega-group', (empty) 118 | # 2: 'phi-group', (currently empty, because it defines only hydrogens) 119 | # 3: 'psi-group', 120 | # 4,5,6,7: 'chi1,2,3,4-group' 121 | # The atom positions are relative to the axis-end-atom of the corresponding 122 | # rotation axis. The x-axis is in direction of the rotation axis, and the y-axis 123 | # is defined such that the dihedral-angle-definiting atom (the last entry in 124 | # chi_angles_atoms above) is in the xy-plane (with a positive y-coordinate). 125 | # format: [atomname, group_idx, rel_position] 126 | rigid_group_atom_positions = { 127 | 'ALA': [ 128 | ['N', 0, (-0.525, 1.363, 0.000)], 129 | ['CA', 0, (0.000, 0.000, 0.000)], 130 | ['C', 0, (1.526, -0.000, -0.000)], 131 | ['CB', 0, (-0.529, -0.774, -1.205)], 132 | ['O', 3, (0.627, 1.062, 0.000)], 133 | ], 134 | 'ARG': [ 135 | ['N', 0, (-0.524, 1.362, -0.000)], 136 | ['CA', 0, (0.000, 0.000, 0.000)], 137 | ['C', 0, (1.525, -0.000, -0.000)], 138 | ['CB', 0, (-0.524, -0.778, -1.209)], 139 | ['O', 3, (0.626, 1.062, 0.000)], 140 | ['CG', 4, (0.616, 1.390, -0.000)], 141 | ['CD', 5, (0.564, 1.414, 0.000)], 142 | ['NE', 6, (0.539, 1.357, -0.000)], 143 | ['NH1', 7, (0.206, 2.301, 0.000)], 144 | ['NH2', 7, (2.078, 0.978, -0.000)], 145 | ['CZ', 7, (0.758, 1.093, -0.000)], 146 | ], 147 | 'ASN': [ 148 | ['N', 0, (-0.536, 1.357, 0.000)], 149 | ['CA', 0, (0.000, 0.000, 0.000)], 150 | ['C', 0, (1.526, -0.000, -0.000)], 151 | ['CB', 0, (-0.531, -0.787, -1.200)], 152 | ['O', 3, (0.625, 1.062, 0.000)], 153 | ['CG', 4, (0.584, 1.399, 0.000)], 154 | ['ND2', 5, (0.593, -1.188, 0.001)], 155 | ['OD1', 5, (0.633, 1.059, 0.000)], 156 | ], 157 | 'ASP': [ 158 | ['N', 0, (-0.525, 1.362, -0.000)], 159 | ['CA', 0, (0.000, 0.000, 0.000)], 160 | ['C', 0, (1.527, 0.000, -0.000)], 161 | ['CB', 0, (-0.526, -0.778, -1.208)], 162 | ['O', 3, (0.626, 1.062, -0.000)], 163 | ['CG', 4, (0.593, 1.398, -0.000)], 164 | ['OD1', 5, (0.610, 1.091, 0.000)], 165 | ['OD2', 5, (0.592, -1.101, -0.003)], 166 | ], 167 | 'CYS': [ 168 | ['N', 0, (-0.522, 1.362, -0.000)], 169 | ['CA', 0, (0.000, 0.000, 0.000)], 170 | ['C', 0, (1.524, 0.000, 0.000)], 171 | ['CB', 0, (-0.519, -0.773, -1.212)], 172 | ['O', 3, (0.625, 1.062, -0.000)], 173 | ['SG', 4, (0.728, 1.653, 0.000)], 174 | ], 175 | 'GLN': [ 176 | ['N', 0, (-0.526, 1.361, -0.000)], 177 | ['CA', 0, (0.000, 0.000, 0.000)], 178 | ['C', 0, (1.526, 0.000, 0.000)], 179 | ['CB', 0, (-0.525, -0.779, -1.207)], 180 | ['O', 3, (0.626, 1.062, -0.000)], 181 | ['CG', 4, (0.615, 1.393, 0.000)], 182 | ['CD', 5, (0.587, 1.399, -0.000)], 183 | ['NE2', 6, (0.593, -1.189, -0.001)], 184 | ['OE1', 6, (0.634, 1.060, 0.000)], 185 | ], 186 | 'GLU': [ 187 | ['N', 0, (-0.528, 1.361, 0.000)], 188 | ['CA', 0, (0.000, 0.000, 0.000)], 189 | ['C', 0, (1.526, -0.000, -0.000)], 190 | ['CB', 0, (-0.526, -0.781, -1.207)], 191 | ['O', 3, (0.626, 1.062, 0.000)], 192 | ['CG', 4, (0.615, 1.392, 0.000)], 193 | ['CD', 5, (0.600, 1.397, 0.000)], 194 | ['OE1', 6, (0.607, 1.095, -0.000)], 195 | ['OE2', 6, (0.589, -1.104, -0.001)], 196 | ], 197 | 'GLY': [ 198 | ['N', 0, (-0.572, 1.337, 0.000)], 199 | ['CA', 0, (0.000, 0.000, 0.000)], 200 | ['C', 0, (1.517, -0.000, -0.000)], 201 | ['O', 3, (0.626, 1.062, -0.000)], 202 | ], 203 | 'HIS': [ 204 | ['N', 0, (-0.527, 1.360, 0.000)], 205 | ['CA', 0, (0.000, 0.000, 0.000)], 206 | ['C', 0, (1.525, 0.000, 0.000)], 207 | ['CB', 0, (-0.525, -0.778, -1.208)], 208 | ['O', 3, (0.625, 1.063, 0.000)], 209 | ['CG', 4, (0.600, 1.370, -0.000)], 210 | ['CD2', 5, (0.889, -1.021, 0.003)], 211 | ['ND1', 5, (0.744, 1.160, -0.000)], 212 | ['CE1', 5, (2.030, 0.851, 0.002)], 213 | ['NE2', 5, (2.145, -0.466, 0.004)], 214 | ], 215 | 'ILE': [ 216 | ['N', 0, (-0.493, 1.373, -0.000)], 217 | ['CA', 0, (0.000, 0.000, 0.000)], 218 | ['C', 0, (1.527, -0.000, -0.000)], 219 | ['CB', 0, (-0.536, -0.793, -1.213)], 220 | ['O', 3, (0.627, 1.062, -0.000)], 221 | ['CG1', 4, (0.534, 1.437, -0.000)], 222 | ['CG2', 4, (0.540, -0.785, -1.199)], 223 | ['CD1', 5, (0.619, 1.391, 0.000)], 224 | ], 225 | 'LEU': [ 226 | ['N', 0, (-0.520, 1.363, 0.000)], 227 | ['CA', 0, (0.000, 0.000, 0.000)], 228 | ['C', 0, (1.525, -0.000, -0.000)], 229 | ['CB', 0, (-0.522, -0.773, -1.214)], 230 | ['O', 3, (0.625, 1.063, -0.000)], 231 | ['CG', 4, (0.678, 1.371, 0.000)], 232 | ['CD1', 5, (0.530, 1.430, -0.000)], 233 | ['CD2', 5, (0.535, -0.774, 1.200)], 234 | ], 235 | 'LYS': [ 236 | ['N', 0, (-0.526, 1.362, -0.000)], 237 | ['CA', 0, (0.000, 0.000, 0.000)], 238 | ['C', 0, (1.526, 0.000, 0.000)], 239 | ['CB', 0, (-0.524, -0.778, -1.208)], 240 | ['O', 3, (0.626, 1.062, -0.000)], 241 | ['CG', 4, (0.619, 1.390, 0.000)], 242 | ['CD', 5, (0.559, 1.417, 0.000)], 243 | ['CE', 6, (0.560, 1.416, 0.000)], 244 | ['NZ', 7, (0.554, 1.387, 0.000)], 245 | ], 246 | 'MET': [ 247 | ['N', 0, (-0.521, 1.364, -0.000)], 248 | ['CA', 0, (0.000, 0.000, 0.000)], 249 | ['C', 0, (1.525, 0.000, 0.000)], 250 | ['CB', 0, (-0.523, -0.776, -1.210)], 251 | ['O', 3, (0.625, 1.062, -0.000)], 252 | ['CG', 4, (0.613, 1.391, -0.000)], 253 | ['SD', 5, (0.703, 1.695, 0.000)], 254 | ['CE', 6, (0.320, 1.786, -0.000)], 255 | ], 256 | 'PHE': [ 257 | ['N', 0, (-0.518, 1.363, 0.000)], 258 | ['CA', 0, (0.000, 0.000, 0.000)], 259 | ['C', 0, (1.524, 0.000, -0.000)], 260 | ['CB', 0, (-0.525, -0.776, -1.212)], 261 | ['O', 3, (0.626, 1.062, -0.000)], 262 | ['CG', 4, (0.607, 1.377, 0.000)], 263 | ['CD1', 5, (0.709, 1.195, -0.000)], 264 | ['CD2', 5, (0.706, -1.196, 0.000)], 265 | ['CE1', 5, (2.102, 1.198, -0.000)], 266 | ['CE2', 5, (2.098, -1.201, -0.000)], 267 | ['CZ', 5, (2.794, -0.003, -0.001)], 268 | ], 269 | 'PRO': [ 270 | ['N', 0, (-0.566, 1.351, -0.000)], 271 | ['CA', 0, (0.000, 0.000, 0.000)], 272 | ['C', 0, (1.527, -0.000, 0.000)], 273 | ['CB', 0, (-0.546, -0.611, -1.293)], 274 | ['O', 3, (0.621, 1.066, 0.000)], 275 | ['CG', 4, (0.382, 1.445, 0.0)], 276 | # ['CD', 5, (0.427, 1.440, 0.0)], 277 | ['CD', 5, (0.477, 1.424, 0.0)], # manually made angle 2 degrees larger 278 | ], 279 | 'SER': [ 280 | ['N', 0, (-0.529, 1.360, -0.000)], 281 | ['CA', 0, (0.000, 0.000, 0.000)], 282 | ['C', 0, (1.525, -0.000, -0.000)], 283 | ['CB', 0, (-0.518, -0.777, -1.211)], 284 | ['O', 3, (0.626, 1.062, -0.000)], 285 | ['OG', 4, (0.503, 1.325, 0.000)], 286 | ], 287 | 'THR': [ 288 | ['N', 0, (-0.517, 1.364, 0.000)], 289 | ['CA', 0, (0.000, 0.000, 0.000)], 290 | ['C', 0, (1.526, 0.000, -0.000)], 291 | ['CB', 0, (-0.516, -0.793, -1.215)], 292 | ['O', 3, (0.626, 1.062, 0.000)], 293 | ['CG2', 4, (0.550, -0.718, -1.228)], 294 | ['OG1', 4, (0.472, 1.353, 0.000)], 295 | ], 296 | 'TRP': [ 297 | ['N', 0, (-0.521, 1.363, 0.000)], 298 | ['CA', 0, (0.000, 0.000, 0.000)], 299 | ['C', 0, (1.525, -0.000, 0.000)], 300 | ['CB', 0, (-0.523, -0.776, -1.212)], 301 | ['O', 3, (0.627, 1.062, 0.000)], 302 | ['CG', 4, (0.609, 1.370, -0.000)], 303 | ['CD1', 5, (0.824, 1.091, 0.000)], 304 | ['CD2', 5, (0.854, -1.148, -0.005)], 305 | ['CE2', 5, (2.186, -0.678, -0.007)], 306 | ['CE3', 5, (0.622, -2.530, -0.007)], 307 | ['NE1', 5, (2.140, 0.690, -0.004)], 308 | ['CH2', 5, (3.028, -2.890, -0.013)], 309 | ['CZ2', 5, (3.283, -1.543, -0.011)], 310 | ['CZ3', 5, (1.715, -3.389, -0.011)], 311 | ], 312 | 'TYR': [ 313 | ['N', 0, (-0.522, 1.362, 0.000)], 314 | ['CA', 0, (0.000, 0.000, 0.000)], 315 | ['C', 0, (1.524, -0.000, -0.000)], 316 | ['CB', 0, (-0.522, -0.776, -1.213)], 317 | ['O', 3, (0.627, 1.062, -0.000)], 318 | ['CG', 4, (0.607, 1.382, -0.000)], 319 | ['CD1', 5, (0.716, 1.195, -0.000)], 320 | ['CD2', 5, (0.713, -1.194, -0.001)], 321 | ['CE1', 5, (2.107, 1.200, -0.002)], 322 | ['CE2', 5, (2.104, -1.201, -0.003)], 323 | ['OH', 5, (4.168, -0.002, -0.005)], 324 | ['CZ', 5, (2.791, -0.001, -0.003)], 325 | ], 326 | 'VAL': [ 327 | ['N', 0, (-0.494, 1.373, -0.000)], 328 | ['CA', 0, (0.000, 0.000, 0.000)], 329 | ['C', 0, (1.527, -0.000, -0.000)], 330 | ['CB', 0, (-0.533, -0.795, -1.213)], 331 | ['O', 3, (0.627, 1.062, -0.000)], 332 | ['CG1', 4, (0.540, 1.429, -0.000)], 333 | ['CG2', 4, (0.533, -0.776, 1.203)], 334 | ], 335 | } 336 | 337 | # A list of atoms (excluding hydrogen) for each AA type. PDB naming convention. 338 | residue_atoms = { 339 | 'ALA': ['C', 'CA', 'CB', 'N', 'O'], 340 | 'ARG': ['C', 'CA', 'CB', 'CG', 'CD', 'CZ', 'N', 'NE', 'O', 'NH1', 'NH2'], 341 | 'ASP': ['C', 'CA', 'CB', 'CG', 'N', 'O', 'OD1', 'OD2'], 342 | 'ASN': ['C', 'CA', 'CB', 'CG', 'N', 'ND2', 'O', 'OD1'], 343 | 'CYS': ['C', 'CA', 'CB', 'N', 'O', 'SG'], 344 | 'GLU': ['C', 'CA', 'CB', 'CG', 'CD', 'N', 'O', 'OE1', 'OE2'], 345 | 'GLN': ['C', 'CA', 'CB', 'CG', 'CD', 'N', 'NE2', 'O', 'OE1'], 346 | 'GLY': ['C', 'CA', 'N', 'O'], 347 | 'HIS': ['C', 'CA', 'CB', 'CG', 'CD2', 'CE1', 'N', 'ND1', 'NE2', 'O'], 348 | 'ILE': ['C', 'CA', 'CB', 'CG1', 'CG2', 'CD1', 'N', 'O'], 349 | 'LEU': ['C', 'CA', 'CB', 'CG', 'CD1', 'CD2', 'N', 'O'], 350 | 'LYS': ['C', 'CA', 'CB', 'CG', 'CD', 'CE', 'N', 'NZ', 'O'], 351 | 'MET': ['C', 'CA', 'CB', 'CG', 'CE', 'N', 'O', 'SD'], 352 | 'PHE': ['C', 'CA', 'CB', 'CG', 'CD1', 'CD2', 'CE1', 'CE2', 'CZ', 'N', 'O'], 353 | 'PRO': ['C', 'CA', 'CB', 'CG', 'CD', 'N', 'O'], 354 | 'SER': ['C', 'CA', 'CB', 'N', 'O', 'OG'], 355 | 'THR': ['C', 'CA', 'CB', 'CG2', 'N', 'O', 'OG1'], 356 | 'TRP': ['C', 'CA', 'CB', 'CG', 'CD1', 'CD2', 'CE2', 'CE3', 'CZ2', 'CZ3', 357 | 'CH2', 'N', 'NE1', 'O'], 358 | 'TYR': ['C', 'CA', 'CB', 'CG', 'CD1', 'CD2', 'CE1', 'CE2', 'CZ', 'N', 'O', 359 | 'OH'], 360 | 'VAL': ['C', 'CA', 'CB', 'CG1', 'CG2', 'N', 'O'] 361 | } 362 | 363 | # Naming swaps for ambiguous atom names. 364 | # Due to symmetries in the amino acids the naming of atoms is ambiguous in 365 | # 4 of the 20 amino acids. 366 | # (The LDDT paper lists 7 amino acids as ambiguous, but the naming ambiguities 367 | # in LEU, VAL and ARG can be resolved by using the 3d constellations of 368 | # the 'ambiguous' atoms and their neighbours) 369 | residue_atom_renaming_swaps = { 370 | 'ASP': {'OD1': 'OD2'}, 371 | 'GLU': {'OE1': 'OE2'}, 372 | 'PHE': {'CD1': 'CD2', 'CE1': 'CE2'}, 373 | 'TYR': {'CD1': 'CD2', 'CE1': 'CE2'}, 374 | } 375 | 376 | # Van der Waals radii [Angstroem] of the atoms (from Wikipedia) 377 | van_der_waals_radius = { 378 | 'C': 1.7, 379 | 'N': 1.55, 380 | 'O': 1.52, 381 | 'S': 1.8, 382 | } 383 | 384 | Bond = collections.namedtuple( 385 | 'Bond', ['atom1_name', 'atom2_name', 'length', 'stddev']) 386 | BondAngle = collections.namedtuple( 387 | 'BondAngle', 388 | ['atom1_name', 'atom2_name', 'atom3name', 'angle_rad', 'stddev']) 389 | 390 | 391 | # Between-residue bond lengths for general bonds (first element) and for Proline 392 | # (second element). 393 | between_res_bond_length_c_n = [1.329, 1.341] 394 | between_res_bond_length_stddev_c_n = [0.014, 0.016] 395 | 396 | # Between-residue cos_angles. 397 | between_res_cos_angles_c_n_ca = [-0.5203, 0.0353] # degrees: 121.352 +- 2.315 398 | between_res_cos_angles_ca_c_n = [-0.4473, 0.0311] # degrees: 116.568 +- 1.995 399 | 400 | # This mapping is used when we need to store atom data in a format that requires 401 | # fixed atom data size for every residue (e.g. a numpy array). 402 | atom_types = [ 403 | 'N', 'CA', 'C', 'CB', 'O', 'CG', 'CG1', 'CG2', 'OG', 'OG1', 'SG', 'CD', 404 | 'CD1', 'CD2', 'ND1', 'ND2', 'OD1', 'OD2', 'SD', 'CE', 'CE1', 'CE2', 'CE3', 405 | 'NE', 'NE1', 'NE2', 'OE1', 'OE2', 'CH2', 'NH1', 'NH2', 'OH', 'CZ', 'CZ2', 406 | 'CZ3', 'NZ', 'OXT' 407 | ] 408 | atom_order = {atom_type: i for i, atom_type in enumerate(atom_types)} 409 | atom_type_num = len(atom_types) # := 37. 410 | 411 | # A compact atom encoding with 14 columns 412 | # pylint: disable=line-too-long 413 | # pylint: disable=bad-whitespace 414 | restype_name_to_atom14_names = { 415 | 'ALA': ['N', 'CA', 'C', 'O', 'CB', '', '', '', '', '', '', '', '', ''], 416 | 'ARG': ['N', 'CA', 'C', 'O', 'CB', 'CG', 'CD', 'NE', 'CZ', 'NH1', 'NH2', '', '', ''], 417 | 'ASN': ['N', 'CA', 'C', 'O', 'CB', 'CG', 'OD1', 'ND2', '', '', '', '', '', ''], 418 | 'ASP': ['N', 'CA', 'C', 'O', 'CB', 'CG', 'OD1', 'OD2', '', '', '', '', '', ''], 419 | 'CYS': ['N', 'CA', 'C', 'O', 'CB', 'SG', '', '', '', '', '', '', '', ''], 420 | 'GLN': ['N', 'CA', 'C', 'O', 'CB', 'CG', 'CD', 'OE1', 'NE2', '', '', '', '', ''], 421 | 'GLU': ['N', 'CA', 'C', 'O', 'CB', 'CG', 'CD', 'OE1', 'OE2', '', '', '', '', ''], 422 | 'GLY': ['N', 'CA', 'C', 'O', '', '', '', '', '', '', '', '', '', ''], 423 | 'HIS': ['N', 'CA', 'C', 'O', 'CB', 'CG', 'ND1', 'CD2', 'CE1', 'NE2', '', '', '', ''], 424 | 'ILE': ['N', 'CA', 'C', 'O', 'CB', 'CG1', 'CG2', 'CD1', '', '', '', '', '', ''], 425 | 'LEU': ['N', 'CA', 'C', 'O', 'CB', 'CG', 'CD1', 'CD2', '', '', '', '', '', ''], 426 | 'LYS': ['N', 'CA', 'C', 'O', 'CB', 'CG', 'CD', 'CE', 'NZ', '', '', '', '', ''], 427 | 'MET': ['N', 'CA', 'C', 'O', 'CB', 'CG', 'SD', 'CE', '', '', '', '', '', ''], 428 | 'PHE': ['N', 'CA', 'C', 'O', 'CB', 'CG', 'CD1', 'CD2', 'CE1', 'CE2', 'CZ', '', '', ''], 429 | 'PRO': ['N', 'CA', 'C', 'O', 'CB', 'CG', 'CD', '', '', '', '', '', '', ''], 430 | 'SER': ['N', 'CA', 'C', 'O', 'CB', 'OG', '', '', '', '', '', '', '', ''], 431 | 'THR': ['N', 'CA', 'C', 'O', 'CB', 'OG1', 'CG2', '', '', '', '', '', '', ''], 432 | 'TRP': ['N', 'CA', 'C', 'O', 'CB', 'CG', 'CD1', 'CD2', 'NE1', 'CE2', 'CE3', 'CZ2', 'CZ3', 'CH2'], 433 | 'TYR': ['N', 'CA', 'C', 'O', 'CB', 'CG', 'CD1', 'CD2', 'CE1', 'CE2', 'CZ', 'OH', '', ''], 434 | 'VAL': ['N', 'CA', 'C', 'O', 'CB', 'CG1', 'CG2', '', '', '', '', '', '', ''], 435 | 'UNK': ['', '', '', '', '', '', '', '', '', '', '', '', '', ''], 436 | 437 | } 438 | # pylint: enable=line-too-long 439 | # pylint: enable=bad-whitespace 440 | 441 | 442 | # This is the standard residue order when coding AA type as a number. 443 | # Reproduce it by taking 3-letter AA codes and sorting them alphabetically. 444 | restypes = [ 445 | 'A', 'R', 'N', 'D', 'C', 'Q', 'E', 'G', 'H', 'I', 'L', 'K', 'M', 'F', 'P', 446 | 'S', 'T', 'W', 'Y', 'V' 447 | ] 448 | restype_order = {restype: i for i, restype in enumerate(restypes)} 449 | restype_num = len(restypes) # := 20. 450 | unk_restype_index = restype_num # Catch-all index for unknown restypes. 451 | 452 | restypes_with_x = restypes + ['X'] 453 | restype_order_with_x = {restype: i for i, restype in enumerate(restypes_with_x)} 454 | 455 | 456 | restype_1to3 = { 457 | 'A': 'ALA', 458 | 'R': 'ARG', 459 | 'N': 'ASN', 460 | 'D': 'ASP', 461 | 'C': 'CYS', 462 | 'Q': 'GLN', 463 | 'E': 'GLU', 464 | 'G': 'GLY', 465 | 'H': 'HIS', 466 | 'I': 'ILE', 467 | 'L': 'LEU', 468 | 'K': 'LYS', 469 | 'M': 'MET', 470 | 'F': 'PHE', 471 | 'P': 'PRO', 472 | 'S': 'SER', 473 | 'T': 'THR', 474 | 'W': 'TRP', 475 | 'Y': 'TYR', 476 | 'V': 'VAL', 477 | } 478 | 479 | 480 | # NB: restype_3to1 differs from Bio.PDB.protein_letters_3to1 by being a simple 481 | # 1-to-1 mapping of 3 letter names to one letter names. The latter contains 482 | # many more, and less common, three letter names as keys and maps many of these 483 | # to the same one letter name (including 'X' and 'U' which we don't use here). 484 | restype_3to1 = {v: k for k, v in restype_1to3.items()} 485 | 486 | # Define a restype name for all unknown residues. 487 | unk_restype = 'UNK' 488 | 489 | resnames = [restype_1to3[r] for r in restypes] + [unk_restype] 490 | resname_to_idx = {resname: i for i, resname in enumerate(resnames)} 491 | 492 | 493 | def _make_standard_atom_mask() -> np.ndarray: 494 | """Returns [num_res_types, num_atom_types] mask array.""" 495 | # +1 to account for unknown (all 0s). 496 | mask = np.zeros([restype_num + 1, atom_type_num], dtype=int) 497 | for restype, restype_letter in enumerate(restypes): 498 | restype_name = restype_1to3[restype_letter] 499 | atom_names = residue_atoms[restype_name] 500 | for atom_name in atom_names: 501 | atom_type = atom_order[atom_name] 502 | mask[restype, atom_type] = 1 503 | return mask 504 | 505 | 506 | STANDARD_ATOM_MASK = _make_standard_atom_mask() 507 | 508 | 509 | # A one hot representation for the first and second atoms defining the axis 510 | # of rotation for each chi-angle in each residue. 511 | def chi_angle_atom(atom_index: int) -> np.ndarray: 512 | """Define chi-angle rigid groups via one-hot representations.""" 513 | chi_angles_index = {} 514 | one_hots = [] 515 | 516 | for k, v in chi_angles_atoms.items(): 517 | indices = [atom_types.index(s[atom_index]) for s in v] 518 | indices.extend([-1]*(4-len(indices))) 519 | chi_angles_index[k] = indices 520 | 521 | for r in restypes: 522 | res3 = restype_1to3[r] 523 | one_hot = np.eye(atom_type_num)[chi_angles_index[res3]] 524 | one_hots.append(one_hot) 525 | 526 | one_hots.append(np.zeros([4, atom_type_num])) # Add zeros for residue `X`. 527 | one_hot = np.stack(one_hots, axis=0) 528 | one_hot = np.transpose(one_hot, [0, 2, 1]) 529 | 530 | return one_hot 531 | 532 | chi_atom_1_one_hot = chi_angle_atom(1) 533 | chi_atom_2_one_hot = chi_angle_atom(2) 534 | 535 | # An array like chi_angles_atoms but using indices rather than names. 536 | chi_angles_atom_indices = [chi_angles_atoms[restype_1to3[r]] for r in restypes] 537 | chi_angles_atom_indices = tree.map_structure( 538 | lambda atom_name: atom_order[atom_name], chi_angles_atom_indices) 539 | chi_angles_atom_indices = np.array([ 540 | chi_atoms + ([[0, 0, 0, 0]] * (4 - len(chi_atoms))) 541 | for chi_atoms in chi_angles_atom_indices]) 542 | 543 | # Mapping from (res_name, atom_name) pairs to the atom's chi group index 544 | # and atom index within that group. 545 | chi_groups_for_atom = collections.defaultdict(list) 546 | for res_name, chi_angle_atoms_for_res in chi_angles_atoms.items(): 547 | for chi_group_i, chi_group in enumerate(chi_angle_atoms_for_res): 548 | for atom_i, atom in enumerate(chi_group): 549 | chi_groups_for_atom[(res_name, atom)].append((chi_group_i, atom_i)) 550 | chi_groups_for_atom = dict(chi_groups_for_atom) 551 | 552 | 553 | def _make_rigid_transformation_4x4(ex, ey, translation): 554 | """Create a rigid 4x4 transformation matrix from two axes and transl.""" 555 | # Normalize ex. 556 | ex_normalized = ex / np.linalg.norm(ex) 557 | 558 | # make ey perpendicular to ex 559 | ey_normalized = ey - np.dot(ey, ex_normalized) * ex_normalized 560 | ey_normalized /= np.linalg.norm(ey_normalized) 561 | 562 | # compute ez as cross product 563 | eznorm = np.cross(ex_normalized, ey_normalized) 564 | m = np.stack([ex_normalized, ey_normalized, eznorm, translation]).transpose() 565 | m = np.concatenate([m, [[0., 0., 0., 1.]]], axis=0) 566 | return m 567 | 568 | 569 | # create an array with (restype, atomtype) --> rigid_group_idx 570 | # and an array with (restype, atomtype, coord) for the atom positions 571 | # and compute affine transformation matrices (4,4) from one rigid group to the 572 | # previous group 573 | restype_atom37_to_rigid_group = np.zeros([21, 37], dtype=int) 574 | restype_atom37_mask = np.zeros([21, 37], dtype=np.float32) 575 | restype_atom37_rigid_group_positions = np.zeros([21, 37, 3], dtype=np.float32) 576 | restype_atom14_to_rigid_group = np.zeros([21, 14], dtype=int) 577 | restype_atom14_mask = np.zeros([21, 14], dtype=np.float32) 578 | restype_atom14_rigid_group_positions = np.zeros([21, 14, 3], dtype=np.float32) 579 | restype_rigid_group_default_frame = np.zeros([21, 8, 4, 4], dtype=np.float32) 580 | restype_atom14_to_atom37 = np.zeros([21, 14], dtype=int) 581 | 582 | def _make_rigid_group_constants(): 583 | """Fill the arrays above.""" 584 | for restype, restype_letter in enumerate(restypes): 585 | resname = restype_1to3[restype_letter] 586 | for atomname, group_idx, atom_position in rigid_group_atom_positions[ 587 | resname]: 588 | atomtype = atom_order[atomname] 589 | restype_atom37_to_rigid_group[restype, atomtype] = group_idx 590 | restype_atom37_mask[restype, atomtype] = 1 591 | restype_atom37_rigid_group_positions[restype, atomtype, :] = atom_position 592 | 593 | atom14idx = restype_name_to_atom14_names[resname].index(atomname) 594 | restype_atom14_to_rigid_group[restype, atom14idx] = group_idx 595 | restype_atom14_mask[restype, atom14idx] = 1 596 | restype_atom14_rigid_group_positions[restype, 597 | atom14idx, :] = atom_position 598 | 599 | for i, restype in enumerate(restype_name_to_atom14_names.keys()): 600 | for j, atomname in enumerate(restype_name_to_atom14_names[restype]): 601 | restype_atom14_to_atom37[i, j] = atom_order.get(atomname, -1) 602 | 603 | for restype, restype_letter in enumerate(restypes): 604 | resname = restype_1to3[restype_letter] 605 | atom_positions = {name: np.array(pos) for name, _, pos 606 | in rigid_group_atom_positions[resname]} 607 | 608 | # backbone to backbone is the identity transform 609 | restype_rigid_group_default_frame[restype, 0, :, :] = np.eye(4) 610 | 611 | # pre-omega-frame to backbone (currently dummy identity matrix) 612 | restype_rigid_group_default_frame[restype, 1, :, :] = np.eye(4) 613 | 614 | # phi-frame to backbone 615 | mat = _make_rigid_transformation_4x4( 616 | ex=atom_positions['N'] - atom_positions['CA'], 617 | ey=np.array([1., 0., 0.]), 618 | translation=atom_positions['N']) 619 | restype_rigid_group_default_frame[restype, 2, :, :] = mat 620 | 621 | # psi-frame to backbone 622 | mat = _make_rigid_transformation_4x4( 623 | ex=atom_positions['C'] - atom_positions['CA'], 624 | ey=atom_positions['CA'] - atom_positions['N'], 625 | translation=atom_positions['C']) 626 | restype_rigid_group_default_frame[restype, 3, :, :] = mat 627 | 628 | # chi1-frame to backbone 629 | if chi_angles_mask[restype][0]: 630 | base_atom_names = chi_angles_atoms[resname][0] 631 | base_atom_positions = [atom_positions[name] for name in base_atom_names] 632 | mat = _make_rigid_transformation_4x4( 633 | ex=base_atom_positions[2] - base_atom_positions[1], 634 | ey=base_atom_positions[0] - base_atom_positions[1], 635 | translation=base_atom_positions[2]) 636 | restype_rigid_group_default_frame[restype, 4, :, :] = mat 637 | 638 | # chi2-frame to chi1-frame 639 | # chi3-frame to chi2-frame 640 | # chi4-frame to chi3-frame 641 | # luckily all rotation axes for the next frame start at (0,0,0) of the 642 | # previous frame 643 | for chi_idx in range(1, 4): 644 | if chi_angles_mask[restype][chi_idx]: 645 | axis_end_atom_name = chi_angles_atoms[resname][chi_idx][2] 646 | axis_end_atom_position = atom_positions[axis_end_atom_name] 647 | mat = _make_rigid_transformation_4x4( 648 | ex=axis_end_atom_position, 649 | ey=np.array([-1., 0., 0.]), 650 | translation=axis_end_atom_position) 651 | restype_rigid_group_default_frame[restype, 4 + chi_idx, :, :] = mat 652 | 653 | 654 | _make_rigid_group_constants() 655 | -------------------------------------------------------------------------------- /gearbind/task.py: -------------------------------------------------------------------------------- 1 | import math 2 | from collections import defaultdict 3 | 4 | import torch 5 | from torch import nn 6 | from torch.nn import functional as F 7 | from torch.utils import data as torch_data 8 | 9 | from torchdrug import core, tasks, layers 10 | from torchdrug.layers import functional 11 | from torchdrug.core import Registry as R 12 | 13 | 14 | @R.register("tasks.BindingAffinityChange") 15 | class BindingAffinityChange(tasks.PropertyPrediction, core.Configurable): 16 | 17 | def __init__(self, model, task=(), criterion="mse", metric=("mae", "rmse"), normalization=True, 18 | graph_construction_model=None, verbose=0): 19 | super(BindingAffinityChange, self).__init__(model, task, criterion, metric, num_mlp_layer=0, 20 | normalization=normalization, num_class=1, 21 | graph_construction_model=graph_construction_model, verbose=verbose) 22 | 23 | def preprocess(self, train_set, valid_set, test_set): 24 | """ 25 | Compute the mean and derivation for each task on the training set. 26 | """ 27 | values = defaultdict(list) 28 | for sample in train_set: 29 | if not sample.get("labeled", True): 30 | continue 31 | for task in self.task: 32 | if not math.isnan(sample[task]): 33 | values[task].append(sample[task]) 34 | mean = [] 35 | std = [] 36 | weight = [] 37 | num_class = [] 38 | for task, w in self.task.items(): 39 | value = torch.tensor(values[task]) 40 | mean.append(value.float().mean()) 41 | std.append(value.float().std()) 42 | weight.append(w) 43 | if value.ndim > 1: 44 | num_class.append(value.shape[1]) 45 | elif value.dtype == torch.long: 46 | num_class.append(value.max().item() + 1) 47 | else: 48 | num_class.append(1) 49 | 50 | self.register_buffer("mean", torch.as_tensor(mean, dtype=torch.float)) 51 | self.register_buffer("std", torch.as_tensor(std, dtype=torch.float)) 52 | self.register_buffer("weight", torch.as_tensor(weight, dtype=torch.float)) 53 | self.num_class = self.num_class or num_class 54 | 55 | def predict(self, batch, all_loss=None, metric=None): 56 | if self.graph_construction_model: 57 | batch["wild_type"] = self.graph_construction_model(batch["wild_type"]) 58 | batch["mutant"] = self.graph_construction_model(batch["mutant"]) 59 | pred = self.model(batch, all_loss=all_loss, metric=metric)['ddG'] 60 | return pred 61 | 62 | 63 | @R.register("tasks.ContrastiveLearning") 64 | class ContrastiveLearning(tasks.Task, core.Configurable): 65 | 66 | def __init__(self, model, num_mlp_layer=2, graph_construction_model=None, temp=1.0, criterion="categorical"): 67 | super().__init__() 68 | self.model = model 69 | self.graph_construction_model = graph_construction_model 70 | self.temp = temp 71 | 72 | hidden_dims = [model.output_dim // 2] * (num_mlp_layer - 1) + [1] 73 | self.mlp = layers.MultiLayerPerceptron( 74 | input_dim=model.output_dim, 75 | hidden_dims=hidden_dims 76 | ) 77 | assert criterion in ["categorical", "bce"] 78 | self.criterion = criterion 79 | 80 | def forward(self, batch): 81 | all_loss = 0. 82 | metric = {} 83 | 84 | pred, target = self.predict_and_target(batch, all_loss=all_loss, metric=metric) 85 | metric.update(self.evaluate(pred, target)) 86 | 87 | if self.criterion == "categorical": 88 | all_loss -= metric["log_likelihood"] 89 | elif self.criterion == "bce": 90 | all_loss += metric["bce"] 91 | return all_loss, metric 92 | 93 | def predict(self, batch, all_loss=None, metric=None): 94 | if self.graph_construction_model: 95 | wild_type = self.graph_construction_model(batch["wild_type"]) 96 | wt_output = self.model(wild_type, wild_type.node_feature.float())["graph_feature"] 97 | mt_outputs = [] 98 | for mutant in batch["mutants"]: 99 | mutant = self.graph_construction_model(mutant) 100 | mt_output = self.model(mutant, mutant.node_feature.float())["graph_feature"] 101 | mt_outputs.append(mt_output) 102 | mt_output = torch.stack(mt_outputs, dim=1) 103 | energy = self.mlp(torch.cat([wt_output[:, None, :], mt_output], dim=1)).squeeze(-1) # (batch_size, 1 + num_mutant) 104 | return energy 105 | 106 | def target(self, batch): 107 | num_mutant = len(batch["mutants"]) 108 | return torch.cat([ 109 | torch.ones((batch["wild_type"].batch_size, 1), dtype=torch.float, device=batch["wild_type"].device), 110 | torch.zeros((batch["wild_type"].batch_size, num_mutant), dtype=torch.float, device=batch["wild_type"].device), 111 | ], dim=-1) 112 | 113 | def evaluate(self, pred, target): 114 | log_prob = torch.log_softmax(-pred / self.temp, dim=-1) # low energy -> high prob 115 | log_prob = log_prob[:, 0].mean() 116 | 117 | ranking = pred.argsort(dim=-1)[:, 0].float() + 1 118 | hits1 = (ranking <= 1).float().mean() 119 | hits5 = (ranking <= 5).float().mean() 120 | hits10 = (ranking <= 10).float().mean() 121 | mean_rank = ranking.mean() 122 | mrr = (1 / ranking).mean() 123 | # (pred[:, 0] < pred[:, 1]).float() 124 | loss_fn = nn.BCEWithLogitsLoss(reduction="none") 125 | bce = loss_fn(-pred / self.temp, target) 126 | num_mutant = pred.shape[1] - 1 127 | weight = torch.tensor([1.0] + [1.0 / num_mutant] * num_mutant, dtype=torch.float, device=bce.device) 128 | bce = (bce * weight[None, :]).mean() 129 | # print(pred) 130 | return {"log_likelihood": log_prob, 131 | "bce": bce, 132 | "hits@1": hits1, 133 | "hits@10": hits10, 134 | "hits@5": hits5, 135 | "mean_rank": mean_rank, 136 | "mrr": mrr} 137 | -------------------------------------------------------------------------------- /gearbind/util.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | import os 5 | import time 6 | import logging 7 | import argparse 8 | 9 | import yaml 10 | import jinja2 11 | from jinja2 import meta 12 | import easydict 13 | 14 | import torch 15 | from torch.utils import data as torch_data 16 | from torch import distributed as dist 17 | 18 | from torchdrug import core, utils 19 | from torchdrug.utils import comm 20 | 21 | from . import model 22 | 23 | 24 | logger = logging.getLogger(__file__) 25 | 26 | 27 | def get_root_logger(file=True): 28 | logger = logging.getLogger("") 29 | logger.setLevel(logging.INFO) 30 | format = logging.Formatter("%(asctime)-10s %(message)s", "%H:%M:%S") 31 | 32 | if file: 33 | handler = logging.FileHandler("log.txt") 34 | handler.setFormatter(format) 35 | logger.addHandler(handler) 36 | 37 | return logger 38 | 39 | 40 | def create_working_directory(cfg): 41 | file_name = "working_dir_%s.tmp" % os.environ["SLURM_JOB_ID"] 42 | world_size = comm.get_world_size() 43 | if world_size > 1 and not dist.is_initialized(): 44 | comm.init_process_group("nccl", init_method="env://") 45 | 46 | working_dir = os.path.join(os.path.expanduser(cfg.output_dir), 47 | cfg.task["class"], cfg.dataset["class"], cfg.task.model["class"], 48 | os.environ["SLURM_JOB_ID"], time.strftime("%Y-%m-%d-%H-%M-%S")) 49 | 50 | # synchronize working directory 51 | if comm.get_rank() == 0: 52 | with open(file_name, "w") as fout: 53 | fout.write(working_dir) 54 | os.makedirs(working_dir) 55 | comm.synchronize() 56 | if comm.get_rank() != 0: 57 | with open(file_name, "r") as fin: 58 | working_dir = fin.read() 59 | comm.synchronize() 60 | if comm.get_rank() == 0: 61 | os.remove(file_name) 62 | 63 | os.chdir(working_dir) 64 | return working_dir 65 | 66 | 67 | def detect_variables(cfg_file): 68 | with open(cfg_file, "r") as fin: 69 | raw = fin.read() 70 | env = jinja2.Environment() 71 | ast = env.parse(raw) 72 | vars = meta.find_undeclared_variables(ast) 73 | return vars 74 | 75 | 76 | def load_config(cfg_file, context=None): 77 | with open(cfg_file, "r") as fin: 78 | raw = fin.read() 79 | template = jinja2.Template(raw) 80 | instance = template.render(context) 81 | cfg = yaml.safe_load(instance) 82 | cfg = easydict.EasyDict(cfg) 83 | return cfg 84 | 85 | 86 | def parse_args(): 87 | parser = argparse.ArgumentParser() 88 | parser.add_argument("-c", "--config", help="yaml configuration file", required=True) 89 | parser.add_argument("-s", "--seed", help="random seed for PyTorch", type=int, default=1024) 90 | 91 | args, unparsed = parser.parse_known_args() 92 | # get dynamic arguments defined in the config file 93 | vars = detect_variables(args.config) 94 | parser = argparse.ArgumentParser() 95 | for var in vars: 96 | parser.add_argument("--%s" % var, required=True) 97 | vars = parser.parse_known_args(unparsed)[0] 98 | vars = {k: utils.literal_eval(v) for k, v in vars._get_kwargs()} 99 | 100 | return args, vars 101 | 102 | 103 | def build_solver(cfg, dataset): 104 | if hasattr(dataset, "split"): 105 | train_set, valid_set, test_set = dataset.split(**cfg.dataset.split) 106 | else: 107 | generator = torch.Generator().manual_seed(0) 108 | lengths = [int(len(dataset) * cfg.split[0]), int(len(dataset) * cfg.split[1])] 109 | lengths.append(len(dataset) - sum(lengths)) 110 | train_set, valid_set, test_set = torch_data.random_split(dataset, lengths, generator=generator) 111 | if comm.get_rank() == 0: 112 | logger.warning(dataset) 113 | logger.warning("#train: %d, #valid: %d, #test: %d" % (len(train_set), len(valid_set), len(test_set))) 114 | 115 | task = core.Configurable.load_config_dict(cfg.task) 116 | cfg.optimizer.params = task.parameters() 117 | optimizer = core.Configurable.load_config_dict(cfg.optimizer) 118 | solver = core.Engine(task, train_set, valid_set, test_set, optimizer, **cfg.engine) 119 | if "lr_ratio" in cfg: 120 | if isinstance(task.model, model.BindModel): 121 | _model = task.model 122 | else: 123 | _model = task 124 | cfg.optimizer.params = [ 125 | {'params': _model.model.parameters(), 'lr': cfg.optimizer.lr * cfg.lr_ratio}, 126 | {'params': _model.mlp.parameters(), 'lr': cfg.optimizer.lr} 127 | ] 128 | optimizer = core.Configurable.load_config_dict(cfg.optimizer) 129 | solver.optimizer = optimizer 130 | 131 | if cfg.get("checkpoint") is not None: 132 | solver.load(cfg.checkpoint) 133 | 134 | if cfg.get("model_checkpoint") is not None: 135 | if comm.get_rank() == 0: 136 | logger.warning("Load checkpoint from %s" % cfg.model_checkpoint) 137 | cfg.model_checkpoint = os.path.expanduser(cfg.model_checkpoint) 138 | model_dict = torch.load(cfg.model_checkpoint, map_location=torch.device('cpu'))['model'] 139 | model_dict = {k: v for k, v in model_dict.items() if not k.startswith("mlp")} 140 | task.model.load_state_dict(model_dict, strict=False) 141 | 142 | return solver 143 | -------------------------------------------------------------------------------- /results/GearBind_HER2_1n8z_renum.pdb_HL_C.csv: -------------------------------------------------------------------------------- 1 | pdb,BindModel_0,BindModel_1,BindModel_2,BindModel_3,BindModel_4,BindModel_mean 2 | "1n8z_HL_A_SH105A,DH110Y.pdb",-0.38453,-0.77025,0.01164,-0.2753,-0.33908,-0.3515 3 | "1n8z_HL_A_SH105T,GH108Y,GH109Y,DH110F,GH111I,FH112Y,AH114Y,YH117V.pdb",-2.5004,-2.07356,-4.10043,-4.56159,-5.33864,-3.71493 4 | "1n8z_HL_A_SH105T,WH107Y,GH108F,GH109F,DH110N,FH112W,AH114Y,MH115F,YH117V.pdb",-1.72266,-1.13322,-3.33754,-3.82852,-3.88842,-2.78207 5 | "1n8z_HL_A_SH105A,WH107Y,GH108Y,DH110Y,FH112G,AH114W,MH115F,DH116A.pdb",-0.9995,-1.32281,-1.76397,-1.63639,-1.94324,-1.53318 6 | "1n8z_HL_A_DH110W,AH114S.pdb",-1.02822,0.12607,-1.29982,-0.71548,-0.225,-0.62849 7 | "1n8z_HL_A_GH108H,DH110Y.pdb",-0.42481,-1.06507,-0.74017,-1.49847,-0.4905,-0.8438 8 | "1n8z_HL_A_SH105T,GH108L,GH109E,DH110G,GH111L,FH112S,AH114F.pdb",-1.02838,-0.52431,-1.51128,-0.68239,-0.70099,-0.88947 9 | "1n8z_HL_A_SH105T,WH107Y,DH110R,FH112A,AH114Y,MH115F,YH117V.pdb",-1.13038,-0.668,-0.28485,-0.50103,0.0261,-0.51163 10 | "1n8z_HL_A_SH105A,GH108P,GH109F,DH110Y,FH112P,AH114N,MH115Y.pdb",-1.20401,-1.14359,-0.33429,-1.43795,-1.08278,-1.04052 11 | "1n8z_HL_A_SH105A,GH108I,GH109D,DH110G,GH111Y,FH112S,AH114F.pdb",-1.06735,0.29374,-1.43981,0.12705,-0.35757,-0.48879 12 | "1n8z_HL_A_SH105T,WH107Y,GH108Y,GH109Y,DH110G,FH112P,AH114Y,MH115F.pdb",-0.50929,-0.58462,-0.98759,-2.2443,-3.1662,-1.4984 13 | "1n8z_HL_A_SH105A,WH107Y,GH109L,DH110G,GH111D,FH112W,AH114Y,MH115F,DH116A.pdb",-1.57325,-2.62768,-1.00254,-2.22304,-4.84708,-2.45472 14 | "1n8z_HL_A_SH105A,WH107Y,GH108E,GH109A,DH110Y,FH112L,AH114P,MH115F,DH116G.pdb",-1.35787,-1.33819,-1.36737,-0.4871,-0.12813,-0.93573 15 | "1n8z_HL_A_SH105A,GH108L,DH110E,FH112Y,AH114N,MH115F.pdb",-0.3859,-0.58803,-0.52319,-0.72855,-1.23825,-0.69279 16 | 1n8z_HL_A_DH110R.pdb,-0.4583,-0.39461,-0.03222,-0.49732,0.4116,-0.19417 17 | "1n8z_HL_A_SH105A,RH106N,WH107D,GH108I,GH109Y,DH110I,GH111Q,FH112G,AH114D,MH115L,DH116N,YH117R.pdb",-0.00088,0.64502,-0.65501,2.5435,-0.20214,0.4661 18 | "1n8z_HL_A_SH105A,GH108T,GH109A,DH110G,GH111Y,FH112T,AH114Y.pdb",-1.10123,0.27019,-1.8485,-0.77244,-0.71095,-0.83259 19 | "1n8z_HL_A_SH105T,GH109Y,DH110Y,FH112Y.pdb",-0.66724,-1.03808,-1.87853,-1.74739,-1.9743,-1.46111 20 | "1n8z_HL_A_SH105A,GH108W,GH109Y,DH110Y,FH112Y,AH114Y,MH115F,YH117V.pdb",-1.7528,-1.1851,-3.7663,-4.08345,-5.30299,-3.21813 21 | "1n8z_HL_A_SH105A,GH108P,DH110Y,FH112S,AH114Y,YH117V.pdb",-0.16185,-0.75766,-0.213,-0.2099,0.70405,-0.12767 22 | "1n8z_HL_A_DH110P,FH112L.pdb",0.11617,-0.37157,-0.29911,0.07425,0.02274,-0.09151 23 | "1n8z_HL_A_SH105A,GH108R.pdb",-0.19134,-0.02035,-0.00169,-0.97773,-0.54588,-0.3474 24 | "1n8z_HL_A_SH105V,WH107Y,GH108Y,FH112G,AH114Y,MH115F.pdb",-0.3822,-0.8102,-0.45481,-1.47917,-1.58712,-0.9427 25 | "1n8z_HL_A_SH105A,GH108Y,GH109Y,DH110Y,FH112Y,AH114Y,MH115F,YH117V.pdb",-1.70957,-1.5765,-3.79651,-3.84696,-5.29963,-3.24583 26 | "1n8z_HL_A_SH105A,GH108Y,GH109Y,DH110L,FH112Y,AH114Y,MH115F.pdb",-1.05834,-2.24214,-2.57194,-3.54128,-5.38985,-2.96071 27 | "1n8z_HL_A_SH105A,GH108W,GH109Y,DH110G,FH112Y,AH114Y,MH115F.pdb",-1.12974,-1.11961,-1.27772,-3.73626,-4.59637,-2.37194 28 | "1n8z_HL_A_SH105A,GH108L,GH109Y,DH110Y,FH112Y,AH114Y,MH115F.pdb",-1.57226,-1.88388,-2.41153,-3.21646,-4.97307,-2.81144 29 | "1n8z_HL_A_SH105A,GH108W,GH109Y,DH110G,FH112Y,AH114Y.pdb",-1.09771,-0.67955,-1.56516,-3.22799,-2.75025,-1.86413 30 | "1n8z_HL_A_SH105V,WH107Y,DH110W,YH113W,AH114Y,MH115F.pdb",-2.04734,-1.62906,-1.56801,-3.05571,-4.87559,-2.63514 31 | "1n8z_HL_A_SH105T,WH107Y,GH108Y,GH109Y,DH110Y,FH112S,AH114H,MH115F.pdb",-1.31091,-2.04406,-2.78148,-3.35566,-3.32871,-2.56416 32 | "1n8z_HL_A_SH105A,GH109Y,DH110S,FH112W,AH114V.pdb",-0.71517,-0.91896,-0.51217,-0.67621,-0.56041,-0.67658 33 | "1n8z_HL_A_SH105A,GH108E,DH110I,FH112G,AH114Y,MH115F,DH116V.pdb",-0.01526,-0.90513,-0.33006,-1.16633,-1.22452,-0.72826 34 | "1n8z_HL_A_SH105A,GH108Y,GH109Y,DH110G,GH111Y,FH112Y,AH114Y,MH115F,YH117V.pdb",-2.45004,-1.5981,-3.65723,-3.66855,-6.51012,-3.57681 35 | "1n8z_HL_A_SH105A,WH107Y,GH108F,GH109Y,GH111Y,FH112Y,AH114Y,MH115F,YH117F.pdb",-3.04651,-1.39111,-5.24099,-3.62358,-7.78972,-4.21838 36 | "1n8z_HL_A_SH105A,WH107Y,GH109D,DH110G,GH111Y,FH112Y,AH114Y,MH115F,DH116A.pdb",-1.39313,-0.93127,-1.49252,-1.90344,-3.68732,-1.88153 37 | "1n8z_HL_A_SH105A,WH107Y,DH110S,GH111Y,AH114Y,MH115Y,DH116S.pdb",-1.66549,-1.19956,-2.08739,-2.47452,-3.70144,-2.22568 38 | "1n8z_HL_A_SH105A,GH108Y,DH110Y,FH112G,AH114Y,MH115F.pdb",-0.4621,-1.35738,-0.88078,-2.19702,-2.02688,-1.38483 39 | "1n8z_HL_A_SH105T,WH107N,GH108Y,GH109Y,GH111Y,FH112Y,AH114Y,MH115F.pdb",-2.09245,-1.22787,-3.72467,-2.00397,-5.35402,-2.8806 40 | "1n8z_HL_A_SH105A,GH108K,DH110Y,FH112H,AH114Y.pdb",-0.72157,-0.9569,-1.54494,-1.27462,-0.19088,-0.93778 41 | "1n8z_HL_A_SH105A,GH108Y,GH109Y,DH110G,GH111H,FH112Y,AH114Y.pdb",-2.07682,-1.63257,-1.93278,-2.8436,-2.98036,-2.29322 42 | "1n8z_HL_A_SH105A,GH109Y,GH111Y,FH112Y,AH114M,YH117V.pdb",-1.69342,-0.18564,-2.91292,-1.77734,-2.82229,-1.87832 43 | "1n8z_HL_A_SH105A,WH107Y,GH108Y,DH110Y,FH112G,AH114Y,MH115F.pdb",-0.34204,-1.41646,-0.24448,-1.4502,-0.6629,-0.82322 44 | "1n8z_HL_A_SH105A,DH110P,FH112Y,MH115F,DH116V,YH117W.pdb",-0.35023,-0.12306,-0.3348,-1.0432,-2.24327,-0.81891 45 | "1n8z_HL_A_SH105A,GH108R,GH109Q,FH112A,AH114Y,MH115L.pdb",0.28605,-1.19386,0.51623,-1.60691,-1.76471,-0.75264 46 | "1n8z_HL_A_SH105A,WH107Y,GH108Y,DH110Y,FH112G,AH114W,MH115Y,YH117T.pdb",-1.04461,-0.28531,-2.08616,-2.22106,-1.52393,-1.43221 47 | "1n8z_HL_A_SH105A,GH108V,GH109Y,DH110G,GH111Y,FH112Y,AH114Y,MH115F.pdb",-2.04502,-1.1558,-2.76695,-2.87362,-3.9888,-2.56604 48 | "1n8z_HL_A_SH105A,GH108Y,GH109Y,DH110Y,FH112G,AH114Y,MH115F.pdb",-0.89259,-2.25822,-1.07453,-3.10999,-3.70201,-2.20747 49 | "1n8z_HL_A_SH105A,WH107N,GH108Y,GH109Y,GH111L,FH112Y,AH114Y,MH115F.pdb",-2.12595,-1.14463,-3.13693,-1.8885,-3.69056,-2.39731 50 | "1n8z_HL_A_SH105A,WH107Y,GH108Y,GH109Y,GH111Y,FH112Y,AH114Y,MH115F.pdb",-2.42212,-1.87779,-4.72206,-2.82586,-6.41405,-3.65238 51 | "1n8z_HL_A_SH105A,GH109Y,DH110G,FH112A,AH114Y.pdb",0.31507,-0.18732,0.51823,0.0057,0.66291,0.26292 52 | "1n8z_HL_A_SH105A,GH108Y,GH109Y,DH110Y,FH112Y,AH114Y,YH117V.pdb",-1.47816,-1.35168,-2.90755,-3.49281,-2.73348,-2.39274 53 | "1n8z_HL_A_SH105T,RH106S,WH107I,GH108F,GH109S,DH110G,FH112Y,AH114G,MH115L,YH117S.pdb",0.48757,-0.26473,0.81819,1.32591,-0.1826,0.43687 54 | "1n8z_HL_A_SH105A,GH108Y,GH109Y,DH110Y,FH112A,AH114Y,MH115F.pdb",-1.22541,-2.50061,-0.90256,-3.38552,-3.57606,-2.31803 55 | "1n8z_HL_A_SH105T,WH107Y,GH109S,DH110F,GH111H,FH112Y,AH114Y,MH115F,YH117V.pdb",-2.82002,-2.21374,-4.14307,-3.68087,-5.45518,-3.66258 56 | "1n8z_HL_A_SH105A,DH110Y,FH112Y,AH114Y,YH117V.pdb",-0.49831,-1.37283,-0.94821,-1.04242,-1.6774,-1.10783 57 | "1n8z_HL_A_SH105T,WH107F,GH108I,GH109D,DH110N,FH112P,AH114Y,MH115F.pdb",-1.29388,-1.09983,-0.60445,-0.58382,0.38365,-0.63967 58 | "1n8z_HL_A_SH105A,WH107Y,GH108L,GH109S,DH110A,GH111V,FH112Y,AH114Y,YH117H.pdb",-1.26194,-1.16888,-1.80311,-2.96495,-3.66415,-2.17261 59 | "1n8z_HL_A_SH105T,WH107Y,GH108A,GH109S,DH110G,GH111Y,MH115F.pdb",-2.11659,-0.02012,-1.49308,-0.86014,-2.5424,-1.40646 60 | "1n8z_HL_A_SH105T,RH106L,GH109L,DH110P,GH111M,FH112M,AH114V,MH115Y,DH116F,YH117F.pdb",-1.9177,-2.111,-3.19135,-1.10637,-3.89368,-2.44402 61 | "1n8z_HL_A_SH105A,GH108L,GH109Y,DH110Y,FH112L,AH114Y,MH115F,YH117V.pdb",-1.45221,-1.86451,-2.44592,-3.38513,-3.65278,-2.56011 62 | "1n8z_HL_A_SH105A,GH109E,DH110F,FH112P,AH114Y,MH115F.pdb",-1.16814,-0.57438,-0.51905,-1.40276,-1.4113,-1.01512 63 | "1n8z_HL_A_SH105A,GH108T,GH109E,DH110R,AH114S,MH115F,YH117I.pdb",-0.63334,-0.66552,-1.31892,-1.5203,-0.65988,-0.95959 64 | "1n8z_HL_A_SH105A,GH109Y,DH110Y,FH112Y,AH114Y,MH115F,YH117V.pdb",-1.67108,-1.7102,-2.38197,-2.45544,-4.96691,-2.63712 65 | "1n8z_HL_A_SH105A,WH107Y,GH108Y,DH110Y,FH112G,AH114Y.pdb",-0.63505,-1.25141,-0.97361,-1.96778,-0.45832,-1.05723 66 | "1n8z_HL_A_SH105A,RH106K,WH107F,GH108A,GH109Y,DH110Y,FH112P,AH114H,MH115F,YH117P.pdb",-1.63439,-1.39521,-1.61541,-1.48442,-1.99154,-1.62419 67 | "1n8z_HL_A_SH105A,GH108Y,DH110Y,FH112Y,AH114F,YH117V.pdb",-1.17422,-1.70025,-1.99336,-2.21934,-1.15271,-1.64798 68 | "1n8z_HL_A_SH105A,DH110G,FH112Y,AH114F.pdb",0.04469,-0.30457,-0.27754,-0.8085,-0.68327,-0.40584 69 | "1n8z_HL_A_SH105A,GH108Y,DH110F,FH112G,AH114Y,MH115F.pdb",-0.34185,-1.15126,-0.73857,-1.97721,-1.48033,-1.13785 70 | "1n8z_HL_A_SH105A,GH108L,DH110S,FH112Y,AH114W,MH115F.pdb",-0.51675,-1.66126,-1.11604,-1.05536,-2.8994,-1.44976 71 | "1n8z_HL_A_SH105A,GH108Y,GH109Y,DH110Y,FH112R,AH114Y,MH115F.pdb",-1.31575,-1.73625,-1.97069,-3.84024,-4.33153,-2.63889 72 | "1n8z_HL_A_SH105T,RH106P,WH107Y,GH108D,GH109V,DH110L,FH112S,AH114Y,MH115F,DH116R,YH117V.pdb",-0.55295,-1.61783,-1.89224,0.20062,-2.70001,-1.31248 73 | "1n8z_HL_A_SH105T,DH110Y,FH112Y.pdb",-0.16062,-0.91476,-1.55687,-0.90372,-1.29086,-0.96537 74 | "1n8z_HL_A_WH107Y,GH108Y,GH109A,DH110G,FH112W,AH114Y,MH115F.pdb",-0.38789,-1.72904,-2.14823,-2.83557,-3.87078,-2.1943 75 | "1n8z_HL_A_SH105A,GH108Y,DH110G,FH112Y,AH114Y.pdb",-0.14424,-0.88055,-1.03477,-2.45893,-1.63815,-1.23133 76 | "1n8z_HL_A_SH105T,WH107Y,DH110Y,FH112Y,AH114Y.pdb",-0.85356,-0.9591,-1.55994,-1.68543,-1.98724,-1.40906 77 | "1n8z_HL_A_SH105T,WH107Y,GH108R,DH110P,GH111Y,FH112Y,AH114Y,MH115F,YH117P.pdb",-0.71362,-0.74803,-3.34521,-2.09113,-4.20216,-2.22003 78 | "1n8z_HL_A_SH105V,GH109V,DH110G,GH111A,FH112Y,AH114N,MH115F.pdb",-0.51318,-0.21384,-0.65193,-0.63808,-1.15868,-0.63514 79 | "1n8z_HL_A_SH105T,WH107Y,GH108D,GH109Y,GH111Y,FH112Y,AH114Y,MH115F.pdb",-2.73437,-1.88674,-4.81933,-2.53188,-5.58397,-3.51126 80 | "1n8z_HL_A_SH105A,GH108Y,GH109Y,DH110Y,FH112G,AH114Y,MH115F,YH117V.pdb",-1.21786,-1.89992,-1.54921,-3.15411,-3.39334,-2.24289 81 | "1n8z_HL_A_SH105A,GH108R,GH109Y,DH110G,GH111Y,FH112Y,AH114Y.pdb",-1.59298,-0.8723,-2.77677,-2.62262,-3.15537,-2.20401 82 | "1n8z_HL_A_SH105T,GH108A,GH109F,FH112V,AH114Y.pdb",-0.64425,-0.98334,-1.4661,-1.19964,-0.43574,-0.94581 83 | "1n8z_HL_A_SH105T,WH107Y,GH108Y,GH109Y,DH110G,GH111L,FH112Y,AH114Y,YH117V.pdb",-1.4273,-0.45438,-2.59657,-2.80546,-3.53363,-2.16347 84 | "1n8z_HL_A_SH105A,GH108R,FH112G,AH114Y,MH115F.pdb",-0.08007,-0.81388,0.29534,-1.28389,-1.82745,-0.74199 85 | "1n8z_HL_A_SH105V,WH107Y,GH109F,FH112S,AH114Y,MH115F,YH117P.pdb",-1.16795,-0.62584,-0.24644,-1.66103,-0.32134,-0.80452 86 | "1n8z_HL_A_SH105A,WH107Y,GH108V,DH110L,FH112G,AH114P,MH115L,DH116G.pdb",-0.04639,-0.08673,0.27696,1.63911,1.04954,0.5665 87 | "1n8z_HL_A_SH105A,GH108Y,GH109Y,DH110Y,FH112Y,YH117V.pdb",-0.795,-1.86159,-2.29897,-2.67529,-1.13325,-1.75282 88 | "1n8z_HL_A_SH105A,GH109Y,DH110Y,FH112N,AH114Y,MH115F.pdb",-1.38204,-1.23076,-0.61846,-1.15505,-2.33237,-1.34374 89 | "1n8z_HL_A_SH105V,DH110Y,FH112Y.pdb",-0.07504,-0.6587,-1.31654,-0.8387,-0.71917,-0.72163 90 | "1n8z_HL_A_SH105A,GH108R,DH110Y,FH112S,YH117V.pdb",0.12355,-0.6333,0.60355,-0.31418,0.49354,0.05463 91 | "1n8z_HL_A_SH105A,GH108W,GH109Y,DH110G,FH112Y,AH114F,MH115F.pdb",-1.62804,-1.29611,-1.26475,-3.46744,-4.78015,-2.4873 92 | "1n8z_HL_A_SH105A,WH107Y,GH109S,DH110S,GH111Y,FH112Y,AH114Y,MH115F.pdb",-1.34374,-1.35411,-1.41736,-2.13918,-3.71408,-1.9937 93 | "1n8z_HL_A_SH105A,WH107H,GH108F,DH110V,GH111A,FH112S,AH114S,MH115F.pdb",0.5374,0.50144,1.411,0.89918,1.88421,1.04665 94 | "1n8z_HL_A_SH105A,WH107Y,DH110Y,FH112G,AH114Y,MH115F.pdb",-0.5834,-1.7243,-0.10023,-0.69776,-1.6476,-0.95066 95 | "1n8z_HL_A_SH105A,RH106K,WH107Y,GH109A,DH110T,FH112W,AH114Y,MH115F.pdb",-0.76184,-1.38613,-1.19063,-1.38301,-3.09883,-1.56409 96 | "1n8z_HL_A_SH105A,WH107Y,GH109Y,DH110Y,FH112P,AH114Y,MH115F.pdb",-1.36462,-1.67221,-1.02594,-1.36123,-1.99188,-1.48318 97 | "1n8z_HL_A_SH105T,WH107Y,GH109Y,DH110G,FH112P,AH114W,MH115F.pdb",-1.52344,-0.05997,-0.19069,-0.68008,-0.75307,-0.64145 98 | "1n8z_HL_A_SH105A,WH107Y,GH108R,DH110V,GH111W,FH112Y,AH114D,MH115F,YH117N.pdb",-1.36697,-0.96783,-2.99029,-2.20659,-4.80093,-2.46652 99 | "1n8z_HL_A_SH105A,WH107Y,GH108L,GH109Q,DH110L,FH112P,AH114Y,MH115F.pdb",-1.11027,-2.2457,-1.07059,-0.90707,-0.72999,-1.21272 100 | "1n8z_HL_A_SH105A,GH108Y,GH109Y,DH110G,GH111Y,FH112Y,AH114W,MH115F,YH117V.pdb",-2.80398,-1.84029,-3.73106,-3.29519,-6.45521,-3.62515 101 | "1n8z_HL_A_SH105A,GH108W,DH110G,FH112A,AH114Y,MH115F.pdb",-0.13737,-0.9074,-0.11633,-2.393,-1.70172,-1.05116 102 | "1n8z_HL_A_SH105A,RH106K,WH107Y,GH108L,DH110Q,GH111E,FH112A,MH115Y,DH116F,YH117S.pdb",-1.27214,-0.50889,-0.57827,-1.50513,-1.69291,-1.11147 103 | "1n8z_HL_A_SH105A,GH108D,GH109S,DH110G,FH112P,AH114Y,MH115F,YH117S.pdb",0.02627,-0.04009,-0.1756,-0.59153,-0.13814,-0.18382 104 | "1n8z_HL_A_SH105A,WH107Y,GH109S,DH110R,GH111Y,FH112Y,AH114Y,MH115F.pdb",-2.53623,-2.00498,-2.76223,-2.36877,-2.74074,-2.48259 105 | "1n8z_HL_A_SH105A,WH107Y,GH109S,DH110G,GH111Y,FH112Y,AH114Y,MH115F.pdb",-1.51967,-1.4071,-1.92966,-2.1643,-3.21107,-2.04636 106 | "1n8z_HL_A_SH105A,GH108L,GH109A,DH110G,GH111Y,FH112N,AH114Y,MH115F,YH117V.pdb",-1.80119,-0.08804,-2.20799,-1.24143,-2.69361,-1.60645 107 | "1n8z_HL_A_SH105A,WH107Y,GH108T,GH109Y,DH110F,FH112S,YH113F,AH114D,MH115F.pdb",-0.95317,-2.49586,-1.13181,-1.06211,-2.00493,-1.52958 108 | "1n8z_HL_A_SH105A,GH108L,GH109R,DH110A,GH111L,FH112G,AH114Y.pdb",-0.27047,-0.26725,-0.56713,-0.54613,-0.32764,-0.39572 109 | "1n8z_HL_A_SH105V,GH108Y,DH110Y,FH112Y,AH114Y.pdb",-1.33429,-0.9206,-2.26224,-2.73257,-1.33242,-1.71642 110 | "1n8z_HL_A_SH105A,GH108Y,GH109Y,DH110G,GH111Y,FH112A,AH114Y.pdb",-1.45834,-0.71789,-2.16683,-2.34052,-2.53847,-1.84441 111 | "1n8z_HL_A_SH105A,WH107Y,GH108W,DH110L,FH112G,AH114Y,MH115F,YH117H.pdb",-0.64735,-2.23565,-1.72965,-3.47914,-1.29966,-1.87829 112 | "1n8z_HL_A_SH105V,WH107Y,GH109F,DH110Y,FH112Y,AH114Y,MH115F.pdb",-1.84397,-2.16653,-2.21212,-2.92229,-4.08631,-2.64624 113 | "1n8z_HL_A_SH105A,GH108L,GH109A,DH110F,FH112Y.pdb",0.15448,-0.29254,-1.06953,-1.60553,0.13094,-0.53644 114 | "1n8z_HL_A_SH105A,RH106K,WH107Y,GH108I,GH109N,DH110A,GH111Y,FH112S,MH115F,DH116F,YH117D.pdb",-0.76287,-0.07617,-2.44159,0.2264,-1.30443,-0.87173 115 | "1n8z_HL_A_SH105A,WH107Y,GH108S,DH110Y,FH112L,AH114P,MH115Y,DH116A.pdb",-0.27843,-0.66576,0.54943,1.09793,0.39403,0.21944 116 | "1n8z_HL_A_SH105A,RH106K,WH107Y,GH108A,GH109Y,DH110Y,FH112D,YH113F,AH114W,MH115G,DH116S,YH117V.pdb",-0.3418,-0.79146,-0.1934,0.34075,-2.10627,-0.61844 117 | "1n8z_HL_A_SH105T,WH107Y,GH108E,GH109Y,DH110Q,GH111D,FH112Y,AH114H,MH115F.pdb",-2.03288,-1.60699,-3.72046,-1.67339,-3.65372,-2.53749 118 | "1n8z_HL_A_TH59S,SH105A,WH107Y,DH110S,GH111Y,FH112A,AH114Y,MH115F,DH116Y.pdb",-2.14562,-1.76605,-1.93779,-0.9445,-2.99194,-1.95718 119 | "1n8z_HL_A_SH105A,GH108Y,DH110Q,GH111V.pdb",-1.60639,-0.8105,-1.59716,-2.36356,-3.10541,-1.8966 120 | "1n8z_HL_A_SH105A,WH107Y,GH108Y,DH110V,FH112P,AH114S,YH117V.pdb",-0.24684,-0.15218,0.30772,0.06647,1.17967,0.23097 121 | "1n8z_HL_A_SH105A,GH109Y,DH110G,FH112Y,AH114Y,MH115F.pdb",-0.43292,-0.96169,-0.59053,-1.95993,-3.35345,-1.4597 122 | "1n8z_HL_A_SH105A,RH106S,WH107Y,GH109L,FH112Y,AH114Y,MH115F,YH117V.pdb",-0.33309,-0.7477,-1.67305,-0.87795,-3.40056,-1.40647 123 | "1n8z_HL_A_SH105A,GH108N,GH109Y,DH110Y,FH112Y,AH114Y,MH115F.pdb",-1.37556,-2.09464,-2.10406,-2.95604,-4.40902,-2.58787 124 | "1n8z_HL_A_SH105A,GH109Y,GH111Y,FH112Y.pdb",-1.81732,-0.77932,-3.47199,-1.66967,-3.04397,-2.15645 125 | "1n8z_HL_A_SH105A,WH107Y,GH108Y,GH109S,DH110Y,FH112Q,MH115F,YH117P.pdb",-0.96427,-0.24295,-1.51724,-1.69692,-1.68633,-1.22154 126 | "1n8z_HL_A_SH105A,WH107Y,DH110G,FH112R,AH114Y,MH115F.pdb",-0.18578,-0.78196,0.99017,-0.3846,-1.4076,-0.35395 127 | "1n8z_HL_A_SH105A,WH107Y,GH108W,GH109Y,DH110G,FH112Y,AH114Y,MH115F.pdb",-1.1624,-1.30706,-1.59283,-3.35241,-5.07238,-2.49742 128 | "1n8z_HL_A_SH105T,GH108L,GH109Y,DH110Y,GH111S,FH112A,AH114Y,MH115F,YH117F.pdb",-2.49705,-2.93958,-3.23706,-4.84783,-6.18334,-3.94097 129 | "1n8z_HL_A_SH105A,WH107Y,GH108A,GH109H,DH110Y,FH112P,AH114Y,MH115F,YH117F.pdb",-1.81837,-1.74668,-0.97977,-1.08116,-1.02709,-1.33062 130 | "1n8z_HL_A_SH105V,WH107Y,GH109S,GH111V,FH112Y,AH114Y,MH115F,YH117I.pdb",-2.34929,-1.08094,-3.18165,-2.96537,-5.84328,-3.08411 131 | "1n8z_HL_A_SH105A,GH108L,GH109T,DH110G,GH111L,FH112S,AH114N,MH115W.pdb",-0.9852,-0.66219,-2.22427,-0.35256,-1.05279,-1.0554 132 | "1n8z_HL_A_SH105A,GH108Y,GH109Y,DH110G,FH112Y.pdb",-0.56063,-1.22822,-0.47299,-2.36794,-2.03989,-1.33393 133 | "1n8z_HL_A_SH105A,WH107Y,GH108Y,DH110Y,FH112Y,AH114Y,MH115F,DH116H.pdb",-1.36721,-2.25412,-2.98732,-2.50624,-4.0751,-2.638 134 | "1n8z_HL_A_SH105A,GH109S,DH110I,FH112Y,MH115F,YH117H.pdb",0.03587,-0.85063,-0.69809,-1.06219,-1.5422,-0.82345 135 | "1n8z_HL_A_SH105A,DH110Y,FH112G,AH114Y,MH115F.pdb",-0.34727,-1.45609,-0.01795,-0.67872,-1.2681,-0.75363 136 | "1n8z_HL_A_SH105A,WH107Y,GH109N,DH110Y,GH111Y,FH112Y,AH114Y,MH115F.pdb",-2.67478,-1.42892,-3.5033,-1.85217,-4.69688,-2.83121 137 | "1n8z_HL_A_SH105A,GH109Y,DH110G,GH111Y,FH112S,AH114Y,MH115F,YH117V.pdb",-1.78314,-0.00888,-1.44942,-1.09594,-2.34926,-1.33733 138 | "1n8z_HL_A_SH105A,WH107Y,GH108T,GH109S,DH110V,FH112I,MH115F,DH116N.pdb",-0.56417,-0.27231,0.30623,0.53682,-0.30409,-0.0595 139 | "1n8z_HL_A_SH105A,GH108P,GH109Y,DH110G,GH111Y,FH112Y,AH114Y.pdb",-1.88944,-0.04655,-2.24994,-1.98893,-2.69728,-1.77443 140 | "1n8z_HL_A_SH105T,GH108N,GH109Y,FH112A,AH114F,MH115F.pdb",-0.6214,-1.43121,-0.91698,-1.98319,-1.96931,-1.38442 141 | "1n8z_HL_A_SH105A,WH107Y,GH108R,DH110R,AH114S,MH115F.pdb",0.27705,-1.29552,-0.4329,-0.32159,-0.35589,-0.42577 142 | "1n8z_HL_A_SH105A,GH108Y,GH109W,DH110Y,FH112A,AH114Y,MH115F.pdb",-1.64405,-2.57766,-2.29526,-3.32071,-4.59096,-2.88573 143 | "1n8z_HL_A_SH105A,GH109Y,DH110Y,FH112Y,AH114W,MH115F.pdb",-1.76606,-2.13831,-1.49175,-1.89056,-4.85981,-2.4293 144 | "1n8z_HL_A_SH105A,WH107H,GH108Y,GH109Y,DH110Y,FH112Y,AH114Y,MH115F,YH117V.pdb",-1.8733,-1.4669,-2.16351,-2.61185,-4.01512,-2.42614 145 | "1n8z_HL_A_SH105A,RH106T,WH107Y,GH108S,GH109T,DH110Y,GH111Y,FH112N,MH115F,DH116G,YH117I.pdb",-1.17518,-0.2974,-1.84442,-0.4882,-2.96251,-1.35354 146 | "1n8z_HL_A_SH105T,WH107Y,GH108L,GH109H,GH111Y,FH112Y,AH114Y,MH115F.pdb",-2.67813,-1.97925,-3.6209,-2.30172,-4.93968,-3.10393 147 | "1n8z_HL_A_SH105V,WH107Y,GH108F,GH109Y,FH112N,AH114Y,MH115F,YH117L.pdb",-2.11884,-0.61964,-1.64007,-2.31801,-3.17576,-1.97446 148 | "1n8z_HL_A_SH105A,WH107F,GH108D,DH110P,GH111F,FH112Y,MH115F,DH116A.pdb",-1.09907,-0.10312,-1.16453,-0.04661,-0.74624,-0.63191 149 | "1n8z_HL_A_SH105A,WH107Y,GH108R,DH110Y,GH111V,FH112L,AH114D,MH115F,DH116A.pdb",-1.77929,-1.87026,-1.7512,-2.05056,-3.65654,-2.22157 150 | "1n8z_HL_A_SH105A,WH107E,GH108N,GH109D,DH110G,GH111S,FH112P,YH113G,AH114S,MH115F,DH116E.pdb",0.33685,0.4367,2.00501,2.38912,2.14523,1.46258 151 | "1n8z_HL_A_SH105A,RH106V,WH107T,GH108D,GH109L,FH112L,YH113H,AH114S,MH115Y,DH116R.pdb",0.04009,0.33971,0.61911,2.13813,0.72045,0.7715 152 | "1n8z_HL_A_SH105T,WH107Y,GH108Y,GH109Y,DH110G,GH111S,FH112G,AH114F,MH115F.pdb",-1.11338,-1.98846,-1.50191,-3.21873,-3.74337,-2.31317 153 | "1n8z_HL_A_SH105A,GH108Y,DH110Y,FH112Y,YH117V.pdb",-0.70605,-1.02797,-1.54698,-1.69906,-0.15868,-1.02775 154 | "1n8z_HL_A_SH105A,GH109Y,DH110G,FH112Y,AH114Y,MH115F,YH117V.pdb",-0.80481,-0.36922,-0.92823,-2.07284,-3.2166,-1.47834 155 | "1n8z_HL_A_SH105A,WH107Y,GH108D,GH109P,DH110Y,AH114H,MH115L.pdb",-1.17813,-1.28109,-1.59141,-1.07027,-1.16877,-1.25793 156 | "1n8z_HL_A_SH105V,WH107Y,GH109Y,DH110G,GH111D,FH112Y,AH114Y,MH115F.pdb",-2.19371,-2.20716,-1.64386,-3.03976,-4.4031,-2.69752 157 | "1n8z_HL_A_SH105T,GH109Y,GH111Y,FH112W,AH114F,MH115F.pdb",-2.66347,-1.88687,-4.30526,-2.88604,-5.9773,-3.54379 158 | "1n8z_HL_A_SH105A,RH106K,WH107Y,DH110V,FH112Y.pdb",0.48426,-0.36939,-0.35411,0.09752,0.00201,-0.02794 159 | "1n8z_HL_A_SH105A,WH107Y,GH108S,GH109A,DH110Y,FH112L,AH114D,MH115F,DH116A.pdb",-1.33005,-1.74876,-1.35021,-0.052,-1.29465,-1.15513 160 | "1n8z_HL_A_SH105A,GH108W,DH110G,FH112Y,AH114Y,MH115F.pdb",-0.25388,-1.9489,-1.20672,-3.76389,-4.44904,-2.32449 161 | "1n8z_HL_A_SH105A,WH107Y,GH108L,GH109T,DH110A,GH111Y,FH112Q,AH114F,MH115F,DH116Y.pdb",-1.88216,-1.40287,-2.94708,-0.74051,-2.81372,-1.95727 162 | "1n8z_HL_A_SH105A,FH112S,AH114Y,MH115F.pdb",-0.41405,-0.88744,0.46172,-0.57312,-1.5329,-0.58916 163 | "1n8z_HL_A_SH105A,WH107Y,DH110R,FH112Y,AH114S,MH115F.pdb",-0.02664,-1.43435,-0.46538,-0.41539,-2.18583,-0.90552 164 | "1n8z_HL_A_SH105A,DH110G,FH112Y,AH114F,MH115F.pdb",-0.17333,-0.48695,0.04402,-0.71748,-2.40549,-0.74785 165 | "1n8z_HL_A_SH105A,GH109Y,GH111Y,FH112Y,AH114Y,MH115F,YH117V.pdb",-2.43557,-1.51475,-3.95607,-2.82923,-6.52249,-3.45162 166 | "1n8z_HL_A_SH105A,RH106A,WH107T,GH108Y,DH110G,GH111L,FH112G,YH113D,AH114M,MH115S,DH116S,YH117I.pdb",1.46125,1.06574,0.40368,2.99302,1.33492,1.45172 167 | "1n8z_HL_A_SH105A,WH107Y,GH109V,DH110Y,GH111P,AH114Y,MH115F.pdb",-2.22846,-3.56874,-1.95851,-3.36039,-4.37476,-3.09817 168 | "1n8z_HL_A_RH106I,GH108E,GH109R,DH110T,FH112Q,AH114S,MH115Y,DH116T,YH117S.pdb",-0.60313,-0.33001,0.04021,0.42892,-0.56395,-0.20559 169 | "1n8z_HL_A_SH105A,GH108E,GH109R,DH110Y,FH112Y,AH114V,MH115L,YH117V.pdb",-1.2443,-0.07572,-1.05487,-1.19259,-3.47948,-1.40939 170 | "1n8z_HL_A_SH105A,GH109Y,DH110G,FH112Y,AH114F,MH115F.pdb",-0.71878,-0.82409,-0.43622,-1.4727,-2.77758,-1.24587 171 | "1n8z_HL_A_SH105A,WH107Y,GH109A,DH110Y,GH111S,FH112S,AH114Y,MH115F,DH116G.pdb",-1.34172,-2.20314,-0.67151,-1.64071,-2.81763,-1.73494 172 | "1n8z_HL_A_SH105A,GH109Y,DH110G,GH111W,FH112S,AH114Y,MH115F.pdb",-1.83932,-0.40803,-1.27824,-1.3758,-3.27581,-1.63544 173 | "1n8z_HL_A_SH105A,GH108R,GH109D,DH110G,FH112Y,AH114Y,MH115F.pdb",-0.52456,-1.46901,-1.0293,-2.44282,-3.99094,-1.89133 174 | "1n8z_HL_A_SH105T,WH107Y,GH108Y,FH112Y,AH114D,MH115F.pdb",-0.75148,-0.59541,-1.94376,-1.56627,-3.59948,-1.69128 175 | "1n8z_HL_A_SH105A,WH107Y,GH108F,GH109Y,GH111H,FH112Y,AH114Y,MH115F,YH117V.pdb",-3.41799,-2.27619,-3.82883,-3.91548,-7.9542,-4.27854 176 | "1n8z_HL_A_SH105A,WH107Y,GH108Y,GH109Y,GH111Y,FH112G,AH114Y,MH115F,YH117V.pdb",-1.2726,-0.15825,-2.30036,-1.26425,-5.39273,-2.07764 177 | "1n8z_HL_A_SH105A,GH109S,DH110Y,FH112Y,AH114Y,MH115F.pdb",-0.61213,-1.98603,-1.20601,-1.20466,-3.85549,-1.77286 178 | "1n8z_HL_A_SH105A,WH107Y,GH108Y,GH109Y,DH110G,GH111V,FH112Y,AH114Y,MH115F.pdb",-2.2036,-2.85767,-2.46711,-4.20734,-6.45102,-3.63735 179 | "1n8z_HL_A_SH105A,WH107H,GH108Y,GH109D,DH110Y,FH112R,AH114Y,YH117V.pdb",-1.32552,-1.04331,-0.69704,-1.00586,1.08323,-0.5977 180 | "1n8z_HL_A_SH105A,DH110F,FH112Y,AH114Y,MH115F.pdb",-1.21351,-2.23891,-1.24246,-1.64052,-3.91566,-2.05021 181 | "1n8z_HL_A_DH110V,FH112K.pdb",0.23225,-0.22805,0.2351,0.22571,0.45739,0.18448 182 | "1n8z_HL_A_SH105A,WH107Y,DH110G,GH111Y,FH112Y,AH114Y,MH115F,YH117V.pdb",-1.18669,-0.97861,-2.91488,-2.82256,-3.89696,-2.35994 183 | "1n8z_HL_A_SH105A,GH108Y,GH109Y,DH110G,GH111S,FH112Y,AH114Y,MH115F,YH117V.pdb",-2.0347,-1.96013,-2.18464,-4.30201,-6.02843,-3.30198 184 | "1n8z_HL_A_SH105A,DH110Y,FH112Y,AH114Y,MH115F,YH117V.pdb",-1.18473,-1.79952,-2.04235,-1.49645,-3.60218,-2.02504 185 | "1n8z_HL_A_SH105A,GH108Y,GH109Y,DH110G,FH112A,AH114Y,MH115F,YH117F.pdb",-1.21906,-1.35398,-0.69681,-3.11471,-3.28713,-1.93434 186 | "1n8z_HL_A_SH105A,GH109S,DH110E,GH111A,AH114W,MH115F.pdb",-0.64168,-0.75487,-0.07961,-0.66281,-1.51253,-0.7303 187 | "1n8z_HL_A_SH105A,RH106P,GH108W,GH109S,DH110G,GH111W,FH112Y,AH114F,MH115F,YH117T.pdb",-1.73119,-0.90175,-4.078,-3.28915,-5.51364,-3.10275 188 | "1n8z_HL_A_SH105A,WH107Y,GH108P,GH109N,DH110Y,AH114M,MH115F.pdb",-0.37436,-1.50099,-0.93333,-0.5614,-1.91881,-1.05778 189 | "1n8z_HL_A_SH105A,GH108V,GH109S,DH110G,GH111A,FH112R,AH114Y,YH117V.pdb",0.8173,0.09571,1.01888,0.44015,1.5688,0.78817 190 | "1n8z_HL_A_SH105A,WH107F,DH110A,FH112G,AH114Y,MH115F.pdb",0.31433,-0.61513,1.28306,0.09401,-0.49017,0.11722 191 | "1n8z_HL_A_SH105T,WH107Y,GH108R,DH110A,GH111H,FH112G,AH114Y,MH115F.pdb",-0.72147,-1.04773,-0.66808,-0.97924,-1.39816,-0.96293 192 | "1n8z_HL_A_SH105A,GH108Y,GH109Y,DH110G,FH112S,AH114Y,MH115F.pdb",-0.71326,-1.05418,0.3047,-2.28177,-2.11611,-1.17212 193 | "1n8z_HL_A_SH105A,WH107Y,GH109D,DH110A,GH111D,MH115F,YH117P.pdb",-0.31304,0.31546,0.11033,0.52867,-0.08538,0.11121 194 | "1n8z_HL_A_SH105A,WH107Y,GH108I,GH109F,DH110G,FH112P,AH114Y,MH115F.pdb",-0.7732,-1.40153,-0.12687,-0.4358,-1.12065,-0.77161 195 | "1n8z_HL_A_GH108E,FH112K.pdb",0.05027,-0.64069,0.04253,-0.4849,0.08636,-0.18929 196 | "1n8z_HL_A_SH105A,WH107Y,GH109D,DH110Y,FH112Y,AH114Y,MH115F.pdb",-0.97121,-2.42998,-2.01563,-1.66672,-3.7207,-2.16085 197 | "1n8z_HL_A_SH105V,WH107Y,GH108P,GH109E,DH110V,GH111Y,FH112G,AH114Y,MH115F.pdb",-1.34536,-0.31593,-1.83388,-1.03126,-2.04137,-1.31356 198 | "1n8z_HL_A_SH105A,RH106N,WH107V,GH109S,DH110S,GH111L,FH112G,YH113I,MH115A,DH116L,YH117D.pdb",1.20325,1.81321,1.10942,1.57277,1.10641,1.36101 199 | "1n8z_HL_A_RH106Y,WH107P,GH108D,GH109F,DH110G,GH111Y,FH112Y,YH113V,AH114Y,MH115F,DH116A.pdb",-1.70515,-0.199,-2.11392,-1.20182,-1.60301,-1.36458 200 | "1n8z_HL_A_SH105A,RH106K,WH107Y,GH108T,GH109R,DH110G,GH111F,FH112S,AH114G,MH115F,DH116G.pdb",-0.92463,-0.39849,-1.17307,1.40228,-2.29486,-0.67776 201 | "1n8z_HL_A_SH105A,DH110S,FH112Y.pdb",0.64254,-0.55512,0.13,-0.36795,0.40958,0.05181 202 | "1n8z_HL_A_SH105A,GH109Y,DH110G,GH111Y,FH112Y,AH114S,MH115F.pdb",-1.58702,-0.38708,-1.91603,-1.61881,-3.64595,-1.83098 203 | "1n8z_HL_A_SH105A,WH107Y,GH109R,DH110N,FH112S,AH114S,MH115Y.pdb",-0.6561,-0.16042,0.57931,0.17302,1.36006,0.25917 204 | "1n8z_HL_A_SH105A,RH106K,WH107F,GH108E,GH109R,DH110G,GH111Y,FH112Y,YH113S,AH114F,MH115D,DH116F,YH117G.pdb",-0.00874,0.65581,-0.7701,0.93572,-1.39725,-0.11691 205 | "1n8z_HL_A_SH105A,GH108E,FH112S,AH114S.pdb",0.13276,-0.31285,0.9437,-0.13378,1.14911,0.35579 206 | "1n8z_HL_A_GH109V,FH112Y.pdb",0.1285,-0.50678,-0.74765,-0.55538,0.37009,-0.26224 207 | "1n8z_HL_A_SH105A,WH107Y,GH109Y,DH110G,GH111Y,FH112Y,AH114Y,MH115F.pdb",-2.11283,-1.55937,-2.74459,-2.49857,-3.97683,-2.57844 208 | "1n8z_HL_A_SH105A,GH108Y,DH110Y,FH112Y,AH114L,MH115F,YH117V.pdb",-1.5205,-1.4036,-2.90211,-2.49594,-2.87196,-2.23882 209 | "1n8z_HL_A_SH105A,WH107Y,GH108Y,GH109W,GH111Y,AH114Y,MH115F.pdb",-2.97198,-2.93281,-4.42685,-3.79699,-7.65806,-4.35734 210 | "1n8z_HL_A_SH105A,WH107Y,GH108P,DH110G,FH112I,AH114D,MH115F,YH117P.pdb",-0.10967,0.13319,0.12999,1.47385,-0.80249,0.16497 211 | "1n8z_HL_A_SH105A,WH107Y,DH110Y,FH112Y,AH114W,MH115F.pdb",-1.40521,-2.13189,-1.16912,-1.04439,-4.21606,-1.99333 212 | "1n8z_HL_A_SH105A,GH108L,GH109R,DH110G,GH111L,FH112G,AH114Y,MH115W.pdb",-0.89593,-1.11184,-1.41685,-1.3473,-1.53058,-1.2605 213 | "1n8z_HL_A_SH105A,WH107Y,GH109D,DH110S,GH111Y,FH112Y,AH114Y,MH115F.pdb",-1.78826,-1.16089,-2.70138,-2.56872,-3.02983,-2.24982 214 | "1n8z_HL_A_SH105A,WH107Y,GH109P,DH110Y,GH111Y,FH112Y.pdb",-1.43409,-0.89898,-2.95706,-1.70215,-2.23095,-1.84464 215 | "1n8z_HL_A_SH105T,WH107Y,GH108Y,DH110G,GH111Y,FH112G,AH114Y,MH115F.pdb",-1.35017,-1.19377,-2.54601,-2.51124,-3.40128,-2.20049 216 | "1n8z_HL_A_SH105A,WH107N,GH108Y,GH109Y,GH111Y,FH112Y,AH114Y,MH115L.pdb",-1.5743,-0.71603,-2.94755,-1.40262,-4.58407,-2.24492 217 | "1n8z_HL_A_SH105V,GH109R,DH110Y,FH112V,AH114Y,MH115F.pdb",-1.93609,-1.46599,-0.77324,-1.80896,-2.24084,-1.64502 218 | "1n8z_HL_A_GH108V,FH112S.pdb",0.45932,-0.30904,0.32323,0.15631,0.56942,0.23985 219 | "1n8z_HL_A_SH105A,WH107Y,DH110Y,FH112N,AH114W,MH115F,YH117T.pdb",-1.24263,-0.80175,-1.58191,-0.44679,-1.24584,-1.06378 220 | "1n8z_HL_A_SH105A,WH107G,GH109Y,DH110G,GH111Y,FH112Y,YH113T,AH114W,MH115F.pdb",-1.58356,-1.3121,-1.67899,-1.92466,-1.45314,-1.59049 221 | "1n8z_HL_A_SH105A,RH106G,WH107S,GH108S,GH109A,DH110S,FH112W,AH114H,MH115Y,DH116T,YH117T.pdb",0.52966,0.29182,0.78763,1.71313,-2.04438,0.25557 222 | "1n8z_HL_A_SH105A,WH107Y,GH109T,DH110G,GH111T,FH112Y,AH114Y,MH115F,DH116L,YH117H.pdb",-1.70447,-2.34005,-1.63489,-2.12629,-5.31957,-2.62506 223 | "1n8z_HL_A_SH105A,GH108E,DH110Y,FH112S,AH114E,MH115F,DH116A.pdb",-0.69977,-0.93774,-0.53966,-0.40973,-0.34858,-0.58709 224 | "1n8z_HL_A_SH105A,WH107Y,GH108Y,GH109Y,GH111F,FH112G,AH114Y,MH115F.pdb",-1.59237,-1.33263,-2.00267,-2.03672,-4.21306,-2.23549 225 | "1n8z_HL_A_SH105A,WH107Y,DH110L,FH112G,AH114T,MH115L,DH116A.pdb",-0.12888,0.2724,0.90604,1.2639,-0.26062,0.41057 226 | "1n8z_HL_A_SH105A,RH106Q,WH107N,GH108W,GH109D,DH110R,FH112S,AH114F,MH115Y,DH116T.pdb",-1.08427,-0.6121,-0.18742,1.13941,-0.52427,-0.25373 227 | "1n8z_HL_A_SH105A,WH107Y,GH109A,DH110R,GH111S,FH112G,MH115Y,DH116E.pdb",-0.61589,-1.58645,0.81174,-0.90398,-1.02836,-0.66459 228 | "1n8z_HL_A_SH105A,WH107N,GH108Y,GH109Y,DH110Y,FH112A,AH114Y,MH115F.pdb",-0.93664,-1.52167,-0.13433,-1.23913,-2.04625,-1.1756 229 | "1n8z_HL_A_SH105A,RH106S,WH107V,GH108D,GH109L,DH110G,AH114D,MH115F,DH116R.pdb",-0.23394,-0.41682,-0.15633,2.15864,0.30193,0.3307 230 | "1n8z_HL_A_SH105A,RH106I,WH107T,GH108F,GH109Y,DH110G,GH111Y,FH112T,YH113I,AH114V,MH115W,DH116E.pdb",-1.24207,0.4616,-1.63973,-0.15317,-1.485,-0.81167 231 | "1n8z_HL_A_SH105A,DH110Y,FH112Y,AH114W,MH115F.pdb",-1.30099,-2.37457,-1.03956,-1.17031,-4.01135,-1.97936 232 | "1n8z_HL_A_SH105A,GH108S,DH110A,GH111S.pdb",-0.33409,-1.06848,-0.085,-0.60751,-0.79042,-0.5771 233 | "1n8z_HL_A_SH105A,GH108Q,DH110R,GH111S,FH112G,AH114Y.pdb",-0.45395,-1.71582,-0.41591,-0.7174,-0.32135,-0.72489 234 | "1n8z_HL_A_SH105A,GH108L,GH109D,DH110Y,GH111F,FH112Y.pdb",-2.21072,-1.36029,-3.43513,-2.01558,-2.76976,-2.3583 235 | "1n8z_HL_A_SH105A,GH108H,GH109Y,GH111V,FH112G,YH113F,AH114Y,MH115F.pdb",-1.37529,-1.57815,-0.91399,-2.70264,-4.42603,-2.19922 236 | "1n8z_HL_A_SH105A,WH107Y,GH109Y,GH111Y,FH112Y,AH114Y,MH115F,YH117V.pdb",-2.50636,-2.03506,-4.69421,-2.88768,-5.90065,-3.60479 237 | "1n8z_HL_A_SH105A,WH107F,GH109P,DH110A,GH111Y,AH114G,MH115F,DH116Y.pdb",-1.25516,-0.37716,-0.91346,-1.41334,-1.2276,-1.03734 238 | "1n8z_HL_A_SH105A,WH107Y,GH108M,GH109R,DH110P,GH111A,AH114P,MH115F,DH116L.pdb",-1.13418,-0.28185,0.29531,0.39183,-1.21952,-0.38968 239 | "1n8z_HL_A_SH105A,GH109S,DH110G,GH111N,FH112Y,AH114E,MH115F.pdb",-0.4931,-0.28206,-0.48545,-0.08675,-1.43572,-0.55662 240 | "1n8z_HL_A_SH105A,RH106S,WH107Y,GH109S,DH110G,GH111S,FH112Y,YH113F,AH114S,MH115F,DH116P,YH117L.pdb",-0.59741,-1.71562,0.66098,0.59717,-3.13305,-0.83759 241 | "1n8z_HL_A_SH105A,WH107Y,GH109Y,DH110G,GH111A,FH112Y,AH114Y,MH115F.pdb",-1.14152,-1.46525,-0.70979,-2.09604,-3.65098,-1.81272 242 | "1n8z_HL_A_SH105T,WH107Y,GH108Y,GH109S,DH110G,GH111H,FH112Y,AH114S,MH115F.pdb",-1.45437,-1.68147,-2.73165,-2.39048,-4.39539,-2.53067 243 | "1n8z_HL_A_SH105A,WH107Y,GH111Y,FH112Y,AH114Y,MH115Y.pdb",-1.27597,-1.6785,-2.39924,-2.402,-4.1513,-2.3814 244 | "1n8z_HL_A_SH105A,WH107Y,DH110G,GH111Y,FH112Y,AH114Y,MH115Y.pdb",-1.01385,-1.16265,-1.72192,-2.36903,-3.88751,-2.03099 245 | "1n8z_HL_A_SH105T,WH107Y,GH109S,DH110F,FH112Y,MH115L,YH117S.pdb",-0.79981,0.26339,-1.18503,-1.13208,-0.83648,-0.738 246 | "1n8z_HL_A_SH105A,WH107Y,DH110L,GH111S,FH112Y,AH114S,MH115F,YH117L.pdb",-0.97473,-2.31793,-1.75375,-2.32424,-3.16649,-2.10743 247 | "1n8z_HL_A_SH105T,WH107Y,GH108F,DH110A,GH111Y,FH112W,AH114W.pdb",-1.3563,-0.43981,-3.96869,-2.54753,-1.91998,-2.04646 248 | "1n8z_HL_A_SH105A,RH106K,WH107F,GH108H,GH109W,DH110G,GH111E,FH112D,YH113W,AH114L,MH115S,YH117N.pdb",-1.38422,-0.39781,-0.61733,-0.12154,-1.34694,-0.77357 249 | "1n8z_HL_A_SH105A,RH106G,WH107S,GH108V,GH109A,DH110E,FH112W,AH114H,MH115Y,DH116R,YH117D.pdb",-0.42025,-1.19813,-0.91211,0.69116,-2.79364,-0.92659 250 | "1n8z_HL_A_SH105A,WH107Y,GH108Y,DH110S,GH111S,FH112S,AH114Y,MH115F,DH116A.pdb",-0.81077,-1.70708,-0.6354,-1.6712,-2.74357,-1.5136 251 | "1n8z_HL_A_SH105A,WH107S,GH109Y,DH110P,FH112Y,YH113G,AH114S,MH115F,DH116A.pdb",1.02149,0.28928,1.88228,0.49279,1.31493,1.00015 252 | "1n8z_HL_A_SH105A,WH107T,GH108V,GH109V,DH110G,GH111W,FH112Y,YH113G,AH114R,MH115F.pdb",-0.21017,0.18087,-1.04962,-0.59048,0.03991,-0.3259 253 | "1n8z_HL_A_SH105A,WH107N,GH108S,DH110T,FH112I,YH113W,MH115F,DH116A.pdb",0.12474,0.29616,1.11355,1.84545,0.25757,0.72749 254 | "1n8z_HL_A_SH105A,DH110T,GH111Y,FH112Y.pdb",-1.54066,-0.46593,-2.5625,-1.66117,-1.35963,-1.51798 255 | "1n8z_HL_A_SH105A,GH108P,GH109P,DH110Y,GH111Y,FH112W,YH113W,MH115F.pdb",-1.54023,-0.47199,-2.39738,-0.51161,-3.38796,-1.66183 256 | "1n8z_HL_A_SH105A,GH109N,DH110V,FH112Y,AH114V,MH115L.pdb",0.20838,0.12199,0.67653,-0.64181,-0.58459,-0.0439 257 | "1n8z_HL_A_SH105A,WH107A,DH110T,GH111S,FH112I,YH113S,AH114L,MH115G,DH116H,YH117G.pdb",0.94751,0.73096,3.42542,1.64265,1.40235,1.62978 258 | "1n8z_HL_A_SH105A,WH107Y,GH109D,DH110A,GH111F,FH112I,YH113M,AH114S,MH115F,DH116G,YH117V.pdb",-0.05673,0.88128,1.3611,1.28698,-0.29985,0.63456 259 | "1n8z_HL_A_SH105A,RH106P,GH109T,DH110Y,GH111R,FH112Y,YH113G,AH114Y,MH115F,YH117H.pdb",-1.44655,-2.44535,-1.85122,-2.17904,-3.74964,-2.33436 260 | "1n8z_HL_A_SH105A,RH106V,WH107Y,GH109P,DH110Y,FH112G,YH113F,AH114S,MH115Y,YH117S.pdb",0.38159,0.62917,-0.15474,1.5011,0.21622,0.51467 261 | "1n8z_HL_A_SH105A,GH108Y,GH109Y,DH110G,GH111T,FH112S,AH114Y,MH115F,YH117V.pdb",-1.86049,-2.12602,-1.13657,-3.39503,-3.82088,-2.4678 262 | "1n8z_HL_A_SH105V,RH106Y,WH107Y,GH108Y,GH109E,DH110A,FH112S,AH114Y,MH115F,YH117G.pdb",-0.75556,-1.23401,-1.61329,-1.59377,-2.85749,-1.61082 263 | "1n8z_HL_A_SH105A,RH106I,GH108S,GH109M,DH110Y,GH111D,FH112V,YH113G,AH114Y,MH115Y,DH116P,YH117F.pdb",-0.95751,-1.74334,-0.24736,-0.15511,-2.77023,-1.17471 264 | "1n8z_HL_A_SH105A,WH107Y,GH109L,DH110Y,FH112S,AH114Y,MH115F,DH116R.pdb",-1.18234,-2.24374,0.28381,-0.46854,-0.75937,-0.87404 265 | "1n8z_HL_A_SH105A,WH107Y,DH110S,GH111S,FH112Y,AH114Y,MH115Y.pdb",-0.86344,-2.31034,-0.62184,-1.81208,-4.23865,-1.96927 266 | "1n8z_HL_A_SH105A,GH108Y,GH109S,DH110G,GH111Y,FH112Y.pdb",-1.02762,-0.88448,-2.45211,-2.54866,-2.84059,-1.95069 267 | "1n8z_HL_A_SH105A,WH107Y,GH108L,GH109T,GH111A,FH112D,YH113F,AH114R,MH115L,DH116H.pdb",-0.22581,-0.94046,-0.09741,0.81259,-0.06019,-0.10226 268 | "1n8z_HL_A_SH105A,RH106Q,GH108Y,GH109D,DH110Y,FH112G,YH113T,AH114Y,MH115L.pdb",-0.66532,-1.64538,-0.70109,0.04845,-2.09755,-1.01218 269 | "1n8z_HL_A_SH105T,GH108R,GH109W,DH110G,GH111Y,FH112G,AH114Y,MH115F,YH117F.pdb",-1.98381,-1.96875,-3.05232,-3.4239,-5.17762,-3.12128 270 | "1n8z_HL_A_SH105A,WH107Y,GH108Y,DH110G,FH112G,AH114Y.pdb",0.02166,-0.83218,-0.65197,-1.13028,-0.00268,-0.51909 271 | "1n8z_HL_A_WH107Y,GH109R,DH110G,GH111V,FH112Y,AH114Y,MH115F.pdb",-1.46492,-2.04467,-1.23551,-2.72509,-3.68065,-2.23017 272 | "1n8z_HL_A_SH105T,WH107Y,GH108S,GH109R,DH110S,GH111Y,FH112Y,AH114G,MH115L,YH117P.pdb",-1.55915,0.7687,-1.96158,-0.53475,-3.08207,-1.27377 273 | "1n8z_HL_A_SH105A,WH107P,GH108S,GH109Y,GH111V,FH112G,YH113G,AH114D,DH116L,YH117F.pdb",0.09946,-0.18998,0.24898,0.29808,0.52271,0.19585 274 | "1n8z_HL_A_SH105A,WH107Y,GH108V,GH109T,DH110A,GH111N,FH112T,AH114S,MH115Y,YH117P.pdb",-0.98416,0.74345,-1.83351,0.43855,-0.19344,-0.36582 275 | "1n8z_HL_A_SH105A,GH109T,DH110Y,GH111T,FH112Y,YH113G,AH114Y,MH115F.pdb",-0.94681,-1.89479,-0.55174,-1.59665,-2.98601,-1.5952 276 | "1n8z_HL_A_SH105A,GH108A,GH109R,DH110G,GH111A,FH112G,AH114Y,MH115W.pdb",0.06165,-0.22611,1.24701,-0.52411,0.16915,0.14552 277 | "1n8z_HL_A_SH105A,WH107Y,GH108P,GH109S,DH110G,GH111Y,FH112Y,AH114Y,MH115F.pdb",-1.48955,-1.09533,-2.18127,-1.69381,-3.94232,-2.08045 278 | "1n8z_HL_A_SH105A,WH107Y,DH110S,GH111S,FH112Y,AH114Y,MH115F.pdb",-0.70426,-2.35132,-0.25528,-2.09148,-4.57091,-1.99465 279 | "1n8z_HL_A_SH105A,WH107Y,GH109D,DH110G,GH111T,FH112Y,AH114F,MH115F,DH116A,YH117H.pdb",-1.15392,-1.05909,-0.9172,-1.03619,-4.72516,-1.77831 280 | "1n8z_HL_A_SH105A,RH106K,WH107Y,GH108D,GH109T,DH110A,FH112S,AH114H,MH115F,YH117V.pdb",-0.78023,-0.59774,-0.68746,0.60936,-0.2793,-0.34707 281 | "1n8z_HL_A_SH105A,RH106F,WH107A,GH108D,GH109S,DH110G,GH111A,FH112Y,YH113G,AH114I,MH115W,DH116S,YH117F.pdb",0.59572,-0.4688,1.45211,1.92477,-0.56783,0.58719 282 | "1n8z_HL_A_SH105A,WH107Y,GH108D,GH109Y,DH110Y,FH112Y,AH114Y,MH115F.pdb",-1.27598,-1.40274,-2.56427,-2.97037,-4.4398,-2.53063 283 | "1n8z_HL_A_SH105A,WH107S,GH108Y,GH109A,DH110Y,GH111L,FH112Y,YH113G,AH114S,MH115W.pdb",-0.26779,0.83355,-0.86264,-0.49073,0.58141,-0.04124 284 | "1n8z_HL_A_SH105A,WH107D,DH110R,GH111S,FH112Y,AH114S,MH115F,DH116Y.pdb",-0.87932,-0.23435,-0.10139,0.18932,-0.74512,-0.35417 285 | "1n8z_HL_A_SH105T,WH107N,GH108V,GH109V,DH110N,GH111L,FH112Y,AH114S,MH115Y,YH117S.pdb",-1.18361,0.51667,-2.25306,0.84747,-0.51938,-0.51838 286 | "1n8z_HL_A_SH105A,WH107Y,GH108Y,GH109S,DH110Y,FH112G,AH114Y,MH115F.pdb",-0.81006,-1.30817,-0.81808,-2.15653,-1.62961,-1.34449 287 | "1n8z_HL_A_SH105A,WH107N,GH109Y,DH110Y,FH112G,MH115F.pdb",0.14692,-0.12553,1.71494,0.97449,0.14725,0.57161 288 | "1n8z_HL_A_SH105V,RH106L,WH107S,GH108R,GH109I,DH110V,GH111V,FH112S,AH114F,MH115Y.pdb",-1.34365,-1.37282,-0.15327,-0.0934,-2.27324,-1.04727 289 | "1n8z_HL_A_TH59S,SH105A,WH107Y,GH108Y,DH110G,GH111S,FH112M,AH114Y,MH115Y,DH116G.pdb",-1.3526,-1.94364,-1.31913,-1.59937,-2.58172,-1.75929 290 | "1n8z_HL_A_WH107I,GH108R,GH109R,DH110W,AH114Y,MH115F.pdb",-1.11757,-0.74347,-1.92237,-2.31021,-3.01618,-1.82196 291 | "1n8z_HL_A_SH105A,WH107G,GH108F,GH109V,DH110Y,GH111A,FH112G,YH113I,AH114P,MH115F.pdb",0.25345,0.06972,0.2535,0.17955,0.7167,0.29459 292 | "1n8z_HL_A_SH105A,WH107Y,GH108Y,GH109S,GH111Y,FH112S,AH114T,MH115F,DH116S.pdb",-1.4693,-0.30195,-1.96575,-0.52268,-1.87236,-1.22641 293 | "1n8z_HL_A_SH105A,GH108W,GH109Y,DH110G,FH112R,YH113N,AH114Y,MH115F,YH117I.pdb",-1.24358,-1.20473,-0.80978,-2.64087,-2.48314,-1.67642 294 | "1n8z_HL_A_SH105T,WH107S,GH109E,DH110L,GH111Y,FH112G,AH114F,MH115H,YH117M.pdb",-1.48745,0.0431,-1.6687,-0.99176,-1.19822,-1.06061 295 | "1n8z_HL_A_SH105A,GH108A,GH109T,DH110A,GH111L,FH112G,AH114Y,MH115W.pdb",-0.78292,-1.36128,-1.43376,-0.65687,-1.95423,-1.23781 296 | "1n8z_HL_A_SH105A,DH110Y,FH112W,AH114G,MH115F.pdb",-0.37112,-0.5424,-0.66645,-0.53867,-2.09403,-0.84253 297 | "1n8z_HL_A_SH105A,WH107D,DH110G,MH115Y.pdb",0.57206,0.2451,1.71085,2.13057,1.72223,1.27616 298 | "1n8z_HL_A_SH105A,WH107F,GH108S,DH110Y,FH112A,AH114D,MH115Y,DH116A.pdb",-0.99918,-1.00002,-1.12814,-0.05776,-1.21187,-0.87939 299 | "1n8z_HL_A_SH105A,WH107D,GH109Y,DH110P,GH111Q,FH112Y,YH113G,AH114G,MH115Y,DH116G.pdb",-0.633,-0.00897,-0.23811,1.04761,1.2275,0.279 300 | "1n8z_HL_A_SH105A,WH107Y,GH109R,FH112S,AH114Y,MH115F.pdb",-0.95538,-1.55286,0.4367,-0.78317,-0.11042,-0.59303 301 | "1n8z_HL_A_SH105A,RH106G,WH107Y,GH108E,DH110Y,FH112L,AH114P,MH115F,DH116A.pdb",-0.68429,-1.03277,-0.7681,1.01549,-0.10561,-0.31506 302 | "1n8z_HL_A_SH105A,RH106T,WH107Y,GH108Y,DH110P,GH111Y,FH112Y.pdb",-1.01581,-0.45759,-2.43337,-1.00752,-1.77884,-1.33863 303 | "1n8z_HL_A_SH105A,WH107S,GH108N,GH109Y,DH110Y,GH111Y,FH112G,YH113S,AH114G,MH115F,DH116A.pdb",0.34875,0.61377,0.08604,1.02503,0.51692,0.5181 304 | "1n8z_HL_A_DH110E,FH112Y,YH113H.pdb",0.62929,-0.29692,0.77034,0.13924,0.91789,0.43197 305 | "1n8z_HL_A_SH105V,WH107L,GH109D,DH110Y,FH112G.pdb",0.5802,-0.11624,0.67282,0.5574,1.38043,0.61492 306 | "1n8z_HL_A_SH105A,GH108W,GH109T,DH110P,GH111A,FH112N,AH114P,MH115F,DH116L.pdb",-1.25203,-0.75159,-1.00575,-1.69609,-2.2792,-1.39693 307 | "1n8z_HL_A_YH57D,TH59A,SH105A,WH107V,DH110R,FH112Y,AH114Y,MH115Y.pdb",0.02808,-1.15289,0.89644,0.70191,-1.0245,-0.11019 308 | "1n8z_HL_A_SH105A,WH107S,GH108H,GH109I,DH110G,GH111Y,FH112Y,YH113G,AH114Q,MH115V,DH116A,YH117L.pdb",0.10159,0.401,1.05501,0.26097,-1.13105,0.1375 309 | "1n8z_HL_A_SH105A,RH106S,WH107Y,GH108Y,GH109A,DH110P,FH112S,AH114G,MH115F,YH117P.pdb",0.34953,0.00834,-0.55492,0.68543,-0.9314,-0.0886 310 | "1n8z_HL_A_SH105A,WH107Y,GH109L,DH110N,GH111H,FH112Y,AH114V,MH115Y,DH116P.pdb",-1.95086,-1.44706,-0.92183,-1.16034,-1.48134,-1.39229 311 | "1n8z_HL_A_SH105A,WH107S,GH108Y,GH109F,DH110R,GH111F,FH112T,YH113G,AH114D,MH115F,DH116F.pdb",-1.24004,-0.38511,-1.06336,-1.36624,0.4302,-0.72491 312 | "1n8z_HL_A_SH105A,GH108W,DH110Y,FH112Y,AH114Y,MH115F,DH116A.pdb",-1.19728,-1.32835,-1.62483,-3.13657,-3.72691,-2.20279 313 | "1n8z_HL_A_WH107Y,GH108Y,GH109D,DH110Y,GH111N,FH112Y,AH114F.pdb",-2.05328,-0.71628,-4.28413,-2.60663,-3.51691,-2.63544 314 | "1n8z_HL_A_SH105A,WH107D,DH110S,GH111S,FH112S,AH114S,MH115Y,DH116S.pdb",-0.17754,-0.91235,1.98314,2.07344,0.81593,0.75652 315 | "1n8z_HL_A_SH105A,WH107T,GH108T,GH109S,DH110S,GH111I,FH112P,YH113S,AH114S,MH115F.pdb",0.0164,0.4566,1.18971,1.21154,-0.12688,0.54947 316 | "1n8z_HL_A_SH105A,WH107Y,GH108R,GH109Y,DH110G,GH111Y,FH112Y,AH114Y,YH117V.pdb",-1.99645,-0.77564,-2.71894,-2.55282,-3.03017,-2.2148 317 | "1n8z_HL_A_SH105A,WH107Y,GH109S,DH110L,GH111T,FH112Y,DH116H.pdb",-0.85244,-1.36329,-1.25222,-1.95838,-2.96246,-1.67776 318 | "1n8z_HL_A_SH105A,WH107Y,GH108Y,GH109Y,DH110L,GH111D,FH112Y,AH114Y,MH115F.pdb",-2.18453,-2.92277,-3.50187,-3.05083,-7.5539,-3.84278 319 | "1n8z_HL_A_SH105A,WH107D,GH109Y,DH110P,GH111F,FH112Y,YH113S,AH114G.pdb",-0.83975,-0.25855,-1.18331,-0.70988,-0.53366,-0.70503 320 | "1n8z_HL_A_SH105A,RH106T,WH107S,GH109S,DH110V,GH111D,FH112R,AH114D,MH115Y,DH116V.pdb",-0.19053,-0.17449,0.77255,1.35239,-0.8062,0.19075 321 | "1n8z_HL_A_SH105A,WH107Y,GH108N,GH109P,DH110F,GH111D,FH112G,YH113F,AH114Y,MH115F,YH117V.pdb",-2.1132,-1.94278,-1.02148,-1.29278,-0.67562,-1.40917 322 | "1n8z_HL_A_SH105A,WH107S,GH108S,DH110Y,GH111Y,FH112Y,AH114G,MH115F,DH116V.pdb",-1.93127,-1.34205,-2.25184,-0.87639,-2.05437,-1.69118 323 | "1n8z_HL_A_YH57D,TH59A,NH62D,SH105A,WH107E,DH110Y,FH112Y.pdb",-0.09517,-1.04641,0.4748,-0.18606,-0.40857,-0.25228 324 | "1n8z_HL_A_SH105A,WH107G,GH108Y,GH109Y,DH110Q,GH111D,FH112S,YH113Q,AH114S,MH115W,DH116G.pdb",-0.2729,-0.55799,1.0436,-0.93222,-0.34151,-0.21221 325 | "1n8z_HL_A_SH105A,WH107V,DH110Y,FH112Y,AH114S,MH115Y.pdb",0.41767,-0.85227,0.09725,0.64259,-0.4622,-0.03139 326 | "1n8z_HL_A_SH105A,RH106S,WH107S,GH109R,DH110L,GH111D,FH112L,AH114D,MH115F,DH116R,YH117L.pdb",-0.79192,-1.60236,0.12718,0.36825,-2.19515,-0.8188 327 | "1n8z_HL_A_SH105A,RH106T,WH107G,GH108Y,DH110Y,GH111L,FH112L,AH114S,MH115D,DH116H,YH117D.pdb",-0.50301,-0.91096,-1.45651,0.49592,-2.61634,-0.99818 328 | "1n8z_HL_A_SH105A,RH106T,WH107G,GH108S,DH110G,FH112G,YH113F,AH114S,MH115Y,DH116G.pdb",1.10322,1.02389,1.40366,3.05476,0.56028,1.42916 329 | "1n8z_HL_A_SH105A,RH106Q,WH107Y,GH109R,DH110G,FH112Y,YH113W,AH114Y,MH115F.pdb",-0.87121,-1.88794,-0.48198,-0.85313,-3.67645,-1.55414 330 | "1n8z_HL_A_SH105A,WH107S,GH108Y,GH109A,DH110F,GH111L,FH112Y,YH113G,AH114R.pdb",-0.52618,0.48087,-0.97013,-0.10991,1.15949,0.00683 331 | "1n8z_HL_A_SH105A,WH107Y,GH108S,GH109Y,DH110Y,FH112G,YH113G,MH115F.pdb",0.20612,-0.73962,0.96974,0.45,0.29446,0.23614 332 | "1n8z_HL_A_TH37Y,TH59S,NH62R,SH105A,WH107H,GH109S,DH110E,FH112R,AH114T,YH117V.pdb",-1.82715,-0.96518,0.65593,-0.42488,1.16525,-0.27921 333 | "1n8z_HL_A_SH105A,WH107D,GH108S,GH109P,DH110Y,GH111Y,FH112G,YH113S,AH114L,MH115Y,DH116L.pdb",-0.95734,-0.00255,-0.6349,0.25081,-0.41997,-0.35279 334 | "1n8z_HL_A_TH59A,SH105A,WH107E,DH110V,FH112Y,AH114S,MH115F,DH116A.pdb",-0.03715,-0.10265,1.10068,0.34866,-1.47874,-0.03384 335 | "1n8z_HL_A_WH107Y,GH108S,GH109Y,DH110S,FH112G,YH113H,MH115F,DH116A.pdb",0.55158,0.12814,1.04533,0.03442,-1.36223,0.07945 336 | "1n8z_HL_A_SH105A,GH108Y,DH110L,FH112S,AH114G,MH115L,DH116T.pdb",0.16203,0.16335,0.3035,-0.06282,0.2877,0.17075 337 | "1n8z_HL_A_IH30V,KH35S,DH36S,TH37S,TH59E,YH64S,WH107Y,GH108S,GH109Y,DH110Y,FH112G,MH115F.pdb",-0.23174,0.68871,0.32849,-0.36508,-1.72547,-0.26102 338 | "1n8z_HL_A_SH105A,GH108E,GH109Q,DH110A,GH111S,FH112V,YH113G,AH114S,MH115F,DH116G.pdb",0.83242,-0.90846,1.77444,0.74098,0.29642,0.54716 339 | "1n8z_HL_A_SH105A,WH107S,DH110Y,GH111Y,FH112H,AH114G,MH115F,DH116V.pdb",-2.03498,-1.10321,-1.17499,-1.42908,-0.95036,-1.33853 340 | "1n8z_HL_A_TH59S,SH105A,WH107S,GH108S,DH110Y,GH111Y,FH112S,AH114S,MH115Y.pdb",-1.50019,-0.42436,-0.60397,0.75731,0.09816,-0.33461 341 | "1n8z_HL_A_SH105A,GH108R,GH109Y,DH110G,FH112A,AH114Q,MH115F,DH116A,YH117L.pdb",0.24518,-0.76759,0.04261,-0.38113,-1.19145,-0.41048 342 | "1n8z_HL_A_GH109T,FH112V.pdb",0.39161,-0.33821,-0.02835,0.37408,0.19593,0.11901 343 | "1n8z_HL_A_SH105A,WH107D,DH110M,GH111Y,FH112R,AH114G,MH115L,DH116Y,YH117G.pdb",-1.06996,1.00693,-1.12649,0.13386,-0.18909,-0.24895 344 | "1n8z_HL_A_GH108D,FH112N.pdb",0.23321,-0.21582,-0.29926,0.13982,0.44142,0.05987 345 | "1n8z_HL_A_SH105A,WH107Y,DH110G,GH111P,FH112S,AH114R,MH115L,DH116S.pdb",0.17551,0.01949,1.46939,1.09182,0.29907,0.61106 346 | "1n8z_HL_A_SH105A,GH108S,DH110G,GH111S,FH112L,MH115L.pdb",-0.29849,-0.31746,0.24788,-0.12939,-0.35205,-0.1699 347 | "1n8z_HL_A_WH107K,AH114G.pdb",0.82673,0.3767,1.33169,0.73667,1.3233,0.91902 348 | "1n8z_HL_A_SH105A,WH107G,GH108H,GH109Y,DH110S,GH111L,FH112G,AH114S,MH115F,YH117F.pdb",-1.35624,-0.36545,-1.20012,0.23394,-0.036,-0.54478 349 | "1n8z_HL_A_WH107R,GH111Y.pdb",-0.3587,0.04882,-1.39592,-0.69911,0.14183,-0.45262 350 | "1n8z_HL_A_SH105A,WH107D,DH110I,GH111A,FH112Y,AH114Y,MH115F,DH116A.pdb",-0.45511,-0.81114,0.68192,0.02896,-1.81737,-0.47455 351 | "1n8z_HL_A_SH105A,WH107Y,DH110R,GH111S,FH112S,AH114Y,MH115F.pdb",-1.37474,-2.49987,-0.25419,-1.56315,-1.26779,-1.39195 352 | "1n8z_HL_A_WH107S,GH111Q.pdb",-0.20643,-0.44137,-1.23977,0.59884,1.17017,-0.02371 353 | "1n8z_HL_A_YH57D,TH59E,SH105A,WH107V,DH110Y,FH112Y,AH114Y,MH115Y.pdb",-0.76148,-1.49853,0.13875,-0.43135,-2.31608,-0.97374 354 | "1n8z_HL_A_SH105A,WH107D,GH109I,DH110Y,FH112Y,YH113G,AH114G,MH115F,DH116A.pdb",0.09999,0.11374,1.13371,0.62984,-0.13865,0.36773 355 | "1n8z_HL_A_SH105A,WH107D,GH108V,GH109Y,DH110V,FH112S,YH113P,AH114V,MH115F.pdb",0.17407,0.4985,0.78221,1.31166,1.47816,0.84892 356 | "1n8z_HL_A_SH105A,WH107S,GH108N,GH109N,DH110W,GH111Y,FH112S,AH114S,MH115F,DH116Q,YH117F.pdb",-0.67383,0.30806,-0.5396,1.46331,-1.72669,-0.23375 357 | "1n8z_HL_A_GH109A,YH113T.pdb",0.64847,0.4285,1.1831,0.76742,1.57864,0.92123 358 | "1n8z_HL_A_SH105A,RH106Y,WH107M,GH109S,DH110H,GH111T,FH112I,AH114S,MH115F,DH116E,YH117H.pdb",-1.29978,-1.3313,-1.69504,-2.02335,-2.39821,-1.74954 359 | "1n8z_HL_A_GH109L,FH112V.pdb",0.37863,-0.40918,-0.27143,0.39716,0.5589,0.13082 360 | "1n8z_HL_A_SH105A,WH107S,DH110G,GH111S,FH112Y,AH114Y,MH115Y.pdb",-0.07797,-1.5712,0.89313,-0.71617,-2.27957,-0.75035 361 | "1n8z_HL_A_YH113T,AH114F.pdb",0.0322,0.13295,0.31873,0.00132,0.6757,0.23218 362 | "1n8z_HL_A_SH105A,RH106T,WH107S,GH109T,DH110A,GH111S,FH112W,YH113Q,AH114H,MH115Y,DH116G,YH117V.pdb",-0.24233,-0.92646,1.42579,0.03103,-1.52292,-0.24698 363 | "1n8z_HL_A_SH105A,WH107L,GH109A,DH110S,GH111H,FH112G,AH114L,MH115Y,YH117D.pdb",-0.75992,0.24266,0.25395,0.19698,-0.30456,-0.07418 364 | "1n8z_HL_A_SH105A,WH107S,GH108T,DH110S,AH114S,MH115Y.pdb",0.70464,-0.15345,1.68104,1.63662,2.32724,1.23922 365 | "1n8z_HL_A_SH105A,WH107S,DH110Y,GH111Y,FH112T,AH114G,MH115F.pdb",-0.95655,-0.65689,-0.9644,-0.33504,0.12599,-0.55738 366 | "1n8z_HL_A_TH59S,SH105A,WH107S,GH109Y,DH110Y,GH111Y,FH112S,AH114S,MH115F.pdb",-1.67432,-1.35421,-1.40639,-0.22635,-2.32755,-1.39776 367 | "1n8z_HL_A_SH105T,WH107Y,GH108S,GH109Y,DH110Y,FH112Y,YH113H.pdb",-0.89893,-0.86088,-1.32679,-1.8478,-1.6432,-1.31552 368 | "1n8z_HL_A_SH105A,WH107D,GH108Y,GH109D,DH110F,FH112L,YH113S,AH114V,MH115G,DH116A,YH117V.pdb",0.98208,0.653,1.99006,2.47918,1.99982,1.62083 369 | "1n8z_HL_A_WH107Y,GH108S,GH109Y,DH110S,FH112G,YH113G,AH114S,MH115F.pdb",1.54724,0.17918,1.26534,1.16565,-0.55418,0.72065 370 | "1n8z_HL_A_SH105A,WH107D,DH110G,FH112V,MH115F,DH116T.pdb",1.00657,0.88038,2.29595,2.83387,1.49853,1.70306 371 | "1n8z_HL_A_SH105A,WH107Y,GH108S,GH111S,FH112Y,AH114Y,MH115Y.pdb",-0.71579,-1.33134,-1.12263,-1.02782,-3.58094,-1.5557 372 | "1n8z_HL_A_SH105A,WH107Y,GH108H,GH109Y,DH110R,GH111T,FH112I,YH113G,AH114S,MH115F,DH116G.pdb",-0.75132,-1.50067,0.08446,-0.66131,-2.24671,-1.01511 373 | "1n8z_HL_A_SH105A,RH106W,WH107A,GH108S,DH110Y,FH112G,AH114G.pdb",0.65412,0.29825,0.30753,1.0918,0.08574,0.48749 374 | "1n8z_HL_A_SH105A,WH107Y,GH108R,GH109D,DH110G,GH111Y,FH112D,AH114Y,MH115F.pdb",-1.7876,-1.05341,-1.63928,-0.98238,-3.08922,-1.71038 375 | "1n8z_HL_A_YH113Q,AH114H.pdb",0.18807,0.04698,0.68532,0.21427,0.46883,0.32069 376 | "1n8z_HL_A_YH38W,YH57D,TH59A,SH105A,WH107V,DH110R,FH112Y,AH114Y,MH115Y.pdb",-0.50072,-1.23551,0.48741,0.17721,-1.34828,-0.48398 377 | "1n8z_HL_A_SH105A,WH107D,DH110R,FH112R.pdb",0.36272,0.39696,1.11428,1.27394,2.75835,1.18125 378 | "1n8z_HL_A_SH105A,WH107Y,GH108S,DH110S,GH111S,FH112Y,AH114Y,MH115Y.pdb",-0.47207,-1.66972,-0.90333,-0.88653,-3.34674,-1.45568 379 | "1n8z_HL_A_SH105A,WH107Y,DH110S,GH111S,FH112N,AH114Y,MH115Y.pdb",-0.99747,-1.92219,0.49364,-1.01518,-1.97762,-1.08377 380 | "1n8z_HL_A_SH105A,RH106T,WH107G,GH108L,GH109S,DH110P,GH111S,FH112G,YH113S,AH114N,MH115G,DH116P.pdb",1.37113,1.09961,2.42339,3.25559,0.32749,1.69544 381 | "1n8z_HL_A_SH105V,WH107S,GH109Y,GH111Y,FH112Y,YH113S,AH114W,MH115F,DH116A.pdb",-1.45064,-0.69066,-1.83791,-1.45477,-1.80908,-1.44861 382 | "1n8z_HL_A_TH59A,SH105A,RH106S,WH107S,DH110G,GH111Y,FH112S,AH114Y,MH115Y,DH116T.pdb",-0.73276,0.89266,0.34945,1.28224,-0.67893,0.22253 383 | "1n8z_HL_A_SH105A,WH107Y,GH108S,GH109Y,DH110Y,FH112G,YH113G,AH114Y,MH115F.pdb",-0.21116,-1.38003,0.75686,-0.01579,-0.79902,-0.32983 384 | "1n8z_HL_A_SH105A,WH107S,GH108Y,DH110S,FH112S,AH114S,MH115F.pdb",0.97725,0.08973,2.12162,1.77448,1.82127,1.35687 385 | "1n8z_HL_A_SH105A,WH107G,GH108Y,GH109A,DH110Y,GH111Y,FH112V,YH113A,AH114G,MH115R,DH116E.pdb",0.08098,0.13106,0.49944,1.13737,0.99474,0.56872 386 | "1n8z_HL_A_WH107Y,GH108S,GH109Y,DH110Y,FH112G,YH113G,AH114G,MH115F.pdb",0.48698,-0.22176,1.09541,0.66819,-0.11336,0.38309 387 | "1n8z_HL_A_NH62S,SH105A,RH106S,WH107D,DH110V,GH111S,FH112S,AH114S,MH115F.pdb",0.46214,-0.44375,1.73188,2.07084,0.90878,0.94598 388 | "1n8z_HL_A_TH59A,SH105A,RH106S,WH107S,DH110S,GH111S,FH112S,AH114Y,MH115Y,DH116N.pdb",-0.19883,0.43666,2.23621,1.82268,-0.38582,0.78218 389 | "1n8z_HL_A_SH105A,WH107S,GH108R,DH110S,GH111S,FH112S,AH114M.pdb",0.52873,0.25692,1.44905,1.76348,2.89467,1.37857 390 | "1n8z_HL_A_SH105A,WH107D,GH108R,DH110V,GH111S,FH112G,AH114Y,MH115L,DH116Y.pdb",-0.2826,-0.82803,0.58221,1.05418,0.48831,0.20281 391 | "1n8z_HL_A_SH105A,WH107N,GH108Y,GH109Y,DH110G,GH111A,FH112A,AH114Y,MH115F.pdb",0.2859,-0.44134,0.61186,0.20667,-0.1788,0.09686 392 | "1n8z_HL_A_TH59S,NH62S,SH105A,RH106S,WH107S,DH110R,GH111Y,FH112Y,AH114Y,MH115Y.pdb",-1.62676,-0.29559,-2.32482,-0.70915,-2.86897,-1.56506 393 | "1n8z_HL_A_SH105A,WH107T,GH108D,GH109I,DH110I,GH111Y,FH112S,YH113G,AH114H,MH115F,DH116A.pdb",-0.51318,0.01178,-0.25393,0.64496,0.88167,0.15426 394 | "1n8z_HL_A_SH105A,WH107S,DH110S,FH112Y,AH114S,MH115Y,DH116N.pdb",0.46395,-0.3009,1.63674,1.18676,1.13879,0.82507 395 | "1n8z_HL_A_SH105A,WH107F,GH108M,DH110G,FH112Y,YH113T,AH114S,MH115S.pdb",1.19161,0.04163,1.82412,1.47379,1.32142,1.17051 396 | "1n8z_HL_A_IH30F,TH59A,SH105A,RH106S,WH107D,DH110S,GH111Y,FH112S,MH115F.pdb",-0.04017,0.63713,0.53184,1.29449,0.60896,0.60645 397 | "1n8z_HL_A_SH105A,WH107S,GH108S,DH110S,GH111S,FH112Y,AH114G,MH115F.pdb",0.53474,-0.2366,1.30695,2.05203,0.26159,0.78374 398 | "1n8z_HL_A_TH59E,NH62D,YH64S,SH105A,WH107S,DH110S,GH111S,FH112T,MH115Y.pdb",0.34122,-0.40286,2.94191,1.96251,1.65839,1.30023 399 | "1n8z_HL_A_SH105A,WH107S,DH110S,GH111S,AH114G.pdb",-0.02601,-0.87238,1.24303,0.17681,1.17685,0.33966 400 | "1n8z_HL_A_SH105A,WH107G,GH108Y,GH109Y,GH111T,FH112S,YH113Q,AH114S,MH115H,DH116A.pdb",0.46414,-0.17833,1.72543,-0.25068,-0.7558,0.20095 401 | "1n8z_HL_A_PH58S,TH59S,NH62D,SH105A,WH107S,DH110S,GH111S,FH112Y,AH114Y,MH115Y.pdb",-0.16267,-1.33989,1.25668,0.2083,-2.49275,-0.50606 402 | "1n8z_HL_A_SH105A,WH107Y,GH108S,DH110S,FH112G,YH113N,MH115F,DH116A.pdb",1.49059,0.24374,2.43418,2.79849,1.68252,1.72991 403 | "1n8z_HL_A_SH105A,WH107T,DH110S,GH111S,FH112Y,MH115Y.pdb",0.52015,-0.02625,1.28824,1.37043,0.89537,0.80959 404 | "1n8z_HL_A_TH59S,SH105A,WH107Y,GH108R,DH110S,GH111S,FH112S,AH114Y,MH115F.pdb",-1.17606,-2.10636,0.16453,-0.13939,-1.9935,-1.05016 405 | "1n8z_HL_A_SH105A,WH107H,GH108Y,GH109Y,DH110G,GH111W,FH112S,YH113S,AH114G,MH115Y.pdb",-0.33581,-0.34963,-0.05311,0.83989,-0.62187,-0.10411 406 | "1n8z_HL_A_SH105A,WH107S,GH108A,DH110I,FH112Y.pdb",1.07097,-0.5895,0.51245,0.61983,0.55209,0.43317 407 | "1n8z_HL_A_WH107Y,GH109Y,DH110S,FH112Y,YH113G,MH115F.pdb",1.11202,0.03938,0.81124,0.3375,0.49081,0.55819 408 | "1n8z_HL_A_SH105A,WH107S,DH110S,GH111Y,FH112S,AH114S,MH115F,YH117V.pdb",-0.7125,0.60435,-0.16437,1.11902,0.6874,0.30678 409 | "1n8z_HL_A_SH105A,WH107S,DH110S,GH111S,FH112Y,AH114Y,MH115Y.pdb",-0.18577,-1.91086,0.76754,-0.50604,-2.25249,-0.81753 410 | "1n8z_HL_A_KH35S,TH37Y,TH59S,NH62S,SH105A,WH107D,DH110V,FH112S,AH114S,YH117V.pdb",-1.1474,-0.66611,1.55949,1.46229,2.72071,0.7858 411 | "1n8z_HL_A_SH105A,WH107S,DH110R,GH111Y,FH112T,AH114G,MH115F.pdb",-2.24335,-0.52355,-0.53333,-0.89373,0.10526,-0.81774 412 | "1n8z_HL_A_SH105A,RH106S,WH107S,DH110S,GH111S,FH112S,AH114S,MH115Y,DH116S.pdb",0.50444,-0.17789,2.37622,2.40325,0.44895,1.111 413 | "1n8z_HL_A_TH59A,NH62D,SH105A,RH106S,WH107S,DH110S,GH111S,FH112Y,AH114Y,MH115Y.pdb",-0.30462,-0.49091,0.65864,1.09868,-2.34574,-0.27679 414 | "1n8z_HL_A_IH30V,TH59S,NH62D,SH105A,RH106S,WH107S,DH110S,GH111S,FH112Y,AH114Y,MH115Y.pdb",-0.38894,-1.46494,1.30818,-0.08065,-2.41201,-0.60767 415 | "1n8z_HL_A_SH105A,RH106S,WH107S,DH110S,GH111S,FH112S,AH114S,MH115Y,DH116Y.pdb",0.18961,-0.53945,2.03653,1.89301,-0.3687,0.6422 416 | "1n8z_HL_A_SH105A,WH107S,DH110S,FH112Y,AH114Y,MH115Y.pdb",0.04216,-0.86927,0.90606,0.24552,-0.95237,-0.12558 417 | "1n8z_HL_A_SH105A,WH107Y,GH108S,GH109S,DH110S,FH112G,YH113S,MH115F.pdb",1.14712,0.14386,2.18722,2.40308,1.04247,1.38475 418 | "1n8z_HL_A_SH105A,WH107V,DH110R,FH112Y,MH115Y.pdb",0.22013,-0.45622,1.18102,0.8669,0.88437,0.53924 419 | "1n8z_HL_A_SH105A,RH106V,WH107S,DH110S,GH111S,FH112S,AH114S,MH115Y,DH116Q.pdb",0.30167,-0.20832,2.28655,2.5199,0.77721,1.1354 420 | "1n8z_HL_A_SH105A,WH107D,DH110S,FH112Y,MH115Y.pdb",0.49613,-0.23937,1.31071,1.43953,1.33715,0.86883 421 | -------------------------------------------------------------------------------- /script/fix_pdb.py: -------------------------------------------------------------------------------- 1 | # Copyright 2021 DeepMind Technologies Limited 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | """Cleans up a PDB file using pdbfixer in preparation for OpenMM simulations. 16 | 17 | fix_pdb uses a third-party tool. We also support fixing some additional edge 18 | cases like removing chains of length one (see clean_structure). 19 | """ 20 | import io 21 | import os 22 | import pdbfixer 23 | try: 24 | # openmm >= 7.6 25 | from openmm import app 26 | from openmm.app import element 27 | from openmm.app.internal.pdbstructure import PdbStructure 28 | except ImportError: 29 | # openmm < 7.6 (requires DeepMind patch) 30 | from simtk.openmm import app 31 | from simtk.openmm.app import element 32 | from simtk.openmm.app.internal.pdbstructure import PdbStructure 33 | 34 | 35 | def fix_pdb(pdbfile, alterations_info, output_file=None, keep_water=False, pH=7.0): 36 | """Apply pdbfixer to the contents of a PDB file; return a PDB string result. 37 | 38 | 1) Replaces nonstandard residues. 39 | 2) Removes heterogens (non protein residues) including water. 40 | 3) Adds missing residues and missing atoms within existing residues. 41 | 4) Adds hydrogens assuming pH=7.0. 42 | 5) KeepIds is currently true, so the fixer must keep the existing chain and 43 | residue identifiers. This will fail for some files in wider PDB that have 44 | invalid IDs. 45 | 46 | Args: 47 | pdbfile: Input PDB file handle. 48 | alterations_info: A dict that will store details of changes made. 49 | 50 | Returns: 51 | If output_file is None, a PDB string representing the fixed structure. 52 | Otherwise, the output_file is written to and the function returns None. 53 | """ 54 | if isinstance(pdbfile, (str, bytes, os.PathLike)): 55 | with open(pdbfile, 'r') as in_handle: 56 | fixer = pdbfixer.PDBFixer(pdbfile=in_handle) 57 | elif isinstance(pdbfile, io.IOBase): 58 | fixer = pdbfixer.PDBFixer(pdbfile=pdbfile) 59 | else: 60 | raise ValueError('pdb_file must be a file handle or path') 61 | fixer.findNonstandardResidues() 62 | alterations_info['nonstandard_residues'] = fixer.nonstandardResidues 63 | fixer.replaceNonstandardResidues() 64 | _remove_heterogens(fixer, alterations_info, keep_water=keep_water) 65 | fixer.findMissingResidues() 66 | alterations_info['missing_residues'] = fixer.missingResidues 67 | fixer.findMissingAtoms() 68 | alterations_info['missing_heavy_atoms'] = fixer.missingAtoms 69 | alterations_info['missing_terminals'] = fixer.missingTerminals 70 | fixer.addMissingAtoms(seed=0) 71 | fixer.addMissingHydrogens(pH) 72 | 73 | tmp_handle = io.StringIO() 74 | app.PDBFile.writeFile(fixer.topology, fixer.positions, tmp_handle, keepIds=True) 75 | tmp_handle.seek(0) 76 | 77 | pdb_structure = PdbStructure(tmp_handle) 78 | _clean_structure(pdb_structure, alterations_info) 79 | 80 | if output_file is None: 81 | out_handle = io.StringIO() 82 | app.PDBFile.writeFile(fixer.topology, fixer.positions, out_handle, keepIds=True) 83 | return out_handle.getvalue() 84 | elif isinstance(output_file, (str, bytes, os.PathLike)): 85 | with open(output_file, 'w') as out_handle: 86 | app.PDBFile.writeFile(fixer.topology, fixer.positions, out_handle, keepIds=True) 87 | elif isinstance(output_file, io.IOBase): 88 | app.PDBFile.writeFile(fixer.topology, fixer.positions, output_file, keepIds=True) 89 | else: 90 | raise ValueError('output_file must be a file handle, a path or None') 91 | 92 | 93 | def _clean_structure(pdb_structure, alterations_info): 94 | """Applies additional fixes to an OpenMM structure, to handle edge cases. 95 | 96 | Args: 97 | pdb_structure: An OpenMM structure to modify and fix. 98 | alterations_info: A dict that will store details of changes made. 99 | """ 100 | _replace_met_se(pdb_structure, alterations_info) 101 | _remove_chains_of_length_one(pdb_structure, alterations_info) 102 | 103 | 104 | def _remove_heterogens(fixer, alterations_info, keep_water): 105 | """Removes the residues that Pdbfixer considers to be heterogens. 106 | 107 | Args: 108 | fixer: A Pdbfixer instance. 109 | alterations_info: A dict that will store details of changes made. 110 | keep_water: If True, water (HOH) is not considered to be a heterogen. 111 | """ 112 | initial_resnames = set() 113 | for chain in fixer.topology.chains(): 114 | for residue in chain.residues(): 115 | initial_resnames.add(residue.name) 116 | fixer.removeHeterogens(keepWater=keep_water) 117 | final_resnames = set() 118 | for chain in fixer.topology.chains(): 119 | for residue in chain.residues(): 120 | final_resnames.add(residue.name) 121 | alterations_info['removed_heterogens'] = ( 122 | initial_resnames.difference(final_resnames)) 123 | 124 | 125 | def _replace_met_se(pdb_structure, alterations_info): 126 | """Replace the Se in any MET residues that were not marked as modified.""" 127 | modified_met_residues = [] 128 | for res in pdb_structure.iter_residues(): 129 | name = res.get_name_with_spaces().strip() 130 | if name == 'MET': 131 | s_atom = res.get_atom('SD') 132 | if s_atom.element_symbol == 'Se': 133 | s_atom.element_symbol = 'S' 134 | s_atom.element = element.get_by_symbol('S') 135 | modified_met_residues.append(s_atom.residue_number) 136 | alterations_info['Se_in_MET'] = modified_met_residues 137 | 138 | 139 | def _remove_chains_of_length_one(pdb_structure, alterations_info): 140 | """Removes chains that correspond to a single amino acid. 141 | 142 | A single amino acid in a chain is both N and C terminus. There is no force 143 | template for this case. 144 | 145 | Args: 146 | pdb_structure: An OpenMM pdb_structure to modify and fix. 147 | alterations_info: A dict that will store details of changes made. 148 | """ 149 | removed_chains = {} 150 | for model in pdb_structure.iter_models(): 151 | valid_chains = [c for c in model.iter_chains() if len(c) > 1] 152 | invalid_chain_ids = [c.chain_id for c in model.iter_chains() if len(c) <= 1] 153 | model.chains = valid_chains 154 | for chain_id in invalid_chain_ids: 155 | model.chains_by_id.pop(chain_id) 156 | removed_chains[model.number] = invalid_chain_ids 157 | alterations_info['removed_chains'] = removed_chains 158 | -------------------------------------------------------------------------------- /script/predict.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | import math 4 | import pprint 5 | import pickle 6 | 7 | from tqdm import tqdm 8 | 9 | import numpy as np 10 | 11 | import torch 12 | 13 | from torchdrug import core, models, data, utils 14 | from torchdrug.utils import comm 15 | 16 | sys.path.append(os.path.dirname(os.path.dirname(__file__))) 17 | from gearbind import dataset, layer, model, task, util 18 | 19 | 20 | def dump(cfg, dataset, solver): 21 | dataloader = data.DataLoader(dataset, solver.batch_size, shuffle=False, num_workers=0) 22 | device = torch.device(solver.gpus[0]) 23 | solver.model.eval() 24 | preds = [] 25 | for batch in tqdm(dataloader): 26 | batch = utils.cuda(batch, device=device) 27 | with torch.no_grad(): 28 | output = solver.model.predict(batch) 29 | preds.append(output.detach().cpu().numpy()) 30 | pred = np.concatenate(preds, axis=0) 31 | return pred 32 | 33 | 34 | def test(cfg, dataset): 35 | if "checkpoints" in cfg: 36 | preds = [] 37 | for i in range(len(cfg.checkpoints)): 38 | cfg.checkpoint = cfg.checkpoints[i] 39 | solver = util.build_solver(cfg, dataset) 40 | pred = dump(cfg, solver.test_set, solver) 41 | preds.append(pred) 42 | pred = np.stack(preds, axis=0) 43 | 44 | test_split = cfg.dataset.split.test_set 45 | pdb_files = [pdb_file for pdb_file in dataset.pdb_files] 46 | 47 | if cfg.task.model["class"] == "BindModel": 48 | model_class = "GearBind" 49 | elif cfg.task.model["class"] == "DDGPredictor": 50 | model_class = "BindDDG" 51 | with open("%s_%s_%s.csv" % (model_class, cfg.dataset["class"], test_split), "w") as fout: 52 | model_name = cfg.task.model["class"] 53 | fout.write("pdb,%s\n" % ( 54 | ",".join([ 55 | "%s_%d" % (model_name, i) for i in range(len(cfg.checkpoints)) 56 | ] + ["%s_mean" % model_name] 57 | ))) 58 | for i in range(pred.shape[1]): 59 | fout.write('"%s",%s\n' % (pdb_files[i], ( 60 | ",".join([ 61 | "%.5f" % pred[j, i] for j in range(pred.shape[0]) 62 | ] + ["%.5f" % pred[:, i].mean(axis=0)] 63 | )))) 64 | 65 | 66 | if __name__ == "__main__": 67 | args, vars = util.parse_args() 68 | cfg = util.load_config(args.config, context=vars) 69 | 70 | torch.manual_seed(args.seed + comm.get_rank()) 71 | 72 | logger = util.get_root_logger() 73 | if comm.get_rank() == 0: 74 | logger.warning("Config file: %s" % args.config) 75 | logger.warning(pprint.pformat(cfg)) 76 | 77 | dataset = core.Configurable.load_config_dict(cfg.dataset) 78 | if "test_sets" in cfg.dataset.split: 79 | test_sets = cfg.dataset.split.pop("test_sets") 80 | for test_set in test_sets: 81 | cfg.dataset.split.test_set = test_set 82 | test(cfg, dataset) 83 | else: 84 | test(cfg, dataset) 85 | -------------------------------------------------------------------------------- /script/process_skempi.py: -------------------------------------------------------------------------------- 1 | import argparse 2 | import subprocess 3 | import requests 4 | import tarfile 5 | import tempfile 6 | import pandas as pd 7 | import numpy as np 8 | 9 | from functools import partial 10 | from pathlib import Path 11 | from tqdm import tqdm 12 | import multiprocessing as mp 13 | 14 | from fix_pdb import fix_pdb 15 | 16 | 17 | MAX_DDG_STD = 1 18 | FOLD2PDBS = [['1AO7_ABC_DE', '1B3S_A_D', '1E50_A_B', '1F5R_A_I', '1FC2_C_D', '1FR2_A_B', '1GL0_E_I', '1H9D_A_B', '1JTD_A_B', '1K8R_A_B', '1KNE_A_P', '1KTZ_A_B', '1MAH_A_F', '1MHP_HL_A', '1MLC_AB_E', '1MQ8_A_B', '1NCA_N_LH', '1QSE_ABC_DE', '1S1Q_A_B', '1SGE_E_I', '1SGY_E_I', '1TM3_E_I', '1TM7_E_I', '1TO1_E_I', '1U7F_B_AC', '1UUZ_A_D', '1VFB_AB_C', '1XGT_AB_C', '1XGU_AB_C', '1Y34_E_I', '1Y3B_E_I', '1YQV_HL_Y', '2B10_A_B', '2B11_A_B', '2BNR_ABC_DE', '2C5D_AB_CD', '2C5D_A_C', '2CCL_A_B', '2HLE_A_B', '2KSO_A_B', '2O3B_A_B', '2PYE_ABC_DE', '2QJA_AB_C', '2QJB_AB_C', '2REX_A_B', '2SGP_E_I', '2SGQ_E_I', '2UWE_ABC_EF', '2VIS_AB_C', '2VN5_A_B', '3BTF_E_I', '3BTM_E_I', '3BTW_E_I', '3EQY_A_C', '3G6D_LH_A', '3HG1_ABC_DE', '3IDX_HL_G', '3KBH_A_E', '3KUD_A_B', '3LNZ_A_B', '3N4I_A_B', '3Q3J_A_B', '3QDG_ABC_DE', '3S9D_A_B', '3SE8_HL_G', '3SZK_AB_C', '3TGK_E_I', '3U82_A_B', '3UII_A_P', '3WWN_A_B', '4BFI_A_B', '4E6K_AB_G', '4EKD_A_B', '4GNK_A_B', '4GU0_A_E', '4JEU_A_B', '4JFD_ABC_DE', '4JFF_ABC_DE', '4KRL_A_B', '4KRP_A_B', '4LRX_AB_CD', '4O27_A_B', '4P23_CD_AB', '4UYQ_A_B', '4Y61_A_B', '4YEB_A_B', '4YFD_A_B', '5E9D_AB_CDE', '5F4E_A_B', '5TAR_A_B'], 19 | ['1AHW_AB_C', '1B2S_A_D', '1B2U_A_D', '1C4Z_ABC_D', '1CBW_FGH_I', '1CSE_E_I', '1CSO_E_I', '1CZ8_HL_VW', '1DAN_HL_UT', '1DQJ_AB_C', '1E96_A_B', '1EAW_A_B', '1EFN_A_B', '1F47_A_B', '1FSS_A_B', '1GL1_A_I', '1KIP_AB_C', '1KIQ_AB_C', '1M9E_A_D', '1N8O_ABC_E', '1N8Z_AB_C', '1S0W_A_C', '1SMF_E_I', '1TM4_E_I', '1TM5_E_I', '1WQJ_I_B', '1X1X_A_D', '1XGR_AB_C', '1Y1K_E_I', '1YCS_A_B', '1YY9_CD_A', '2BDN_HL_A', '2BTF_A_P', '2DVW_A_B', '2G2W_A_B', '2I26_N_L', '2J0T_A_D', '2J12_A_B', '2JCC_ABC_EF', '2NOJ_A_B', '2NU0_E_I', '2OOB_A_B', '2P5E_ABC_DE', '2QJ9_AB_C', '2VIR_AB_C', '2VLQ_A_B', '3BDY_HL_V', '3BN9_B_CD', '3BT1_A_U', '3BTG_E_I', '3BTT_E_I', '3BX1_A_C', '3D3V_ABC_DE', '3D5S_A_C', '3EG5_A_B', '3EQS_A_B', '3F1S_A_B', '3HH2_AB_C', '3MZG_A_B', '3QHY_A_B', '3QIB_ABP_CD', '3SE9_HL_G', '4B0M_A_BM', '4CVW_A_C', '4FZA_A_B', '4G0N_A_B', '4G2V_A_B', '4HFK_A_BD', '4J2L_A_CD', '4JGH_ABC_D', '4K71_A_BC', '4KRO_A_B', '4L0P_A_B', '4MYW_A_B', '4NKQ_C_AB', '4OFY_A_D', '4PWX_AB_CD', '4UYP_A_D', '4WND_A_B', '5E6P_A_B', '5K39_A_B', '5M2O_A_B', '5UFE_A_B', '5UFQ_A_C'], 20 | ['1A4Y_A_B', '1ACB_E_I', '1BD2_ABC_DE', '1BRS_A_D', '1CT2_E_I', '1CT4_E_I', '1DVF_AB_CD', '1FY8_E_I', '1GC1_G_C', '1GRN_A_B', '1JCK_A_B', '1KBH_A_B', '1KIR_AB_C', '1LP9_ABC_EF', '1NMB_N_LH', '1OGA_ABC_DE', '1OHZ_A_B', '1P6A_A_B', '1PPF_E_I', '1TMG_E_I', '1X1W_A_D', '1XGQ_AB_C', '1Y33_E_I', '1Y3C_E_I', '1Y3D_E_I', '2A9K_A_B', '2ABZ_B_E', '2B2X_HL_A', '2B42_A_B', '2BNQ_ABC_DE', '2DSQ_I_G', '2E7L_EQ_AD', '2GYK_A_B', '2J8U_ABC_EF', '2JEL_LH_P', '2NU2_E_I', '2NU4_E_I', '2NYY_DC_A', '2NZ9_DC_A', '2OI9_AQ_BC', '2VLO_A_B', '2VLP_A_B', '2VLR_ABC_DE', '2WPT_A_B', '3AAA_AB_C', '3B4V_AB_C', '3BTE_E_I', '3BTH_E_I', '3L5X_A_HL', '3LZF_AB_HL', '3N0P_A_B', '3NCC_A_B', '3NGB_HL_G', '3NVQ_B_A', '3PWP_ABC_DE', '3QDJ_ABC_DE', '3R9A_AC_B', '3RF3_A_C', '3SE3_B_A', '3SE3_B_C', '3SEK_B_C', '3SF4_A_D', '3UIG_A_P', '4CPA_A_I', '4HRN_A_D', '4HSA_AB_C', '4NM8_ABCDEF_HL', '4P5T_CD_AB', '4U6H_AB_E', '4X4M_AB_E', '4YH7_A_B', '4ZS6_HL_A', '5C6T_HL_A'], 21 | ['1A22_A_B', '1AK4_A_D', '1B41_A_B', '1BJ1_HL_VW', '1CT0_E_I', '1FCC_A_C', '1JRH_LH_I', '1KAC_A_B', '1LFD_A_B', '1P69_A_B', '1QAB_ABCD_E', '1REW_AB_C', '1SBB_A_B', '1SGD_E_I', '1SGN_E_I', '1SGP_E_I', '1TM1_E_I', '1XGP_AB_C', '1XXM_A_C', '1Y4A_E_I', '2AJF_A_E', '2AW2_A_B', '2B0U_AB_C', '2B12_A_B', '2C0L_A_B', '2FTL_E_I', '2J1K_C_T', '2NY7_HL_G', '2PCB_A_B', '2VLN_A_B', '3BTD_E_I', '3D5R_A_C', '3HFM_HL_Y', '3M62_A_B', '3M63_A_B', '3MZW_A_B', '3N06_A_B', '3NCB_A_B', '3NVN_B_A', '3Q8D_A_E', '3SE4_B_A', '3SE4_B_C', '3SGB_E_I', '3VR6_ABCDEF_GH', '4GXU_ABCDEF_MN', '4JFE_ABC_DE', '4L3E_ABC_DE', '4MNQ_ABC_DE', '4OZG_ABJ_GH', '4RA0_A_C', '4RS1_A_B', '5CXB_A_B', '5CYK_A_B', '5XCO_A_B'], 22 | ['1BP3_A_B', '1C1Y_A_B', '1CHO_EFG_I', '1EMV_A_B', '1FFW_A_B', '1GCQ_AB_C', '1GUA_A_B', '1HE8_A_B', '1IAR_A_B', '1JTG_A_B', '1MI5_ABC_DE', '1R0R_E_I', '1SBN_E_I', '1SGQ_E_I', '1SIB_E_I', '1XD3_A_B', '1Y48_E_I', '1Z7X_W_X', '2AK4_ABC_DE', '2B0Z_A_B', '2G2U_A_B', '2GOX_A_B', '2HRK_A_B', '2NU1_E_I', '2PCC_A_B', '2SIC_E_I', '3BE1_HL_A', '3BK3_A_C', '3BP8_A_C', '3BTQ_E_I', '3C60_CD_AB', '3H9S_ABC_DE', '3LB6_A_C', '3N85_A_LH', '3NPS_A_BC', '3QFJ_ABC_DE', '3UIH_A_P', '3W2D_A_HL', '4FTV_ABC_DE', '4JPK_HL_A', '4N8V_G_ABC', '4NZW_A_B']] 23 | PDB_TO_FIX = ['1C4Z', '2NYY', '2NZ9', '3VR6', '4GNK', '4GXU', '4K71', '4NM8'] 24 | 25 | 26 | def download_file(url, destination_path): 27 | response = requests.get(url, stream=True) 28 | 29 | if response.status_code == 200: 30 | with open(destination_path, 'wb') as file: 31 | for chunk in response.iter_content(chunk_size=1024): 32 | if chunk: 33 | file.write(chunk) 34 | else: 35 | print(f"Failed to download file. HTTP response status code: {response.status_code}") 36 | 37 | 38 | def extract_tar_gz(file_path, destination_path): 39 | with tarfile.open(file_path, 'r:gz') as tar: 40 | tar.extractall(path=destination_path, filter="data") 41 | 42 | 43 | def process_csv(df, max_ddg_std=MAX_DDG_STD, fold2pdbs=FOLD2PDBS): 44 | 45 | # parse temperature and ddG 46 | df['Temperature'] = df['Temperature'].apply(lambda x: float(x[:3]) if isinstance(x, str) else 298.) 47 | 48 | df['pKd_wt'] = -np.log10(df['Affinity_wt_parsed']) 49 | df['pKd_mt'] = -np.log10(df['Affinity_mut_parsed']) 50 | df['dG_wt'] = (8.314/4184) * df['Temperature'] * np.log(df['Affinity_wt_parsed']) 51 | df['dG_mt'] = (8.314/4184) * df['Temperature'] * np.log(df['Affinity_mut_parsed']) 52 | df['ddG'] = df['dG_mt'] - df['dG_wt'] 53 | 54 | def _is_float(x): 55 | try: 56 | float(x) 57 | return True 58 | except ValueError: 59 | return False 60 | valid = (df['Affinity_mut (M)'].apply(_is_float)) & (df['Affinity_wt (M)'].apply(_is_float)) 61 | idf = df.loc[~valid] # 474 invalid entries, discarded 62 | vdf = df.loc[valid] # 6611 valid entries 63 | print(f"Total entries: {len(df)}, Entries with valid ddG: {len(vdf)}, {len(idf)} invalid entries will be discarded.") 64 | 65 | # filter out non-unique entries 66 | _vdf = vdf.set_index(['#Pdb', 'Mutation(s)_cleaned']) 67 | print(f'{_vdf.index.nunique()} unique #Pdb-mutation pairs detected.') # 5747 unique #Pdb-mutation pairs 68 | 69 | cnt = _vdf.index.value_counts() 70 | not_unique_entries = cnt[cnt > 1].index # 585 non-unique #Pdb-mutation pairs 71 | not_unique_df = _vdf.loc[not_unique_entries].reset_index() 72 | print(f"{len(not_unique_entries)} non-unique #Pdb-mutation pairs detected. This accounts for {len(not_unique_df)} entries.") 73 | 74 | # calculate ddG std for non-unique entries, and filter out highly-variable entries 75 | rows = [] 76 | for (pdb_chains, mutations), sdf in not_unique_df.groupby(['#Pdb', 'Mutation(s)_cleaned']): 77 | _dict = sdf.ddG.describe().to_dict() 78 | _dict['#Pdb'] = pdb_chains 79 | _dict['Mutation(s)_cleaned'] = mutations 80 | rows.append(_dict) 81 | not_unique_stat = pd.DataFrame(rows).set_index(['#Pdb', 'Mutation(s)_cleaned']) 82 | bad_data = not_unique_stat.loc[(not_unique_stat['std'] > max_ddg_std)] # 95 entries have > 0.5 ddG, 18 entries have > 1 ddG 83 | filtered_data = _vdf.loc[~_vdf.index.isin(bad_data.index)] 84 | print(f"{len(bad_data)} entries have ddG std > {max_ddg_std} and will be discarded. {len(filtered_data)} entries have ddG std <= {max_ddg_std}.") 85 | 86 | # aggregate data so that each #Pdb-mutation corresponds to one entry only 87 | dfs = [] 88 | for (pdb_chains, mutations), sdf in filtered_data.groupby(['#Pdb', 'Mutation(s)_cleaned']): 89 | first_row = sdf.iloc[0].copy() 90 | first_row['ddG'] = sdf.ddG.mean() 91 | if (pdb_chains, mutations) in not_unique_stat.index: 92 | assert first_row['ddG'] == not_unique_stat.loc[(pdb_chains, mutations), 'mean'] 93 | dfs.append(first_row.to_frame().T) 94 | aggr_data = pd.concat(dfs) 95 | aggr_data.index.names = ['#Pdb', 'Mutation(s)_cleaned'] 96 | assert aggr_data.index.is_unique 97 | print(f"Aggregation complete. {len(aggr_data)} unique #Pdb-mutation pairs from {aggr_data.index.get_level_values('#Pdb').nunique()} #Pdbs remain in the processed dataset.") 98 | 99 | # split by #Pdb 100 | dfs = [] 101 | for i, pdbs in enumerate(fold2pdbs): 102 | aggr_data.loc[pdbs, 'fold'] = i 103 | print(f"Fold {i}: {aggr_data.loc[pdbs].shape[0]} entries, {len(pdbs)} unique #Pdbs") 104 | 105 | # convert format for subsequent processing 106 | aggr_data['pdb_id'] = aggr_data['#Pdb'].apply(lambda x: x.split('_')[0]) 107 | aggr_data['pdb_fname'] = aggr_data['pdb_id'] + '_Repair.pdb' 108 | aggr_data['chain_a'] = aggr_data['#Pdb'].apply(lambda x: x.split('_')[1]) 109 | aggr_data['chain_b'] = aggr_data['#Pdb'].apply(lambda x: x.split('_')[2]) 110 | aggr_data['mutation'] = aggr_data['Mutation(s)_cleaned'] 111 | 112 | return aggr_data 113 | 114 | 115 | def process_pdbs(pdb_dir): 116 | pdb_dir = Path(pdb_dir) 117 | 118 | # fix 1KBH. It stores all states in a single state, causing unresolvable clash. 119 | with open(pdb_dir / '1KBH.pdb') as f: 120 | lines = f.readlines() 121 | new_lines = lines[13471:14181] + lines[29285:] 122 | with open(pdb_dir / '1KBH.pdb', 'w') as f: 123 | f.write('\n'.join(new_lines) + '\n') 124 | print("Fixed 1KBH") 125 | 126 | # fix 4BFI 127 | with open(pdb_dir / '4BFI.pdb') as f: 128 | lines = f.readlines() 129 | new_lines = lines[:3062] + lines[3069:] 130 | with open(pdb_dir / '4BFI.pdb', 'w') as f: 131 | f.write('\n'.join(new_lines) + '\n') 132 | print("Fixed 4BFI") 133 | 134 | # fix PDB_TO_FIX 135 | for pdb_code in PDB_TO_FIX: 136 | fpath = pdb_dir / f'{pdb_code}.pdb' 137 | fix_pdb(fpath, {}, output_file=fpath) 138 | print(f'Fixed {pdb_code}') 139 | 140 | 141 | def run_foldx_repair(file: Path, timeout: float = 3600, output_dir: Path = Path("repaired_pdbs")): 142 | command = f"foldx --command RepairPDB --ionStrength 0.15 --pdb-dir {file.parent} --output-dir {output_dir} --pdb {file.name}" 143 | # Use subprocess to execute the command in the shell 144 | try: 145 | result = subprocess.run(command, shell=True, check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, timeout=timeout) 146 | # Return a tuple of the file name and the stdout or stderr if command fails 147 | return (file, None) if result.returncode == 0 else (file, result.stderr) 148 | except subprocess.CalledProcessError as e: 149 | # Handle errors in the called executable 150 | return (file, e.stderr) 151 | except Exception as e: 152 | # Handle other exceptions such as file not found or permissions issues 153 | return (file, str(e).encode()) 154 | 155 | 156 | if __name__ == '__main__': 157 | parser = argparse.ArgumentParser() 158 | parser.add_argument('--csv-path', type=Path, default=Path('SKEMPI_v2/skempi_v2.csv'), help='Path to the SKEMPI CSV file') 159 | parser.add_argument('--output-csv-path', type=Path, default=Path('SKEMPI_v2_processed/processed_skempi.csv'), help='Path to the processed SKEMPI CSV file') 160 | parser.add_argument('--pdb-dir', type=Path, default=Path('SKEMPI_v2_processed/PDBs'), help='Path to the SKEMPI PDB directory, must have name "PDBs"') 161 | parser.add_argument('--output-pdb-dir', type=Path, default=Path('SKEMPI_v2_processed/processed_pdbs'), help='Path to the output directory for repaired PDBs') 162 | parser.add_argument('--no-repair', action='store_true', help='skip FoldX RepairPDB step') 163 | args = parser.parse_args() 164 | 165 | 166 | if not args.csv_path.exists(): 167 | args.csv_path.parent.mkdir(exist_ok=True, parents=True) 168 | download_file('https://life.bsc.es/pid/skempi2/database/download/skempi_v2.csv', args.csv_path) 169 | 170 | assert args.pdb_dir.name == 'PDBs' 171 | if not args.pdb_dir.exists(): 172 | args.pdb_dir.parent.mkdir(exist_ok=True, parents=True) 173 | temp_fpath = Path(tempfile.gettempdir()) / 'SKEMPI2_PDBs.tgz' 174 | download_file('https://life.bsc.es/pid/skempi2/database/download/SKEMPI2_PDBs.tgz', temp_fpath) 175 | extract_tar_gz(temp_fpath, args.pdb_dir.parent) 176 | 177 | df = pd.read_csv(args.csv_path, sep=';') 178 | aggr_data = process_csv(df) 179 | aggr_data.to_csv(args.output_csv_path) 180 | 181 | process_pdbs(args.pdb_dir) 182 | 183 | if args.no_repair: 184 | print("Skipping repair step.") 185 | exit() 186 | 187 | args.output_pdb_dir.mkdir(parents=True, exist_ok=True) 188 | pdb_fpaths = [p for p in args.pdb_dir.glob('*.pdb') if not p.name.startswith('.')] 189 | _run_foldx_repair = partial(run_foldx_repair, output_dir=args.output_pdb_dir) 190 | with mp.Pool(min(64, mp.cpu_count())) as pool: 191 | result = pool.map(_run_foldx_repair, tqdm(pdb_fpaths)) 192 | success_count = sum(r[1] is None for r in result) 193 | print(f"{success_count} PDBs repaired by FoldX") 194 | 195 | repaired_list = list(args.output_pdb_dir.glob('*.pdb')) 196 | assert len(repaired_list) == len(pdb_fpaths), f'Repaired pdbs ({len(repaired_list)}) != Original pdbs ({len(pdb_fpaths)})' 197 | --------------------------------------------------------------------------------