Spaces:
Build error
Build error
Commit
·
fba25b8
0
Parent(s):
Duplicate from simonduerr/diffdock
Browse filesCo-authored-by: Simon Duerr <simonduerr@users.noreply.huggingface.co>
This view is limited to 50 files because it contains too many changes.
See raw diff
- .gitattributes +23 -0
- .gitignore +164 -0
- LICENSE +21 -0
- README.md +158 -0
- app.py +610 -0
- baselines/baseline_evaluation.py +219 -0
- baselines/baseline_gnina.py +175 -0
- baselines/baseline_run_tankbind_parallel.sh +5 -0
- baselines/baseline_tankbind_evaluation.py +239 -0
- baselines/baseline_tankbind_runtime.py +342 -0
- confidence/confidence_train.py +319 -0
- confidence/dataset.py +272 -0
- data/protein_ligand_example_csv.csv +2 -0
- data/splits/timesplit_no_lig_overlap_train +16379 -0
- data/splits/timesplit_no_lig_overlap_val +968 -0
- data/splits/timesplit_test +363 -0
- data/splits/timesplit_test_no_rec_overlap +144 -0
- datasets/__init__.py +0 -0
- datasets/conformer_matching.py +196 -0
- datasets/esm_embedding_preparation.py +88 -0
- datasets/esm_embeddings_to_pt.py +17 -0
- datasets/pdbbind.py +705 -0
- datasets/pdbbind_lm_embedding_preparation.py +94 -0
- datasets/process_mols.py +550 -0
- environment.yml +102 -0
- esm/LICENSE +21 -0
- esm/esm/__init__.py +12 -0
- esm/esm/axial_attention.py +239 -0
- esm/esm/constants.py +10 -0
- esm/esm/data.py +493 -0
- esm/esm/inverse_folding/__init__.py +8 -0
- esm/esm/inverse_folding/features.py +352 -0
- esm/esm/inverse_folding/gvp_encoder.py +56 -0
- esm/esm/inverse_folding/gvp_modules.py +473 -0
- esm/esm/inverse_folding/gvp_transformer.py +137 -0
- esm/esm/inverse_folding/gvp_transformer_encoder.py +184 -0
- esm/esm/inverse_folding/gvp_utils.py +68 -0
- esm/esm/inverse_folding/multichain_util.py +151 -0
- esm/esm/inverse_folding/transformer_decoder.py +228 -0
- esm/esm/inverse_folding/transformer_layer.py +304 -0
- esm/esm/inverse_folding/util.py +320 -0
- esm/esm/model/esm1.py +200 -0
- esm/esm/model/esm2.py +147 -0
- esm/esm/model/msa_transformer.py +238 -0
- esm/esm/modules.py +418 -0
- esm/esm/multihead_attention.py +508 -0
- esm/esm/pretrained.py +397 -0
- esm/esm/rotary_embedding.py +69 -0
- esm/esm/version.py +6 -0
- esm/scripts/extract.py +142 -0
.gitattributes
ADDED
@@ -0,0 +1,23 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
*.ipynb linguist-vendored=false
|
2 |
+
*.ipynb linguist-detectable=false
|
3 |
+
/jupyter_notebooks linguist-vendored=false
|
4 |
+
jupyter_notebooks/** linguist-vendored
|
5 |
+
jupyter_notebooks/** linguist-vendored=false
|
6 |
+
jupyter_notebooks/* linguist-vendored
|
7 |
+
jupyter_notebooks/* linguist-vendored=false
|
8 |
+
data/esm2_output_back/1a46_protein_processed.pdb_chain_1.pt filter=lfs diff=lfs merge=lfs -text
|
9 |
+
data/esm2_output/1a46_protein_processed0t6cxvmshf54nq5e.pdb_chain_0.pt filter=lfs diff=lfs merge=lfs -text
|
10 |
+
data/esm2_output/1a46_protein_processedhoiape3r6cbddini.pdb_chain_0.pt filter=lfs diff=lfs merge=lfs -text
|
11 |
+
data/esm2_output/1a46_protein_processedhoiape3r6cbddini.pdb_chain_1.pt filter=lfs diff=lfs merge=lfs -text
|
12 |
+
data/esm2_output/1a46_protein_processeds5c7cs3aj6rvbhy_.pdb_chain_0.pt filter=lfs diff=lfs merge=lfs -text
|
13 |
+
data/esm2_output/1a46_protein_processedtyfuvx9z8y4_86ft.pdb_chain_0.pt filter=lfs diff=lfs merge=lfs -text
|
14 |
+
data/esm2_output_back/1a46_protein_processed.pdb_chain_0.pt filter=lfs diff=lfs merge=lfs -text
|
15 |
+
data/esm2_output/1a46_protein_processed.pdb_chain_0.pt filter=lfs diff=lfs merge=lfs -text
|
16 |
+
data/esm2_output_back/1cbr_protein.pdb_chain_1.pt filter=lfs diff=lfs merge=lfs -text
|
17 |
+
workdir/paper_confidence_model/best_model_epoch75.pt filter=lfs diff=lfs merge=lfs -text
|
18 |
+
data/esm2_output/1a46_protein_processeds5c7cs3aj6rvbhy_.pdb_chain_1.pt filter=lfs diff=lfs merge=lfs -text
|
19 |
+
data/esm2_output_back/1cbr_protein.pdb_chain_0.pt filter=lfs diff=lfs merge=lfs -text
|
20 |
+
data/esm2_output/1a46_protein_processed0t6cxvmshf54nq5e.pdb_chain_1.pt filter=lfs diff=lfs merge=lfs -text
|
21 |
+
data/esm2_output/1a46_protein_processed.pdb_chain_1.pt filter=lfs diff=lfs merge=lfs -text
|
22 |
+
data/esm2_output/1a46_protein_processedtyfuvx9z8y4_86ft.pdb_chain_1.pt filter=lfs diff=lfs merge=lfs -text
|
23 |
+
workdir/paper_score_model/best_ema_inference_epoch_model.pt filter=lfs diff=lfs merge=lfs -text
|
.gitignore
ADDED
@@ -0,0 +1,164 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
homework
|
2 |
+
inference_out_dir_not_specified
|
3 |
+
.plotly_cache
|
4 |
+
.DS_store
|
5 |
+
renew.sh
|
6 |
+
tmux_renew.sh
|
7 |
+
images
|
8 |
+
# Byte-compiled / optimized / DLL files
|
9 |
+
__pycache__/
|
10 |
+
*.py[cod]
|
11 |
+
*$py.class
|
12 |
+
|
13 |
+
# C extensions
|
14 |
+
*.so
|
15 |
+
.so3_*
|
16 |
+
|
17 |
+
# Distribution / packaging
|
18 |
+
.Python
|
19 |
+
build/
|
20 |
+
develop-eggs/
|
21 |
+
dist/
|
22 |
+
downloads/
|
23 |
+
eggs/
|
24 |
+
.eggs/
|
25 |
+
lib/
|
26 |
+
lib64/
|
27 |
+
parts/
|
28 |
+
sdist/
|
29 |
+
var/
|
30 |
+
wheels/
|
31 |
+
*.egg-info/
|
32 |
+
.installed.cfg
|
33 |
+
*.egg
|
34 |
+
MANIFEST
|
35 |
+
|
36 |
+
# PyInstaller
|
37 |
+
# Usually these files are written by a python script from a template
|
38 |
+
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
39 |
+
*.manifest
|
40 |
+
*.spec
|
41 |
+
|
42 |
+
# Installer logs
|
43 |
+
pip-log.txt
|
44 |
+
pip-delete-this-directory.txt
|
45 |
+
|
46 |
+
# Unit test / coverage reports
|
47 |
+
htmlcov/
|
48 |
+
.tox/
|
49 |
+
.coverage
|
50 |
+
.coverage.*
|
51 |
+
.cache
|
52 |
+
nosetests.xml
|
53 |
+
coverage.xml
|
54 |
+
*.cover
|
55 |
+
.hypothesis/
|
56 |
+
.pytest_cache/
|
57 |
+
|
58 |
+
# Translations
|
59 |
+
*.mo
|
60 |
+
*.pot
|
61 |
+
|
62 |
+
# Django stuff:
|
63 |
+
*.log
|
64 |
+
local_settings.py
|
65 |
+
db.sqlite3
|
66 |
+
|
67 |
+
# Flask stuff:
|
68 |
+
instance/
|
69 |
+
.webassets-cache
|
70 |
+
|
71 |
+
# Scrapy stuff:
|
72 |
+
.scrapy
|
73 |
+
|
74 |
+
# Sphinx documentation
|
75 |
+
docs/_build/
|
76 |
+
|
77 |
+
# PyBuilder
|
78 |
+
target/
|
79 |
+
|
80 |
+
# Jupyter Notebook
|
81 |
+
.ipynb_checkpoints
|
82 |
+
|
83 |
+
# pyenv
|
84 |
+
.python-version
|
85 |
+
|
86 |
+
# celery beat schedule file
|
87 |
+
celerybeat-schedule
|
88 |
+
|
89 |
+
# SageMath parsed files
|
90 |
+
*.sage.py
|
91 |
+
|
92 |
+
# Environments
|
93 |
+
.env
|
94 |
+
.venv
|
95 |
+
env/
|
96 |
+
venv/
|
97 |
+
ENV/
|
98 |
+
env.bak/
|
99 |
+
venv.bak/
|
100 |
+
|
101 |
+
# Spyder project settings
|
102 |
+
.spyderproject
|
103 |
+
.spyproject
|
104 |
+
|
105 |
+
# Rope project settings
|
106 |
+
.ropeproject
|
107 |
+
|
108 |
+
# mkdocs documentation
|
109 |
+
/site
|
110 |
+
|
111 |
+
# mypy
|
112 |
+
.mypy_cache/
|
113 |
+
local_config_inference2.yml
|
114 |
+
.vscode/
|
115 |
+
|
116 |
+
|
117 |
+
*.zip
|
118 |
+
|
119 |
+
.idea/
|
120 |
+
|
121 |
+
|
122 |
+
#################### Project specific
|
123 |
+
.p.npy
|
124 |
+
.score.npy
|
125 |
+
# this ignores everything in data except for the file
|
126 |
+
!/data
|
127 |
+
/data/*
|
128 |
+
!/data/splits
|
129 |
+
!/data/protein_ligand_example_csv.csv
|
130 |
+
!/data/testset_csv.csv
|
131 |
+
!/data/INDEX_general_PL_data.2020
|
132 |
+
test_run
|
133 |
+
|
134 |
+
cache
|
135 |
+
wandb
|
136 |
+
logs
|
137 |
+
|
138 |
+
# temporary files
|
139 |
+
.openbabel_cache
|
140 |
+
temp/
|
141 |
+
bsub*
|
142 |
+
stderr*
|
143 |
+
stdout*
|
144 |
+
!/workdir
|
145 |
+
/workdir/*
|
146 |
+
!/workdir/paper_confidence_model
|
147 |
+
!/workdir/paper_score_model
|
148 |
+
runs2
|
149 |
+
results
|
150 |
+
# this excludes everything in the runs directory except for that specific run
|
151 |
+
!/runs
|
152 |
+
/runs/*
|
153 |
+
!/runs/rigid_redocking
|
154 |
+
!/runs/flexible_self_docking
|
155 |
+
local_config.yml
|
156 |
+
local_config_inference.yml
|
157 |
+
local_config_confidence.yml
|
158 |
+
temp1.py
|
159 |
+
temp5.py
|
160 |
+
temp3.py
|
161 |
+
temp4.py
|
162 |
+
temp5.py
|
163 |
+
temp6.py
|
164 |
+
temp7.py
|
LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
MIT License
|
2 |
+
|
3 |
+
Copyright (c) 2022 Gabriele Corso, Hannes Stärk, Bowen Jing
|
4 |
+
|
5 |
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6 |
+
of this software and associated documentation files (the "Software"), to deal
|
7 |
+
in the Software without restriction, including without limitation the rights
|
8 |
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9 |
+
copies of the Software, and to permit persons to whom the Software is
|
10 |
+
furnished to do so, subject to the following conditions:
|
11 |
+
|
12 |
+
The above copyright notice and this permission notice shall be included in all
|
13 |
+
copies or substantial portions of the Software.
|
14 |
+
|
15 |
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16 |
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17 |
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18 |
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19 |
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20 |
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21 |
+
SOFTWARE.
|
README.md
ADDED
@@ -0,0 +1,158 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
---
|
2 |
+
title: Diffdock
|
3 |
+
emoji: 🐠
|
4 |
+
colorFrom: indigo
|
5 |
+
colorTo: pink
|
6 |
+
sdk: gradio
|
7 |
+
sdk_version: 3.4.1
|
8 |
+
app_file: app.py
|
9 |
+
pinned: false
|
10 |
+
license: mit
|
11 |
+
duplicated_from: simonduerr/diffdock
|
12 |
+
---
|
13 |
+
|
14 |
+
# DiffDock: Diffusion Steps, Twists, and Turns for Molecular Docking
|
15 |
+
|
16 |
+
### [Paper on arXiv](https://arxiv.org/abs/2210.01776)
|
17 |
+
|
18 |
+
Implementation of DiffDock, state-of-the-art method for molecular docking, by Gabriele Corso*, Hannes Stark*, Bowen Jing*, Regina Barzilay and Tommi Jaakkola.
|
19 |
+
This repository contains all code, instructions and model weights necessary to run the method or to retrain a model.
|
20 |
+
If you have any question, feel free to open an issue or reach out to us: [gcorso@mit.edu](gcorso@mit.edu), [hstark@mit.edu](hstark@mit.edu), [bjing@mit.edu](bjing@mit.edu).
|
21 |
+
|
22 |
+

|
23 |
+
|
24 |
+
The repository also contains all the scripts to run the baselines and generate the figures.
|
25 |
+
Additionally, there are visualization videos in `visualizations`.
|
26 |
+
|
27 |
+
|
28 |
+
|
29 |
+
# Dataset
|
30 |
+
|
31 |
+
The files in `data` contain the names for the time-based data split.
|
32 |
+
|
33 |
+
If you want to train one of our models with the data then:
|
34 |
+
1. download it from [zenodo](https://zenodo.org/record/6034088)
|
35 |
+
2. unzip the directory and place it into `data` such that you have the path `data/PDBBind_processed`
|
36 |
+
|
37 |
+
|
38 |
+
|
39 |
+
## Setup Environment
|
40 |
+
|
41 |
+
We will set up the environment using [Anaconda](https://docs.anaconda.com/anaconda/install/index.html). Clone the
|
42 |
+
current repo
|
43 |
+
|
44 |
+
git clone https://github.com/gcorso/DiffDock.git
|
45 |
+
|
46 |
+
Create a new environment with all required packages using `environment.yml`. While in the project directory run:
|
47 |
+
|
48 |
+
conda env create
|
49 |
+
|
50 |
+
Activate the environment
|
51 |
+
|
52 |
+
conda activate diffdock
|
53 |
+
|
54 |
+
If you want to install the packages yourself in case something does not work, these are the required ones:
|
55 |
+
|
56 |
+
pytorch
|
57 |
+
pyg
|
58 |
+
pyyaml
|
59 |
+
scipy
|
60 |
+
networkx
|
61 |
+
biopython
|
62 |
+
rdkit-pypi
|
63 |
+
e3nn
|
64 |
+
spyrmsd
|
65 |
+
pandas
|
66 |
+
biopandas
|
67 |
+
|
68 |
+
# Running DiffDock on your own complexes
|
69 |
+
We support multiple input formats depending on whether you only want to make predictions for a single complex or for many at once.\
|
70 |
+
The protein inputs need to be .pdb files. The ligand input can either be a SMILES string or a filetype that RDKit can read like `.sdf` or `.mol2`.
|
71 |
+
|
72 |
+
For a single complex: specify the protein with, e.g., `--protein_path protein.pdb` and the ligand with `--ligand_path ligand.sdf` or `--ligand_smiles COc(cc1)ccc1C#N`
|
73 |
+
|
74 |
+
For many complexes: create a csv file with paths to proteins and ligand files or SMILES. The first column of the .csv has to be called `protein_path` and the second one `ligand`.
|
75 |
+
An example .csv is at `data/protein_ligand_example_csv.csv` and you would use it with `--protein_ligand_csv protein_ligand_example_csv.csv`.
|
76 |
+
|
77 |
+
### Generate the ESM2 embeddings for the proteins
|
78 |
+
We will soon also provide weights of a trained model without ESM2 embeddings such that this step is not necessary. Luckily, it is rather easy. First prepare a fasta for ESM2 (for a single protein use `--protein_path protein.pdb` instead):
|
79 |
+
|
80 |
+
python datasets/esm_embedding_preparation.py --protein_ligand_csv data/protein_ligand_example_csv.csv --out_file data/prepared_for_esm.fasta
|
81 |
+
|
82 |
+
Generate the embeddings with ESM2 (assuming that you are in the DiffDock directory):
|
83 |
+
|
84 |
+
git clone https://github.com/facebookresearch/esm
|
85 |
+
cd esm
|
86 |
+
pip install -e .
|
87 |
+
cd ..
|
88 |
+
HOME=esm/model_weights python esm/scripts/extract.py esm2_t33_650M_UR50D data/prepared_for_esm.fasta data/esm2_output --repr_layers 33 --include per_tok
|
89 |
+
|
90 |
+
And done, that is it!
|
91 |
+
|
92 |
+
### Run inference
|
93 |
+
|
94 |
+
python -m inference --protein_ligand_csv data/protein_ligand_example_csv.csv --out_dir results/user_predictions_small --inference_steps 20 --samples_per_complex 40 --batch_size 10
|
95 |
+
|
96 |
+
|
97 |
+
|
98 |
+
# Running DiffDock to reproduce paper numbers
|
99 |
+
Download the data and place it as described in the "Dataset" section above.
|
100 |
+
|
101 |
+
### Generate the ESM2 embeddings for the proteins
|
102 |
+
First run:
|
103 |
+
|
104 |
+
python datasets/pdbbind_lm_embedding_preparation.py
|
105 |
+
|
106 |
+
Use the generated file `data/pdbbind_sequences.fasta` to generate the ESM2 language model embeddings using the library https://github.com/facebookresearch/esm by installing their repository and executing the following in their repository:
|
107 |
+
|
108 |
+
python scripts/extract.py esm2_t33_650M_UR50D pdbbind_sequences.fasta embeddings_output --repr_layers 33 --include per_tok
|
109 |
+
|
110 |
+
This generates the `embeddings_output` directory which you have to copy into the `data` folder of our repository to have `data/embeddings_output`.
|
111 |
+
Then run the command:
|
112 |
+
|
113 |
+
python datasets/esm_embeddings_to_pt.py
|
114 |
+
|
115 |
+
### Using the provided model weights for evaluation
|
116 |
+
To predict binding structures using the provided model weights run:
|
117 |
+
|
118 |
+
python -m evaluate --model_dir workdir/paper_score_model --ckpt best_ema_inference_epoch_model.pt --confidence_ckpt best_model_epoch75.pt --confidence_model_dir workdir/paper_confidence_model --run_name DiffDockInference --inference_steps 20 --split_path data/splits/timesplit_test --samples_per_complex 40 --batch_size 10
|
119 |
+
|
120 |
+
To additionally save the .sdf files of the generated molecules, add the flag `--save_visualisation`
|
121 |
+
|
122 |
+
### Training a model yourself and using those weights
|
123 |
+
Train the large score model:
|
124 |
+
|
125 |
+
python -m train --run_name big_score_model --test_sigma_intervals --esm_embeddings_path data/esm2_3billion_embeddings.pt --log_dir workdir --lr 1e-3 --tr_sigma_min 0.1 --tr_sigma_max 19 --rot_sigma_min 0.03 --rot_sigma_max 1.55 --batch_size 16 --ns 48 --nv 10 --num_conv_layers 6 --dynamic_max_cross --scheduler plateau --scale_by_sigma --dropout 0.1 --sampling_alpha 1 --sampling_beta 1 --remove_hs --c_alpha_max_neighbors 24 --receptor_radius 15 --num_dataloader_workers 1 --cudnn_benchmark --rot_alpha 1 --rot_beta 1 --tor_alpha 1 --tor_beta 1 --val_inference_freq 5 --num_inference_complexes 500 --use_ema --distance_embed_dim 64 --cross_distance_embed_dim 64 --sigma_embed_dim 64 --scheduler_patience 30 --n_epochs 850
|
126 |
+
|
127 |
+
The model weights are saved in the `workdir` directory.
|
128 |
+
|
129 |
+
Train a small score model with higher maximum translation sigma that will be used to generate the samples for training the confidence model:
|
130 |
+
|
131 |
+
python -m train --run_name small_score_model --test_sigma_intervals --esm_embeddings_path data/esm2_3billion_embeddings.pt --log_dir workdir --lr 1e-3 --tr_sigma_min 0.1 --tr_sigma_max 34 --rot_sigma_min 0.03 --rot_sigma_max 1.55 --batch_size 16 --ns 24 --nv 6 --num_conv_layers 5 --dynamic_max_cross --scheduler plateau --scale_by_sigma --dropout 0.1 --sampling_alpha 1 --sampling_beta 1 --remove_hs --c_alpha_max_neighbors 24 --receptor_radius 15 --num_dataloader_workers 1 --cudnn_benchmark --rot_alpha 1 --rot_beta 1 --tor_alpha 1 --tor_beta 1 --val_inference_freq 5 --num_inference_complexes 500 --use_ema --scheduler_patience 30 --n_epochs 300
|
132 |
+
|
133 |
+
In practice, you could also likely achieve the same or better results by using the first score model for creating the samples to train the confidence model, but this is what we did in the paper.
|
134 |
+
The score model used to generate the samples to train the confidence model does not have to be the same as the score model that is used with that confidence model during inference.
|
135 |
+
|
136 |
+
Train the confidence model by running the following:
|
137 |
+
|
138 |
+
python -m confidence.confidence_train --original_model_dir workdir/small_score_model --run_name confidence_model --inference_steps 20 --samples_per_complex 7 --inf_sched_alpha 1 --inf_sched_beta 1 --batch_size 16 --n_epochs 100 --lr 3e-4 --scheduler_patience 50 --tr_sigma_min 0.1 --tr_sigma_max 34 --rot_sigma_min 0.03 --rot_sigma_max 1.55 --ns 24 --nv 6 --num_conv_layers 5 --dynamic_max_cross --scale_by_sigma --dropout 0.1 --all_atoms --remove_hs --c_alpha_max_neighbors 24 --receptor_radius 15 --esm_embeddings_path data/esm2_3billion_embeddings.pt --main_metric loss --main_metric_goal min --best_model_save_frequency 5 --rmsd_classification_cutoff 2 --cache_creation_id 1 --cache_ids_to_combine 1 2 3 4
|
139 |
+
|
140 |
+
first with `--cache_creation_id 1` then `--cache_creation_id 2` etc. up to 4
|
141 |
+
|
142 |
+
Now everything is trained and you can run inference with:
|
143 |
+
|
144 |
+
python -m evaluate --model_dir workdir/big_score_model --ckpt best_ema_inference_epoch_model.pt --confidence_ckpt best_model_epoch75.pt --confidence_model_dir workdir/confidence_model --run_name DiffDockInference --inference_steps 20 --split_path data/splits/timesplit_test --samples_per_complex 40 --batch_size 10
|
145 |
+
|
146 |
+
|
147 |
+
## Citation
|
148 |
+
@article{corso2022diffdock,
|
149 |
+
title={DiffDock: Diffusion Steps, Twists, and Turns for Molecular Docking},
|
150 |
+
author = {Corso, Gabriele and Stärk, Hannes and Jing, Bowen and Barzilay, Regina and Jaakkola, Tommi},
|
151 |
+
journal={arXiv preprint arXiv:2210.01776},
|
152 |
+
year={2022}
|
153 |
+
}
|
154 |
+
|
155 |
+
## License
|
156 |
+
MIT
|
157 |
+
|
158 |
+

|
app.py
ADDED
@@ -0,0 +1,610 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import gradio as gr
|
2 |
+
import os
|
3 |
+
|
4 |
+
import copy
|
5 |
+
import os
|
6 |
+
import torch
|
7 |
+
|
8 |
+
import subprocess
|
9 |
+
|
10 |
+
|
11 |
+
import time
|
12 |
+
from argparse import ArgumentParser, Namespace, FileType
|
13 |
+
from rdkit.Chem import RemoveHs
|
14 |
+
from functools import partial
|
15 |
+
import numpy as np
|
16 |
+
import pandas as pd
|
17 |
+
from rdkit import RDLogger
|
18 |
+
from rdkit.Chem import MolFromSmiles, AddHs
|
19 |
+
from torch_geometric.loader import DataLoader
|
20 |
+
import yaml
|
21 |
+
import sys
|
22 |
+
import csv
|
23 |
+
|
24 |
+
csv.field_size_limit(sys.maxsize)
|
25 |
+
|
26 |
+
print(torch.__version__)
|
27 |
+
os.makedirs("data/esm2_output", exist_ok=True)
|
28 |
+
os.makedirs("results", exist_ok=True)
|
29 |
+
from datasets.process_mols import (
|
30 |
+
read_molecule,
|
31 |
+
generate_conformer,
|
32 |
+
write_mol_with_coords,
|
33 |
+
)
|
34 |
+
from datasets.pdbbind import PDBBind
|
35 |
+
from utils.diffusion_utils import t_to_sigma as t_to_sigma_compl, get_t_schedule
|
36 |
+
from utils.sampling import randomize_position, sampling
|
37 |
+
from utils.utils import get_model
|
38 |
+
from utils.visualise import PDBFile
|
39 |
+
from tqdm import tqdm
|
40 |
+
from datasets.esm_embedding_preparation import esm_embedding_prep
|
41 |
+
import subprocess
|
42 |
+
|
43 |
+
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
|
44 |
+
|
45 |
+
with open(f"workdir/paper_score_model/model_parameters.yml") as f:
|
46 |
+
score_model_args = Namespace(**yaml.full_load(f))
|
47 |
+
|
48 |
+
with open(f"workdir/paper_confidence_model/model_parameters.yml") as f:
|
49 |
+
confidence_args = Namespace(**yaml.full_load(f))
|
50 |
+
|
51 |
+
import shutil
|
52 |
+
|
53 |
+
t_to_sigma = partial(t_to_sigma_compl, args=score_model_args)
|
54 |
+
|
55 |
+
model = get_model(score_model_args, device, t_to_sigma=t_to_sigma, no_parallel=True)
|
56 |
+
state_dict = torch.load(
|
57 |
+
f"workdir/paper_score_model/best_ema_inference_epoch_model.pt",
|
58 |
+
map_location=torch.device("cpu"),
|
59 |
+
)
|
60 |
+
model.load_state_dict(state_dict, strict=True)
|
61 |
+
model = model.to(device)
|
62 |
+
model.eval()
|
63 |
+
|
64 |
+
confidence_model = get_model(
|
65 |
+
confidence_args,
|
66 |
+
device,
|
67 |
+
t_to_sigma=t_to_sigma,
|
68 |
+
no_parallel=True,
|
69 |
+
confidence_mode=True,
|
70 |
+
)
|
71 |
+
state_dict = torch.load(
|
72 |
+
f"workdir/paper_confidence_model/best_model_epoch75.pt",
|
73 |
+
map_location=torch.device("cpu"),
|
74 |
+
)
|
75 |
+
confidence_model.load_state_dict(state_dict, strict=True)
|
76 |
+
confidence_model = confidence_model.to(device)
|
77 |
+
confidence_model.eval()
|
78 |
+
|
79 |
+
|
80 |
+
def get_pdb(pdb_code="", filepath=""):
|
81 |
+
try:
|
82 |
+
return filepath.name
|
83 |
+
except AttributeError as e:
|
84 |
+
if pdb_code is None or pdb_code == "":
|
85 |
+
return None
|
86 |
+
else:
|
87 |
+
os.system(f"wget -qnc https://files.rcsb.org/view/{pdb_code}.pdb")
|
88 |
+
return f"{pdb_code}.pdb"
|
89 |
+
|
90 |
+
|
91 |
+
def get_ligand(smiles="", filepath=""):
|
92 |
+
if smiles is None or smiles == "":
|
93 |
+
try:
|
94 |
+
return filepath.name
|
95 |
+
except AttributeError as e:
|
96 |
+
return None
|
97 |
+
else:
|
98 |
+
return smiles
|
99 |
+
|
100 |
+
|
101 |
+
def read_mol(molpath):
|
102 |
+
with open(molpath, "r") as fp:
|
103 |
+
lines = fp.readlines()
|
104 |
+
mol = ""
|
105 |
+
for l in lines:
|
106 |
+
mol += l
|
107 |
+
return mol
|
108 |
+
|
109 |
+
|
110 |
+
def molecule(input_pdb, ligand_pdb, original_ligand):
|
111 |
+
|
112 |
+
structure = read_mol(input_pdb)
|
113 |
+
mol = read_mol(ligand_pdb)
|
114 |
+
|
115 |
+
try:
|
116 |
+
ligand = read_mol(original_ligand.name)
|
117 |
+
_, ext = os.path.splitext(original_ligand.name)
|
118 |
+
lig_str_1 = """let original_ligand = `""" + ligand + """`"""
|
119 |
+
lig_str_2 = f"""
|
120 |
+
viewer.addModel( original_ligand, "{ext[1:]}" );
|
121 |
+
viewer.getModel(2).setStyle({{stick:{{colorscheme:"greenCarbon"}}}});"""
|
122 |
+
except AttributeError as e:
|
123 |
+
ligand = None
|
124 |
+
lig_str_1 = ""
|
125 |
+
lig_str_2 = ""
|
126 |
+
|
127 |
+
x = (
|
128 |
+
"""<!DOCTYPE html>
|
129 |
+
<html>
|
130 |
+
<head>
|
131 |
+
<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
|
132 |
+
<style>
|
133 |
+
body{
|
134 |
+
font-family:sans-serif
|
135 |
+
}
|
136 |
+
.mol-container {
|
137 |
+
width: 600px;
|
138 |
+
height: 600px;
|
139 |
+
position: relative;
|
140 |
+
mx-auto:0
|
141 |
+
}
|
142 |
+
.mol-container select{
|
143 |
+
background-image:None;
|
144 |
+
}
|
145 |
+
.green{
|
146 |
+
width:20px;
|
147 |
+
height:20px;
|
148 |
+
background-color:#33ff45;
|
149 |
+
display:inline-block;
|
150 |
+
}
|
151 |
+
.magenta{
|
152 |
+
width:20px;
|
153 |
+
height:20px;
|
154 |
+
background-color:magenta;
|
155 |
+
display:inline-block;
|
156 |
+
}
|
157 |
+
</style>
|
158 |
+
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.3/jquery.min.js" integrity="sha512-STof4xm1wgkfm7heWqFJVn58Hm3EtS31XFaagaa8VMReCXAkQnJZ+jEy8PCC/iT18dFy95WcExNHFTqLyp72eQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
|
159 |
+
<script src="https://3Dmol.csb.pitt.edu/build/3Dmol-min.js"></script>
|
160 |
+
</head>
|
161 |
+
<body>
|
162 |
+
<button id="startanimation">Replay diffusion process</button>
|
163 |
+
<button id="togglesurface">Toggle surface representation</button>
|
164 |
+
<div>
|
165 |
+
<span class="green"></span> Uploaded ligand position
|
166 |
+
<span class="magenta"></span> Predicted ligand position
|
167 |
+
</div>
|
168 |
+
<div id="container" class="mol-container"></div>
|
169 |
+
|
170 |
+
<script>
|
171 |
+
let ligand = `"""
|
172 |
+
+ mol
|
173 |
+
+ """`
|
174 |
+
let structure = `"""
|
175 |
+
+ structure
|
176 |
+
+ """`
|
177 |
+
"""
|
178 |
+
+ lig_str_1
|
179 |
+
+ """
|
180 |
+
|
181 |
+
let viewer = null;
|
182 |
+
let surface = false;
|
183 |
+
let surf = null;
|
184 |
+
$(document).ready(function () {
|
185 |
+
let element = $("#container");
|
186 |
+
let config = { backgroundColor: "white" };
|
187 |
+
viewer = $3Dmol.createViewer(element, config);
|
188 |
+
viewer.addModel( structure, "pdb" );
|
189 |
+
viewer.setStyle({}, {cartoon: {color: "gray"}});
|
190 |
+
viewer.zoomTo();
|
191 |
+
viewer.zoom(0.7);
|
192 |
+
viewer.addModelsAsFrames(ligand, "pdb");
|
193 |
+
viewer.animate({loop: "forward",reps: 1});
|
194 |
+
|
195 |
+
viewer.getModel(1).setStyle({stick:{colorscheme:"magentaCarbon"}});
|
196 |
+
"""
|
197 |
+
+ lig_str_2
|
198 |
+
+ """
|
199 |
+
viewer.render();
|
200 |
+
|
201 |
+
})
|
202 |
+
|
203 |
+
$("#startanimation").click(function() {
|
204 |
+
viewer.animate({loop: "forward",reps: 1});
|
205 |
+
});
|
206 |
+
$("#togglesurface").click(function() {
|
207 |
+
if (surface != true) {
|
208 |
+
surf = viewer.addSurface($3Dmol.SurfaceType.VDW, { "opacity": 0.9, "color": "white" }, { model: 0 });
|
209 |
+
surface = true;
|
210 |
+
} else {
|
211 |
+
viewer.removeAllSurfaces()
|
212 |
+
surface = false;
|
213 |
+
}
|
214 |
+
});
|
215 |
+
</script>
|
216 |
+
</body></html>"""
|
217 |
+
)
|
218 |
+
|
219 |
+
return f"""<iframe style="width: 100%; height: 700px" name="result" allow="midi; geolocation; microphone; camera;
|
220 |
+
display-capture; encrypted-media;" sandbox="allow-modals allow-forms
|
221 |
+
allow-scripts allow-same-origin allow-popups
|
222 |
+
allow-top-navigation-by-user-activation allow-downloads" allowfullscreen=""
|
223 |
+
allowpaymentrequest="" frameborder="0" srcdoc='{x}'></iframe>"""
|
224 |
+
|
225 |
+
|
226 |
+
import sys
|
227 |
+
|
228 |
+
|
229 |
+
def esm(protein_path, out_file):
|
230 |
+
print("running esm")
|
231 |
+
esm_embedding_prep(out_file, protein_path)
|
232 |
+
# create args object with defaults
|
233 |
+
os.environ["HOME"] = "esm/model_weights"
|
234 |
+
subprocess.call(
|
235 |
+
f"python esm/scripts/extract.py esm2_t33_650M_UR50D {out_file} data/esm2_output --repr_layers 33 --include per_tok",
|
236 |
+
shell=True,
|
237 |
+
env=os.environ,
|
238 |
+
)
|
239 |
+
|
240 |
+
|
241 |
+
def update(inp, file, ligand_inp, ligand_file, n_it, n_samples, actual_steps, no_final_step_noise):
|
242 |
+
pdb_path = get_pdb(inp, file)
|
243 |
+
ligand_path = get_ligand(ligand_inp, ligand_file)
|
244 |
+
|
245 |
+
esm(
|
246 |
+
pdb_path,
|
247 |
+
f"data/{os.path.basename(pdb_path)}_prepared_for_esm.fasta",
|
248 |
+
)
|
249 |
+
tr_schedule = get_t_schedule(inference_steps=n_it)
|
250 |
+
rot_schedule = tr_schedule
|
251 |
+
tor_schedule = tr_schedule
|
252 |
+
print("common t schedule", tr_schedule)
|
253 |
+
(
|
254 |
+
failures,
|
255 |
+
skipped,
|
256 |
+
confidences_list,
|
257 |
+
names_list,
|
258 |
+
run_times,
|
259 |
+
min_self_distances_list,
|
260 |
+
) = (
|
261 |
+
0,
|
262 |
+
0,
|
263 |
+
[],
|
264 |
+
[],
|
265 |
+
[],
|
266 |
+
[],
|
267 |
+
)
|
268 |
+
N = n_samples # number of samples to generate
|
269 |
+
protein_path_list = [pdb_path]
|
270 |
+
ligand_descriptions = [ligand_path]
|
271 |
+
no_random = False
|
272 |
+
ode = False
|
273 |
+
no_final_step_noise = no_final_step_noise
|
274 |
+
out_dir = "results/"
|
275 |
+
test_dataset = PDBBind(
|
276 |
+
transform=None,
|
277 |
+
root="",
|
278 |
+
protein_path_list=protein_path_list,
|
279 |
+
ligand_descriptions=ligand_descriptions,
|
280 |
+
receptor_radius=score_model_args.receptor_radius,
|
281 |
+
cache_path="data/cache",
|
282 |
+
remove_hs=score_model_args.remove_hs,
|
283 |
+
max_lig_size=None,
|
284 |
+
c_alpha_max_neighbors=score_model_args.c_alpha_max_neighbors,
|
285 |
+
matching=False,
|
286 |
+
keep_original=False,
|
287 |
+
popsize=score_model_args.matching_popsize,
|
288 |
+
maxiter=score_model_args.matching_maxiter,
|
289 |
+
all_atoms=score_model_args.all_atoms,
|
290 |
+
atom_radius=score_model_args.atom_radius,
|
291 |
+
atom_max_neighbors=score_model_args.atom_max_neighbors,
|
292 |
+
esm_embeddings_path="data/esm2_output",
|
293 |
+
require_ligand=True,
|
294 |
+
num_workers=1,
|
295 |
+
keep_local_structures=False,
|
296 |
+
)
|
297 |
+
test_loader = DataLoader(dataset=test_dataset, batch_size=1, shuffle=False)
|
298 |
+
confidence_test_dataset = PDBBind(
|
299 |
+
transform=None,
|
300 |
+
root="",
|
301 |
+
protein_path_list=protein_path_list,
|
302 |
+
ligand_descriptions=ligand_descriptions,
|
303 |
+
receptor_radius=confidence_args.receptor_radius,
|
304 |
+
cache_path="data/cache",
|
305 |
+
remove_hs=confidence_args.remove_hs,
|
306 |
+
max_lig_size=None,
|
307 |
+
c_alpha_max_neighbors=confidence_args.c_alpha_max_neighbors,
|
308 |
+
matching=False,
|
309 |
+
keep_original=False,
|
310 |
+
popsize=confidence_args.matching_popsize,
|
311 |
+
maxiter=confidence_args.matching_maxiter,
|
312 |
+
all_atoms=confidence_args.all_atoms,
|
313 |
+
atom_radius=confidence_args.atom_radius,
|
314 |
+
atom_max_neighbors=confidence_args.atom_max_neighbors,
|
315 |
+
esm_embeddings_path="data/esm2_output",
|
316 |
+
require_ligand=True,
|
317 |
+
num_workers=1,
|
318 |
+
)
|
319 |
+
confidence_complex_dict = {d.name: d for d in confidence_test_dataset}
|
320 |
+
for idx, orig_complex_graph in tqdm(enumerate(test_loader)):
|
321 |
+
if (
|
322 |
+
confidence_model is not None
|
323 |
+
and not (
|
324 |
+
confidence_args.use_original_model_cache
|
325 |
+
or confidence_args.transfer_weights
|
326 |
+
)
|
327 |
+
and orig_complex_graph.name[0] not in confidence_complex_dict.keys()
|
328 |
+
):
|
329 |
+
skipped += 1
|
330 |
+
print(
|
331 |
+
f"HAPPENING | The confidence dataset did not contain {orig_complex_graph.name[0]}. We are skipping this complex."
|
332 |
+
)
|
333 |
+
continue
|
334 |
+
try:
|
335 |
+
data_list = [copy.deepcopy(orig_complex_graph) for _ in range(N)]
|
336 |
+
randomize_position(
|
337 |
+
data_list,
|
338 |
+
score_model_args.no_torsion,
|
339 |
+
no_random,
|
340 |
+
score_model_args.tr_sigma_max,
|
341 |
+
)
|
342 |
+
pdb = None
|
343 |
+
lig = orig_complex_graph.mol[0]
|
344 |
+
visualization_list = []
|
345 |
+
for graph in data_list:
|
346 |
+
pdb = PDBFile(lig)
|
347 |
+
pdb.add(lig, 0, 0)
|
348 |
+
pdb.add(
|
349 |
+
(
|
350 |
+
orig_complex_graph["ligand"].pos
|
351 |
+
+ orig_complex_graph.original_center
|
352 |
+
)
|
353 |
+
.detach()
|
354 |
+
.cpu(),
|
355 |
+
1,
|
356 |
+
0,
|
357 |
+
)
|
358 |
+
pdb.add(
|
359 |
+
(graph["ligand"].pos + graph.original_center).detach().cpu(),
|
360 |
+
part=1,
|
361 |
+
order=1,
|
362 |
+
)
|
363 |
+
visualization_list.append(pdb)
|
364 |
+
|
365 |
+
start_time = time.time()
|
366 |
+
if confidence_model is not None and not (
|
367 |
+
confidence_args.use_original_model_cache
|
368 |
+
or confidence_args.transfer_weights
|
369 |
+
):
|
370 |
+
confidence_data_list = [
|
371 |
+
copy.deepcopy(confidence_complex_dict[orig_complex_graph.name[0]])
|
372 |
+
for _ in range(N)
|
373 |
+
]
|
374 |
+
else:
|
375 |
+
confidence_data_list = None
|
376 |
+
|
377 |
+
data_list, confidence = sampling(
|
378 |
+
data_list=data_list,
|
379 |
+
model=model,
|
380 |
+
inference_steps=actual_steps,
|
381 |
+
tr_schedule=tr_schedule,
|
382 |
+
rot_schedule=rot_schedule,
|
383 |
+
tor_schedule=tor_schedule,
|
384 |
+
device=device,
|
385 |
+
t_to_sigma=t_to_sigma,
|
386 |
+
model_args=score_model_args,
|
387 |
+
no_random=no_random,
|
388 |
+
ode=ode,
|
389 |
+
visualization_list=visualization_list,
|
390 |
+
confidence_model=confidence_model,
|
391 |
+
confidence_data_list=confidence_data_list,
|
392 |
+
confidence_model_args=confidence_args,
|
393 |
+
batch_size=1,
|
394 |
+
no_final_step_noise=no_final_step_noise,
|
395 |
+
)
|
396 |
+
ligand_pos = np.asarray(
|
397 |
+
[
|
398 |
+
complex_graph["ligand"].pos.cpu().numpy()
|
399 |
+
+ orig_complex_graph.original_center.cpu().numpy()
|
400 |
+
for complex_graph in data_list
|
401 |
+
]
|
402 |
+
)
|
403 |
+
run_times.append(time.time() - start_time)
|
404 |
+
|
405 |
+
if confidence is not None and isinstance(
|
406 |
+
confidence_args.rmsd_classification_cutoff, list
|
407 |
+
):
|
408 |
+
confidence = confidence[:, 0]
|
409 |
+
if confidence is not None:
|
410 |
+
confidence = confidence.cpu().numpy()
|
411 |
+
re_order = np.argsort(confidence)[::-1]
|
412 |
+
confidence = confidence[re_order]
|
413 |
+
confidences_list.append(confidence)
|
414 |
+
ligand_pos = ligand_pos[re_order]
|
415 |
+
write_dir = (
|
416 |
+
f'{out_dir}/index{idx}_{data_list[0]["name"][0].replace("/","-")}'
|
417 |
+
)
|
418 |
+
os.makedirs(write_dir, exist_ok=True)
|
419 |
+
confidences = []
|
420 |
+
for rank, pos in enumerate(ligand_pos):
|
421 |
+
mol_pred = copy.deepcopy(lig)
|
422 |
+
if score_model_args.remove_hs:
|
423 |
+
mol_pred = RemoveHs(mol_pred)
|
424 |
+
if rank == 0:
|
425 |
+
write_mol_with_coords(
|
426 |
+
mol_pred, pos, os.path.join(write_dir, f"rank{rank+1}.sdf")
|
427 |
+
)
|
428 |
+
confidences.append(confidence[rank])
|
429 |
+
write_mol_with_coords(
|
430 |
+
mol_pred,
|
431 |
+
pos,
|
432 |
+
os.path.join(
|
433 |
+
write_dir, f"rank{rank+1}_confidence{confidence[rank]:.2f}.sdf"
|
434 |
+
),
|
435 |
+
)
|
436 |
+
self_distances = np.linalg.norm(
|
437 |
+
ligand_pos[:, :, None, :] - ligand_pos[:, None, :, :], axis=-1
|
438 |
+
)
|
439 |
+
self_distances = np.where(
|
440 |
+
np.eye(self_distances.shape[2]), np.inf, self_distances
|
441 |
+
)
|
442 |
+
min_self_distances_list.append(np.min(self_distances, axis=(1, 2)))
|
443 |
+
|
444 |
+
filenames = []
|
445 |
+
if confidence is not None:
|
446 |
+
for rank, batch_idx in enumerate(re_order):
|
447 |
+
visualization_list[batch_idx].write(
|
448 |
+
os.path.join(write_dir, f"rank{rank+1}_reverseprocess.pdb")
|
449 |
+
)
|
450 |
+
filenames.append(
|
451 |
+
os.path.join(write_dir, f"rank{rank+1}_reverseprocess.pdb")
|
452 |
+
)
|
453 |
+
else:
|
454 |
+
for rank, batch_idx in enumerate(ligand_pos):
|
455 |
+
visualization_list[batch_idx].write(
|
456 |
+
os.path.join(write_dir, f"rank{rank+1}_reverseprocess.pdb")
|
457 |
+
)
|
458 |
+
filenames.append(
|
459 |
+
os.path.join(write_dir, f"rank{rank+1}_reverseprocess.pdb")
|
460 |
+
)
|
461 |
+
names_list.append(orig_complex_graph.name[0])
|
462 |
+
except Exception as e:
|
463 |
+
print("Failed on", orig_complex_graph["name"], e)
|
464 |
+
failures += 1
|
465 |
+
return None
|
466 |
+
# zip outputs
|
467 |
+
zippath = shutil.make_archive(
|
468 |
+
os.path.join("results", os.path.basename(pdb_path)), "zip", write_dir
|
469 |
+
)
|
470 |
+
print("Zipped outputs to", zippath)
|
471 |
+
labels = [
|
472 |
+
f"rank {i+1}, confidence {confidences[i]:.2f}" for i in range(len(filenames))
|
473 |
+
]
|
474 |
+
|
475 |
+
torch.cuda.empty_cache()
|
476 |
+
return (
|
477 |
+
molecule(pdb_path, filenames[0], ligand_file),
|
478 |
+
gr.Dropdown.update(choices=labels, value=labels[0]),
|
479 |
+
filenames,
|
480 |
+
pdb_path,
|
481 |
+
zippath,
|
482 |
+
)
|
483 |
+
|
484 |
+
|
485 |
+
def updateView(out, filenames, pdb, ligand_file):
|
486 |
+
print("updating view")
|
487 |
+
i = out # int(out.replace("rank", ""))
|
488 |
+
print(i)
|
489 |
+
i = int(i.split(",")[0].replace("rank", "")) - 1
|
490 |
+
return molecule(pdb, filenames[i], ligand_file)
|
491 |
+
|
492 |
+
|
493 |
+
demo = gr.Blocks()
|
494 |
+
|
495 |
+
with demo:
|
496 |
+
gr.Markdown("# DiffDock")
|
497 |
+
gr.Markdown(
|
498 |
+
">**DiffDock: Diffusion Steps, Twists, and Turns for Molecular Docking**, Corso, Gabriele and Stärk, Hannes and Jing, Bowen and Barzilay, Regina and Jaakkola, Tommi, arXiv:2210.01776 [GitHub](https://github.com/gcorso/diffdock)"
|
499 |
+
)
|
500 |
+
gr.Markdown("")
|
501 |
+
with gr.Box():
|
502 |
+
with gr.Row():
|
503 |
+
with gr.Column():
|
504 |
+
gr.Markdown("## Protein")
|
505 |
+
inp = gr.Textbox(
|
506 |
+
placeholder="PDB Code or upload file below", label="Input structure"
|
507 |
+
)
|
508 |
+
file = gr.File(file_count="single", label="Input PDB")
|
509 |
+
with gr.Column():
|
510 |
+
gr.Markdown("## Ligand")
|
511 |
+
ligand_inp = gr.Textbox(
|
512 |
+
placeholder="Provide SMILES input or upload mol2/sdf file below",
|
513 |
+
label="SMILES string",
|
514 |
+
)
|
515 |
+
ligand_file = gr.File(file_count="single", label="Input Ligand")
|
516 |
+
n_it = gr.Slider(value=20,
|
517 |
+
minimum=10, maximum=40, label="Number of inference steps", step=1
|
518 |
+
)
|
519 |
+
actual_steps = gr.Slider(value=18,
|
520 |
+
minimum=10, maximum=40, label="Number of actual inference steps", step=1
|
521 |
+
)
|
522 |
+
n_samples = gr.Slider(value=40,
|
523 |
+
minimum=10, maximum=40, label="Number of samples", step=1
|
524 |
+
)
|
525 |
+
no_final_step_noise = gr.Checkbox(value=True,label="No final step noise"
|
526 |
+
)
|
527 |
+
|
528 |
+
btn = gr.Button("Run predictions")
|
529 |
+
|
530 |
+
gr.Markdown("## Output")
|
531 |
+
pdb = gr.Variable()
|
532 |
+
filenames = gr.Variable()
|
533 |
+
out = gr.Dropdown(interactive=True, label="Ranked samples")
|
534 |
+
mol = gr.HTML()
|
535 |
+
output_file = gr.File(file_count="single", label="Output files")
|
536 |
+
gr.Examples(
|
537 |
+
[
|
538 |
+
[
|
539 |
+
"6w70",
|
540 |
+
"examples/6w70.pdb",
|
541 |
+
"COc1ccc(cc1)n2c3c(c(n2)C(=O)N)CCN(C3=O)c4ccc(cc4)N5CCCCC5=O",
|
542 |
+
"examples/6w70_ligand.sdf",
|
543 |
+
20,
|
544 |
+
10,
|
545 |
+
18,
|
546 |
+
True
|
547 |
+
],
|
548 |
+
[
|
549 |
+
"6moa",
|
550 |
+
"examples/6moa_protein_processed.pdb",
|
551 |
+
"",
|
552 |
+
"examples/6moa_ligand.sdf",
|
553 |
+
20,
|
554 |
+
10,
|
555 |
+
18,
|
556 |
+
True
|
557 |
+
],
|
558 |
+
[
|
559 |
+
"",
|
560 |
+
"examples/6o5u_protein_processed.pdb",
|
561 |
+
"",
|
562 |
+
"examples/6o5u_ligand.sdf",
|
563 |
+
20,
|
564 |
+
10,
|
565 |
+
18,
|
566 |
+
True
|
567 |
+
],
|
568 |
+
[
|
569 |
+
"",
|
570 |
+
"examples/6o5u_protein_processed.pdb",
|
571 |
+
"[NH3+]C[C@H]1O[C@H](O[C@@H]2[C@@H]([NH3+])C[C@H]([C@@H]([C@H]2O)O[C@H]2O[C@H](CO)[C@H]([C@@H]([C@H]2O)[NH3+])O)[NH3+])[C@@H]([C@H]([C@@H]1O)O)O",
|
572 |
+
"examples/6o5u_ligand.sdf",
|
573 |
+
20,
|
574 |
+
10,
|
575 |
+
18,
|
576 |
+
True
|
577 |
+
],
|
578 |
+
[
|
579 |
+
"",
|
580 |
+
"examples/6o5u_protein_processed.pdb",
|
581 |
+
"",
|
582 |
+
"examples/6o5u_ligand.sdf",
|
583 |
+
20,
|
584 |
+
10,
|
585 |
+
18,
|
586 |
+
True
|
587 |
+
],
|
588 |
+
[
|
589 |
+
"",
|
590 |
+
"examples/6ahs_protein_processed.pdb",
|
591 |
+
"",
|
592 |
+
"examples/6ahs_ligand.sdf",
|
593 |
+
20,
|
594 |
+
10,
|
595 |
+
18,
|
596 |
+
True
|
597 |
+
],
|
598 |
+
],
|
599 |
+
[inp, file, ligand_inp, ligand_file, n_it, n_samples, actual_steps, no_final_step_noise],
|
600 |
+
[mol, out, filenames, pdb, output_file],
|
601 |
+
# fn=update,
|
602 |
+
# cache_examples=True,
|
603 |
+
)
|
604 |
+
btn.click(
|
605 |
+
fn=update,
|
606 |
+
inputs=[inp, file, ligand_inp, ligand_file, n_it, n_samples, actual_steps, no_final_step_noise],
|
607 |
+
outputs=[mol, out, filenames, pdb, output_file],
|
608 |
+
)
|
609 |
+
out.change(fn=updateView, inputs=[out, filenames, pdb, ligand_file], outputs=mol)
|
610 |
+
demo.launch()
|
baselines/baseline_evaluation.py
ADDED
@@ -0,0 +1,219 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# small script to extract the ligand and save it in a separate file because GNINA will use the ligand position as initial pose
|
2 |
+
import os
|
3 |
+
|
4 |
+
import plotly.express as px
|
5 |
+
import time
|
6 |
+
from argparse import FileType, ArgumentParser
|
7 |
+
|
8 |
+
import numpy as np
|
9 |
+
import pandas as pd
|
10 |
+
import wandb
|
11 |
+
from biopandas.pdb import PandasPdb
|
12 |
+
from rdkit import Chem
|
13 |
+
|
14 |
+
from tqdm import tqdm
|
15 |
+
|
16 |
+
from datasets.pdbbind import read_mol
|
17 |
+
from datasets.process_mols import read_molecule
|
18 |
+
from utils.utils import read_strings_from_txt, get_symmetry_rmsd
|
19 |
+
|
20 |
+
parser = ArgumentParser()
|
21 |
+
parser.add_argument('--config', type=FileType(mode='r'), default=None)
|
22 |
+
parser.add_argument('--run_name', type=str, default='gnina_results', help='')
|
23 |
+
parser.add_argument('--data_dir', type=str, default='data/PDBBind_processed', help='')
|
24 |
+
parser.add_argument('--results_path', type=str, default='results/user_inference', help='Path to folder with trained model and hyperparameters')
|
25 |
+
parser.add_argument('--file_suffix', type=str, default='_baseline_ligand.pdb', help='Path to folder with trained model and hyperparameters')
|
26 |
+
parser.add_argument('--project', type=str, default='ligbind_inf', help='')
|
27 |
+
parser.add_argument('--wandb', action='store_true', default=False, help='')
|
28 |
+
parser.add_argument('--file_to_exclude', type=str, default=None, help='')
|
29 |
+
parser.add_argument('--all_dirs_in_results', action='store_true', default=True, help='Evaluate all directories in the results path instead of using directly looking for the names')
|
30 |
+
parser.add_argument('--num_predictions', type=int, default=10, help='')
|
31 |
+
parser.add_argument('--no_id_in_filename', action='store_true', default=False, help='')
|
32 |
+
args = parser.parse_args()
|
33 |
+
|
34 |
+
print('Reading paths and names.')
|
35 |
+
names = read_strings_from_txt(f'data/splits/timesplit_test')
|
36 |
+
names_no_rec_overlap = read_strings_from_txt(f'data/splits/timesplit_test_no_rec_overlap')
|
37 |
+
results_path_containments = os.listdir(args.results_path)
|
38 |
+
|
39 |
+
if args.wandb:
|
40 |
+
wandb.init(
|
41 |
+
entity='coarse-graining-mit',
|
42 |
+
settings=wandb.Settings(start_method="fork"),
|
43 |
+
project=args.project,
|
44 |
+
name=args.run_name,
|
45 |
+
config=args
|
46 |
+
)
|
47 |
+
|
48 |
+
all_times = []
|
49 |
+
successful_names_list = []
|
50 |
+
rmsds_list = []
|
51 |
+
centroid_distances_list = []
|
52 |
+
min_cross_distances_list = []
|
53 |
+
min_self_distances_list = []
|
54 |
+
without_rec_overlap_list = []
|
55 |
+
start_time = time.time()
|
56 |
+
for i, name in enumerate(tqdm(names)):
|
57 |
+
mol = read_mol(args.data_dir, name, remove_hs=True)
|
58 |
+
mol = Chem.RemoveAllHs(mol)
|
59 |
+
orig_ligand_pos = np.array(mol.GetConformer().GetPositions())
|
60 |
+
|
61 |
+
if args.all_dirs_in_results:
|
62 |
+
directory_with_name = [directory for directory in results_path_containments if name in directory][0]
|
63 |
+
ligand_pos = []
|
64 |
+
for i in range(args.num_predictions):
|
65 |
+
file_paths = os.listdir(os.path.join(args.results_path, directory_with_name))
|
66 |
+
file_path = [path for path in file_paths if f'rank{i+1}' in path][0]
|
67 |
+
if args.file_to_exclude is not None and args.file_to_exclude in file_path: continue
|
68 |
+
mol_pred = read_molecule(os.path.join(args.results_path, directory_with_name, file_path),remove_hs=True, sanitize=True)
|
69 |
+
mol_pred = Chem.RemoveAllHs(mol_pred)
|
70 |
+
ligand_pos.append(mol_pred.GetConformer().GetPositions())
|
71 |
+
ligand_pos = np.asarray(ligand_pos)
|
72 |
+
else:
|
73 |
+
if not os.path.exists(os.path.join(args.results_path, name, f'{"" if args.no_id_in_filename else name}{args.file_suffix}')): raise Exception('path did not exists:', os.path.join(args.results_path, name, f'{"" if args.no_id_in_filename else name}{args.file_suffix}'))
|
74 |
+
mol_pred = read_molecule(os.path.join(args.results_path, name, f'{"" if args.no_id_in_filename else name}{args.file_suffix}'), remove_hs=True, sanitize=True)
|
75 |
+
if mol_pred == None:
|
76 |
+
print("Skipping ", name, ' because RDKIT could not read it.')
|
77 |
+
continue
|
78 |
+
mol_pred = Chem.RemoveAllHs(mol_pred)
|
79 |
+
ligand_pos = np.asarray([np.array(mol_pred.GetConformer(i).GetPositions()) for i in range(args.num_predictions)])
|
80 |
+
try:
|
81 |
+
rmsd = get_symmetry_rmsd(mol, orig_ligand_pos, [l for l in ligand_pos], mol_pred)
|
82 |
+
except Exception as e:
|
83 |
+
print("Using non corrected RMSD because of the error:", e)
|
84 |
+
rmsd = np.sqrt(((ligand_pos - orig_ligand_pos) ** 2).sum(axis=2).mean(axis=1))
|
85 |
+
|
86 |
+
rmsds_list.append(rmsd)
|
87 |
+
centroid_distances_list.append(np.linalg.norm(ligand_pos.mean(axis=1) - orig_ligand_pos[None,:].mean(axis=1), axis=1))
|
88 |
+
|
89 |
+
rec_path = os.path.join(args.data_dir, name, f'{name}_protein_processed.pdb')
|
90 |
+
if not os.path.exists(rec_path):
|
91 |
+
rec_path = os.path.join(args.data_dir, name,f'{name}_protein_obabel_reduce.pdb')
|
92 |
+
rec = PandasPdb().read_pdb(rec_path)
|
93 |
+
rec_df = rec.df['ATOM']
|
94 |
+
receptor_pos = rec_df[['x_coord', 'y_coord', 'z_coord']].to_numpy().squeeze().astype(np.float32)
|
95 |
+
receptor_pos = np.tile(receptor_pos, (args.num_predictions, 1, 1))
|
96 |
+
|
97 |
+
cross_distances = np.linalg.norm(receptor_pos[:, :, None, :] - ligand_pos[:, None, :, :], axis=-1)
|
98 |
+
self_distances = np.linalg.norm(ligand_pos[:, :, None, :] - ligand_pos[:, None, :, :], axis=-1)
|
99 |
+
self_distances = np.where(np.eye(self_distances.shape[2]), np.inf, self_distances)
|
100 |
+
min_cross_distances_list.append(np.min(cross_distances, axis=(1,2)))
|
101 |
+
min_self_distances_list.append(np.min(self_distances, axis=(1, 2)))
|
102 |
+
successful_names_list.append(name)
|
103 |
+
without_rec_overlap_list.append(1 if name in names_no_rec_overlap else 0)
|
104 |
+
performance_metrics = {}
|
105 |
+
for overlap in ['', 'no_overlap_']:
|
106 |
+
if 'no_overlap_' == overlap:
|
107 |
+
without_rec_overlap = np.array(without_rec_overlap_list, dtype=bool)
|
108 |
+
rmsds = np.array(rmsds_list)[without_rec_overlap]
|
109 |
+
centroid_distances = np.array(centroid_distances_list)[without_rec_overlap]
|
110 |
+
min_cross_distances = np.array(min_cross_distances_list)[without_rec_overlap]
|
111 |
+
min_self_distances = np.array(min_self_distances_list)[without_rec_overlap]
|
112 |
+
successful_names = np.array(successful_names_list)[without_rec_overlap]
|
113 |
+
else:
|
114 |
+
rmsds = np.array(rmsds_list)
|
115 |
+
centroid_distances = np.array(centroid_distances_list)
|
116 |
+
min_cross_distances = np.array(min_cross_distances_list)
|
117 |
+
min_self_distances = np.array(min_self_distances_list)
|
118 |
+
successful_names = np.array(successful_names_list)
|
119 |
+
|
120 |
+
np.save(os.path.join(args.results_path, f'{overlap}rmsds.npy'), rmsds)
|
121 |
+
np.save(os.path.join(args.results_path, f'{overlap}names.npy'), successful_names)
|
122 |
+
np.save(os.path.join(args.results_path, f'{overlap}min_cross_distances.npy'), np.array(min_cross_distances))
|
123 |
+
np.save(os.path.join(args.results_path, f'{overlap}min_self_distances.npy'), np.array(min_self_distances))
|
124 |
+
|
125 |
+
performance_metrics.update({
|
126 |
+
f'{overlap}steric_clash_fraction': (100 * (min_cross_distances < 0.4).sum() / len(min_cross_distances) / args.num_predictions).__round__(2),
|
127 |
+
f'{overlap}self_intersect_fraction': (100 * (min_self_distances < 0.4).sum() / len(min_self_distances) / args.num_predictions).__round__(2),
|
128 |
+
f'{overlap}mean_rmsd': rmsds[:,0].mean(),
|
129 |
+
f'{overlap}rmsds_below_2': (100 * (rmsds[:,0] < 2).sum() / len(rmsds[:,0])),
|
130 |
+
f'{overlap}rmsds_below_5': (100 * (rmsds[:,0] < 5).sum() / len(rmsds[:,0])),
|
131 |
+
f'{overlap}rmsds_percentile_25': np.percentile(rmsds[:,0], 25).round(2),
|
132 |
+
f'{overlap}rmsds_percentile_50': np.percentile(rmsds[:,0], 50).round(2),
|
133 |
+
f'{overlap}rmsds_percentile_75': np.percentile(rmsds[:,0], 75).round(2),
|
134 |
+
|
135 |
+
f'{overlap}mean_centroid': centroid_distances[:,0].mean().__round__(2),
|
136 |
+
f'{overlap}centroid_below_2': (100 * (centroid_distances[:,0] < 2).sum() / len(centroid_distances[:,0])).__round__(2),
|
137 |
+
f'{overlap}centroid_below_5': (100 * (centroid_distances[:,0] < 5).sum() / len(centroid_distances[:,0])).__round__(2),
|
138 |
+
f'{overlap}centroid_percentile_25': np.percentile(centroid_distances[:,0], 25).round(2),
|
139 |
+
f'{overlap}centroid_percentile_50': np.percentile(centroid_distances[:,0], 50).round(2),
|
140 |
+
f'{overlap}centroid_percentile_75': np.percentile(centroid_distances[:,0], 75).round(2),
|
141 |
+
})
|
142 |
+
|
143 |
+
top5_rmsds = np.min(rmsds[:, :5], axis=1)
|
144 |
+
top5_centroid_distances = centroid_distances[np.arange(rmsds.shape[0])[:,None],np.argsort(rmsds[:, :5], axis=1)][:,0]
|
145 |
+
top5_min_cross_distances = min_cross_distances[np.arange(rmsds.shape[0])[:,None],np.argsort(rmsds[:, :5], axis=1)][:,0]
|
146 |
+
top5_min_self_distances = min_self_distances[np.arange(rmsds.shape[0])[:,None],np.argsort(rmsds[:, :5], axis=1)][:,0]
|
147 |
+
performance_metrics.update({
|
148 |
+
f'{overlap}top5_steric_clash_fraction': (100 * (top5_min_cross_distances < 0.4).sum() / len(top5_min_cross_distances)).__round__(2),
|
149 |
+
f'{overlap}top5_self_intersect_fraction': (100 * (top5_min_self_distances < 0.4).sum() / len(top5_min_self_distances)).__round__(2),
|
150 |
+
f'{overlap}top5_rmsds_below_2': (100 * (top5_rmsds < 2).sum() / len(top5_rmsds)).__round__(2),
|
151 |
+
f'{overlap}top5_rmsds_below_5': (100 * (top5_rmsds < 5).sum() / len(top5_rmsds)).__round__(2),
|
152 |
+
f'{overlap}top5_rmsds_percentile_25': np.percentile(top5_rmsds, 25).round(2),
|
153 |
+
f'{overlap}top5_rmsds_percentile_50': np.percentile(top5_rmsds, 50).round(2),
|
154 |
+
f'{overlap}top5_rmsds_percentile_75': np.percentile(top5_rmsds, 75).round(2),
|
155 |
+
|
156 |
+
f'{overlap}top5_centroid_below_2': (100 * (top5_centroid_distances < 2).sum() / len(top5_centroid_distances)).__round__(2),
|
157 |
+
f'{overlap}top5_centroid_below_5': (100 * (top5_centroid_distances < 5).sum() / len(top5_centroid_distances)).__round__(2),
|
158 |
+
f'{overlap}top5_centroid_percentile_25': np.percentile(top5_centroid_distances, 25).round(2),
|
159 |
+
f'{overlap}top5_centroid_percentile_50': np.percentile(top5_centroid_distances, 50).round(2),
|
160 |
+
f'{overlap}top5_centroid_percentile_75': np.percentile(top5_centroid_distances, 75).round(2),
|
161 |
+
})
|
162 |
+
|
163 |
+
|
164 |
+
top10_rmsds = np.min(rmsds[:, :10], axis=1)
|
165 |
+
top10_centroid_distances = centroid_distances[np.arange(rmsds.shape[0])[:,None],np.argsort(rmsds[:, :10], axis=1)][:,0]
|
166 |
+
top10_min_cross_distances = min_cross_distances[np.arange(rmsds.shape[0])[:,None],np.argsort(rmsds[:, :10], axis=1)][:,0]
|
167 |
+
top10_min_self_distances = min_self_distances[np.arange(rmsds.shape[0])[:,None],np.argsort(rmsds[:, :10], axis=1)][:,0]
|
168 |
+
performance_metrics.update({
|
169 |
+
f'{overlap}top10_self_intersect_fraction': (100 * (top10_min_self_distances < 0.4).sum() / len(top10_min_self_distances)).__round__(2),
|
170 |
+
f'{overlap}top10_steric_clash_fraction': ( 100 * (top10_min_cross_distances < 0.4).sum() / len(top10_min_cross_distances)).__round__(2),
|
171 |
+
f'{overlap}top10_rmsds_below_2': (100 * (top10_rmsds < 2).sum() / len(top10_rmsds)).__round__(2),
|
172 |
+
f'{overlap}top10_rmsds_below_5': (100 * (top10_rmsds < 5).sum() / len(top10_rmsds)).__round__(2),
|
173 |
+
f'{overlap}top10_rmsds_percentile_25': np.percentile(top10_rmsds, 25).round(2),
|
174 |
+
f'{overlap}top10_rmsds_percentile_50': np.percentile(top10_rmsds, 50).round(2),
|
175 |
+
f'{overlap}top10_rmsds_percentile_75': np.percentile(top10_rmsds, 75).round(2),
|
176 |
+
|
177 |
+
f'{overlap}top10_centroid_below_2': (100 * (top10_centroid_distances < 2).sum() / len(top10_centroid_distances)).__round__(2),
|
178 |
+
f'{overlap}top10_centroid_below_5': (100 * (top10_centroid_distances < 5).sum() / len(top10_centroid_distances)).__round__(2),
|
179 |
+
f'{overlap}top10_centroid_percentile_25': np.percentile(top10_centroid_distances, 25).round(2),
|
180 |
+
f'{overlap}top10_centroid_percentile_50': np.percentile(top10_centroid_distances, 50).round(2),
|
181 |
+
f'{overlap}top10_centroid_percentile_75': np.percentile(top10_centroid_distances, 75).round(2),
|
182 |
+
})
|
183 |
+
for k in performance_metrics:
|
184 |
+
print(k, performance_metrics[k])
|
185 |
+
|
186 |
+
if args.wandb:
|
187 |
+
wandb.log(performance_metrics)
|
188 |
+
histogram_metrics_list = [('rmsd', rmsds[:,0]),
|
189 |
+
('centroid_distance', centroid_distances[:,0]),
|
190 |
+
('mean_rmsd', rmsds[:,0]),
|
191 |
+
('mean_centroid_distance', centroid_distances[:,0])]
|
192 |
+
histogram_metrics_list.append(('top5_rmsds', top5_rmsds))
|
193 |
+
histogram_metrics_list.append(('top5_centroid_distances', top5_centroid_distances))
|
194 |
+
histogram_metrics_list.append(('top10_rmsds', top10_rmsds))
|
195 |
+
histogram_metrics_list.append(('top10_centroid_distances', top10_centroid_distances))
|
196 |
+
|
197 |
+
os.makedirs(f'.plotly_cache/baseline_cache', exist_ok=True)
|
198 |
+
images = []
|
199 |
+
for metric_name, metric in histogram_metrics_list:
|
200 |
+
d = {args.results_path: metric}
|
201 |
+
df = pd.DataFrame(data=d)
|
202 |
+
fig = px.ecdf(df, width=900, height=600, range_x=[0, 40])
|
203 |
+
fig.add_vline(x=2, annotation_text='2 A;', annotation_font_size=20, annotation_position="top right",
|
204 |
+
line_dash='dash', line_color='firebrick', annotation_font_color='firebrick')
|
205 |
+
fig.add_vline(x=5, annotation_text='5 A;', annotation_font_size=20, annotation_position="top right",
|
206 |
+
line_dash='dash', line_color='green', annotation_font_color='green')
|
207 |
+
fig.update_xaxes(title=f'{metric_name} in Angstrom', title_font={"size": 20}, tickfont={"size": 20})
|
208 |
+
fig.update_yaxes(title=f'Fraction of predictions with lower error', title_font={"size": 20},
|
209 |
+
tickfont={"size": 20})
|
210 |
+
fig.update_layout(autosize=False, margin={'l': 0, 'r': 0, 't': 0, 'b': 0}, plot_bgcolor='white',
|
211 |
+
paper_bgcolor='white', legend_title_text='Method', legend_title_font_size=17,
|
212 |
+
legend=dict(yanchor="bottom", y=0.1, xanchor="right", x=0.99, font=dict(size=17), ), )
|
213 |
+
fig.update_xaxes(showgrid=True, gridcolor='lightgrey')
|
214 |
+
fig.update_yaxes(showgrid=True, gridcolor='lightgrey')
|
215 |
+
|
216 |
+
fig.write_image(os.path.join(f'.plotly_cache/baseline_cache', f'{metric_name}.png'))
|
217 |
+
wandb.log({metric_name: wandb.Image(os.path.join(f'.plotly_cache/baseline_cache', f'{metric_name}.png'), caption=f"{metric_name}")})
|
218 |
+
images.append(wandb.Image(os.path.join(f'.plotly_cache/baseline_cache', f'{metric_name}.png'), caption=f"{metric_name}"))
|
219 |
+
wandb.log({'images': images})
|
baselines/baseline_gnina.py
ADDED
@@ -0,0 +1,175 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# small script to extract the ligand and save it in a separate file because GNINA will use the ligand position as
|
2 |
+
# initial pose
|
3 |
+
import os
|
4 |
+
import shutil
|
5 |
+
import subprocess
|
6 |
+
import sys
|
7 |
+
|
8 |
+
import time
|
9 |
+
from argparse import ArgumentParser, FileType
|
10 |
+
from datetime import datetime
|
11 |
+
|
12 |
+
import numpy as np
|
13 |
+
import pandas as pd
|
14 |
+
from biopandas.pdb import PandasPdb
|
15 |
+
from rdkit import Chem
|
16 |
+
from rdkit.Chem import AllChem, MolToPDBFile
|
17 |
+
from scipy.spatial.distance import cdist
|
18 |
+
|
19 |
+
from datasets.pdbbind import read_mol
|
20 |
+
from utils.utils import read_strings_from_txt
|
21 |
+
|
22 |
+
parser = ArgumentParser()
|
23 |
+
parser.add_argument('--data_dir', type=str, default='data/PDBBind_processed', help='')
|
24 |
+
parser.add_argument('--file_suffix', type=str, default='_baseline_ligand', help='Path to folder with trained model and hyperparameters')
|
25 |
+
parser.add_argument('--results_path', type=str, default='results/gnina_predictions', help='')
|
26 |
+
parser.add_argument('--complex_names_path', type=str, default='data/splits/timesplit_test', help='')
|
27 |
+
parser.add_argument('--seed_molecules_path', type=str, default=None, help='Use the molecules at seed molecule path as initialization and only search around them')
|
28 |
+
parser.add_argument('--seed_molecule_filename', type=str, default='equibind_corrected.sdf', help='Use the molecules at seed molecule path as initialization and only search around them')
|
29 |
+
parser.add_argument('--smina', action='store_true', default=False, help='')
|
30 |
+
parser.add_argument('--no_gpu', action='store_true', default=False, help='')
|
31 |
+
parser.add_argument('--exhaustiveness', type=int, default=8, help='')
|
32 |
+
parser.add_argument('--num_cpu', type=int, default=16, help='')
|
33 |
+
parser.add_argument('--pocket_mode', action='store_true', default=False, help='')
|
34 |
+
parser.add_argument('--pocket_cutoff', type=int, default=5, help='')
|
35 |
+
parser.add_argument('--num_modes', type=int, default=10, help='')
|
36 |
+
parser.add_argument('--autobox_add', type=int, default=4, help='')
|
37 |
+
parser.add_argument('--use_p2rank_pocket', action='store_true', default=False, help='')
|
38 |
+
parser.add_argument('--skip_p2rank', action='store_true', default=False, help='')
|
39 |
+
parser.add_argument('--prank_path', type=str, default='/Users/hstark/projects/p2rank_2.3/prank', help='')
|
40 |
+
parser.add_argument('--skip_existing', action='store_true', default=False, help='')
|
41 |
+
|
42 |
+
|
43 |
+
|
44 |
+
|
45 |
+
|
46 |
+
args = parser.parse_args()
|
47 |
+
|
48 |
+
class Logger(object):
|
49 |
+
def __init__(self, logpath, syspart=sys.stdout):
|
50 |
+
self.terminal = syspart
|
51 |
+
self.log = open(logpath, "a")
|
52 |
+
|
53 |
+
def write(self, message):
|
54 |
+
self.terminal.write(message)
|
55 |
+
self.log.write(message)
|
56 |
+
self.log.flush()
|
57 |
+
|
58 |
+
def flush(self):
|
59 |
+
# this flush method is needed for python 3 compatibility.
|
60 |
+
# this handles the flush command by doing nothing.
|
61 |
+
# you might want to specify some extra behavior here.
|
62 |
+
pass
|
63 |
+
|
64 |
+
|
65 |
+
def log(*args):
|
66 |
+
print(f'[{datetime.now()}]', *args)
|
67 |
+
|
68 |
+
|
69 |
+
# parameters
|
70 |
+
names = read_strings_from_txt(args.complex_names_path)
|
71 |
+
|
72 |
+
if os.path.exists(args.results_path) and not args.skip_existing:
|
73 |
+
shutil.rmtree(args.results_path)
|
74 |
+
os.makedirs(args.results_path, exist_ok=True)
|
75 |
+
sys.stdout = Logger(logpath=f'{args.results_path}/gnina.log', syspart=sys.stdout)
|
76 |
+
sys.stderr = Logger(logpath=f'{args.results_path}/error.log', syspart=sys.stderr)
|
77 |
+
|
78 |
+
p2rank_cache_path = "results/.p2rank_cache"
|
79 |
+
if args.use_p2rank_pocket and not args.skip_p2rank:
|
80 |
+
os.makedirs(p2rank_cache_path, exist_ok=True)
|
81 |
+
pdb_files_cache = os.path.join(p2rank_cache_path,'pdb_files')
|
82 |
+
os.makedirs(pdb_files_cache, exist_ok=True)
|
83 |
+
with open(f"{p2rank_cache_path}/pdb_list_p2rank.txt", "w") as out:
|
84 |
+
for name in names:
|
85 |
+
shutil.copy(os.path.join(args.data_dir, name, f'{name}_protein_processed.pdb'), f'{pdb_files_cache}/{name}_protein_processed.pdb')
|
86 |
+
out.write(os.path.join('pdb_files', f'{name}_protein_processed.pdb\n'))
|
87 |
+
cmd = f"bash {args.prank_path} predict {p2rank_cache_path}/pdb_list_p2rank.txt -o {p2rank_cache_path}/p2rank_output -threads 4"
|
88 |
+
os.system(cmd)
|
89 |
+
|
90 |
+
|
91 |
+
all_times = []
|
92 |
+
start_time = time.time()
|
93 |
+
for i, name in enumerate(names):
|
94 |
+
os.makedirs(os.path.join(args.results_path, name), exist_ok=True)
|
95 |
+
log('\n')
|
96 |
+
log(f'complex {i} of {len(names)}')
|
97 |
+
# call gnina to find binding pose
|
98 |
+
rec_path = os.path.join(args.data_dir, name, f'{name}_protein_processed.pdb')
|
99 |
+
prediction_output_name = os.path.join(args.results_path, name, f'{name}{args.file_suffix}.pdb')
|
100 |
+
log_path = os.path.join(args.results_path, name, f'{name}{args.file_suffix}.log')
|
101 |
+
if args.seed_molecules_path is not None: seed_mol_path = os.path.join(args.seed_molecules_path, name, f'{args.seed_molecule_filename}')
|
102 |
+
if args.skip_existing and os.path.exists(prediction_output_name): continue
|
103 |
+
|
104 |
+
if args.pocket_mode:
|
105 |
+
mol = read_mol(args.data_dir, name, remove_hs=False)
|
106 |
+
rec = PandasPdb().read_pdb(rec_path)
|
107 |
+
rec_df = rec.get(s='c-alpha')
|
108 |
+
rec_pos = rec_df[['x_coord', 'y_coord', 'z_coord']].to_numpy().squeeze().astype(np.float32)
|
109 |
+
lig_pos = mol.GetConformer().GetPositions()
|
110 |
+
d = cdist(rec_pos, lig_pos)
|
111 |
+
label = np.any(d < args.pocket_cutoff, axis=1)
|
112 |
+
|
113 |
+
if np.any(label):
|
114 |
+
center_pocket = rec_pos[label].mean(axis=0)
|
115 |
+
else:
|
116 |
+
print("No pocket residue below minimum distance ", args.pocket_cutoff, "taking closest at", np.min(d))
|
117 |
+
center_pocket = rec_pos[np.argmin(np.min(d, axis=1)[0])]
|
118 |
+
radius_pocket = np.max(np.linalg.norm(lig_pos - center_pocket[None, :], axis=1))
|
119 |
+
diameter_pocket = radius_pocket * 2
|
120 |
+
center_x = center_pocket[0]
|
121 |
+
size_x = diameter_pocket + 8
|
122 |
+
center_y = center_pocket[1]
|
123 |
+
size_y = diameter_pocket + 8
|
124 |
+
center_z = center_pocket[2]
|
125 |
+
size_z = diameter_pocket + 8
|
126 |
+
|
127 |
+
|
128 |
+
mol_rdkit = read_mol(args.data_dir, name, remove_hs=False)
|
129 |
+
single_time = time.time()
|
130 |
+
|
131 |
+
mol_rdkit.RemoveAllConformers()
|
132 |
+
ps = AllChem.ETKDGv2()
|
133 |
+
id = AllChem.EmbedMolecule(mol_rdkit, ps)
|
134 |
+
if id == -1:
|
135 |
+
print('rdkit pos could not be generated without using random pos. using random pos now.')
|
136 |
+
ps.useRandomCoords = True
|
137 |
+
AllChem.EmbedMolecule(mol_rdkit, ps)
|
138 |
+
AllChem.MMFFOptimizeMolecule(mol_rdkit, confId=0)
|
139 |
+
rdkit_mol_path = os.path.join(args.data_dir, name, f'{name}_rdkit_ligand.pdb')
|
140 |
+
MolToPDBFile(mol_rdkit, rdkit_mol_path)
|
141 |
+
|
142 |
+
fallback_without_p2rank = False
|
143 |
+
if args.use_p2rank_pocket:
|
144 |
+
df = pd.read_csv(f'{p2rank_cache_path}/p2rank_output/{name}_protein_processed.pdb_predictions.csv')
|
145 |
+
rdkit_lig_pos = mol_rdkit.GetConformer().GetPositions()
|
146 |
+
diameter_pocket = np.max(cdist(rdkit_lig_pos, rdkit_lig_pos))
|
147 |
+
size_x = diameter_pocket + args.autobox_add * 2
|
148 |
+
size_y = diameter_pocket + args.autobox_add * 2
|
149 |
+
size_z = diameter_pocket + args.autobox_add * 2
|
150 |
+
if df.empty:
|
151 |
+
fallback_without_p2rank = True
|
152 |
+
else:
|
153 |
+
center_x = df.iloc[0][' center_x']
|
154 |
+
center_y = df.iloc[0][' center_y']
|
155 |
+
center_z = df.iloc[0][' center_z']
|
156 |
+
|
157 |
+
|
158 |
+
|
159 |
+
log(f'processing {rec_path}')
|
160 |
+
if not args.pocket_mode and not args.use_p2rank_pocket or fallback_without_p2rank:
|
161 |
+
return_code = subprocess.run(
|
162 |
+
f"gnina --receptor {rec_path} --ligand {rdkit_mol_path} --num_modes {args.num_modes} -o {prediction_output_name} {'--no_gpu' if args.no_gpu else ''} --autobox_ligand {rec_path if args.seed_molecules_path is None else seed_mol_path} --autobox_add {args.autobox_add} --log {log_path} --exhaustiveness {args.exhaustiveness} --cpu {args.num_cpu} {'--cnn_scoring none' if args.smina else ''}",
|
163 |
+
shell=True)
|
164 |
+
else:
|
165 |
+
return_code = subprocess.run(
|
166 |
+
f"gnina --receptor {rec_path} --ligand {rdkit_mol_path} --num_modes {args.num_modes} -o {prediction_output_name} {'--no_gpu' if args.no_gpu else ''} --log {log_path} --exhaustiveness {args.exhaustiveness} --cpu {args.num_cpu} {'--cnn_scoring none' if args.smina else ''} --center_x {center_x} --center_y {center_y} --center_z {center_z} --size_x {size_x} --size_y {size_y} --size_z {size_z}",
|
167 |
+
shell=True)
|
168 |
+
log(return_code)
|
169 |
+
all_times.append(time.time() - single_time)
|
170 |
+
|
171 |
+
log("single time: --- %s seconds ---" % (time.time() - single_time))
|
172 |
+
log("time so far: --- %s seconds ---" % (time.time() - start_time))
|
173 |
+
log('\n')
|
174 |
+
log(all_times)
|
175 |
+
log("--- %s seconds ---" % (time.time() - start_time))
|
baselines/baseline_run_tankbind_parallel.sh
ADDED
@@ -0,0 +1,5 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
for i in $(seq 0 15); do
|
2 |
+
python baseline_tankbind_runtime.py --parallel_id $i --parallel_tot 16 --prank_path /data/rsg/nlp/hstark/TankBind/packages/p2rank_2.3/prank --data_dir /data/rsg/nlp/hstark/ligbind/data/PDBBind_processed --split_path /data/rsg/nlp/hstark/ligbind/data/splits/timesplit_test --results_path /data/rsg/nlp/hstark/ligbind/results/tankbind_16_worker_runtime --device cpu --skip_p2rank --num_workers 1 --skip_multiple_pocket_outputs &
|
3 |
+
done
|
4 |
+
wait
|
5 |
+
|
baselines/baseline_tankbind_evaluation.py
ADDED
@@ -0,0 +1,239 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
|
2 |
+
import copy
|
3 |
+
import os
|
4 |
+
|
5 |
+
import plotly.express as px
|
6 |
+
import time
|
7 |
+
from argparse import FileType, ArgumentParser
|
8 |
+
|
9 |
+
import numpy as np
|
10 |
+
import pandas as pd
|
11 |
+
import wandb
|
12 |
+
from biopandas.pdb import PandasPdb
|
13 |
+
from rdkit import Chem
|
14 |
+
from rdkit.Chem import RemoveHs
|
15 |
+
|
16 |
+
from tqdm import tqdm
|
17 |
+
|
18 |
+
from datasets.pdbbind import read_mol
|
19 |
+
from datasets.process_mols import read_molecule, read_sdf_or_mol2
|
20 |
+
from utils.utils import read_strings_from_txt, get_symmetry_rmsd, remove_all_hs
|
21 |
+
|
22 |
+
parser = ArgumentParser()
|
23 |
+
parser.add_argument('--config', type=FileType(mode='r'), default=None)
|
24 |
+
parser.add_argument('--run_name', type=str, default='tankbind', help='')
|
25 |
+
parser.add_argument('--data_dir', type=str, default='data/PDBBind_processed', help='')
|
26 |
+
parser.add_argument('--renumbered_atoms_dir', type=str, default='../TankBind/examples/tankbind_pdb/renumber_atom_index_same_as_smiles', help='')
|
27 |
+
parser.add_argument('--results_path', type=str, default='results/tankbind_top5', help='Path to folder with trained model and hyperparameters')
|
28 |
+
parser.add_argument('--project', type=str, default='ligbind_inf', help='')
|
29 |
+
parser.add_argument('--wandb', action='store_true', default=True, help='')
|
30 |
+
parser.add_argument('--num_predictions', type=int, default=5, help='')
|
31 |
+
args = parser.parse_args()
|
32 |
+
|
33 |
+
names = read_strings_from_txt(f'data/splits/timesplit_test')
|
34 |
+
names_no_rec_overlap = read_strings_from_txt(f'data/splits/timesplit_test_no_rec_overlap')
|
35 |
+
|
36 |
+
if args.wandb:
|
37 |
+
wandb.init(
|
38 |
+
entity='coarse-graining-mit',
|
39 |
+
settings=wandb.Settings(start_method="fork"),
|
40 |
+
project=args.project,
|
41 |
+
name=args.run_name,
|
42 |
+
config=args
|
43 |
+
)
|
44 |
+
|
45 |
+
all_times = []
|
46 |
+
rmsds_list = []
|
47 |
+
unsym_rmsds_list = []
|
48 |
+
centroid_distances_list = []
|
49 |
+
min_cross_distances_list = []
|
50 |
+
min_self_distances_list = []
|
51 |
+
made_prediction_list = []
|
52 |
+
steric_clash_list = []
|
53 |
+
without_rec_overlap_list = []
|
54 |
+
|
55 |
+
start_time = time.time()
|
56 |
+
successful_names_list = []
|
57 |
+
for i, name in enumerate(tqdm(names)):
|
58 |
+
mol, _ = read_sdf_or_mol2(f"{args.renumbered_atoms_dir}/{name}.sdf", None)
|
59 |
+
sm = Chem.MolToSmiles(mol)
|
60 |
+
m_order = list(mol.GetPropsAsDict(includePrivate=True, includeComputed=True)['_smilesAtomOutputOrder'])
|
61 |
+
mol = Chem.RenumberAtoms(mol, m_order)
|
62 |
+
mol = Chem.RemoveHs(mol)
|
63 |
+
orig_ligand_pos = np.array(mol.GetConformer().GetPositions())
|
64 |
+
|
65 |
+
assert(os.path.exists(os.path.join(args.results_path, name, f'{name}_tankbind_0.sdf')))
|
66 |
+
ligand_pos = []
|
67 |
+
for i in range(args.num_predictions):
|
68 |
+
if not os.path.exists(os.path.join(args.results_path, name, f'{name}_tankbind_{i}.sdf')): break
|
69 |
+
mol_pred, _ = read_sdf_or_mol2(os.path.join(args.results_path, name, f'{name}_tankbind_{i}.sdf'),None)
|
70 |
+
sm = Chem.MolToSmiles(mol_pred)
|
71 |
+
m_order = list(mol_pred.GetPropsAsDict(includePrivate=True, includeComputed=True)['_smilesAtomOutputOrder'])
|
72 |
+
mol_pred = Chem.RenumberAtoms(mol_pred, m_order)
|
73 |
+
mol_pred = RemoveHs(mol_pred)
|
74 |
+
ligand_pos.append(np.array(mol_pred.GetConformer().GetPositions()))
|
75 |
+
ligand_pos = np.asarray(ligand_pos)
|
76 |
+
|
77 |
+
try:
|
78 |
+
unsym_rmsd = np.sqrt(((ligand_pos - orig_ligand_pos) ** 2).sum(axis=2).mean(axis=1))
|
79 |
+
rmsd = np.array(get_symmetry_rmsd(mol, orig_ligand_pos, [l for l in ligand_pos], mol_pred))
|
80 |
+
except Exception as e:
|
81 |
+
print("Using non corrected RMSD because of the error:", e)
|
82 |
+
rmsd = np.sqrt(((ligand_pos - orig_ligand_pos) ** 2).sum(axis=2).mean(axis=1))
|
83 |
+
|
84 |
+
num_pockets = len(ligand_pos)
|
85 |
+
unsym_rmsds_list.append(np.lib.pad(unsym_rmsd, (0,10-len(unsym_rmsd)), 'constant', constant_values=(0)) )
|
86 |
+
rmsds_list.append(np.lib.pad(rmsd, (0,10-len(rmsd)), 'constant', constant_values=(0)) )
|
87 |
+
centroid_distance = np.linalg.norm(ligand_pos.mean(axis=1) - orig_ligand_pos[None,:].mean(axis=1), axis=1)
|
88 |
+
centroid_distances_list.append(np.lib.pad(centroid_distance, (0,10-len(rmsd)), 'constant', constant_values=(0)) )
|
89 |
+
|
90 |
+
rec_path = os.path.join(args.data_dir, name, f'{name}_protein_processed.pdb')
|
91 |
+
if not os.path.exists(rec_path):
|
92 |
+
rec_path = os.path.join(args.data_dir, name,f'{name}_protein_obabel_reduce.pdb')
|
93 |
+
rec = PandasPdb().read_pdb(rec_path)
|
94 |
+
rec_df = rec.df['ATOM']
|
95 |
+
receptor_pos = rec_df[['x_coord', 'y_coord', 'z_coord']].to_numpy().squeeze().astype(np.float32)
|
96 |
+
receptor_pos = np.tile(receptor_pos, (10, 1, 1))
|
97 |
+
|
98 |
+
ligand_pos_padded = np.lib.pad(ligand_pos, ((0,10-len(ligand_pos)), (0,0), (0,0)), 'constant', constant_values=(np.inf))
|
99 |
+
ligand_pos_padded_zero = np.lib.pad(ligand_pos, ((0, 10 - len(ligand_pos)), (0, 0), (0, 0)), 'constant',constant_values=0)
|
100 |
+
cross_distances = np.linalg.norm(receptor_pos[:, :, None, :] - ligand_pos_padded[:, None, :, :], axis=-1)
|
101 |
+
self_distances = np.linalg.norm(ligand_pos_padded_zero[:, :, None, :] - ligand_pos_padded_zero[:, None, :, :], axis=-1)
|
102 |
+
self_distances = np.where(np.eye(self_distances.shape[2]), np.inf, self_distances)
|
103 |
+
min_self_distances_list.append(np.min(self_distances, axis=(1, 2)))
|
104 |
+
min_cross_distance = np.min(cross_distances, axis=(1, 2))
|
105 |
+
individual_made_prediction = np.lib.pad(np.ones(num_pockets), (0,10-len(rmsd)), 'constant', constant_values=(0))
|
106 |
+
made_prediction_list.append(individual_made_prediction)
|
107 |
+
min_cross_distances_list.append(min_cross_distance)
|
108 |
+
successful_names_list.append(name)
|
109 |
+
without_rec_overlap_list.append(1 if name in names_no_rec_overlap else 0)
|
110 |
+
|
111 |
+
performance_metrics = {}
|
112 |
+
for overlap in ['', 'no_overlap_']:
|
113 |
+
if 'no_overlap_' == overlap:
|
114 |
+
without_rec_overlap = np.array(without_rec_overlap_list, dtype=bool)
|
115 |
+
unsym_rmsds = np.array(unsym_rmsds_list)[without_rec_overlap]
|
116 |
+
rmsds = np.array(rmsds_list)[without_rec_overlap]
|
117 |
+
centroid_distances = np.array(centroid_distances_list)[without_rec_overlap]
|
118 |
+
min_cross_distances = np.array(min_cross_distances_list)[without_rec_overlap]
|
119 |
+
min_self_distances = np.array(min_self_distances_list)[without_rec_overlap]
|
120 |
+
made_prediction = np.array(made_prediction_list)[without_rec_overlap]
|
121 |
+
successful_names = np.array(successful_names_list)[without_rec_overlap]
|
122 |
+
else:
|
123 |
+
unsym_rmsds = np.array(unsym_rmsds_list)
|
124 |
+
rmsds = np.array(rmsds_list)
|
125 |
+
centroid_distances = np.array(centroid_distances_list)
|
126 |
+
min_cross_distances = np.array(min_cross_distances_list)
|
127 |
+
min_self_distances = np.array(min_self_distances_list)
|
128 |
+
made_prediction = np.array(made_prediction_list)
|
129 |
+
successful_names = np.array(successful_names_list)
|
130 |
+
|
131 |
+
inf_rmsds = copy.deepcopy(rmsds)
|
132 |
+
inf_rmsds[~made_prediction.astype(bool)] = np.inf
|
133 |
+
inf_centroid_distances = copy.deepcopy(centroid_distances)
|
134 |
+
inf_centroid_distances[~made_prediction.astype(bool)] = np.inf
|
135 |
+
|
136 |
+
np.save(os.path.join(args.results_path, f'{overlap}rmsds.npy'), rmsds)
|
137 |
+
np.save(os.path.join(args.results_path, f'{overlap}names.npy'), np.array(successful_names))
|
138 |
+
np.save(os.path.join(args.results_path, f'{overlap}centroid_distances.npy'), centroid_distances)
|
139 |
+
np.save(os.path.join(args.results_path, f'{overlap}min_cross_distances.npy'), min_cross_distances)
|
140 |
+
np.save(os.path.join(args.results_path, f'{overlap}min_self_distances.npy'), min_self_distances)
|
141 |
+
|
142 |
+
performance_metrics.update({
|
143 |
+
f'{overlap}self_intersect_fraction': (100 * (min_self_distances[:, 0] < 0.4).sum() / len(min_self_distances[:, 0])),
|
144 |
+
f'{overlap}steric_clash_fraction': (100 * (min_cross_distances[:,0] < 0.4).sum() / len(min_cross_distances[:,0])),
|
145 |
+
f'{overlap}mean_rmsd': rmsds[:,0].mean(),
|
146 |
+
f'{overlap}unsym_rmsds_below_2': (100 * (unsym_rmsds[:,0] < 2).sum() / len(unsym_rmsds[:,0])),
|
147 |
+
f'{overlap}rmsds_below_2': (100 * (rmsds[:,0] < 2).sum() / len(rmsds[:,0])),
|
148 |
+
f'{overlap}rmsds_below_5': (100 * (rmsds[:,0] < 5).sum() / len(rmsds[:,0])),
|
149 |
+
f'{overlap}rmsds_percentile_25': np.percentile(rmsds[:,0], 25).round(2),
|
150 |
+
f'{overlap}rmsds_percentile_50': np.percentile(rmsds[:,0], 50).round(2),
|
151 |
+
f'{overlap}rmsds_percentile_75': np.percentile(rmsds[:,0], 75).round(2),
|
152 |
+
|
153 |
+
f'{overlap}mean_centroid': centroid_distances[:,0].mean().__round__(2),
|
154 |
+
f'{overlap}centroid_below_2': (100 * (centroid_distances[:,0] < 2).sum() / len(centroid_distances[:,0])).__round__(2),
|
155 |
+
f'{overlap}centroid_below_5': (100 * (centroid_distances[:,0] < 5).sum() / len(centroid_distances[:,0])).__round__(2),
|
156 |
+
f'{overlap}centroid_percentile_25': np.percentile(centroid_distances[:,0], 25).round(2),
|
157 |
+
f'{overlap}centroid_percentile_50': np.percentile(centroid_distances[:,0], 50).round(2),
|
158 |
+
f'{overlap}centroid_percentile_75': np.percentile(centroid_distances[:,0], 75).round(2),
|
159 |
+
})
|
160 |
+
|
161 |
+
top5_rmsds = np.min(inf_rmsds[:, :5], axis=1)
|
162 |
+
top5_centroid_distances = centroid_distances[np.arange(rmsds.shape[0])[:,None],np.argsort(inf_rmsds[:, :5], axis=1)][:,0]
|
163 |
+
top5_min_cross_distances = min_cross_distances[np.arange(rmsds.shape[0])[:,None],np.argsort(inf_rmsds[:, :5], axis=1)][:,0]
|
164 |
+
top5_min_self_distances = min_self_distances[np.arange(rmsds.shape[0])[:,None],np.argsort(inf_rmsds[:, :5], axis=1)][:,0]
|
165 |
+
performance_metrics.update({
|
166 |
+
f'{overlap}top5_steric_clash_fraction': (100 * (top5_min_cross_distances < 0.4).sum() / len(top5_min_cross_distances)).__round__(2),
|
167 |
+
f'{overlap}top5_self_intersect_fraction': (100 * (top5_min_self_distances < 0.4).sum() / len(top5_min_self_distances)).__round__(2),
|
168 |
+
f'{overlap}top5_rmsds_below_2': (100 * (top5_rmsds < 2).sum() / len(top5_rmsds)).__round__(2),
|
169 |
+
f'{overlap}top5_rmsds_below_5': (100 * (top5_rmsds < 5).sum() / len(top5_rmsds)).__round__(2),
|
170 |
+
f'{overlap}top5_rmsds_percentile_25': np.percentile(top5_rmsds, 25).round(2),
|
171 |
+
f'{overlap}top5_rmsds_percentile_50': np.percentile(top5_rmsds, 50).round(2),
|
172 |
+
f'{overlap}top5_rmsds_percentile_75': np.percentile(top5_rmsds, 75).round(2),
|
173 |
+
|
174 |
+
f'{overlap}top5_centroid_below_2': (100 * (top5_centroid_distances < 2).sum() / len(top5_centroid_distances)).__round__(2),
|
175 |
+
f'{overlap}top5_centroid_below_5': (100 * (top5_centroid_distances < 5).sum() / len(top5_centroid_distances)).__round__(2),
|
176 |
+
f'{overlap}top5_centroid_percentile_25': np.percentile(top5_centroid_distances, 25).round(2),
|
177 |
+
f'{overlap}top5_centroid_percentile_50': np.percentile(top5_centroid_distances, 50).round(2),
|
178 |
+
f'{overlap}top5_centroid_percentile_75': np.percentile(top5_centroid_distances, 75).round(2),
|
179 |
+
})
|
180 |
+
|
181 |
+
|
182 |
+
|
183 |
+
|
184 |
+
top10_rmsds = np.min(inf_rmsds[:, :10], axis=1)
|
185 |
+
top10_centroid_distances = centroid_distances[np.arange(rmsds.shape[0])[:,None],np.argsort(inf_rmsds[:, :10], axis=1)][:,0]
|
186 |
+
top10_min_cross_distances = min_cross_distances[np.arange(rmsds.shape[0])[:,None],np.argsort(inf_rmsds[:, :10], axis=1)][:,0]
|
187 |
+
top10_min_self_distances = min_self_distances[np.arange(rmsds.shape[0])[:,None],np.argsort(inf_rmsds[:, :10], axis=1)][:,0]
|
188 |
+
performance_metrics.update({
|
189 |
+
f'{overlap}top10_steric_clash_fraction': (100 * (top10_min_cross_distances < 0.4).sum() / len(top10_min_cross_distances)).__round__(2),
|
190 |
+
f'{overlap}top10_self_intersect_fraction': (100 * (top10_min_self_distances < 0.4).sum() / len(top10_min_self_distances)).__round__(2),
|
191 |
+
f'{overlap}top10_rmsds_below_2': (100 * (top10_rmsds < 2).sum() / len(top10_rmsds)).__round__(2),
|
192 |
+
f'{overlap}top10_rmsds_below_5': (100 * (top10_rmsds < 5).sum() / len(top10_rmsds)).__round__(2),
|
193 |
+
f'{overlap}top10_rmsds_percentile_25': np.percentile(top10_rmsds, 25).round(2),
|
194 |
+
f'{overlap}top10_rmsds_percentile_50': np.percentile(top10_rmsds, 50).round(2),
|
195 |
+
f'{overlap}top10_rmsds_percentile_75': np.percentile(top10_rmsds, 75).round(2),
|
196 |
+
|
197 |
+
f'{overlap}top10_centroid_below_2': (100 * (top10_centroid_distances < 2).sum() / len(top10_centroid_distances)).__round__(2),
|
198 |
+
f'{overlap}top10_centroid_below_5': (100 * (top10_centroid_distances < 5).sum() / len(top10_centroid_distances)).__round__(2),
|
199 |
+
f'{overlap}top10_centroid_percentile_25': np.percentile(top10_centroid_distances, 25).round(2),
|
200 |
+
f'{overlap}top10_centroid_percentile_50': np.percentile(top10_centroid_distances, 50).round(2),
|
201 |
+
f'{overlap}top10_centroid_percentile_75': np.percentile(top10_centroid_distances, 75).round(2),
|
202 |
+
})
|
203 |
+
for k in performance_metrics:
|
204 |
+
print(k, performance_metrics[k])
|
205 |
+
|
206 |
+
if args.wandb:
|
207 |
+
wandb.log(performance_metrics)
|
208 |
+
histogram_metrics_list = [('rmsd', rmsds[:,0]),
|
209 |
+
('centroid_distance', centroid_distances[:,0]),
|
210 |
+
('mean_rmsd', rmsds[:,0]),
|
211 |
+
('mean_centroid_distance', centroid_distances[:,0])]
|
212 |
+
histogram_metrics_list.append(('top5_rmsds', top5_rmsds))
|
213 |
+
histogram_metrics_list.append(('top5_centroid_distances', top5_centroid_distances))
|
214 |
+
histogram_metrics_list.append(('top10_rmsds', top10_rmsds))
|
215 |
+
histogram_metrics_list.append(('top10_centroid_distances', top10_centroid_distances))
|
216 |
+
|
217 |
+
os.makedirs(f'.plotly_cache/baseline_cache', exist_ok=True)
|
218 |
+
images = []
|
219 |
+
for metric_name, metric in histogram_metrics_list:
|
220 |
+
d = {args.results_path: metric}
|
221 |
+
df = pd.DataFrame(data=d)
|
222 |
+
fig = px.ecdf(df, width=900, height=600, range_x=[0, 40])
|
223 |
+
fig.add_vline(x=2, annotation_text='2 A;', annotation_font_size=20, annotation_position="top right",
|
224 |
+
line_dash='dash', line_color='firebrick', annotation_font_color='firebrick')
|
225 |
+
fig.add_vline(x=5, annotation_text='5 A;', annotation_font_size=20, annotation_position="top right",
|
226 |
+
line_dash='dash', line_color='green', annotation_font_color='green')
|
227 |
+
fig.update_xaxes(title=f'{metric_name} in Angstrom', title_font={"size": 20}, tickfont={"size": 20})
|
228 |
+
fig.update_yaxes(title=f'Fraction of predictions with lower error', title_font={"size": 20},
|
229 |
+
tickfont={"size": 20})
|
230 |
+
fig.update_layout(autosize=False, margin={'l': 0, 'r': 0, 't': 0, 'b': 0}, plot_bgcolor='white',
|
231 |
+
paper_bgcolor='white', legend_title_text='Method', legend_title_font_size=17,
|
232 |
+
legend=dict(yanchor="bottom", y=0.1, xanchor="right", x=0.99, font=dict(size=17), ), )
|
233 |
+
fig.update_xaxes(showgrid=True, gridcolor='lightgrey')
|
234 |
+
fig.update_yaxes(showgrid=True, gridcolor='lightgrey')
|
235 |
+
|
236 |
+
fig.write_image(os.path.join(f'.plotly_cache/baseline_cache', f'{metric_name}.png'))
|
237 |
+
wandb.log({metric_name: wandb.Image(os.path.join(f'.plotly_cache/baseline_cache', f'{metric_name}.png'), caption=f"{metric_name}")})
|
238 |
+
images.append(wandb.Image(os.path.join(f'.plotly_cache/baseline_cache', f'{metric_name}.png'), caption=f"{metric_name}"))
|
239 |
+
wandb.log({'images': images})
|
baselines/baseline_tankbind_runtime.py
ADDED
@@ -0,0 +1,342 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# This file needs to be ran in the TANKBind repository together with baseline_run_tankbind_parallel.sh
|
2 |
+
|
3 |
+
import sys
|
4 |
+
import time
|
5 |
+
from multiprocessing import Pool
|
6 |
+
|
7 |
+
|
8 |
+
import copy
|
9 |
+
import warnings
|
10 |
+
from argparse import ArgumentParser
|
11 |
+
|
12 |
+
from rdkit.Chem import AllChem, RemoveHs
|
13 |
+
|
14 |
+
from feature_utils import save_cleaned_protein, read_mol
|
15 |
+
from generation_utils import get_LAS_distance_constraint_mask, get_info_pred_distance, write_with_new_coords
|
16 |
+
import logging
|
17 |
+
from torch_geometric.loader import DataLoader
|
18 |
+
from tqdm import tqdm # pip install tqdm if fails.
|
19 |
+
from model import get_model
|
20 |
+
# from utils import *
|
21 |
+
import torch
|
22 |
+
|
23 |
+
|
24 |
+
from data import TankBind_prediction
|
25 |
+
|
26 |
+
import os
|
27 |
+
import numpy as np
|
28 |
+
import pandas as pd
|
29 |
+
import rdkit.Chem as Chem
|
30 |
+
from feature_utils import generate_sdf_from_smiles_using_rdkit
|
31 |
+
from feature_utils import get_protein_feature
|
32 |
+
from Bio.PDB import PDBParser
|
33 |
+
from feature_utils import extract_torchdrug_feature_from_mol
|
34 |
+
|
35 |
+
|
36 |
+
def read_strings_from_txt(path):
|
37 |
+
# every line will be one element of the returned list
|
38 |
+
with open(path) as file:
|
39 |
+
lines = file.readlines()
|
40 |
+
return [line.rstrip() for line in lines]
|
41 |
+
|
42 |
+
|
43 |
+
def read_molecule(molecule_file, sanitize=False, calc_charges=False, remove_hs=False):
|
44 |
+
if molecule_file.endswith('.mol2'):
|
45 |
+
mol = Chem.MolFromMol2File(molecule_file, sanitize=False, removeHs=False)
|
46 |
+
elif molecule_file.endswith('.sdf'):
|
47 |
+
supplier = Chem.SDMolSupplier(molecule_file, sanitize=False, removeHs=False)
|
48 |
+
mol = supplier[0]
|
49 |
+
elif molecule_file.endswith('.pdbqt'):
|
50 |
+
with open(molecule_file) as file:
|
51 |
+
pdbqt_data = file.readlines()
|
52 |
+
pdb_block = ''
|
53 |
+
for line in pdbqt_data:
|
54 |
+
pdb_block += '{}\n'.format(line[:66])
|
55 |
+
mol = Chem.MolFromPDBBlock(pdb_block, sanitize=False, removeHs=False)
|
56 |
+
elif molecule_file.endswith('.pdb'):
|
57 |
+
mol = Chem.MolFromPDBFile(molecule_file, sanitize=False, removeHs=False)
|
58 |
+
else:
|
59 |
+
return ValueError('Expect the format of the molecule_file to be '
|
60 |
+
'one of .mol2, .sdf, .pdbqt and .pdb, got {}'.format(molecule_file))
|
61 |
+
try:
|
62 |
+
if sanitize or calc_charges:
|
63 |
+
Chem.SanitizeMol(mol)
|
64 |
+
|
65 |
+
if calc_charges:
|
66 |
+
# Compute Gasteiger charges on the molecule.
|
67 |
+
try:
|
68 |
+
AllChem.ComputeGasteigerCharges(mol)
|
69 |
+
except:
|
70 |
+
warnings.warn('Unable to compute charges for the molecule.')
|
71 |
+
|
72 |
+
if remove_hs:
|
73 |
+
mol = Chem.RemoveHs(mol, sanitize=sanitize)
|
74 |
+
except:
|
75 |
+
return None
|
76 |
+
|
77 |
+
return mol
|
78 |
+
|
79 |
+
|
80 |
+
def parallel_save_prediction(arguments):
|
81 |
+
dataset, y_pred_list, chosen,rdkit_mol_path, result_folder, name = arguments
|
82 |
+
for idx, line in chosen.iterrows():
|
83 |
+
pocket_name = line['pocket_name']
|
84 |
+
compound_name = line['compound_name']
|
85 |
+
ligandName = compound_name.split("_")[1]
|
86 |
+
dataset_index = line['dataset_index']
|
87 |
+
coords = dataset[dataset_index].coords.to('cpu')
|
88 |
+
protein_nodes_xyz = dataset[dataset_index].node_xyz.to('cpu')
|
89 |
+
n_compound = coords.shape[0]
|
90 |
+
n_protein = protein_nodes_xyz.shape[0]
|
91 |
+
y_pred = y_pred_list[dataset_index].reshape(n_protein, n_compound).to('cpu')
|
92 |
+
compound_pair_dis_constraint = torch.cdist(coords, coords)
|
93 |
+
mol = Chem.MolFromMolFile(rdkit_mol_path)
|
94 |
+
LAS_distance_constraint_mask = get_LAS_distance_constraint_mask(mol).bool()
|
95 |
+
pred_dist_info = get_info_pred_distance(coords, y_pred, protein_nodes_xyz, compound_pair_dis_constraint,
|
96 |
+
LAS_distance_constraint_mask=LAS_distance_constraint_mask,
|
97 |
+
n_repeat=1, show_progress=False)
|
98 |
+
|
99 |
+
toFile = f'{result_folder}/{name}_tankbind_chosen.sdf'
|
100 |
+
new_coords = pred_dist_info.sort_values("loss")['coords'].iloc[0].astype(np.double)
|
101 |
+
write_with_new_coords(mol, new_coords, toFile)
|
102 |
+
|
103 |
+
if __name__ == '__main__':
|
104 |
+
tankbind_src_folder = "../tankbind"
|
105 |
+
sys.path.insert(0, tankbind_src_folder)
|
106 |
+
torch.set_num_threads(16)
|
107 |
+
parser = ArgumentParser()
|
108 |
+
parser.add_argument('--data_dir', type=str, default='/Users/hstark/projects/ligbind/data/PDBBind_processed', help='')
|
109 |
+
parser.add_argument('--split_path', type=str, default='/Users/hstark/projects/ligbind/data/splits/timesplit_test', help='')
|
110 |
+
parser.add_argument('--prank_path', type=str, default='/Users/hstark/projects/p2rank_2.3/prank', help='')
|
111 |
+
parser.add_argument('--results_path', type=str, default='results/tankbind_results', help='')
|
112 |
+
parser.add_argument('--skip_existing', action='store_true', default=False, help='')
|
113 |
+
parser.add_argument('--skip_p2rank', action='store_true', default=False, help='')
|
114 |
+
parser.add_argument('--skip_multiple_pocket_outputs', action='store_true', default=False, help='')
|
115 |
+
parser.add_argument('--device', type=str, default='cpu', help='')
|
116 |
+
parser.add_argument('--num_workers', type=int, default=1, help='')
|
117 |
+
parser.add_argument('--parallel_id', type=int, default=0, help='')
|
118 |
+
parser.add_argument('--parallel_tot', type=int, default=1, help='')
|
119 |
+
args = parser.parse_args()
|
120 |
+
|
121 |
+
device = args.device
|
122 |
+
cache_path = "tankbind_cache"
|
123 |
+
os.makedirs(cache_path, exist_ok=True)
|
124 |
+
os.makedirs(args.results_path, exist_ok=True)
|
125 |
+
|
126 |
+
|
127 |
+
|
128 |
+
logging.basicConfig(level=logging.INFO)
|
129 |
+
model = get_model(0, logging, device)
|
130 |
+
# re-dock model
|
131 |
+
# modelFile = "../saved_models/re_dock.pt"
|
132 |
+
# self-dock model
|
133 |
+
modelFile = f"{tankbind_src_folder}/../saved_models/self_dock.pt"
|
134 |
+
|
135 |
+
model.load_state_dict(torch.load(modelFile, map_location=device))
|
136 |
+
_ = model.eval()
|
137 |
+
batch_size = 5
|
138 |
+
names = read_strings_from_txt(args.split_path)
|
139 |
+
if args.parallel_tot > 1:
|
140 |
+
size = len(names) // args.parallel_tot + 1
|
141 |
+
names = names[args.parallel_id*size:(args.parallel_id+1)*size]
|
142 |
+
rmsds = []
|
143 |
+
|
144 |
+
forward_pass_time = []
|
145 |
+
times_preprocess = []
|
146 |
+
times_inference = []
|
147 |
+
top_10_generation_time = []
|
148 |
+
top_1_generation_time = []
|
149 |
+
start_time = time.time()
|
150 |
+
if not args.skip_p2rank:
|
151 |
+
for name in names:
|
152 |
+
if args.skip_existing and os.path.exists(f'{args.results_path}/{name}/{name}_tankbind_1.sdf'): continue
|
153 |
+
print("Now processing: ", name)
|
154 |
+
protein_path = f'{args.data_dir}/{name}/{name}_protein_processed.pdb'
|
155 |
+
cleaned_protein_path = f"{cache_path}/{name}_protein_tankbind_cleaned.pdb" # if you change this you also need to change below
|
156 |
+
parser = PDBParser(QUIET=True)
|
157 |
+
s = parser.get_structure(name, protein_path)
|
158 |
+
c = s[0]
|
159 |
+
clean_res_list, ligand_list = save_cleaned_protein(c, cleaned_protein_path)
|
160 |
+
|
161 |
+
with open(f"{cache_path}/pdb_list_p2rank.txt", "w") as out:
|
162 |
+
for name in names:
|
163 |
+
out.write(f"{name}_protein_tankbind_cleaned.pdb\n")
|
164 |
+
cmd = f"bash {args.prank_path} predict {cache_path}/pdb_list_p2rank.txt -o {cache_path}/p2rank -threads 4"
|
165 |
+
os.system(cmd)
|
166 |
+
times_preprocess.append(time.time() - start_time)
|
167 |
+
p2_rank_time = time.time() - start_time
|
168 |
+
|
169 |
+
|
170 |
+
|
171 |
+
|
172 |
+
list_to_parallelize = []
|
173 |
+
for name in tqdm(names):
|
174 |
+
single_preprocess_time = time.time()
|
175 |
+
if args.skip_existing and os.path.exists(f'{args.results_path}/{name}/{name}_tankbind_1.sdf'): continue
|
176 |
+
print("Now processing: ", name)
|
177 |
+
protein_path = f'{args.data_dir}/{name}/{name}_protein_processed.pdb'
|
178 |
+
ligand_path = f"{args.data_dir}/{name}/{name}_ligand.sdf"
|
179 |
+
cleaned_protein_path = f"{cache_path}/{name}_protein_tankbind_cleaned.pdb" # if you change this you also need to change below
|
180 |
+
rdkit_mol_path = f"{cache_path}/{name}_rdkit_ligand.sdf"
|
181 |
+
|
182 |
+
parser = PDBParser(QUIET=True)
|
183 |
+
s = parser.get_structure(name, protein_path)
|
184 |
+
c = s[0]
|
185 |
+
clean_res_list, ligand_list = save_cleaned_protein(c, cleaned_protein_path)
|
186 |
+
lig, _ = read_mol(f"{args.data_dir}/{name}/{name}_ligand.sdf", f"{args.data_dir}/{name}/{name}_ligand.mol2")
|
187 |
+
|
188 |
+
lig = RemoveHs(lig)
|
189 |
+
smiles = Chem.MolToSmiles(lig)
|
190 |
+
generate_sdf_from_smiles_using_rdkit(smiles, rdkit_mol_path, shift_dis=0)
|
191 |
+
|
192 |
+
parser = PDBParser(QUIET=True)
|
193 |
+
s = parser.get_structure("x", cleaned_protein_path)
|
194 |
+
res_list = list(s.get_residues())
|
195 |
+
|
196 |
+
protein_dict = {}
|
197 |
+
protein_dict[name] = get_protein_feature(res_list)
|
198 |
+
compound_dict = {}
|
199 |
+
|
200 |
+
mol = Chem.MolFromMolFile(rdkit_mol_path)
|
201 |
+
compound_dict[name + f"_{name}" + "_rdkit"] = extract_torchdrug_feature_from_mol(mol, has_LAS_mask=True)
|
202 |
+
|
203 |
+
info = []
|
204 |
+
for compound_name in list(compound_dict.keys()):
|
205 |
+
# use protein center as the block center.
|
206 |
+
com = ",".join([str(a.round(3)) for a in protein_dict[name][0].mean(axis=0).numpy()])
|
207 |
+
info.append([name, compound_name, "protein_center", com])
|
208 |
+
|
209 |
+
p2rankFile = f"{cache_path}/p2rank/{name}_protein_tankbind_cleaned.pdb_predictions.csv"
|
210 |
+
pocket = pd.read_csv(p2rankFile)
|
211 |
+
pocket.columns = pocket.columns.str.strip()
|
212 |
+
pocket_coms = pocket[['center_x', 'center_y', 'center_z']].values
|
213 |
+
for ith_pocket, com in enumerate(pocket_coms):
|
214 |
+
com = ",".join([str(a.round(3)) for a in com])
|
215 |
+
info.append([name, compound_name, f"pocket_{ith_pocket + 1}", com])
|
216 |
+
info = pd.DataFrame(info, columns=['protein_name', 'compound_name', 'pocket_name', 'pocket_com'])
|
217 |
+
|
218 |
+
dataset_path = f"{cache_path}/{name}_dataset/"
|
219 |
+
os.system(f"rm -r {dataset_path}")
|
220 |
+
os.system(f"mkdir -p {dataset_path}")
|
221 |
+
dataset = TankBind_prediction(dataset_path, data=info, protein_dict=protein_dict, compound_dict=compound_dict)
|
222 |
+
|
223 |
+
# dataset = TankBind_prediction(dataset_path)
|
224 |
+
times_preprocess.append(time.time() - single_preprocess_time)
|
225 |
+
single_forward_pass_time = time.time()
|
226 |
+
data_loader = DataLoader(dataset, batch_size=batch_size, follow_batch=['x', 'y', 'compound_pair'], shuffle=False,
|
227 |
+
num_workers=0)
|
228 |
+
affinity_pred_list = []
|
229 |
+
y_pred_list = []
|
230 |
+
for data in tqdm(data_loader):
|
231 |
+
data = data.to(device)
|
232 |
+
y_pred, affinity_pred = model(data)
|
233 |
+
affinity_pred_list.append(affinity_pred.detach().cpu())
|
234 |
+
for i in range(data.y_batch.max() + 1):
|
235 |
+
y_pred_list.append((y_pred[data['y_batch'] == i]).detach().cpu())
|
236 |
+
|
237 |
+
affinity_pred_list = torch.cat(affinity_pred_list)
|
238 |
+
forward_pass_time.append(time.time() - single_forward_pass_time)
|
239 |
+
output_info = copy.deepcopy(dataset.data)
|
240 |
+
output_info['affinity'] = affinity_pred_list
|
241 |
+
output_info['dataset_index'] = range(len(output_info))
|
242 |
+
output_info_sorted = output_info.sort_values('affinity', ascending=False)
|
243 |
+
|
244 |
+
|
245 |
+
result_folder = f'{args.results_path}/{name}'
|
246 |
+
os.makedirs(result_folder, exist_ok=True)
|
247 |
+
output_info_sorted.to_csv(f"{result_folder}/output_info_sorted_by_affinity.csv")
|
248 |
+
|
249 |
+
if not args.skip_multiple_pocket_outputs:
|
250 |
+
for idx, (dataframe_idx, line) in enumerate(copy.deepcopy(output_info_sorted).iterrows()):
|
251 |
+
single_top10_generation_time = time.time()
|
252 |
+
pocket_name = line['pocket_name']
|
253 |
+
compound_name = line['compound_name']
|
254 |
+
ligandName = compound_name.split("_")[1]
|
255 |
+
coords = dataset[dataframe_idx].coords.to('cpu')
|
256 |
+
protein_nodes_xyz = dataset[dataframe_idx].node_xyz.to('cpu')
|
257 |
+
n_compound = coords.shape[0]
|
258 |
+
n_protein = protein_nodes_xyz.shape[0]
|
259 |
+
y_pred = y_pred_list[dataframe_idx].reshape(n_protein, n_compound).to('cpu')
|
260 |
+
y = dataset[dataframe_idx].dis_map.reshape(n_protein, n_compound).to('cpu')
|
261 |
+
compound_pair_dis_constraint = torch.cdist(coords, coords)
|
262 |
+
mol = Chem.MolFromMolFile(rdkit_mol_path)
|
263 |
+
LAS_distance_constraint_mask = get_LAS_distance_constraint_mask(mol).bool()
|
264 |
+
pred_dist_info = get_info_pred_distance(coords, y_pred, protein_nodes_xyz, compound_pair_dis_constraint,
|
265 |
+
LAS_distance_constraint_mask=LAS_distance_constraint_mask,
|
266 |
+
n_repeat=1, show_progress=False)
|
267 |
+
|
268 |
+
toFile = f'{result_folder}/{name}_tankbind_{idx}.sdf'
|
269 |
+
new_coords = pred_dist_info.sort_values("loss")['coords'].iloc[0].astype(np.double)
|
270 |
+
write_with_new_coords(mol, new_coords, toFile)
|
271 |
+
if idx < 10:
|
272 |
+
top_10_generation_time.append(time.time() - single_top10_generation_time)
|
273 |
+
if idx == 0:
|
274 |
+
top_1_generation_time.append(time.time() - single_top10_generation_time)
|
275 |
+
|
276 |
+
output_info_chosen = copy.deepcopy(dataset.data)
|
277 |
+
output_info_chosen['affinity'] = affinity_pred_list
|
278 |
+
output_info_chosen['dataset_index'] = range(len(output_info_chosen))
|
279 |
+
chosen = output_info_chosen.loc[
|
280 |
+
output_info_chosen.groupby(['protein_name', 'compound_name'], sort=False)['affinity'].agg(
|
281 |
+
'idxmax')].reset_index()
|
282 |
+
|
283 |
+
list_to_parallelize.append((dataset, y_pred_list, chosen, rdkit_mol_path, result_folder, name))
|
284 |
+
|
285 |
+
chosen_generation_start_time = time.time()
|
286 |
+
if args.num_workers > 1:
|
287 |
+
p = Pool(args.num_workers, maxtasksperchild=1)
|
288 |
+
p.__enter__()
|
289 |
+
with tqdm(total=len(list_to_parallelize), desc=f'running optimization {i}/{len(list_to_parallelize)}') as pbar:
|
290 |
+
map_fn = p.imap_unordered if args.num_workers > 1 else map
|
291 |
+
for t in map_fn(parallel_save_prediction, list_to_parallelize):
|
292 |
+
pbar.update()
|
293 |
+
if args.num_workers > 1: p.__exit__(None, None, None)
|
294 |
+
chosen_generation_time = time.time() - chosen_generation_start_time
|
295 |
+
"""
|
296 |
+
lig, _ = read_mol(f"{args.data_dir}/{name}/{name}_ligand.sdf", f"{args.data_dir}/{name}/{name}_ligand.mol2")
|
297 |
+
sm = Chem.MolToSmiles(lig)
|
298 |
+
m_order = list(lig.GetPropsAsDict(includePrivate=True, includeComputed=True)['_smilesAtomOutputOrder'])
|
299 |
+
lig = Chem.RenumberAtoms(lig, m_order)
|
300 |
+
lig = Chem.RemoveAllHs(lig)
|
301 |
+
lig = RemoveHs(lig)
|
302 |
+
true_ligand_pos = np.array(lig.GetConformer().GetPositions())
|
303 |
+
|
304 |
+
toFile = f'{result_folder}/{name}_tankbind_chosen.sdf'
|
305 |
+
mol_pred, _ = read_mol(toFile, None)
|
306 |
+
sm = Chem.MolToSmiles(mol_pred)
|
307 |
+
m_order = list(mol_pred.GetPropsAsDict(includePrivate=True, includeComputed=True)['_smilesAtomOutputOrder'])
|
308 |
+
mol_pred = Chem.RenumberAtoms(mol_pred, m_order)
|
309 |
+
mol_pred = RemoveHs(mol_pred)
|
310 |
+
mol_pred_pos = np.array(mol_pred.GetConformer().GetPositions())
|
311 |
+
rmsds.append(np.sqrt(((true_ligand_pos - mol_pred_pos) ** 2).sum(axis=1).mean(axis=0)))
|
312 |
+
print(np.sqrt(((true_ligand_pos - mol_pred_pos) ** 2).sum(axis=1).mean(axis=0)))
|
313 |
+
"""
|
314 |
+
forward_pass_time = np.array(forward_pass_time).sum()
|
315 |
+
times_preprocess = np.array(times_preprocess).sum()
|
316 |
+
times_inference = np.array(times_inference).sum()
|
317 |
+
top_10_generation_time = np.array(top_10_generation_time).sum()
|
318 |
+
top_1_generation_time = np.array(top_1_generation_time).sum()
|
319 |
+
|
320 |
+
rmsds = np.array(rmsds)
|
321 |
+
|
322 |
+
print(f'forward_pass_time: {forward_pass_time}')
|
323 |
+
print(f'times_preprocess: {times_preprocess}')
|
324 |
+
print(f'times_inference: {times_inference}')
|
325 |
+
print(f'top_10_generation_time: {top_10_generation_time}')
|
326 |
+
print(f'top_1_generation_time: {top_1_generation_time}')
|
327 |
+
print(f'chosen_generation_time: {chosen_generation_time}')
|
328 |
+
print(f'rmsds_below_2: {(100 * (rmsds < 2).sum() / len(rmsds))}')
|
329 |
+
print(f'p2rank Time: {p2_rank_time}')
|
330 |
+
print(
|
331 |
+
f'total_time: '
|
332 |
+
f'{forward_pass_time + times_preprocess + times_inference + top_10_generation_time + top_1_generation_time + p2_rank_time}')
|
333 |
+
|
334 |
+
with open(os.path.join(args.results_path, 'tankbind_log.log'), 'w') as file:
|
335 |
+
file.write(f'forward_pass_time: {forward_pass_time}')
|
336 |
+
file.write(f'times_preprocess: {times_preprocess}')
|
337 |
+
file.write(f'times_inference: {times_inference}')
|
338 |
+
file.write(f'top_10_generation_time: {top_10_generation_time}')
|
339 |
+
file.write(f'top_1_generation_time: {top_1_generation_time}')
|
340 |
+
file.write(f'rmsds_below_2: {(100 * (rmsds < 2).sum() / len(rmsds))}')
|
341 |
+
file.write(f'p2rank Time: {p2_rank_time}')
|
342 |
+
file.write(f'total_time: {forward_pass_time + times_preprocess + times_inference + top_10_generation_time + top_1_generation_time + p2_rank_time}')
|
confidence/confidence_train.py
ADDED
@@ -0,0 +1,319 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import gc
|
2 |
+
import math
|
3 |
+
import os
|
4 |
+
|
5 |
+
import shutil
|
6 |
+
|
7 |
+
from argparse import Namespace, ArgumentParser, FileType
|
8 |
+
import torch.nn.functional as F
|
9 |
+
|
10 |
+
import wandb
|
11 |
+
import torch
|
12 |
+
from sklearn.metrics import roc_auc_score
|
13 |
+
from torch_geometric.loader import DataListLoader, DataLoader
|
14 |
+
from tqdm import tqdm
|
15 |
+
|
16 |
+
from confidence.dataset import ConfidenceDataset
|
17 |
+
from utils.training import AverageMeter
|
18 |
+
|
19 |
+
torch.multiprocessing.set_sharing_strategy('file_system')
|
20 |
+
|
21 |
+
import yaml
|
22 |
+
from utils.utils import save_yaml_file, get_optimizer_and_scheduler, get_model
|
23 |
+
|
24 |
+
|
25 |
+
parser = ArgumentParser()
|
26 |
+
parser.add_argument('--config', type=FileType(mode='r'), default=None)
|
27 |
+
parser.add_argument('--original_model_dir', type=str, default='workdir', help='Path to folder with trained model and hyperparameters')
|
28 |
+
parser.add_argument('--restart_dir', type=str, default=None, help='')
|
29 |
+
parser.add_argument('--use_original_model_cache', action='store_true', default=False, help='If this is true, the same dataset as in the original model will be used. Otherwise, the dataset parameters are used.')
|
30 |
+
parser.add_argument('--data_dir', type=str, default='data/PDBBind_processed/', help='Folder containing original structures')
|
31 |
+
parser.add_argument('--ckpt', type=str, default='best_model.pt', help='Checkpoint to use inside the folder')
|
32 |
+
parser.add_argument('--model_save_frequency', type=int, default=0, help='Frequency with which to save the last model. If 0, then only the early stopping criterion best model is saved and overwritten.')
|
33 |
+
parser.add_argument('--best_model_save_frequency', type=int, default=0, help='Frequency with which to save the best model. If 0, then only the early stopping criterion best model is saved and overwritten.')
|
34 |
+
parser.add_argument('--run_name', type=str, default='test_confidence', help='')
|
35 |
+
parser.add_argument('--project', type=str, default='diffdock_confidence', help='')
|
36 |
+
parser.add_argument('--split_train', type=str, default='data/splits/timesplit_no_lig_overlap_train', help='Path of file defining the split')
|
37 |
+
parser.add_argument('--split_val', type=str, default='data/splits/timesplit_no_lig_overlap_val', help='Path of file defining the split')
|
38 |
+
parser.add_argument('--split_test', type=str, default='data/splits/timesplit_test', help='Path of file defining the split')
|
39 |
+
|
40 |
+
# Inference parameters for creating the positions and rmsds that the confidence predictor will be trained on.
|
41 |
+
parser.add_argument('--cache_path', type=str, default='data/cacheNew', help='Folder from where to load/restore cached dataset')
|
42 |
+
parser.add_argument('--cache_ids_to_combine', nargs='+', type=str, default=None, help='RMSD value below which a prediction is considered a postitive. This can also be multiple cutoffs.')
|
43 |
+
parser.add_argument('--cache_creation_id', type=int, default=None, help='number of times that inference is run on the full dataset before concatenating it and coming up with the full confidence dataset')
|
44 |
+
parser.add_argument('--wandb', action='store_true', default=False, help='')
|
45 |
+
parser.add_argument('--inference_steps', type=int, default=2, help='Number of denoising steps')
|
46 |
+
parser.add_argument('--samples_per_complex', type=int, default=3, help='')
|
47 |
+
parser.add_argument('--balance', action='store_true', default=False, help='If this is true than we do not force the samples seen during training to be the same amount of negatives as positives')
|
48 |
+
parser.add_argument('--rmsd_prediction', action='store_true', default=False, help='')
|
49 |
+
parser.add_argument('--rmsd_classification_cutoff', nargs='+', type=float, default=2, help='RMSD value below which a prediction is considered a postitive. This can also be multiple cutoffs.')
|
50 |
+
|
51 |
+
parser.add_argument('--log_dir', type=str, default='workdir', help='')
|
52 |
+
parser.add_argument('--main_metric', type=str, default='accuracy', help='Metric to track for early stopping. Mostly [loss, accuracy, ROC AUC]')
|
53 |
+
parser.add_argument('--main_metric_goal', type=str, default='max', help='Can be [min, max]')
|
54 |
+
parser.add_argument('--transfer_weights', action='store_true', default=False, help='')
|
55 |
+
parser.add_argument('--batch_size', type=int, default=5, help='')
|
56 |
+
parser.add_argument('--lr', type=float, default=1e-3, help='')
|
57 |
+
parser.add_argument('--w_decay', type=float, default=0.0, help='')
|
58 |
+
parser.add_argument('--scheduler', type=str, default='plateau', help='')
|
59 |
+
parser.add_argument('--scheduler_patience', type=int, default=20, help='')
|
60 |
+
parser.add_argument('--n_epochs', type=int, default=5, help='')
|
61 |
+
|
62 |
+
# Dataset
|
63 |
+
parser.add_argument('--limit_complexes', type=int, default=0, help='')
|
64 |
+
parser.add_argument('--all_atoms', action='store_true', default=True, help='')
|
65 |
+
parser.add_argument('--multiplicity', type=int, default=1, help='')
|
66 |
+
parser.add_argument('--chain_cutoff', type=float, default=10, help='')
|
67 |
+
parser.add_argument('--receptor_radius', type=float, default=30, help='')
|
68 |
+
parser.add_argument('--c_alpha_max_neighbors', type=int, default=10, help='')
|
69 |
+
parser.add_argument('--atom_radius', type=float, default=5, help='')
|
70 |
+
parser.add_argument('--atom_max_neighbors', type=int, default=8, help='')
|
71 |
+
parser.add_argument('--matching_popsize', type=int, default=20, help='')
|
72 |
+
parser.add_argument('--matching_maxiter', type=int, default=20, help='')
|
73 |
+
parser.add_argument('--max_lig_size', type=int, default=None, help='Maximum number of heavy atoms')
|
74 |
+
parser.add_argument('--remove_hs', action='store_true', default=False, help='remove Hs')
|
75 |
+
parser.add_argument('--num_conformers', type=int, default=1, help='')
|
76 |
+
parser.add_argument('--esm_embeddings_path', type=str, default=None,help='If this is set then the LM embeddings at that path will be used for the receptor features')
|
77 |
+
parser.add_argument('--no_torsion', action='store_true', default=False, help='')
|
78 |
+
|
79 |
+
# Model
|
80 |
+
parser.add_argument('--num_conv_layers', type=int, default=2, help='Number of interaction layers')
|
81 |
+
parser.add_argument('--max_radius', type=float, default=5.0, help='Radius cutoff for geometric graph')
|
82 |
+
parser.add_argument('--scale_by_sigma', action='store_true', default=True, help='Whether to normalise the score')
|
83 |
+
parser.add_argument('--ns', type=int, default=16, help='Number of hidden features per node of order 0')
|
84 |
+
parser.add_argument('--nv', type=int, default=4, help='Number of hidden features per node of order >0')
|
85 |
+
parser.add_argument('--distance_embed_dim', type=int, default=32, help='')
|
86 |
+
parser.add_argument('--cross_distance_embed_dim', type=int, default=32, help='')
|
87 |
+
parser.add_argument('--no_batch_norm', action='store_true', default=False, help='If set, it removes the batch norm')
|
88 |
+
parser.add_argument('--use_second_order_repr', action='store_true', default=False, help='Whether to use only up to first order representations or also second')
|
89 |
+
parser.add_argument('--cross_max_distance', type=float, default=80, help='')
|
90 |
+
parser.add_argument('--dynamic_max_cross', action='store_true', default=False, help='')
|
91 |
+
parser.add_argument('--dropout', type=float, default=0.0, help='MLP dropout')
|
92 |
+
parser.add_argument('--embedding_type', type=str, default="sinusoidal", help='')
|
93 |
+
parser.add_argument('--sigma_embed_dim', type=int, default=32, help='')
|
94 |
+
parser.add_argument('--embedding_scale', type=int, default=10000, help='')
|
95 |
+
parser.add_argument('--confidence_no_batchnorm', action='store_true', default=False, help='')
|
96 |
+
parser.add_argument('--confidence_dropout', type=float, default=0.0, help='MLP dropout in confidence readout')
|
97 |
+
|
98 |
+
args = parser.parse_args()
|
99 |
+
if args.config:
|
100 |
+
config_dict = yaml.load(args.config, Loader=yaml.FullLoader)
|
101 |
+
arg_dict = args.__dict__
|
102 |
+
for key, value in config_dict.items():
|
103 |
+
if isinstance(value, list):
|
104 |
+
for v in value:
|
105 |
+
arg_dict[key].append(v)
|
106 |
+
else:
|
107 |
+
arg_dict[key] = value
|
108 |
+
args.config = args.config.name
|
109 |
+
assert(args.main_metric_goal == 'max' or args.main_metric_goal == 'min')
|
110 |
+
|
111 |
+
def train_epoch(model, loader, optimizer, rmsd_prediction):
|
112 |
+
model.train()
|
113 |
+
meter = AverageMeter(['confidence_loss'])
|
114 |
+
|
115 |
+
for data in tqdm(loader, total=len(loader)):
|
116 |
+
if device.type == 'cuda' and len(data) % torch.cuda.device_count() == 1 or device.type == 'cpu' and data.num_graphs == 1:
|
117 |
+
print("Skipping batch of size 1 since otherwise batchnorm would not work.")
|
118 |
+
optimizer.zero_grad()
|
119 |
+
try:
|
120 |
+
pred = model(data)
|
121 |
+
if rmsd_prediction:
|
122 |
+
labels = torch.cat([graph.rmsd for graph in data]).to(device) if isinstance(data, list) else data.rmsd
|
123 |
+
confidence_loss = F.mse_loss(pred, labels)
|
124 |
+
else:
|
125 |
+
if isinstance(args.rmsd_classification_cutoff, list):
|
126 |
+
labels = torch.cat([graph.y_binned for graph in data]).to(device) if isinstance(data, list) else data.y_binned
|
127 |
+
confidence_loss = F.cross_entropy(pred, labels)
|
128 |
+
else:
|
129 |
+
labels = torch.cat([graph.y for graph in data]).to(device) if isinstance(data, list) else data.y
|
130 |
+
confidence_loss = F.binary_cross_entropy_with_logits(pred, labels)
|
131 |
+
confidence_loss.backward()
|
132 |
+
optimizer.step()
|
133 |
+
meter.add([confidence_loss.cpu().detach()])
|
134 |
+
except RuntimeError as e:
|
135 |
+
if 'out of memory' in str(e):
|
136 |
+
print('| WARNING: ran out of memory, skipping batch')
|
137 |
+
for p in model.parameters():
|
138 |
+
if p.grad is not None:
|
139 |
+
del p.grad # free some memory
|
140 |
+
torch.cuda.empty_cache()
|
141 |
+
gc.collect()
|
142 |
+
continue
|
143 |
+
else:
|
144 |
+
raise e
|
145 |
+
|
146 |
+
return meter.summary()
|
147 |
+
|
148 |
+
def test_epoch(model, loader, rmsd_prediction):
|
149 |
+
model.eval()
|
150 |
+
meter = AverageMeter(['loss'], unpooled_metrics=True) if rmsd_prediction else AverageMeter(['confidence_loss', 'accuracy', 'ROC AUC'], unpooled_metrics=True)
|
151 |
+
all_labels = []
|
152 |
+
all_affinities = []
|
153 |
+
for data in tqdm(loader, total=len(loader)):
|
154 |
+
try:
|
155 |
+
with torch.no_grad():
|
156 |
+
pred = model(data)
|
157 |
+
affinity_loss = torch.tensor(0.0, dtype=torch.float, device=pred[0].device)
|
158 |
+
accuracy = torch.tensor(0.0, dtype=torch.float, device=pred[0].device)
|
159 |
+
if rmsd_prediction:
|
160 |
+
labels = torch.cat([graph.rmsd for graph in data]).to(device) if isinstance(data, list) else data.rmsd
|
161 |
+
confidence_loss = F.mse_loss(pred, labels)
|
162 |
+
meter.add([confidence_loss.cpu().detach()])
|
163 |
+
else:
|
164 |
+
if isinstance(args.rmsd_classification_cutoff, list):
|
165 |
+
labels = torch.cat([graph.y_binned for graph in data]).to(device) if isinstance(data,list) else data.y_binned
|
166 |
+
confidence_loss = F.cross_entropy(pred, labels)
|
167 |
+
else:
|
168 |
+
labels = torch.cat([graph.y for graph in data]).to(device) if isinstance(data, list) else data.y
|
169 |
+
confidence_loss = F.binary_cross_entropy_with_logits(pred, labels)
|
170 |
+
accuracy = torch.mean((labels == (pred > 0).float()).float())
|
171 |
+
try:
|
172 |
+
roc_auc = roc_auc_score(labels.detach().cpu().numpy(), pred.detach().cpu().numpy())
|
173 |
+
except ValueError as e:
|
174 |
+
if 'Only one class present in y_true. ROC AUC score is not defined in that case.' in str(e):
|
175 |
+
roc_auc = 0
|
176 |
+
else:
|
177 |
+
raise e
|
178 |
+
meter.add([confidence_loss.cpu().detach(), accuracy.cpu().detach(), torch.tensor(roc_auc)])
|
179 |
+
all_labels.append(labels)
|
180 |
+
|
181 |
+
except RuntimeError as e:
|
182 |
+
if 'out of memory' in str(e):
|
183 |
+
print('| WARNING: ran out of memory, skipping batch')
|
184 |
+
for p in model.parameters():
|
185 |
+
if p.grad is not None:
|
186 |
+
del p.grad # free some memory
|
187 |
+
torch.cuda.empty_cache()
|
188 |
+
continue
|
189 |
+
else:
|
190 |
+
raise e
|
191 |
+
|
192 |
+
all_labels = torch.cat(all_labels)
|
193 |
+
|
194 |
+
if rmsd_prediction:
|
195 |
+
baseline_metric = ((all_labels - all_labels.mean()).abs()).mean()
|
196 |
+
else:
|
197 |
+
baseline_metric = all_labels.sum() / len(all_labels)
|
198 |
+
results = meter.summary()
|
199 |
+
results.update({'baseline_metric': baseline_metric})
|
200 |
+
return meter.summary(), baseline_metric
|
201 |
+
|
202 |
+
|
203 |
+
def train(args, model, optimizer, scheduler, train_loader, val_loader, run_dir):
|
204 |
+
best_val_metric = math.inf if args.main_metric_goal == 'min' else 0
|
205 |
+
best_epoch = 0
|
206 |
+
|
207 |
+
print("Starting training...")
|
208 |
+
for epoch in range(args.n_epochs):
|
209 |
+
logs = {}
|
210 |
+
train_metrics = train_epoch(model, train_loader, optimizer, args.rmsd_prediction)
|
211 |
+
print("Epoch {}: Training loss {:.4f}".format(epoch, train_metrics['confidence_loss']))
|
212 |
+
|
213 |
+
val_metrics, baseline_metric = test_epoch(model, val_loader, args.rmsd_prediction)
|
214 |
+
if args.rmsd_prediction:
|
215 |
+
print("Epoch {}: Validation loss {:.4f}".format(epoch, val_metrics['confidence_loss']))
|
216 |
+
else:
|
217 |
+
print("Epoch {}: Validation loss {:.4f} accuracy {:.4f}".format(epoch, val_metrics['confidence_loss'], val_metrics['accuracy']))
|
218 |
+
|
219 |
+
if args.wandb:
|
220 |
+
logs.update({'valinf_' + k: v for k, v in val_metrics.items()}, step=epoch + 1)
|
221 |
+
logs.update({'train_' + k: v for k, v in train_metrics.items()}, step=epoch + 1)
|
222 |
+
logs.update({'mean_rmsd' if args.rmsd_prediction else 'fraction_positives': baseline_metric,
|
223 |
+
'current_lr': optimizer.param_groups[0]['lr']})
|
224 |
+
wandb.log(logs, step=epoch + 1)
|
225 |
+
|
226 |
+
if scheduler:
|
227 |
+
scheduler.step(val_metrics[args.main_metric])
|
228 |
+
|
229 |
+
state_dict = model.module.state_dict() if device.type == 'cuda' else model.state_dict()
|
230 |
+
|
231 |
+
if args.main_metric_goal == 'min' and val_metrics[args.main_metric] < best_val_metric or \
|
232 |
+
args.main_metric_goal == 'max' and val_metrics[args.main_metric] > best_val_metric:
|
233 |
+
best_val_metric = val_metrics[args.main_metric]
|
234 |
+
best_epoch = epoch
|
235 |
+
torch.save(state_dict, os.path.join(run_dir, 'best_model.pt'))
|
236 |
+
if args.model_save_frequency > 0 and (epoch + 1) % args.model_save_frequency == 0:
|
237 |
+
torch.save(state_dict, os.path.join(run_dir, f'model_epoch{epoch+1}.pt'))
|
238 |
+
if args.best_model_save_frequency > 0 and (epoch + 1) % args.best_model_save_frequency == 0:
|
239 |
+
shutil.copyfile(os.path.join(run_dir, 'best_model.pt'), os.path.join(run_dir, f'best_model_epoch{epoch+1}.pt'))
|
240 |
+
|
241 |
+
torch.save({
|
242 |
+
'epoch': epoch,
|
243 |
+
'model': state_dict,
|
244 |
+
'optimizer': optimizer.state_dict(),
|
245 |
+
}, os.path.join(run_dir, 'last_model.pt'))
|
246 |
+
|
247 |
+
print("Best Validation accuracy {} on Epoch {}".format(best_val_metric, best_epoch))
|
248 |
+
|
249 |
+
|
250 |
+
def construct_loader_confidence(args, device):
|
251 |
+
common_args = {'cache_path': args.cache_path, 'original_model_dir': args.original_model_dir, 'device': device,
|
252 |
+
'inference_steps': args.inference_steps, 'samples_per_complex': args.samples_per_complex,
|
253 |
+
'limit_complexes': args.limit_complexes, 'all_atoms': args.all_atoms, 'balance': args.balance, 'rmsd_classification_cutoff': args.rmsd_classification_cutoff,
|
254 |
+
'use_original_model_cache': args.use_original_model_cache, 'cache_creation_id': args.cache_creation_id, "cache_ids_to_combine": args.cache_ids_to_combine}
|
255 |
+
loader_class = DataListLoader if torch.cuda.is_available() else DataLoader
|
256 |
+
|
257 |
+
exception_flag = False
|
258 |
+
try:
|
259 |
+
train_dataset = ConfidenceDataset(split="train", args=args, **common_args)
|
260 |
+
train_loader = loader_class(dataset=train_dataset, batch_size=args.batch_size, shuffle=True)
|
261 |
+
except Exception as e:
|
262 |
+
if 'The generated ligand positions with cache_id do not exist:' in str(e):
|
263 |
+
print("HAPPENING | Encountered the following exception when loading the confidence train dataset:")
|
264 |
+
print(str(e))
|
265 |
+
print("HAPPENING | We are still continuing because we want to try to generate the validation dataset if it has not been created yet:")
|
266 |
+
exception_flag = True
|
267 |
+
else: raise e
|
268 |
+
|
269 |
+
val_dataset = ConfidenceDataset(split="val", args=args, **common_args)
|
270 |
+
val_loader = loader_class(dataset=val_dataset, batch_size=args.batch_size, shuffle=True)
|
271 |
+
|
272 |
+
if exception_flag: raise Exception('We encountered the exception during train dataset loading: ', e)
|
273 |
+
return train_loader, val_loader
|
274 |
+
|
275 |
+
|
276 |
+
if __name__ == '__main__':
|
277 |
+
device = torch.device('cuda:0' if torch.cuda.is_available() else 'cpu')
|
278 |
+
with open(f'{args.original_model_dir}/model_parameters.yml') as f:
|
279 |
+
score_model_args = Namespace(**yaml.full_load(f))
|
280 |
+
|
281 |
+
# construct loader
|
282 |
+
train_loader, val_loader = construct_loader_confidence(args, device)
|
283 |
+
model = get_model(score_model_args if args.transfer_weights else args, device, t_to_sigma=None, confidence_mode=True)
|
284 |
+
optimizer, scheduler = get_optimizer_and_scheduler(args, model, scheduler_mode=args.main_metric_goal)
|
285 |
+
|
286 |
+
if args.transfer_weights:
|
287 |
+
print("HAPPENING | Transferring weights from original_model_dir to the new model after using original_model_dir's arguments to construct the new model.")
|
288 |
+
checkpoint = torch.load(os.path.join(args.original_model_dir,args.ckpt), map_location=device)
|
289 |
+
model_state_dict = model.state_dict()
|
290 |
+
transfer_weights_dict = {k: v for k, v in checkpoint.items() if k in list(model_state_dict.keys())}
|
291 |
+
model_state_dict.update(transfer_weights_dict) # update the layers with the pretrained weights
|
292 |
+
model.load_state_dict(model_state_dict)
|
293 |
+
|
294 |
+
elif args.restart_dir:
|
295 |
+
dict = torch.load(f'{args.restart_dir}/last_model.pt', map_location=torch.device('cpu'))
|
296 |
+
model.module.load_state_dict(dict['model'], strict=True)
|
297 |
+
optimizer.load_state_dict(dict['optimizer'])
|
298 |
+
print("Restarting from epoch", dict['epoch'])
|
299 |
+
|
300 |
+
numel = sum([p.numel() for p in model.parameters()])
|
301 |
+
print('Model with', numel, 'parameters')
|
302 |
+
|
303 |
+
if args.wandb:
|
304 |
+
wandb.init(
|
305 |
+
entity='entity',
|
306 |
+
settings=wandb.Settings(start_method="fork"),
|
307 |
+
project=args.project,
|
308 |
+
name=args.run_name,
|
309 |
+
config=args
|
310 |
+
)
|
311 |
+
wandb.log({'numel': numel})
|
312 |
+
|
313 |
+
# record parameters
|
314 |
+
run_dir = os.path.join(args.log_dir, args.run_name)
|
315 |
+
yaml_file_name = os.path.join(run_dir, 'model_parameters.yml')
|
316 |
+
save_yaml_file(yaml_file_name, args.__dict__)
|
317 |
+
args.device = device
|
318 |
+
|
319 |
+
train(args, model, optimizer, scheduler, train_loader, val_loader, run_dir)
|
confidence/dataset.py
ADDED
@@ -0,0 +1,272 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import itertools
|
2 |
+
import math
|
3 |
+
import os
|
4 |
+
import pickle
|
5 |
+
import random
|
6 |
+
from argparse import Namespace
|
7 |
+
from functools import partial
|
8 |
+
import copy
|
9 |
+
|
10 |
+
import numpy as np
|
11 |
+
import pandas as pd
|
12 |
+
import torch
|
13 |
+
import yaml
|
14 |
+
from torch_geometric.data import Dataset, Data
|
15 |
+
from torch_geometric.loader import DataLoader
|
16 |
+
from tqdm import tqdm
|
17 |
+
|
18 |
+
from datasets.pdbbind import PDBBind
|
19 |
+
from utils.diffusion_utils import get_t_schedule
|
20 |
+
from utils.sampling import randomize_position, sampling
|
21 |
+
from utils.utils import get_model
|
22 |
+
from utils.diffusion_utils import t_to_sigma as t_to_sigma_compl
|
23 |
+
|
24 |
+
|
25 |
+
class ListDataset(Dataset):
|
26 |
+
def __init__(self, list):
|
27 |
+
super().__init__()
|
28 |
+
self.data_list = list
|
29 |
+
|
30 |
+
def len(self) -> int:
|
31 |
+
return len(self.data_list)
|
32 |
+
|
33 |
+
def get(self, idx: int) -> Data:
|
34 |
+
return self.data_list[idx]
|
35 |
+
|
36 |
+
def get_cache_path(args, split):
|
37 |
+
cache_path = args.cache_path
|
38 |
+
if not args.no_torsion:
|
39 |
+
cache_path += '_torsion'
|
40 |
+
if args.all_atoms:
|
41 |
+
cache_path += '_allatoms'
|
42 |
+
split_path = args.split_train if split == 'train' else args.split_val
|
43 |
+
cache_path = os.path.join(cache_path, f'limit{args.limit_complexes}_INDEX{os.path.splitext(os.path.basename(split_path))[0]}_maxLigSize{args.max_lig_size}_H{int(not args.remove_hs)}_recRad{args.receptor_radius}_recMax{args.c_alpha_max_neighbors}'
|
44 |
+
+ ('' if not args.all_atoms else f'_atomRad{args.atom_radius}_atomMax{args.atom_max_neighbors}')
|
45 |
+
+ ('' if args.no_torsion or args.num_conformers == 1 else
|
46 |
+
f'_confs{args.num_conformers}')
|
47 |
+
+ ('' if args.esm_embeddings_path is None else f'_esmEmbeddings'))
|
48 |
+
return cache_path
|
49 |
+
|
50 |
+
def get_args_and_cache_path(original_model_dir, split):
|
51 |
+
with open(f'{original_model_dir}/model_parameters.yml') as f:
|
52 |
+
model_args = Namespace(**yaml.full_load(f))
|
53 |
+
return model_args, get_cache_path(model_args,split)
|
54 |
+
|
55 |
+
|
56 |
+
|
57 |
+
class ConfidenceDataset(Dataset):
|
58 |
+
def __init__(self, cache_path, original_model_dir, split, device, limit_complexes,
|
59 |
+
inference_steps, samples_per_complex, all_atoms,
|
60 |
+
args, balance=False, use_original_model_cache=True, rmsd_classification_cutoff=2,
|
61 |
+
cache_ids_to_combine= None, cache_creation_id=None):
|
62 |
+
|
63 |
+
super(ConfidenceDataset, self).__init__()
|
64 |
+
|
65 |
+
self.device = device
|
66 |
+
self.inference_steps = inference_steps
|
67 |
+
self.limit_complexes = limit_complexes
|
68 |
+
self.all_atoms = all_atoms
|
69 |
+
self.original_model_dir = original_model_dir
|
70 |
+
self.balance = balance
|
71 |
+
self.use_original_model_cache = use_original_model_cache
|
72 |
+
self.rmsd_classification_cutoff = rmsd_classification_cutoff
|
73 |
+
self.cache_ids_to_combine = cache_ids_to_combine
|
74 |
+
self.cache_creation_id = cache_creation_id
|
75 |
+
self.samples_per_complex = samples_per_complex
|
76 |
+
|
77 |
+
self.original_model_args, original_model_cache = get_args_and_cache_path(original_model_dir, split)
|
78 |
+
self.complex_graphs_cache = original_model_cache if self.use_original_model_cache else get_cache_path(args, split)
|
79 |
+
print('Using the cached complex graphs of the original model args' if self.use_original_model_cache else 'Not using the cached complex graphs of the original model args. Instead the complex graphs are used that are at the location given by the dataset parameters given to confidence_train.py')
|
80 |
+
print(self.complex_graphs_cache)
|
81 |
+
if not os.path.exists(os.path.join(self.complex_graphs_cache, "heterographs.pkl")):
|
82 |
+
print(f'HAPPENING | Complex graphs path does not exist yet: {os.path.join(self.complex_graphs_cache, "heterographs.pkl")}. For that reason, we are now creating the dataset.')
|
83 |
+
PDBBind(transform=None, root=args.data_dir, limit_complexes=args.limit_complexes,
|
84 |
+
receptor_radius=args.receptor_radius,
|
85 |
+
cache_path=args.cache_path, split_path=args.split_val if split == 'val' else args.split_train,
|
86 |
+
remove_hs=args.remove_hs, max_lig_size=None,
|
87 |
+
c_alpha_max_neighbors=args.c_alpha_max_neighbors,
|
88 |
+
matching=not args.no_torsion, keep_original=True,
|
89 |
+
popsize=args.matching_popsize,
|
90 |
+
maxiter=args.matching_maxiter,
|
91 |
+
all_atoms=args.all_atoms,
|
92 |
+
atom_radius=args.atom_radius,
|
93 |
+
atom_max_neighbors=args.atom_max_neighbors,
|
94 |
+
esm_embeddings_path=args.esm_embeddings_path,
|
95 |
+
require_ligand=True)
|
96 |
+
|
97 |
+
print(f'HAPPENING | Loading complex graphs from: {os.path.join(self.complex_graphs_cache, "heterographs.pkl")}')
|
98 |
+
with open(os.path.join(self.complex_graphs_cache, "heterographs.pkl"), 'rb') as f:
|
99 |
+
complex_graphs = pickle.load(f)
|
100 |
+
self.complex_graph_dict = {d.name: d for d in complex_graphs}
|
101 |
+
|
102 |
+
self.full_cache_path = os.path.join(cache_path, f'model_{os.path.splitext(os.path.basename(original_model_dir))[0]}'
|
103 |
+
f'_split_{split}_limit_{limit_complexes}')
|
104 |
+
|
105 |
+
if (not os.path.exists(os.path.join(self.full_cache_path, "ligand_positions.pkl")) and self.cache_creation_id is None) or \
|
106 |
+
(not os.path.exists(os.path.join(self.full_cache_path, f"ligand_positions_id{self.cache_creation_id}.pkl")) and self.cache_creation_id is not None):
|
107 |
+
os.makedirs(self.full_cache_path, exist_ok=True)
|
108 |
+
self.preprocessing(original_model_cache)
|
109 |
+
|
110 |
+
if self.cache_ids_to_combine is None:
|
111 |
+
print(f'HAPPENING | Loading positions and rmsds from: {os.path.join(self.full_cache_path, "ligand_positions.pkl")}')
|
112 |
+
with open(os.path.join(self.full_cache_path, "ligand_positions.pkl"), 'rb') as f:
|
113 |
+
self.full_ligand_positions, self.rmsds = pickle.load(f)
|
114 |
+
if os.path.exists(os.path.join(self.full_cache_path, "complex_names_in_same_order.pkl")):
|
115 |
+
with open(os.path.join(self.full_cache_path, "complex_names_in_same_order.pkl"), 'rb') as f:
|
116 |
+
generated_rmsd_complex_names = pickle.load(f)
|
117 |
+
else:
|
118 |
+
print('HAPPENING | The path, ', os.path.join(self.full_cache_path, "complex_names_in_same_order.pkl"),
|
119 |
+
' does not exist. \n => We assume that means that we are using a ligand_positions.pkl where the '
|
120 |
+
'code was not saving the complex names for them yet. We now instead use the complex names of '
|
121 |
+
'the dataset that the original model used to create the ligand positions and RMSDs.')
|
122 |
+
with open(os.path.join(original_model_cache, "heterographs.pkl"), 'rb') as f:
|
123 |
+
original_model_complex_graphs = pickle.load(f)
|
124 |
+
generated_rmsd_complex_names = [d.name for d in original_model_complex_graphs]
|
125 |
+
assert (len(self.rmsds) == len(generated_rmsd_complex_names))
|
126 |
+
else:
|
127 |
+
all_rmsds_unsorted, all_full_ligand_positions_unsorted, all_names_unsorted = [], [], []
|
128 |
+
for idx, cache_id in enumerate(self.cache_ids_to_combine):
|
129 |
+
print(f'HAPPENING | Loading positions and rmsds from cache_id from the path: {os.path.join(self.full_cache_path, "ligand_positions_"+ str(cache_id)+ ".pkl")}')
|
130 |
+
if not os.path.exists(os.path.join(self.full_cache_path, f"ligand_positions_id{cache_id}.pkl")): raise Exception(f'The generated ligand positions with cache_id do not exist: {cache_id}') # be careful with changing this error message since it is sometimes cought in a try catch
|
131 |
+
with open(os.path.join(self.full_cache_path, f"ligand_positions_id{cache_id}.pkl"), 'rb') as f:
|
132 |
+
full_ligand_positions, rmsds = pickle.load(f)
|
133 |
+
with open(os.path.join(self.full_cache_path, f"complex_names_in_same_order_id{cache_id}.pkl"), 'rb') as f:
|
134 |
+
names_unsorted = pickle.load(f)
|
135 |
+
all_names_unsorted.append(names_unsorted)
|
136 |
+
all_rmsds_unsorted.append(rmsds)
|
137 |
+
all_full_ligand_positions_unsorted.append(full_ligand_positions)
|
138 |
+
names_order = list(set(sum(all_names_unsorted, [])))
|
139 |
+
all_rmsds, all_full_ligand_positions, all_names = [], [], []
|
140 |
+
for idx, (rmsds_unsorted, full_ligand_positions_unsorted, names_unsorted) in enumerate(zip(all_rmsds_unsorted,all_full_ligand_positions_unsorted, all_names_unsorted)):
|
141 |
+
name_to_pos_dict = {name: (rmsd, pos) for name, rmsd, pos in zip(names_unsorted, full_ligand_positions_unsorted, rmsds_unsorted) }
|
142 |
+
intermediate_rmsds = [name_to_pos_dict[name][1] for name in names_order]
|
143 |
+
all_rmsds.append((intermediate_rmsds))
|
144 |
+
intermediate_pos = [name_to_pos_dict[name][0] for name in names_order]
|
145 |
+
all_full_ligand_positions.append((intermediate_pos))
|
146 |
+
self.full_ligand_positions, self.rmsds = [], []
|
147 |
+
for positions_tuple in list(zip(*all_full_ligand_positions)):
|
148 |
+
self.full_ligand_positions.append(np.concatenate(positions_tuple, axis=0))
|
149 |
+
for positions_tuple in list(zip(*all_rmsds)):
|
150 |
+
self.rmsds.append(np.concatenate(positions_tuple, axis=0))
|
151 |
+
generated_rmsd_complex_names = names_order
|
152 |
+
print('Number of complex graphs: ', len(self.complex_graph_dict))
|
153 |
+
print('Number of RMSDs and positions for the complex graphs: ', len(self.full_ligand_positions))
|
154 |
+
|
155 |
+
self.all_samples_per_complex = samples_per_complex * (1 if self.cache_ids_to_combine is None else len(self.cache_ids_to_combine))
|
156 |
+
|
157 |
+
self.positions_rmsds_dict = {name: (pos, rmsd) for name, pos, rmsd in zip (generated_rmsd_complex_names, self.full_ligand_positions, self.rmsds)}
|
158 |
+
self.dataset_names = list(set(self.positions_rmsds_dict.keys()) & set(self.complex_graph_dict.keys()))
|
159 |
+
if limit_complexes > 0:
|
160 |
+
self.dataset_names = self.dataset_names[:limit_complexes]
|
161 |
+
|
162 |
+
def len(self):
|
163 |
+
return len(self.dataset_names)
|
164 |
+
|
165 |
+
def get(self, idx):
|
166 |
+
complex_graph = copy.deepcopy(self.complex_graph_dict[self.dataset_names[idx]])
|
167 |
+
positions, rmsds = self.positions_rmsds_dict[self.dataset_names[idx]]
|
168 |
+
|
169 |
+
if self.balance:
|
170 |
+
if isinstance(self.rmsd_classification_cutoff, list): raise ValueError("a list for --rmsd_classification_cutoff can only be used without --balance")
|
171 |
+
label = random.randint(0, 1)
|
172 |
+
success = rmsds < self.rmsd_classification_cutoff
|
173 |
+
n_success = np.count_nonzero(success)
|
174 |
+
if label == 0 and n_success != self.all_samples_per_complex:
|
175 |
+
# sample negative complex
|
176 |
+
sample = random.randint(0, self.all_samples_per_complex - n_success - 1)
|
177 |
+
lig_pos = positions[~success][sample]
|
178 |
+
complex_graph['ligand'].pos = torch.from_numpy(lig_pos)
|
179 |
+
else:
|
180 |
+
# sample positive complex
|
181 |
+
if n_success > 0: # if no successfull sample returns the matched complex
|
182 |
+
sample = random.randint(0, n_success - 1)
|
183 |
+
lig_pos = positions[success][sample]
|
184 |
+
complex_graph['ligand'].pos = torch.from_numpy(lig_pos)
|
185 |
+
complex_graph.y = torch.tensor(label).float()
|
186 |
+
else:
|
187 |
+
sample = random.randint(0, self.all_samples_per_complex - 1)
|
188 |
+
complex_graph['ligand'].pos = torch.from_numpy(positions[sample])
|
189 |
+
complex_graph.y = torch.tensor(rmsds[sample] < self.rmsd_classification_cutoff).float().unsqueeze(0)
|
190 |
+
if isinstance(self.rmsd_classification_cutoff, list):
|
191 |
+
complex_graph.y_binned = torch.tensor(np.logical_and(rmsds[sample] < self.rmsd_classification_cutoff + [math.inf],rmsds[sample] >= [0] + self.rmsd_classification_cutoff), dtype=torch.float).unsqueeze(0)
|
192 |
+
complex_graph.y = torch.tensor(rmsds[sample] < self.rmsd_classification_cutoff[0]).unsqueeze(0).float()
|
193 |
+
complex_graph.rmsd = torch.tensor(rmsds[sample]).unsqueeze(0).float()
|
194 |
+
|
195 |
+
complex_graph['ligand'].node_t = {'tr': 0 * torch.ones(complex_graph['ligand'].num_nodes),
|
196 |
+
'rot': 0 * torch.ones(complex_graph['ligand'].num_nodes),
|
197 |
+
'tor': 0 * torch.ones(complex_graph['ligand'].num_nodes)}
|
198 |
+
complex_graph['receptor'].node_t = {'tr': 0 * torch.ones(complex_graph['receptor'].num_nodes),
|
199 |
+
'rot': 0 * torch.ones(complex_graph['receptor'].num_nodes),
|
200 |
+
'tor': 0 * torch.ones(complex_graph['receptor'].num_nodes)}
|
201 |
+
if self.all_atoms:
|
202 |
+
complex_graph['atom'].node_t = {'tr': 0 * torch.ones(complex_graph['atom'].num_nodes),
|
203 |
+
'rot': 0 * torch.ones(complex_graph['atom'].num_nodes),
|
204 |
+
'tor': 0 * torch.ones(complex_graph['atom'].num_nodes)}
|
205 |
+
complex_graph.complex_t = {'tr': 0 * torch.ones(1), 'rot': 0 * torch.ones(1), 'tor': 0 * torch.ones(1)}
|
206 |
+
return complex_graph
|
207 |
+
|
208 |
+
def preprocessing(self, original_model_cache):
|
209 |
+
t_to_sigma = partial(t_to_sigma_compl, args=self.original_model_args)
|
210 |
+
|
211 |
+
model = get_model(self.original_model_args, self.device, t_to_sigma=t_to_sigma, no_parallel=True)
|
212 |
+
state_dict = torch.load(f'{self.original_model_dir}/best_model.pt', map_location=torch.device('cpu'))
|
213 |
+
model.load_state_dict(state_dict, strict=True)
|
214 |
+
model = model.to(self.device)
|
215 |
+
model.eval()
|
216 |
+
|
217 |
+
tr_schedule = get_t_schedule(inference_steps=self.inference_steps)
|
218 |
+
rot_schedule = tr_schedule
|
219 |
+
tor_schedule = tr_schedule
|
220 |
+
print('common t schedule', tr_schedule)
|
221 |
+
|
222 |
+
print('HAPPENING | loading cached complexes of the original model to create the confidence dataset RMSDs and predicted positions. Doing that from: ', os.path.join(self.complex_graphs_cache, "heterographs.pkl"))
|
223 |
+
with open(os.path.join(original_model_cache, "heterographs.pkl"), 'rb') as f:
|
224 |
+
complex_graphs = pickle.load(f)
|
225 |
+
dataset = ListDataset(complex_graphs)
|
226 |
+
loader = DataLoader(dataset=dataset, batch_size=1, shuffle=False)
|
227 |
+
|
228 |
+
rmsds, full_ligand_positions, names = [], [], []
|
229 |
+
for idx, orig_complex_graph in tqdm(enumerate(loader)):
|
230 |
+
data_list = [copy.deepcopy(orig_complex_graph) for _ in range(self.samples_per_complex)]
|
231 |
+
randomize_position(data_list, self.original_model_args.no_torsion, False, self.original_model_args.tr_sigma_max)
|
232 |
+
|
233 |
+
predictions_list = None
|
234 |
+
failed_convergence_counter = 0
|
235 |
+
while predictions_list is None:
|
236 |
+
try:
|
237 |
+
predictions_list, confidences = sampling(data_list=data_list, model=model, inference_steps=self.inference_steps,
|
238 |
+
tr_schedule=tr_schedule, rot_schedule=rot_schedule, tor_schedule=tor_schedule,
|
239 |
+
device=self.device, t_to_sigma=t_to_sigma, model_args=self.original_model_args)
|
240 |
+
except Exception as e:
|
241 |
+
if 'failed to converge' in str(e):
|
242 |
+
failed_convergence_counter += 1
|
243 |
+
if failed_convergence_counter > 5:
|
244 |
+
print('| WARNING: SVD failed to converge 5 times - skipping the complex')
|
245 |
+
break
|
246 |
+
print('| WARNING: SVD failed to converge - trying again with a new sample')
|
247 |
+
else:
|
248 |
+
raise e
|
249 |
+
if failed_convergence_counter > 5: predictions_list = data_list
|
250 |
+
if self.original_model_args.no_torsion:
|
251 |
+
orig_complex_graph['ligand'].orig_pos = (orig_complex_graph['ligand'].pos.cpu().numpy() + orig_complex_graph.original_center.cpu().numpy())
|
252 |
+
|
253 |
+
filterHs = torch.not_equal(predictions_list[0]['ligand'].x[:, 0], 0).cpu().numpy()
|
254 |
+
|
255 |
+
if isinstance(orig_complex_graph['ligand'].orig_pos, list):
|
256 |
+
orig_complex_graph['ligand'].orig_pos = orig_complex_graph['ligand'].orig_pos[0]
|
257 |
+
|
258 |
+
ligand_pos = np.asarray([complex_graph['ligand'].pos.cpu().numpy()[filterHs] for complex_graph in predictions_list])
|
259 |
+
orig_ligand_pos = np.expand_dims(orig_complex_graph['ligand'].orig_pos[filterHs] - orig_complex_graph.original_center.cpu().numpy(), axis=0)
|
260 |
+
rmsd = np.sqrt(((ligand_pos - orig_ligand_pos) ** 2).sum(axis=2).mean(axis=1))
|
261 |
+
|
262 |
+
rmsds.append(rmsd)
|
263 |
+
full_ligand_positions.append(np.asarray([complex_graph['ligand'].pos.cpu().numpy() for complex_graph in predictions_list]))
|
264 |
+
names.append(orig_complex_graph.name[0])
|
265 |
+
assert(len(orig_complex_graph.name) == 1) # I just put this assert here because of the above line where I assumed that the list is always only lenght 1. Just in case it isn't maybe check what the names in there are.
|
266 |
+
with open(os.path.join(self.full_cache_path, f"ligand_positions{'' if self.cache_creation_id is None else '_id' + str(self.cache_creation_id)}.pkl"), 'wb') as f:
|
267 |
+
pickle.dump((full_ligand_positions, rmsds), f)
|
268 |
+
with open(os.path.join(self.full_cache_path, f"complex_names_in_same_order{'' if self.cache_creation_id is None else '_id' + str(self.cache_creation_id)}.pkl"), 'wb') as f:
|
269 |
+
pickle.dump((names), f)
|
270 |
+
|
271 |
+
|
272 |
+
|
data/protein_ligand_example_csv.csv
ADDED
@@ -0,0 +1,2 @@
|
|
|
|
|
|
|
1 |
+
protein_path,ligand
|
2 |
+
examples/1cbr_protein.pdb,CCCC
|
data/splits/timesplit_no_lig_overlap_train
ADDED
@@ -0,0 +1,16379 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
3dpf
|
2 |
+
2zy1
|
3 |
+
6h77
|
4 |
+
5c0m
|
5 |
+
4o2c
|
6 |
+
3a2c
|
7 |
+
3b2t
|
8 |
+
1v2q
|
9 |
+
4q87
|
10 |
+
4j28
|
11 |
+
3efw
|
12 |
+
4mi6
|
13 |
+
3k8c
|
14 |
+
3s54
|
15 |
+
2fda
|
16 |
+
2q55
|
17 |
+
5ylv
|
18 |
+
4ozo
|
19 |
+
3fzn
|
20 |
+
3eoc
|
21 |
+
4tn2
|
22 |
+
3hfv
|
23 |
+
5gg4
|
24 |
+
5svi
|
25 |
+
2r58
|
26 |
+
5d1n
|
27 |
+
4yqv
|
28 |
+
1hs6
|
29 |
+
3zxh
|
30 |
+
1ft7
|
31 |
+
4hww
|
32 |
+
6b1j
|
33 |
+
3di6
|
34 |
+
5jaz
|
35 |
+
5ema
|
36 |
+
6gip
|
37 |
+
5am5
|
38 |
+
4bnt
|
39 |
+
1fq6
|
40 |
+
3pqz
|
41 |
+
6eil
|
42 |
+
2q11
|
43 |
+
4nw7
|
44 |
+
4ahr
|
45 |
+
1p1o
|
46 |
+
3le8
|
47 |
+
3nzk
|
48 |
+
1eub
|
49 |
+
1eoc
|
50 |
+
3std
|
51 |
+
3qw8
|
52 |
+
4za0
|
53 |
+
5l8a
|
54 |
+
5teg
|
55 |
+
5u6j
|
56 |
+
3g2n
|
57 |
+
2wp1
|
58 |
+
1zyr
|
59 |
+
1xs7
|
60 |
+
4m6q
|
61 |
+
2jq9
|
62 |
+
4m5h
|
63 |
+
4d63
|
64 |
+
3shb
|
65 |
+
3i6m
|
66 |
+
4hw3
|
67 |
+
6eq5
|
68 |
+
3hqy
|
69 |
+
3zos
|
70 |
+
6h96
|
71 |
+
2gv6
|
72 |
+
5yjb
|
73 |
+
4lm4
|
74 |
+
4lwv
|
75 |
+
3g30
|
76 |
+
5f32
|
77 |
+
4dkr
|
78 |
+
6b4l
|
79 |
+
4j9a
|
80 |
+
5w86
|
81 |
+
4mpn
|
82 |
+
5m51
|
83 |
+
1ro6
|
84 |
+
5q0m
|
85 |
+
3bea
|
86 |
+
1mu6
|
87 |
+
2wtd
|
88 |
+
3sr4
|
89 |
+
6dqb
|
90 |
+
5hh5
|
91 |
+
5q0e
|
92 |
+
2r03
|
93 |
+
4xv9
|
94 |
+
4y0a
|
95 |
+
5ota
|
96 |
+
3u5l
|
97 |
+
3m3o
|
98 |
+
4idz
|
99 |
+
2w47
|
100 |
+
2g5u
|
101 |
+
6cec
|
102 |
+
5wzs
|
103 |
+
3iu7
|
104 |
+
5mky
|
105 |
+
3ibc
|
106 |
+
2qwf
|
107 |
+
3p76
|
108 |
+
4np3
|
109 |
+
4kb8
|
110 |
+
1uyi
|
111 |
+
4tkf
|
112 |
+
2fai
|
113 |
+
2xvd
|
114 |
+
5ar8
|
115 |
+
2lzg
|
116 |
+
3e62
|
117 |
+
1p6e
|
118 |
+
5wqa
|
119 |
+
1p02
|
120 |
+
6gjr
|
121 |
+
1nhu
|
122 |
+
4yyl
|
123 |
+
3jzq
|
124 |
+
4pce
|
125 |
+
4gvu
|
126 |
+
4n7g
|
127 |
+
3s9e
|
128 |
+
3k3b
|
129 |
+
1pmn
|
130 |
+
1ogd
|
131 |
+
2j4i
|
132 |
+
1oss
|
133 |
+
1v0k
|
134 |
+
6cn6
|
135 |
+
3k3e
|
136 |
+
2btr
|
137 |
+
1ppk
|
138 |
+
6egw
|
139 |
+
4zx1
|
140 |
+
4zfi
|
141 |
+
5yso
|
142 |
+
2rfn
|
143 |
+
5cep
|
144 |
+
2xyu
|
145 |
+
3eou
|
146 |
+
4mme
|
147 |
+
4fnn
|
148 |
+
4og7
|
149 |
+
4gkh
|
150 |
+
6d1l
|
151 |
+
6dlj
|
152 |
+
5i94
|
153 |
+
1eb2
|
154 |
+
4qzw
|
155 |
+
3fu0
|
156 |
+
4aif
|
157 |
+
5eec
|
158 |
+
2qlj
|
159 |
+
5cfb
|
160 |
+
5sy3
|
161 |
+
1mhw
|
162 |
+
2flu
|
163 |
+
3e6y
|
164 |
+
4wiv
|
165 |
+
5oot
|
166 |
+
4bae
|
167 |
+
6bfd
|
168 |
+
3po6
|
169 |
+
2wo9
|
170 |
+
1rp7
|
171 |
+
1l2s
|
172 |
+
5ab1
|
173 |
+
3pce
|
174 |
+
2w6z
|
175 |
+
1iew
|
176 |
+
3e85
|
177 |
+
3e12
|
178 |
+
5arf
|
179 |
+
4jgv
|
180 |
+
1ikw
|
181 |
+
6goo
|
182 |
+
4zdu
|
183 |
+
3wcb
|
184 |
+
2w1h
|
185 |
+
4x2i
|
186 |
+
6ggv
|
187 |
+
3h0b
|
188 |
+
5nwe
|
189 |
+
1o46
|
190 |
+
5f2u
|
191 |
+
2feq
|
192 |
+
2jnw
|
193 |
+
3gpj
|
194 |
+
5uex
|
195 |
+
1ndw
|
196 |
+
1zhk
|
197 |
+
4mcd
|
198 |
+
3r4m
|
199 |
+
4cps
|
200 |
+
3gcp
|
201 |
+
2g9v
|
202 |
+
5try
|
203 |
+
4c2v
|
204 |
+
4og3
|
205 |
+
3otq
|
206 |
+
2yns
|
207 |
+
4m0e
|
208 |
+
5tkj
|
209 |
+
2m3z
|
210 |
+
3pa5
|
211 |
+
3iww
|
212 |
+
5o0b
|
213 |
+
3m58
|
214 |
+
5lz2
|
215 |
+
5u6k
|
216 |
+
4yw6
|
217 |
+
3ewh
|
218 |
+
3wc7
|
219 |
+
1rhk
|
220 |
+
3gi4
|
221 |
+
2wd7
|
222 |
+
3jq8
|
223 |
+
5yr5
|
224 |
+
6fnf
|
225 |
+
3hx3
|
226 |
+
4mz6
|
227 |
+
1ol2
|
228 |
+
4aa5
|
229 |
+
1rry
|
230 |
+
1ozv
|
231 |
+
5jf6
|
232 |
+
4mnq
|
233 |
+
5wa5
|
234 |
+
3nlb
|
235 |
+
3f6e
|
236 |
+
2xu5
|
237 |
+
3wk7
|
238 |
+
4p6w
|
239 |
+
2pmc
|
240 |
+
3byo
|
241 |
+
5ehe
|
242 |
+
6chq
|
243 |
+
6c8x
|
244 |
+
3pp1
|
245 |
+
3uev
|
246 |
+
3ad7
|
247 |
+
5aqv
|
248 |
+
3qzq
|
249 |
+
2z97
|
250 |
+
5d1r
|
251 |
+
5ajy
|
252 |
+
4k67
|
253 |
+
2w1e
|
254 |
+
5j3v
|
255 |
+
3upk
|
256 |
+
4gj8
|
257 |
+
1td7
|
258 |
+
5lz9
|
259 |
+
6erw
|
260 |
+
4rhx
|
261 |
+
1hxw
|
262 |
+
6cbf
|
263 |
+
5qal
|
264 |
+
1q8w
|
265 |
+
4mf0
|
266 |
+
5t1s
|
267 |
+
1fzk
|
268 |
+
4tju
|
269 |
+
5t2y
|
270 |
+
4el5
|
271 |
+
2v87
|
272 |
+
1epo
|
273 |
+
2r5p
|
274 |
+
4pis
|
275 |
+
3ehy
|
276 |
+
5erg
|
277 |
+
2r1x
|
278 |
+
2f8i
|
279 |
+
2wi7
|
280 |
+
5wre
|
281 |
+
3dek
|
282 |
+
3hp2
|
283 |
+
4bcw
|
284 |
+
4uau
|
285 |
+
5ap3
|
286 |
+
3udy
|
287 |
+
2ksa
|
288 |
+
5ekg
|
289 |
+
5lh8
|
290 |
+
2uw7
|
291 |
+
3uvq
|
292 |
+
2glp
|
293 |
+
3m3r
|
294 |
+
6bsx
|
295 |
+
2ddf
|
296 |
+
6eqm
|
297 |
+
3ufl
|
298 |
+
2mwp
|
299 |
+
1h4n
|
300 |
+
5f4r
|
301 |
+
4ybj
|
302 |
+
4kz8
|
303 |
+
2z60
|
304 |
+
4ogi
|
305 |
+
5ufp
|
306 |
+
4uiw
|
307 |
+
3igv
|
308 |
+
5b56
|
309 |
+
1bn3
|
310 |
+
2xg9
|
311 |
+
1u59
|
312 |
+
4m5j
|
313 |
+
5oua
|
314 |
+
5qaa
|
315 |
+
6h7j
|
316 |
+
2o7v
|
317 |
+
5v7t
|
318 |
+
2r02
|
319 |
+
2j94
|
320 |
+
5o87
|
321 |
+
1o3k
|
322 |
+
4mr4
|
323 |
+
5am7
|
324 |
+
6g35
|
325 |
+
1ljt
|
326 |
+
3srv
|
327 |
+
4bi6
|
328 |
+
2yoh
|
329 |
+
4zed
|
330 |
+
5tln
|
331 |
+
3rkb
|
332 |
+
5jiq
|
333 |
+
2ll6
|
334 |
+
1tkz
|
335 |
+
2vj6
|
336 |
+
3qrk
|
337 |
+
3c45
|
338 |
+
4pks
|
339 |
+
3nf3
|
340 |
+
2oaz
|
341 |
+
3pwk
|
342 |
+
3ryy
|
343 |
+
2y7k
|
344 |
+
6dm8
|
345 |
+
5ism
|
346 |
+
5i7u
|
347 |
+
2qtn
|
348 |
+
5cuu
|
349 |
+
5n1y
|
350 |
+
4kot
|
351 |
+
5wa1
|
352 |
+
2wyi
|
353 |
+
188l
|
354 |
+
3h2o
|
355 |
+
1sw1
|
356 |
+
1zuc
|
357 |
+
2nnq
|
358 |
+
4l8m
|
359 |
+
5j75
|
360 |
+
4afe
|
361 |
+
5nwi
|
362 |
+
2n06
|
363 |
+
3l4w
|
364 |
+
3ibl
|
365 |
+
4l31
|
366 |
+
4ruy
|
367 |
+
4ufm
|
368 |
+
5sxk
|
369 |
+
4hnn
|
370 |
+
5q0x
|
371 |
+
4zij
|
372 |
+
3fdn
|
373 |
+
5fe6
|
374 |
+
3nuj
|
375 |
+
5h8x
|
376 |
+
5ets
|
377 |
+
4x5z
|
378 |
+
1w3k
|
379 |
+
3hs9
|
380 |
+
3ro0
|
381 |
+
3zi8
|
382 |
+
1nl4
|
383 |
+
5cao
|
384 |
+
4gjd
|
385 |
+
2p3d
|
386 |
+
2z8e
|
387 |
+
3w2p
|
388 |
+
1f28
|
389 |
+
2iw6
|
390 |
+
1h9l
|
391 |
+
4o78
|
392 |
+
1soj
|
393 |
+
3krw
|
394 |
+
5g4n
|
395 |
+
3t4v
|
396 |
+
5drr
|
397 |
+
5o0a
|
398 |
+
4c4i
|
399 |
+
2vwx
|
400 |
+
6miq
|
401 |
+
6guk
|
402 |
+
5c3k
|
403 |
+
5fhn
|
404 |
+
3o75
|
405 |
+
5kap
|
406 |
+
4zo5
|
407 |
+
2jko
|
408 |
+
3iss
|
409 |
+
4eg6
|
410 |
+
4fcd
|
411 |
+
3v7s
|
412 |
+
4bcf
|
413 |
+
2qyn
|
414 |
+
1ikx
|
415 |
+
6f6i
|
416 |
+
5os5
|
417 |
+
1om2
|
418 |
+
6axb
|
419 |
+
3s3n
|
420 |
+
1fl6
|
421 |
+
4luo
|
422 |
+
1qiw
|
423 |
+
5f2w
|
424 |
+
3udj
|
425 |
+
5tbj
|
426 |
+
5k0c
|
427 |
+
5ndf
|
428 |
+
1ek2
|
429 |
+
4zb8
|
430 |
+
3r9o
|
431 |
+
5qah
|
432 |
+
3avb
|
433 |
+
4c52
|
434 |
+
4ybi
|
435 |
+
5mi6
|
436 |
+
6fu5
|
437 |
+
1yc4
|
438 |
+
4ymq
|
439 |
+
1xn3
|
440 |
+
3dpo
|
441 |
+
4z7q
|
442 |
+
5ehn
|
443 |
+
5mri
|
444 |
+
2vcw
|
445 |
+
2byp
|
446 |
+
5du8
|
447 |
+
1i7z
|
448 |
+
1ec3
|
449 |
+
5jmx
|
450 |
+
4yxi
|
451 |
+
3iw7
|
452 |
+
3l4v
|
453 |
+
3wcf
|
454 |
+
5igk
|
455 |
+
1sz0
|
456 |
+
4x6i
|
457 |
+
1wum
|
458 |
+
1d3d
|
459 |
+
3rv6
|
460 |
+
1x7r
|
461 |
+
2c57
|
462 |
+
4u82
|
463 |
+
6cwh
|
464 |
+
2vrj
|
465 |
+
2xag
|
466 |
+
5nw7
|
467 |
+
5qau
|
468 |
+
4ocz
|
469 |
+
3chg
|
470 |
+
5oh1
|
471 |
+
1hkm
|
472 |
+
3ayd
|
473 |
+
3mn8
|
474 |
+
5ngf
|
475 |
+
4bo6
|
476 |
+
1b57
|
477 |
+
5wzt
|
478 |
+
4uzd
|
479 |
+
1cyn
|
480 |
+
3eys
|
481 |
+
4umc
|
482 |
+
6guh
|
483 |
+
2e99
|
484 |
+
2xb8
|
485 |
+
5tus
|
486 |
+
6ap7
|
487 |
+
4ajn
|
488 |
+
4od7
|
489 |
+
6g2l
|
490 |
+
5v40
|
491 |
+
5wjj
|
492 |
+
2bow
|
493 |
+
3kc0
|
494 |
+
3zs1
|
495 |
+
4igq
|
496 |
+
3b24
|
497 |
+
5e8r
|
498 |
+
5a4l
|
499 |
+
4ci1
|
500 |
+
3qd0
|
501 |
+
2ohv
|
502 |
+
3uw5
|
503 |
+
3lp4
|
504 |
+
3ftw
|
505 |
+
6c5q
|
506 |
+
4e0x
|
507 |
+
4hbw
|
508 |
+
2yoj
|
509 |
+
4b2i
|
510 |
+
3mkn
|
511 |
+
1i5r
|
512 |
+
5tig
|
513 |
+
5bqs
|
514 |
+
5j2x
|
515 |
+
1oz0
|
516 |
+
5a2s
|
517 |
+
3fkv
|
518 |
+
3qnj
|
519 |
+
5w5o
|
520 |
+
2cht
|
521 |
+
5dj5
|
522 |
+
5oje
|
523 |
+
5o9y
|
524 |
+
4hxs
|
525 |
+
5t36
|
526 |
+
5gmh
|
527 |
+
4eh9
|
528 |
+
3kr2
|
529 |
+
3rk5
|
530 |
+
2b54
|
531 |
+
4ufh
|
532 |
+
2zxa
|
533 |
+
4mji
|
534 |
+
4e70
|
535 |
+
4huo
|
536 |
+
3zrk
|
537 |
+
3wb5
|
538 |
+
2iw8
|
539 |
+
4ge4
|
540 |
+
6ccs
|
541 |
+
5nwc
|
542 |
+
5lmb
|
543 |
+
4i6h
|
544 |
+
4dhu
|
545 |
+
5y6e
|
546 |
+
5bvn
|
547 |
+
4lxd
|
548 |
+
3b3s
|
549 |
+
5j9f
|
550 |
+
3jzp
|
551 |
+
2no3
|
552 |
+
1ouk
|
553 |
+
5epk
|
554 |
+
1fo2
|
555 |
+
1g7g
|
556 |
+
4dve
|
557 |
+
6au2
|
558 |
+
4wt6
|
559 |
+
3w2q
|
560 |
+
5tdr
|
561 |
+
4xx9
|
562 |
+
1jg0
|
563 |
+
2n27
|
564 |
+
5lyn
|
565 |
+
1p1q
|
566 |
+
1hi3
|
567 |
+
2wih
|
568 |
+
4hym
|
569 |
+
4ew3
|
570 |
+
5ixq
|
571 |
+
1h60
|
572 |
+
3ppk
|
573 |
+
4x8s
|
574 |
+
5nzn
|
575 |
+
3ddf
|
576 |
+
1yvm
|
577 |
+
1kv2
|
578 |
+
4djq
|
579 |
+
3sym
|
580 |
+
4fz3
|
581 |
+
1ze8
|
582 |
+
5ia1
|
583 |
+
2qcm
|
584 |
+
5m9d
|
585 |
+
2erz
|
586 |
+
4g0l
|
587 |
+
5tqg
|
588 |
+
2i5j
|
589 |
+
3ow6
|
590 |
+
1met
|
591 |
+
3r42
|
592 |
+
5tdi
|
593 |
+
3i97
|
594 |
+
1alw
|
595 |
+
1doj
|
596 |
+
3f5j
|
597 |
+
2r5q
|
598 |
+
6eir
|
599 |
+
2ie4
|
600 |
+
5cav
|
601 |
+
1n4m
|
602 |
+
5wj6
|
603 |
+
2o7n
|
604 |
+
2r4f
|
605 |
+
5nkn
|
606 |
+
2g6p
|
607 |
+
1bnu
|
608 |
+
4uc5
|
609 |
+
3kze
|
610 |
+
5dg6
|
611 |
+
1nym
|
612 |
+
6cki
|
613 |
+
4kmz
|
614 |
+
6mjf
|
615 |
+
4ch8
|
616 |
+
6hsh
|
617 |
+
1txr
|
618 |
+
4zj8
|
619 |
+
6ggn
|
620 |
+
4qzx
|
621 |
+
4qsu
|
622 |
+
5ety
|
623 |
+
1o5a
|
624 |
+
4otf
|
625 |
+
1pgp
|
626 |
+
5wex
|
627 |
+
4p4b
|
628 |
+
4h4m
|
629 |
+
3k54
|
630 |
+
4j53
|
631 |
+
5dva
|
632 |
+
1e3v
|
633 |
+
4wop
|
634 |
+
1c3i
|
635 |
+
4jls
|
636 |
+
5mxv
|
637 |
+
4qrc
|
638 |
+
3fvn
|
639 |
+
5ivn
|
640 |
+
4xu1
|
641 |
+
2o4n
|
642 |
+
1m5b
|
643 |
+
3t1a
|
644 |
+
1mqi
|
645 |
+
5n84
|
646 |
+
5ifu
|
647 |
+
5eie
|
648 |
+
5lgr
|
649 |
+
5unf
|
650 |
+
5w5u
|
651 |
+
5tq1
|
652 |
+
3dkj
|
653 |
+
5ye8
|
654 |
+
1br8
|
655 |
+
3tsd
|
656 |
+
6dvn
|
657 |
+
1oxg
|
658 |
+
4kz5
|
659 |
+
5v3h
|
660 |
+
5in9
|
661 |
+
4avi
|
662 |
+
220l
|
663 |
+
4b7z
|
664 |
+
2xbv
|
665 |
+
3twx
|
666 |
+
5zo8
|
667 |
+
2w4i
|
668 |
+
5opc
|
669 |
+
4q8y
|
670 |
+
5acy
|
671 |
+
5ncz
|
672 |
+
3in4
|
673 |
+
3arp
|
674 |
+
4rt1
|
675 |
+
4mq6
|
676 |
+
6ey7
|
677 |
+
3uzd
|
678 |
+
2b9a
|
679 |
+
5o4z
|
680 |
+
2ow0
|
681 |
+
6f5w
|
682 |
+
1x7q
|
683 |
+
5agv
|
684 |
+
5pzm
|
685 |
+
6afh
|
686 |
+
4z1e
|
687 |
+
5flp
|
688 |
+
5xsr
|
689 |
+
1b4z
|
690 |
+
5f1r
|
691 |
+
1o2g
|
692 |
+
1uwh
|
693 |
+
3bmo
|
694 |
+
1p19
|
695 |
+
2ans
|
696 |
+
6fbv
|
697 |
+
4lrr
|
698 |
+
1gi9
|
699 |
+
4xuh
|
700 |
+
2weo
|
701 |
+
5xpi
|
702 |
+
4btm
|
703 |
+
5h0e
|
704 |
+
4gye
|
705 |
+
6bgu
|
706 |
+
5wlt
|
707 |
+
5oul
|
708 |
+
1t49
|
709 |
+
5k1v
|
710 |
+
5lz4
|
711 |
+
1fsw
|
712 |
+
6cvx
|
713 |
+
6c3e
|
714 |
+
6cj5
|
715 |
+
5fqc
|
716 |
+
1cze
|
717 |
+
3uwl
|
718 |
+
5l3g
|
719 |
+
5jnc
|
720 |
+
3ps6
|
721 |
+
6csr
|
722 |
+
6bw4
|
723 |
+
3hau
|
724 |
+
3ud9
|
725 |
+
6csp
|
726 |
+
5uyu
|
727 |
+
5lqf
|
728 |
+
4bfz
|
729 |
+
2xp6
|
730 |
+
3sjo
|
731 |
+
5os3
|
732 |
+
4z8d
|
733 |
+
5un1
|
734 |
+
6esy
|
735 |
+
3kjq
|
736 |
+
3sl4
|
737 |
+
5mgl
|
738 |
+
5dp5
|
739 |
+
3n0h
|
740 |
+
5fao
|
741 |
+
4dmy
|
742 |
+
6dxl
|
743 |
+
4qw0
|
744 |
+
3q92
|
745 |
+
3rwf
|
746 |
+
2xke
|
747 |
+
4gfo
|
748 |
+
3t03
|
749 |
+
3pd8
|
750 |
+
3f18
|
751 |
+
4utr
|
752 |
+
4cu7
|
753 |
+
5n1s
|
754 |
+
3wkb
|
755 |
+
2zdt
|
756 |
+
2yit
|
757 |
+
4cmt
|
758 |
+
5dpa
|
759 |
+
4rt0
|
760 |
+
2y5h
|
761 |
+
3cde
|
762 |
+
5lud
|
763 |
+
3vva
|
764 |
+
2wev
|
765 |
+
5mrm
|
766 |
+
4ypf
|
767 |
+
5ea4
|
768 |
+
3fr5
|
769 |
+
4tkh
|
770 |
+
5tyi
|
771 |
+
1db1
|
772 |
+
4hxj
|
773 |
+
3hu1
|
774 |
+
5ftg
|
775 |
+
2eh8
|
776 |
+
1jiz
|
777 |
+
1gww
|
778 |
+
5nih
|
779 |
+
1rr6
|
780 |
+
4fp1
|
781 |
+
4y24
|
782 |
+
1fki
|
783 |
+
3lea
|
784 |
+
4lch
|
785 |
+
2xk1
|
786 |
+
4qjr
|
787 |
+
4os1
|
788 |
+
4pft
|
789 |
+
5eb3
|
790 |
+
5qad
|
791 |
+
3cpc
|
792 |
+
3c94
|
793 |
+
5jhb
|
794 |
+
6b22
|
795 |
+
3vfj
|
796 |
+
6hmx
|
797 |
+
1kuk
|
798 |
+
2gh9
|
799 |
+
1xh6
|
800 |
+
3eyl
|
801 |
+
5hng
|
802 |
+
3nes
|
803 |
+
3i1y
|
804 |
+
2anl
|
805 |
+
4xit
|
806 |
+
3n2e
|
807 |
+
2n0u
|
808 |
+
5hdx
|
809 |
+
4zt6
|
810 |
+
4f6v
|
811 |
+
5n7g
|
812 |
+
4mc1
|
813 |
+
4yc9
|
814 |
+
3q6w
|
815 |
+
2cmb
|
816 |
+
5g4m
|
817 |
+
3pww
|
818 |
+
5d7x
|
819 |
+
4cpr
|
820 |
+
3muf
|
821 |
+
5f95
|
822 |
+
5o9o
|
823 |
+
5e2w
|
824 |
+
2chx
|
825 |
+
2pk6
|
826 |
+
3bet
|
827 |
+
6cje
|
828 |
+
2rd6
|
829 |
+
5khk
|
830 |
+
4eh5
|
831 |
+
1i9l
|
832 |
+
1swg
|
833 |
+
4q4o
|
834 |
+
1kf0
|
835 |
+
1llb
|
836 |
+
5aep
|
837 |
+
2zp0
|
838 |
+
3zze
|
839 |
+
5csp
|
840 |
+
5eyk
|
841 |
+
3u7n
|
842 |
+
4z0e
|
843 |
+
5fh6
|
844 |
+
5kj2
|
845 |
+
2o4k
|
846 |
+
5llg
|
847 |
+
4b5t
|
848 |
+
3li2
|
849 |
+
3of8
|
850 |
+
3mvh
|
851 |
+
1jut
|
852 |
+
1auj
|
853 |
+
5awj
|
854 |
+
5x73
|
855 |
+
1eol
|
856 |
+
1f90
|
857 |
+
4crd
|
858 |
+
1d2e
|
859 |
+
2oht
|
860 |
+
1ua4
|
861 |
+
2h9m
|
862 |
+
5byz
|
863 |
+
3rse
|
864 |
+
4mp2
|
865 |
+
3hhk
|
866 |
+
5tur
|
867 |
+
2xxr
|
868 |
+
2r3w
|
869 |
+
4u6e
|
870 |
+
4qlt
|
871 |
+
3db8
|
872 |
+
2bub
|
873 |
+
1ths
|
874 |
+
3s8o
|
875 |
+
3x1k
|
876 |
+
3eg6
|
877 |
+
1jaq
|
878 |
+
3anr
|
879 |
+
3ua8
|
880 |
+
2kfg
|
881 |
+
4m3g
|
882 |
+
3d3x
|
883 |
+
5a5v
|
884 |
+
3nuu
|
885 |
+
1jh1
|
886 |
+
1iy7
|
887 |
+
5dlz
|
888 |
+
4wpf
|
889 |
+
4pvy
|
890 |
+
1sve
|
891 |
+
4qmy
|
892 |
+
1pyg
|
893 |
+
5drq
|
894 |
+
4ivt
|
895 |
+
2gcd
|
896 |
+
1azg
|
897 |
+
3wjw
|
898 |
+
2qiq
|
899 |
+
4leq
|
900 |
+
2qfu
|
901 |
+
1thz
|
902 |
+
1y3a
|
903 |
+
5yjp
|
904 |
+
5cgv
|
905 |
+
1oi9
|
906 |
+
3cd5
|
907 |
+
3w1f
|
908 |
+
2v12
|
909 |
+
5f37
|
910 |
+
1e03
|
911 |
+
3b67
|
912 |
+
4q8x
|
913 |
+
5uk8
|
914 |
+
4v25
|
915 |
+
3u8k
|
916 |
+
5l8o
|
917 |
+
5hlb
|
918 |
+
4qfn
|
919 |
+
4li7
|
920 |
+
1dth
|
921 |
+
4gkm
|
922 |
+
6f3e
|
923 |
+
4rn4
|
924 |
+
3vtb
|
925 |
+
5l6i
|
926 |
+
4lrh
|
927 |
+
4jvq
|
928 |
+
5est
|
929 |
+
3gtc
|
930 |
+
2jbu
|
931 |
+
2yfx
|
932 |
+
4yx9
|
933 |
+
5bs0
|
934 |
+
5ea3
|
935 |
+
1vyf
|
936 |
+
5a4e
|
937 |
+
3kku
|
938 |
+
3cyw
|
939 |
+
3tvx
|
940 |
+
5mkj
|
941 |
+
6b4d
|
942 |
+
4bny
|
943 |
+
5j8x
|
944 |
+
5tza
|
945 |
+
1uk1
|
946 |
+
5yg2
|
947 |
+
1d6v
|
948 |
+
5t4e
|
949 |
+
2j4g
|
950 |
+
5tci
|
951 |
+
1z9y
|
952 |
+
2ca8
|
953 |
+
4hyf
|
954 |
+
5mg2
|
955 |
+
4bcq
|
956 |
+
1lqf
|
957 |
+
6b3v
|
958 |
+
5htc
|
959 |
+
2qh6
|
960 |
+
4pul
|
961 |
+
1gj7
|
962 |
+
4mmf
|
963 |
+
3sfg
|
964 |
+
5ap2
|
965 |
+
2oi9
|
966 |
+
4h81
|
967 |
+
3s77
|
968 |
+
1awh
|
969 |
+
3s74
|
970 |
+
3oyp
|
971 |
+
4u5u
|
972 |
+
6euz
|
973 |
+
6eq3
|
974 |
+
4obq
|
975 |
+
4u4x
|
976 |
+
2r23
|
977 |
+
4tjw
|
978 |
+
4anq
|
979 |
+
2a4z
|
980 |
+
2mwy
|
981 |
+
4pzh
|
982 |
+
5m7m
|
983 |
+
4mzj
|
984 |
+
1o3l
|
985 |
+
3d62
|
986 |
+
2xow
|
987 |
+
5hog
|
988 |
+
3rwq
|
989 |
+
2kmx
|
990 |
+
4fpf
|
991 |
+
5ajx
|
992 |
+
1f5k
|
993 |
+
4de7
|
994 |
+
5c7c
|
995 |
+
3q77
|
996 |
+
4pnr
|
997 |
+
5tkb
|
998 |
+
5hz8
|
999 |
+
2vle
|
1000 |
+
5ho7
|
1001 |
+
5xmx
|
1002 |
+
2xpk
|
1003 |
+
6mdq
|
1004 |
+
3tge
|
1005 |
+
5fls
|
1006 |
+
3oku
|
1007 |
+
5jr2
|
1008 |
+
3e0q
|
1009 |
+
2l98
|
1010 |
+
2uzj
|
1011 |
+
5csz
|
1012 |
+
5yr6
|
1013 |
+
3f7i
|
1014 |
+
1ex8
|
1015 |
+
6ft7
|
1016 |
+
2bdj
|
1017 |
+
5l7g
|
1018 |
+
1cnx
|
1019 |
+
1mmp
|
1020 |
+
5j8m
|
1021 |
+
2ay2
|
1022 |
+
6fnq
|
1023 |
+
5eng
|
1024 |
+
1pg2
|
1025 |
+
4a6v
|
1026 |
+
3ivv
|
1027 |
+
2zq2
|
1028 |
+
4wag
|
1029 |
+
3s7a
|
1030 |
+
4is6
|
1031 |
+
1lhw
|
1032 |
+
5tq8
|
1033 |
+
3v51
|
1034 |
+
4w9x
|
1035 |
+
5lto
|
1036 |
+
1o86
|
1037 |
+
5a69
|
1038 |
+
4zg7
|
1039 |
+
4unq
|
1040 |
+
2q88
|
1041 |
+
5c1m
|
1042 |
+
6bgy
|
1043 |
+
4fil
|
1044 |
+
2qi1
|
1045 |
+
2x7o
|
1046 |
+
6exj
|
1047 |
+
3nkk
|
1048 |
+
1q65
|
1049 |
+
2xxw
|
1050 |
+
3l7d
|
1051 |
+
1om9
|
1052 |
+
4jq7
|
1053 |
+
1lf2
|
1054 |
+
4xg4
|
1055 |
+
3sgx
|
1056 |
+
1sdt
|
1057 |
+
3ow4
|
1058 |
+
4kp8
|
1059 |
+
2cem
|
1060 |
+
5nzo
|
1061 |
+
3oaw
|
1062 |
+
2wwj
|
1063 |
+
2v6n
|
1064 |
+
4g11
|
1065 |
+
1lf3
|
1066 |
+
3ljz
|
1067 |
+
1amn
|
1068 |
+
6hm4
|
1069 |
+
3jq9
|
1070 |
+
1qx1
|
1071 |
+
2wi5
|
1072 |
+
4old
|
1073 |
+
1g5s
|
1074 |
+
3tic
|
1075 |
+
3cs8
|
1076 |
+
4er4
|
1077 |
+
5kr0
|
1078 |
+
2pe0
|
1079 |
+
5abf
|
1080 |
+
3v04
|
1081 |
+
4e6q
|
1082 |
+
2yc3
|
1083 |
+
3bys
|
1084 |
+
5jeo
|
1085 |
+
4b00
|
1086 |
+
4bek
|
1087 |
+
4fci
|
1088 |
+
4qna
|
1089 |
+
5eh5
|
1090 |
+
4r02
|
1091 |
+
5ef7
|
1092 |
+
4hu1
|
1093 |
+
5v5n
|
1094 |
+
5ehp
|
1095 |
+
5yr4
|
1096 |
+
3dt1
|
1097 |
+
4cd0
|
1098 |
+
6gl8
|
1099 |
+
3uvl
|
1100 |
+
3v0l
|
1101 |
+
5ne5
|
1102 |
+
4nvp
|
1103 |
+
4qok
|
1104 |
+
4ipj
|
1105 |
+
4zyi
|
1106 |
+
1o3j
|
1107 |
+
1lrt
|
1108 |
+
3iog
|
1109 |
+
5zwe
|
1110 |
+
4hbn
|
1111 |
+
2gz2
|
1112 |
+
5tco
|
1113 |
+
3gc5
|
1114 |
+
4l6t
|
1115 |
+
5mnx
|
1116 |
+
5m23
|
1117 |
+
2etr
|
1118 |
+
5gwy
|
1119 |
+
3b5j
|
1120 |
+
1oai
|
1121 |
+
2ath
|
1122 |
+
2v11
|
1123 |
+
5wuk
|
1124 |
+
2ym6
|
1125 |
+
4mwu
|
1126 |
+
5u69
|
1127 |
+
4i8w
|
1128 |
+
6g86
|
1129 |
+
4f7l
|
1130 |
+
2yi5
|
1131 |
+
4nan
|
1132 |
+
1j37
|
1133 |
+
2xup
|
1134 |
+
2byi
|
1135 |
+
4f63
|
1136 |
+
3m3x
|
1137 |
+
2bpm
|
1138 |
+
2wb5
|
1139 |
+
6fel
|
1140 |
+
3tdc
|
1141 |
+
4z1s
|
1142 |
+
4fgy
|
1143 |
+
3cyz
|
1144 |
+
6bh1
|
1145 |
+
3m8p
|
1146 |
+
2df6
|
1147 |
+
3jrs
|
1148 |
+
2wmv
|
1149 |
+
6fau
|
1150 |
+
5oah
|
1151 |
+
3d50
|
1152 |
+
3aza
|
1153 |
+
1uwt
|
1154 |
+
4nct
|
1155 |
+
1jqe
|
1156 |
+
4nb3
|
1157 |
+
4y3b
|
1158 |
+
1okw
|
1159 |
+
1db4
|
1160 |
+
4n98
|
1161 |
+
3inh
|
1162 |
+
6hzp
|
1163 |
+
1hdt
|
1164 |
+
6aoy
|
1165 |
+
4o3u
|
1166 |
+
5es1
|
1167 |
+
5i9i
|
1168 |
+
6ccm
|
1169 |
+
5nev
|
1170 |
+
5wp5
|
1171 |
+
4bo7
|
1172 |
+
5byy
|
1173 |
+
3su2
|
1174 |
+
4hlf
|
1175 |
+
4c1g
|
1176 |
+
3sww
|
1177 |
+
2os9
|
1178 |
+
4men
|
1179 |
+
2wxd
|
1180 |
+
4qq4
|
1181 |
+
5eei
|
1182 |
+
4hnf
|
1183 |
+
3b26
|
1184 |
+
3eht
|
1185 |
+
3oqf
|
1186 |
+
3dd0
|
1187 |
+
3si4
|
1188 |
+
4v1f
|
1189 |
+
4e6d
|
1190 |
+
2c8w
|
1191 |
+
1jyi
|
1192 |
+
4ob1
|
1193 |
+
5x4n
|
1194 |
+
5alc
|
1195 |
+
2pbw
|
1196 |
+
5eym
|
1197 |
+
4e28
|
1198 |
+
2xui
|
1199 |
+
4qtl
|
1200 |
+
5jz9
|
1201 |
+
3chr
|
1202 |
+
2p2a
|
1203 |
+
1v1j
|
1204 |
+
4o3b
|
1205 |
+
5v83
|
1206 |
+
5v5e
|
1207 |
+
3byu
|
1208 |
+
7abp
|
1209 |
+
5jga
|
1210 |
+
3sw2
|
1211 |
+
5jgb
|
1212 |
+
4dtk
|
1213 |
+
1q91
|
1214 |
+
3cqu
|
1215 |
+
1nje
|
1216 |
+
3vhd
|
1217 |
+
4knm
|
1218 |
+
4yrt
|
1219 |
+
1bgo
|
1220 |
+
5ih5
|
1221 |
+
6afe
|
1222 |
+
4res
|
1223 |
+
1akt
|
1224 |
+
1kyv
|
1225 |
+
1sqn
|
1226 |
+
4oas
|
1227 |
+
5u5l
|
1228 |
+
1v79
|
1229 |
+
3hp5
|
1230 |
+
5ivc
|
1231 |
+
1q84
|
1232 |
+
3avg
|
1233 |
+
3tws
|
1234 |
+
1rmz
|
1235 |
+
4rse
|
1236 |
+
5zae
|
1237 |
+
5w2q
|
1238 |
+
5glu
|
1239 |
+
5b4w
|
1240 |
+
5f62
|
1241 |
+
4y6r
|
1242 |
+
4mha
|
1243 |
+
5etk
|
1244 |
+
5nzm
|
1245 |
+
4o2b
|
1246 |
+
4cwq
|
1247 |
+
2pj8
|
1248 |
+
3lvw
|
1249 |
+
2fw3
|
1250 |
+
1dwc
|
1251 |
+
3zln
|
1252 |
+
3ejq
|
1253 |
+
2f6y
|
1254 |
+
6bic
|
1255 |
+
4p0x
|
1256 |
+
2cct
|
1257 |
+
3dxh
|
1258 |
+
2xhx
|
1259 |
+
1d3q
|
1260 |
+
3qbh
|
1261 |
+
5tkt
|
1262 |
+
4acd
|
1263 |
+
1yt7
|
1264 |
+
5aki
|
1265 |
+
3zy2
|
1266 |
+
4tw7
|
1267 |
+
3b3w
|
1268 |
+
1nkm
|
1269 |
+
5uoo
|
1270 |
+
2l75
|
1271 |
+
4l7u
|
1272 |
+
4iut
|
1273 |
+
1pbq
|
1274 |
+
4dow
|
1275 |
+
3hab
|
1276 |
+
1owe
|
1277 |
+
6ft3
|
1278 |
+
4y2q
|
1279 |
+
2hs1
|
1280 |
+
6gu6
|
1281 |
+
4dpi
|
1282 |
+
5aac
|
1283 |
+
4j2c
|
1284 |
+
1s50
|
1285 |
+
6nao
|
1286 |
+
5fox
|
1287 |
+
3jvs
|
1288 |
+
4ozl
|
1289 |
+
1zub
|
1290 |
+
5wxp
|
1291 |
+
5iuh
|
1292 |
+
5oh7
|
1293 |
+
2c90
|
1294 |
+
5owl
|
1295 |
+
3oof
|
1296 |
+
4ona
|
1297 |
+
4ydg
|
1298 |
+
1h08
|
1299 |
+
1uk0
|
1300 |
+
2fxs
|
1301 |
+
3f37
|
1302 |
+
4xtz
|
1303 |
+
4mww
|
1304 |
+
6gg4
|
1305 |
+
4zz3
|
1306 |
+
5cf4
|
1307 |
+
3blr
|
1308 |
+
4twc
|
1309 |
+
3zsz
|
1310 |
+
4er2
|
1311 |
+
4uuh
|
1312 |
+
1i8j
|
1313 |
+
6faw
|
1314 |
+
5opv
|
1315 |
+
3voz
|
1316 |
+
3d1g
|
1317 |
+
5q0n
|
1318 |
+
3kfc
|
1319 |
+
3qqs
|
1320 |
+
1oay
|
1321 |
+
1uvs
|
1322 |
+
5os4
|
1323 |
+
4abe
|
1324 |
+
1r0x
|
1325 |
+
4jwr
|
1326 |
+
1l6m
|
1327 |
+
3nf6
|
1328 |
+
3qip
|
1329 |
+
1nlt
|
1330 |
+
3zdg
|
1331 |
+
3o84
|
1332 |
+
3ehn
|
1333 |
+
3k16
|
1334 |
+
5szb
|
1335 |
+
2j2u
|
1336 |
+
5aiv
|
1337 |
+
2weg
|
1338 |
+
3dz4
|
1339 |
+
4jdf
|
1340 |
+
1ttm
|
1341 |
+
3wyy
|
1342 |
+
3ifo
|
1343 |
+
5j41
|
1344 |
+
3fl5
|
1345 |
+
1q1m
|
1346 |
+
2y80
|
1347 |
+
3fr4
|
1348 |
+
3o56
|
1349 |
+
1yrs
|
1350 |
+
2gvv
|
1351 |
+
3uxk
|
1352 |
+
2zq0
|
1353 |
+
5uac
|
1354 |
+
3sfi
|
1355 |
+
2wk6
|
1356 |
+
184l
|
1357 |
+
6gvz
|
1358 |
+
6dik
|
1359 |
+
3u8w
|
1360 |
+
3rxb
|
1361 |
+
2qpq
|
1362 |
+
3nwe
|
1363 |
+
13gs
|
1364 |
+
4gpl
|
1365 |
+
4rxz
|
1366 |
+
4qbm
|
1367 |
+
5y9l
|
1368 |
+
4nh8
|
1369 |
+
4rra
|
1370 |
+
5ey8
|
1371 |
+
4j03
|
1372 |
+
2ou7
|
1373 |
+
5tt3
|
1374 |
+
1uwf
|
1375 |
+
4dgr
|
1376 |
+
5xzr
|
1377 |
+
4mw4
|
1378 |
+
3n5k
|
1379 |
+
4umq
|
1380 |
+
2l6e
|
1381 |
+
6drg
|
1382 |
+
6ghp
|
1383 |
+
2ksp
|
1384 |
+
1sps
|
1385 |
+
5hna
|
1386 |
+
6gnp
|
1387 |
+
3dxk
|
1388 |
+
5eom
|
1389 |
+
1e34
|
1390 |
+
2xfi
|
1391 |
+
2itp
|
1392 |
+
2zlf
|
1393 |
+
4iva
|
1394 |
+
2y4m
|
1395 |
+
4o1b
|
1396 |
+
2o9v
|
1397 |
+
4i7f
|
1398 |
+
4ezw
|
1399 |
+
1k4h
|
1400 |
+
2xgm
|
1401 |
+
4nud
|
1402 |
+
3m55
|
1403 |
+
6ezg
|
1404 |
+
4x34
|
1405 |
+
1czo
|
1406 |
+
5fqr
|
1407 |
+
5he4
|
1408 |
+
2h6k
|
1409 |
+
3fmr
|
1410 |
+
4kzb
|
1411 |
+
2g9q
|
1412 |
+
3tpx
|
1413 |
+
4hpy
|
1414 |
+
2bo4
|
1415 |
+
4nhx
|
1416 |
+
4mvh
|
1417 |
+
2nq7
|
1418 |
+
3n5u
|
1419 |
+
3rjw
|
1420 |
+
3emg
|
1421 |
+
2xm9
|
1422 |
+
1kzn
|
1423 |
+
5faq
|
1424 |
+
5f1u
|
1425 |
+
1c6y
|
1426 |
+
4j8g
|
1427 |
+
5lvr
|
1428 |
+
1xuo
|
1429 |
+
2vgo
|
1430 |
+
1grp
|
1431 |
+
4uxb
|
1432 |
+
2rol
|
1433 |
+
5cbm
|
1434 |
+
6hke
|
1435 |
+
5tr6
|
1436 |
+
1uyc
|
1437 |
+
3d6o
|
1438 |
+
5awu
|
1439 |
+
4wz8
|
1440 |
+
5egm
|
1441 |
+
1duv
|
1442 |
+
6b4n
|
1443 |
+
1t7j
|
1444 |
+
5aqj
|
1445 |
+
4jh0
|
1446 |
+
4q7s
|
1447 |
+
5cpr
|
1448 |
+
1bqm
|
1449 |
+
1g9c
|
1450 |
+
4fem
|
1451 |
+
4wnk
|
1452 |
+
4uv8
|
1453 |
+
5hgq
|
1454 |
+
1ayu
|
1455 |
+
6co4
|
1456 |
+
6ck3
|
1457 |
+
3uzj
|
1458 |
+
2qwe
|
1459 |
+
3u2q
|
1460 |
+
1nl9
|
1461 |
+
6bd1
|
1462 |
+
5yzd
|
1463 |
+
4r92
|
1464 |
+
2i0j
|
1465 |
+
4hvh
|
1466 |
+
4ool
|
1467 |
+
3s0n
|
1468 |
+
1ba8
|
1469 |
+
3b4p
|
1470 |
+
2ea4
|
1471 |
+
5k76
|
1472 |
+
2xzq
|
1473 |
+
4yur
|
1474 |
+
1pq6
|
1475 |
+
2y81
|
1476 |
+
3f8s
|
1477 |
+
2hwh
|
1478 |
+
1q4w
|
1479 |
+
4h39
|
1480 |
+
3zmh
|
1481 |
+
1ftl
|
1482 |
+
4ok5
|
1483 |
+
2qcn
|
1484 |
+
3qtf
|
1485 |
+
1g52
|
1486 |
+
3vw0
|
1487 |
+
3i4a
|
1488 |
+
5x79
|
1489 |
+
2am2
|
1490 |
+
2ym7
|
1491 |
+
5odu
|
1492 |
+
3adu
|
1493 |
+
6cea
|
1494 |
+
3t6y
|
1495 |
+
4pgc
|
1496 |
+
1k1j
|
1497 |
+
3d14
|
1498 |
+
3el4
|
1499 |
+
4nyf
|
1500 |
+
2y0j
|
1501 |
+
2w1c
|
1502 |
+
5l7k
|
1503 |
+
4n6g
|
1504 |
+
5cp5
|
1505 |
+
3ekr
|
1506 |
+
2isc
|
1507 |
+
5cbs
|
1508 |
+
5hvu
|
1509 |
+
4n00
|
1510 |
+
5mpn
|
1511 |
+
5zoo
|
1512 |
+
3v43
|
1513 |
+
1t69
|
1514 |
+
1oj5
|
1515 |
+
5lle
|
1516 |
+
5wef
|
1517 |
+
2ya8
|
1518 |
+
4ezk
|
1519 |
+
2c6o
|
1520 |
+
5vrl
|
1521 |
+
1b4d
|
1522 |
+
5za8
|
1523 |
+
1i80
|
1524 |
+
2ccb
|
1525 |
+
6ce2
|
1526 |
+
4cfx
|
1527 |
+
3m5e
|
1528 |
+
1k22
|
1529 |
+
6eea
|
1530 |
+
3s3m
|
1531 |
+
5t4f
|
1532 |
+
2xyn
|
1533 |
+
6br3
|
1534 |
+
3krl
|
1535 |
+
3upy
|
1536 |
+
2rm0
|
1537 |
+
5q1f
|
1538 |
+
4app
|
1539 |
+
7gch
|
1540 |
+
5hx8
|
1541 |
+
4ok6
|
1542 |
+
4zla
|
1543 |
+
5g3w
|
1544 |
+
1h27
|
1545 |
+
1fkb
|
1546 |
+
1idg
|
1547 |
+
5c8n
|
1548 |
+
1h46
|
1549 |
+
3w33
|
1550 |
+
3rzb
|
1551 |
+
4xg6
|
1552 |
+
2rib
|
1553 |
+
2uuo
|
1554 |
+
1r1h
|
1555 |
+
5agu
|
1556 |
+
6dcz
|
1557 |
+
1r58
|
1558 |
+
1nlo
|
1559 |
+
3g70
|
1560 |
+
2ofu
|
1561 |
+
4k6z
|
1562 |
+
4x13
|
1563 |
+
5ihc
|
1564 |
+
2yiw
|
1565 |
+
6bgw
|
1566 |
+
6gji
|
1567 |
+
1tve
|
1568 |
+
1gpn
|
1569 |
+
5tq5
|
1570 |
+
4ujb
|
1571 |
+
4l33
|
1572 |
+
6cqz
|
1573 |
+
4avh
|
1574 |
+
5uga
|
1575 |
+
5tzy
|
1576 |
+
5op6
|
1577 |
+
1m7d
|
1578 |
+
4aia
|
1579 |
+
2bxt
|
1580 |
+
4qgh
|
1581 |
+
3uuo
|
1582 |
+
5vkm
|
1583 |
+
4jr3
|
1584 |
+
1wdy
|
1585 |
+
4o4r
|
1586 |
+
2c3j
|
1587 |
+
2r9m
|
1588 |
+
5ual
|
1589 |
+
3vfq
|
1590 |
+
4c16
|
1591 |
+
6h7l
|
1592 |
+
3tv6
|
1593 |
+
2pyn
|
1594 |
+
2bj4
|
1595 |
+
4qvy
|
1596 |
+
4abk
|
1597 |
+
3m53
|
1598 |
+
3cwk
|
1599 |
+
3d52
|
1600 |
+
1a4q
|
1601 |
+
4rvl
|
1602 |
+
1d04
|
1603 |
+
3thd
|
1604 |
+
1ogz
|
1605 |
+
3luo
|
1606 |
+
2ftd
|
1607 |
+
4ran
|
1608 |
+
3uph
|
1609 |
+
3c8b
|
1610 |
+
2xp3
|
1611 |
+
2vtl
|
1612 |
+
1fj4
|
1613 |
+
2zm3
|
1614 |
+
3rxl
|
1615 |
+
1xmy
|
1616 |
+
3uo5
|
1617 |
+
1q1y
|
1618 |
+
2ql9
|
1619 |
+
1bhf
|
1620 |
+
2jg8
|
1621 |
+
6fuh
|
1622 |
+
2q2n
|
1623 |
+
4aof
|
1624 |
+
3ff3
|
1625 |
+
1heg
|
1626 |
+
4cae
|
1627 |
+
6fkq
|
1628 |
+
4i9i
|
1629 |
+
3ask
|
1630 |
+
1dbj
|
1631 |
+
4zbf
|
1632 |
+
2io6
|
1633 |
+
3d1y
|
1634 |
+
5t2l
|
1635 |
+
3kwf
|
1636 |
+
1juj
|
1637 |
+
3i0r
|
1638 |
+
4gui
|
1639 |
+
2hy0
|
1640 |
+
3i7c
|
1641 |
+
6g9m
|
1642 |
+
3nnx
|
1643 |
+
5u48
|
1644 |
+
2v2v
|
1645 |
+
6f5h
|
1646 |
+
5mwh
|
1647 |
+
5m0d
|
1648 |
+
5fue
|
1649 |
+
3k5k
|
1650 |
+
5edi
|
1651 |
+
4d2p
|
1652 |
+
2cm7
|
1653 |
+
8cpa
|
1654 |
+
3doy
|
1655 |
+
3k99
|
1656 |
+
1vyg
|
1657 |
+
6ckw
|
1658 |
+
6bmv
|
1659 |
+
5m4q
|
1660 |
+
5j4n
|
1661 |
+
4tpt
|
1662 |
+
2jbv
|
1663 |
+
3uqr
|
1664 |
+
4di2
|
1665 |
+
5ue4
|
1666 |
+
5enj
|
1667 |
+
3csl
|
1668 |
+
3m35
|
1669 |
+
4a9t
|
1670 |
+
5khx
|
1671 |
+
5f0h
|
1672 |
+
4wq3
|
1673 |
+
4ktu
|
1674 |
+
2qbr
|
1675 |
+
1sbr
|
1676 |
+
2f6z
|
1677 |
+
6cgt
|
1678 |
+
1t4v
|
1679 |
+
5nra
|
1680 |
+
3fed
|
1681 |
+
5l2o
|
1682 |
+
3mb7
|
1683 |
+
4bzn
|
1684 |
+
1efi
|
1685 |
+
3nrm
|
1686 |
+
5kjm
|
1687 |
+
2cle
|
1688 |
+
1j07
|
1689 |
+
3h9k
|
1690 |
+
4d83
|
1691 |
+
5n4s
|
1692 |
+
5yie
|
1693 |
+
5yz7
|
1694 |
+
5cr7
|
1695 |
+
4e35
|
1696 |
+
6di0
|
1697 |
+
3omm
|
1698 |
+
4w9n
|
1699 |
+
4z1j
|
1700 |
+
6b98
|
1701 |
+
4x61
|
1702 |
+
4x6m
|
1703 |
+
2pu1
|
1704 |
+
4q1s
|
1705 |
+
3n7a
|
1706 |
+
4qbb
|
1707 |
+
6fng
|
1708 |
+
5ya5
|
1709 |
+
3qiz
|
1710 |
+
5awt
|
1711 |
+
3sv8
|
1712 |
+
3doz
|
1713 |
+
6dlx
|
1714 |
+
4rkx
|
1715 |
+
3h91
|
1716 |
+
4uma
|
1717 |
+
1lvc
|
1718 |
+
1uy9
|
1719 |
+
5gso
|
1720 |
+
5gsa
|
1721 |
+
5drc
|
1722 |
+
4j5e
|
1723 |
+
2o22
|
1724 |
+
4loo
|
1725 |
+
5t66
|
1726 |
+
3rz0
|
1727 |
+
5unj
|
1728 |
+
4g17
|
1729 |
+
6bhv
|
1730 |
+
3cii
|
1731 |
+
5qcl
|
1732 |
+
4nw6
|
1733 |
+
4qqi
|
1734 |
+
3r0i
|
1735 |
+
5uff
|
1736 |
+
4lbp
|
1737 |
+
4bqy
|
1738 |
+
4l51
|
1739 |
+
5akh
|
1740 |
+
2yjb
|
1741 |
+
3dx0
|
1742 |
+
3v49
|
1743 |
+
3g42
|
1744 |
+
5xpp
|
1745 |
+
2c4g
|
1746 |
+
2bz6
|
1747 |
+
4fny
|
1748 |
+
3x00
|
1749 |
+
4nat
|
1750 |
+
6f8g
|
1751 |
+
4ppc
|
1752 |
+
3lpb
|
1753 |
+
3tlh
|
1754 |
+
4bcs
|
1755 |
+
3nok
|
1756 |
+
3lfs
|
1757 |
+
3o9h
|
1758 |
+
2vf6
|
1759 |
+
3we4
|
1760 |
+
2yig
|
1761 |
+
2kgi
|
1762 |
+
5llc
|
1763 |
+
2jgs
|
1764 |
+
1fkh
|
1765 |
+
5ogb
|
1766 |
+
5w8i
|
1767 |
+
1a42
|
1768 |
+
5web
|
1769 |
+
2llq
|
1770 |
+
5j7b
|
1771 |
+
2c6l
|
1772 |
+
4u0e
|
1773 |
+
2g9r
|
1774 |
+
1lt5
|
1775 |
+
5ai5
|
1776 |
+
3khj
|
1777 |
+
6hh3
|
1778 |
+
4uac
|
1779 |
+
5nob
|
1780 |
+
1ynd
|
1781 |
+
2on6
|
1782 |
+
6hd4
|
1783 |
+
3msj
|
1784 |
+
5ut4
|
1785 |
+
2wkz
|
1786 |
+
5jvi
|
1787 |
+
3gww
|
1788 |
+
4uja
|
1789 |
+
1pq3
|
1790 |
+
4u5v
|
1791 |
+
4z83
|
1792 |
+
6dh8
|
1793 |
+
1h36
|
1794 |
+
3vjk
|
1795 |
+
1unh
|
1796 |
+
3hv7
|
1797 |
+
2vxj
|
1798 |
+
3l38
|
1799 |
+
1a08
|
1800 |
+
5lgo
|
1801 |
+
1fgi
|
1802 |
+
5fqs
|
1803 |
+
5a5p
|
1804 |
+
5oss
|
1805 |
+
4o0z
|
1806 |
+
1gvx
|
1807 |
+
1xur
|
1808 |
+
5vqe
|
1809 |
+
2j7w
|
1810 |
+
2adm
|
1811 |
+
3b1m
|
1812 |
+
5zah
|
1813 |
+
1iwq
|
1814 |
+
4zx8
|
1815 |
+
3wkd
|
1816 |
+
5mtv
|
1817 |
+
5myd
|
1818 |
+
3t6r
|
1819 |
+
2c6n
|
1820 |
+
2c6e
|
1821 |
+
2gpp
|
1822 |
+
3opm
|
1823 |
+
5n9r
|
1824 |
+
3r0t
|
1825 |
+
6gue
|
1826 |
+
4b70
|
1827 |
+
3gnv
|
1828 |
+
5nyz
|
1829 |
+
1fh7
|
1830 |
+
5wae
|
1831 |
+
2bvs
|
1832 |
+
1tow
|
1833 |
+
1toj
|
1834 |
+
5een
|
1835 |
+
5fog
|
1836 |
+
6e9a
|
1837 |
+
5jek
|
1838 |
+
1jet
|
1839 |
+
5qck
|
1840 |
+
6coj
|
1841 |
+
1if8
|
1842 |
+
5t6g
|
1843 |
+
4b85
|
1844 |
+
2fm0
|
1845 |
+
5eje
|
1846 |
+
1ezf
|
1847 |
+
3twd
|
1848 |
+
3mo8
|
1849 |
+
4rvt
|
1850 |
+
6bbu
|
1851 |
+
4ejl
|
1852 |
+
1waw
|
1853 |
+
4heu
|
1854 |
+
4hgs
|
1855 |
+
6b67
|
1856 |
+
2cmc
|
1857 |
+
3arv
|
1858 |
+
4r4t
|
1859 |
+
1j80
|
1860 |
+
5ads
|
1861 |
+
6abp
|
1862 |
+
3el7
|
1863 |
+
6fex
|
1864 |
+
4m5o
|
1865 |
+
3qgw
|
1866 |
+
5t8o
|
1867 |
+
3pcn
|
1868 |
+
3nw3
|
1869 |
+
5w84
|
1870 |
+
3bqn
|
1871 |
+
4pin
|
1872 |
+
2w3o
|
1873 |
+
5yic
|
1874 |
+
4lwh
|
1875 |
+
3vo3
|
1876 |
+
4unr
|
1877 |
+
4cp5
|
1878 |
+
4b73
|
1879 |
+
6c6o
|
1880 |
+
1xz8
|
1881 |
+
5zo9
|
1882 |
+
2qn3
|
1883 |
+
2g1r
|
1884 |
+
4xc2
|
1885 |
+
1oe8
|
1886 |
+
2z94
|
1887 |
+
5aic
|
1888 |
+
4m12
|
1889 |
+
1sld
|
1890 |
+
2h96
|
1891 |
+
6cn5
|
1892 |
+
3bvb
|
1893 |
+
5x27
|
1894 |
+
3usx
|
1895 |
+
1ddm
|
1896 |
+
3fal
|
1897 |
+
2iit
|
1898 |
+
3fzt
|
1899 |
+
5vgi
|
1900 |
+
5jv1
|
1901 |
+
1py1
|
1902 |
+
5ktx
|
1903 |
+
4b35
|
1904 |
+
1m0q
|
1905 |
+
5kjk
|
1906 |
+
2vey
|
1907 |
+
6dkg
|
1908 |
+
5ei3
|
1909 |
+
6gbx
|
1910 |
+
3e01
|
1911 |
+
1p03
|
1912 |
+
4zuq
|
1913 |
+
4wbo
|
1914 |
+
4rfd
|
1915 |
+
3zlo
|
1916 |
+
5alb
|
1917 |
+
5b5o
|
1918 |
+
3liw
|
1919 |
+
2mwo
|
1920 |
+
4yjl
|
1921 |
+
4ab8
|
1922 |
+
5nau
|
1923 |
+
4at4
|
1924 |
+
1ke0
|
1925 |
+
1zz2
|
1926 |
+
2ccs
|
1927 |
+
5hz6
|
1928 |
+
2cll
|
1929 |
+
4m2v
|
1930 |
+
1q3d
|
1931 |
+
3ozt
|
1932 |
+
4ge7
|
1933 |
+
3pkd
|
1934 |
+
5t70
|
1935 |
+
3ts4
|
1936 |
+
5q0y
|
1937 |
+
5q1a
|
1938 |
+
3ogm
|
1939 |
+
5t18
|
1940 |
+
5c7d
|
1941 |
+
3g2k
|
1942 |
+
1ikv
|
1943 |
+
2j7b
|
1944 |
+
4obp
|
1945 |
+
4k6y
|
1946 |
+
2fb8
|
1947 |
+
3vbd
|
1948 |
+
5ung
|
1949 |
+
4b32
|
1950 |
+
2qlq
|
1951 |
+
3jzs
|
1952 |
+
3tiz
|
1953 |
+
1v2k
|
1954 |
+
6ee2
|
1955 |
+
3zzf
|
1956 |
+
1hpv
|
1957 |
+
5xo2
|
1958 |
+
5e2l
|
1959 |
+
1jn4
|
1960 |
+
5aly
|
1961 |
+
2jjr
|
1962 |
+
4agm
|
1963 |
+
3rwp
|
1964 |
+
3r7r
|
1965 |
+
3zbf
|
1966 |
+
4url
|
1967 |
+
2wm0
|
1968 |
+
6dcy
|
1969 |
+
2brg
|
1970 |
+
5dlx
|
1971 |
+
4g2y
|
1972 |
+
5jzs
|
1973 |
+
5fd2
|
1974 |
+
5nqr
|
1975 |
+
4jpe
|
1976 |
+
3tkm
|
1977 |
+
5ti0
|
1978 |
+
5lxp
|
1979 |
+
3avi
|
1980 |
+
5zuj
|
1981 |
+
3p3h
|
1982 |
+
3d9v
|
1983 |
+
4gs8
|
1984 |
+
4cwn
|
1985 |
+
5q1i
|
1986 |
+
6b7a
|
1987 |
+
1gjc
|
1988 |
+
4dbn
|
1989 |
+
5yp5
|
1990 |
+
5ukj
|
1991 |
+
6arj
|
1992 |
+
4iuo
|
1993 |
+
4ibk
|
1994 |
+
5ali
|
1995 |
+
6fgq
|
1996 |
+
1b5h
|
1997 |
+
2bvx
|
1998 |
+
2y36
|
1999 |
+
3f81
|
2000 |
+
4e3f
|
2001 |
+
3t84
|
2002 |
+
4na7
|
2003 |
+
2ow7
|
2004 |
+
4ob0
|
2005 |
+
1qb1
|
2006 |
+
2iku
|
2007 |
+
5kh7
|
2008 |
+
1eve
|
2009 |
+
1k2v
|
2010 |
+
3npc
|
2011 |
+
2w68
|
2012 |
+
6gqm
|
2013 |
+
1b2h
|
2014 |
+
4dfl
|
2015 |
+
4l19
|
2016 |
+
3dri
|
2017 |
+
5ab9
|
2018 |
+
4qzs
|
2019 |
+
3sqq
|
2020 |
+
1d4l
|
2021 |
+
4dn0
|
2022 |
+
9hvp
|
2023 |
+
2lko
|
2024 |
+
1lev
|
2025 |
+
3aau
|
2026 |
+
4mib
|
2027 |
+
3g2l
|
2028 |
+
1lee
|
2029 |
+
1o5e
|
2030 |
+
4os4
|
2031 |
+
4b34
|
2032 |
+
3m56
|
2033 |
+
4qvw
|
2034 |
+
4i4f
|
2035 |
+
5wf6
|
2036 |
+
3u7k
|
2037 |
+
4j5d
|
2038 |
+
1r4w
|
2039 |
+
5iaw
|
2040 |
+
3buw
|
2041 |
+
1eou
|
2042 |
+
3vbq
|
2043 |
+
6g5j
|
2044 |
+
5t4u
|
2045 |
+
3fuh
|
2046 |
+
2pj4
|
2047 |
+
2zn7
|
2048 |
+
4n4v
|
2049 |
+
2obo
|
2050 |
+
1tjp
|
2051 |
+
6b1w
|
2052 |
+
1ru2
|
2053 |
+
1fh9
|
2054 |
+
4wcf
|
2055 |
+
6hh5
|
2056 |
+
5orz
|
2057 |
+
4xmb
|
2058 |
+
4jfv
|
2059 |
+
6ekq
|
2060 |
+
5q0i
|
2061 |
+
3h1z
|
2062 |
+
4ycv
|
2063 |
+
4ura
|
2064 |
+
4prn
|
2065 |
+
6ev0
|
2066 |
+
1v3x
|
2067 |
+
2pqz
|
2068 |
+
2xjx
|
2069 |
+
3k5i
|
2070 |
+
5dtq
|
2071 |
+
4pn1
|
2072 |
+
5bue
|
2073 |
+
3ik1
|
2074 |
+
2h5d
|
2075 |
+
4jbl
|
2076 |
+
2x97
|
2077 |
+
2q72
|
2078 |
+
2qpj
|
2079 |
+
1acj
|
2080 |
+
4k6t
|
2081 |
+
6b1e
|
2082 |
+
3f3e
|
2083 |
+
2yog
|
2084 |
+
4kio
|
2085 |
+
3qem
|
2086 |
+
3ued
|
2087 |
+
5mge
|
2088 |
+
2bfq
|
2089 |
+
3mxs
|
2090 |
+
4k1b
|
2091 |
+
4p6g
|
2092 |
+
3td4
|
2093 |
+
5mnh
|
2094 |
+
5ien
|
2095 |
+
3lk8
|
2096 |
+
2zx6
|
2097 |
+
1rql
|
2098 |
+
3rm4
|
2099 |
+
5u4c
|
2100 |
+
4kb7
|
2101 |
+
5ap1
|
2102 |
+
4rj8
|
2103 |
+
5tkk
|
2104 |
+
4j04
|
2105 |
+
6i8b
|
2106 |
+
2nxl
|
2107 |
+
3zm4
|
2108 |
+
4dy6
|
2109 |
+
3h0z
|
2110 |
+
4zyf
|
2111 |
+
3e7o
|
2112 |
+
5li3
|
2113 |
+
4qjw
|
2114 |
+
4aq4
|
2115 |
+
3kpu
|
2116 |
+
5oq7
|
2117 |
+
3h2c
|
2118 |
+
2qnq
|
2119 |
+
5jn9
|
2120 |
+
5lvx
|
2121 |
+
1r10
|
2122 |
+
2l8r
|
2123 |
+
5ega
|
2124 |
+
2wi3
|
2125 |
+
3rxk
|
2126 |
+
1upf
|
2127 |
+
6chm
|
2128 |
+
4w9k
|
2129 |
+
1vja
|
2130 |
+
4zw7
|
2131 |
+
5ov8
|
2132 |
+
5wag
|
2133 |
+
1x8j
|
2134 |
+
5a6b
|
2135 |
+
6br2
|
2136 |
+
4owv
|
2137 |
+
5ev8
|
2138 |
+
3drs
|
2139 |
+
6fdc
|
2140 |
+
3tvl
|
2141 |
+
5mlo
|
2142 |
+
2xaf
|
2143 |
+
3h0j
|
2144 |
+
4yas
|
2145 |
+
1o35
|
2146 |
+
5dex
|
2147 |
+
2x52
|
2148 |
+
3lgs
|
2149 |
+
3fkt
|
2150 |
+
3dcr
|
2151 |
+
2ax6
|
2152 |
+
6cnj
|
2153 |
+
4y5d
|
2154 |
+
4umb
|
2155 |
+
3l4y
|
2156 |
+
6fkp
|
2157 |
+
5aoj
|
2158 |
+
1ony
|
2159 |
+
6b95
|
2160 |
+
5ueu
|
2161 |
+
5ahj
|
2162 |
+
2xel
|
2163 |
+
2g1y
|
2164 |
+
6iiv
|
2165 |
+
3b1t
|
2166 |
+
5dht
|
2167 |
+
4zup
|
2168 |
+
4rlk
|
2169 |
+
1axs
|
2170 |
+
5fnj
|
2171 |
+
1izi
|
2172 |
+
4gvm
|
2173 |
+
4xmr
|
2174 |
+
5yhg
|
2175 |
+
3g45
|
2176 |
+
3tao
|
2177 |
+
2q7o
|
2178 |
+
1pme
|
2179 |
+
4rrs
|
2180 |
+
6gl3
|
2181 |
+
4pct
|
2182 |
+
2tsr
|
2183 |
+
3qtw
|
2184 |
+
4uua
|
2185 |
+
5abe
|
2186 |
+
3ozp
|
2187 |
+
4lc7
|
2188 |
+
2bu5
|
2189 |
+
5kya
|
2190 |
+
2q6h
|
2191 |
+
1n95
|
2192 |
+
3k84
|
2193 |
+
3bl1
|
2194 |
+
3ui2
|
2195 |
+
2cgv
|
2196 |
+
4ez5
|
2197 |
+
3t3c
|
2198 |
+
3puk
|
2199 |
+
6css
|
2200 |
+
1ghw
|
2201 |
+
3ezr
|
2202 |
+
5il1
|
2203 |
+
1a2c
|
2204 |
+
5j6l
|
2205 |
+
2gss
|
2206 |
+
1n1m
|
2207 |
+
5f1x
|
2208 |
+
5vt4
|
2209 |
+
4y62
|
2210 |
+
1bcd
|
2211 |
+
1pwu
|
2212 |
+
4fht
|
2213 |
+
3w9k
|
2214 |
+
3qu0
|
2215 |
+
1zxc
|
2216 |
+
2vtj
|
2217 |
+
3dnt
|
2218 |
+
2pu2
|
2219 |
+
4hej
|
2220 |
+
4x3e
|
2221 |
+
5ive
|
2222 |
+
2wo8
|
2223 |
+
4ozn
|
2224 |
+
5i2f
|
2225 |
+
6dj7
|
2226 |
+
4a6w
|
2227 |
+
4q1x
|
2228 |
+
2g63
|
2229 |
+
1jak
|
2230 |
+
5knr
|
2231 |
+
5y7z
|
2232 |
+
5npb
|
2233 |
+
2izx
|
2234 |
+
3jpx
|
2235 |
+
2x38
|
2236 |
+
4knr
|
2237 |
+
3rwe
|
2238 |
+
4aze
|
2239 |
+
4nrm
|
2240 |
+
6er3
|
2241 |
+
6d59
|
2242 |
+
5a2k
|
2243 |
+
4cr9
|
2244 |
+
5i29
|
2245 |
+
4mbi
|
2246 |
+
6ht1
|
2247 |
+
2d1n
|
2248 |
+
1uj5
|
2249 |
+
3ljt
|
2250 |
+
1kyn
|
2251 |
+
5osd
|
2252 |
+
5whc
|
2253 |
+
4qws
|
2254 |
+
3uwo
|
2255 |
+
3th9
|
2256 |
+
2r2l
|
2257 |
+
5n8v
|
2258 |
+
2y54
|
2259 |
+
4m5n
|
2260 |
+
1yy6
|
2261 |
+
6fui
|
2262 |
+
3lvp
|
2263 |
+
2gdo
|
2264 |
+
3hyf
|
2265 |
+
2zva
|
2266 |
+
3zmu
|
2267 |
+
2pt9
|
2268 |
+
5nxg
|
2269 |
+
4zsm
|
2270 |
+
5eif
|
2271 |
+
4qsk
|
2272 |
+
4djr
|
2273 |
+
2ceo
|
2274 |
+
4apo
|
2275 |
+
5gj9
|
2276 |
+
1q4x
|
2277 |
+
4wz5
|
2278 |
+
2vx9
|
2279 |
+
2qzl
|
2280 |
+
4keq
|
2281 |
+
2b17
|
2282 |
+
4kzu
|
2283 |
+
1bdr
|
2284 |
+
4zjr
|
2285 |
+
3ftz
|
2286 |
+
3cic
|
2287 |
+
2c2l
|
2288 |
+
4yo8
|
2289 |
+
1vj5
|
2290 |
+
1w4p
|
2291 |
+
1aaq
|
2292 |
+
2q9n
|
2293 |
+
2yay
|
2294 |
+
4bea
|
2295 |
+
1szd
|
2296 |
+
5acb
|
2297 |
+
5db1
|
2298 |
+
5ne1
|
2299 |
+
1vj6
|
2300 |
+
3n5h
|
2301 |
+
3kpv
|
2302 |
+
2hvc
|
2303 |
+
3arr
|
2304 |
+
3v0p
|
2305 |
+
2fqw
|
2306 |
+
5jf7
|
2307 |
+
3udq
|
2308 |
+
2n14
|
2309 |
+
5mk3
|
2310 |
+
2pj6
|
2311 |
+
4pp5
|
2312 |
+
4c68
|
2313 |
+
5q15
|
2314 |
+
3u8h
|
2315 |
+
4erw
|
2316 |
+
1sb1
|
2317 |
+
5iz8
|
2318 |
+
6iiu
|
2319 |
+
3txo
|
2320 |
+
4nah
|
2321 |
+
4ir6
|
2322 |
+
4ufy
|
2323 |
+
6fer
|
2324 |
+
4zba
|
2325 |
+
1jij
|
2326 |
+
2piy
|
2327 |
+
5td2
|
2328 |
+
4yzc
|
2329 |
+
5qap
|
2330 |
+
5yhl
|
2331 |
+
1h1p
|
2332 |
+
5ni7
|
2333 |
+
4pf3
|
2334 |
+
4a6b
|
2335 |
+
4uy1
|
2336 |
+
2xwy
|
2337 |
+
4el0
|
2338 |
+
2w71
|
2339 |
+
2p8h
|
2340 |
+
4d7b
|
2341 |
+
4yoj
|
2342 |
+
2ms4
|
2343 |
+
4iwz
|
2344 |
+
5ctb
|
2345 |
+
3t85
|
2346 |
+
4lpg
|
2347 |
+
5bvw
|
2348 |
+
3uri
|
2349 |
+
3hfb
|
2350 |
+
4mr3
|
2351 |
+
3lq8
|
2352 |
+
3mlb
|
2353 |
+
4qwf
|
2354 |
+
4ixv
|
2355 |
+
4njd
|
2356 |
+
5tzo
|
2357 |
+
5qa9
|
2358 |
+
5ai8
|
2359 |
+
3o23
|
2360 |
+
4rn6
|
2361 |
+
5i22
|
2362 |
+
5u2j
|
2363 |
+
4o72
|
2364 |
+
4ej8
|
2365 |
+
1rv1
|
2366 |
+
4ixh
|
2367 |
+
1w82
|
2368 |
+
3arx
|
2369 |
+
3k02
|
2370 |
+
3uf9
|
2371 |
+
5wij
|
2372 |
+
4oq5
|
2373 |
+
1z4o
|
2374 |
+
2qf6
|
2375 |
+
3lq5
|
2376 |
+
4yw2
|
2377 |
+
3u4h
|
2378 |
+
4f20
|
2379 |
+
4mg5
|
2380 |
+
5ufi
|
2381 |
+
4n8d
|
2382 |
+
6mu1
|
2383 |
+
5zag
|
2384 |
+
4az2
|
2385 |
+
4fbx
|
2386 |
+
4emv
|
2387 |
+
4bqt
|
2388 |
+
3t2q
|
2389 |
+
5ajw
|
2390 |
+
4q81
|
2391 |
+
2fqx
|
2392 |
+
4kza
|
2393 |
+
5k51
|
2394 |
+
3u4i
|
2395 |
+
5ho8
|
2396 |
+
3lkz
|
2397 |
+
4ciz
|
2398 |
+
1yy4
|
2399 |
+
3bmy
|
2400 |
+
3vf5
|
2401 |
+
2w6p
|
2402 |
+
6fa2
|
2403 |
+
4flh
|
2404 |
+
4w4s
|
2405 |
+
3i28
|
2406 |
+
3oyl
|
2407 |
+
2nn1
|
2408 |
+
5lrk
|
2409 |
+
4e3i
|
2410 |
+
4xg9
|
2411 |
+
4d8n
|
2412 |
+
3lik
|
2413 |
+
4aj2
|
2414 |
+
4jt8
|
2415 |
+
5j7w
|
2416 |
+
5std
|
2417 |
+
3h2a
|
2418 |
+
2pwd
|
2419 |
+
6bjo
|
2420 |
+
3nik
|
2421 |
+
5lxc
|
2422 |
+
3qce
|
2423 |
+
1vrt
|
2424 |
+
4qxo
|
2425 |
+
2y1w
|
2426 |
+
1wok
|
2427 |
+
5lne
|
2428 |
+
5am6
|
2429 |
+
5er1
|
2430 |
+
3ob1
|
2431 |
+
1w4l
|
2432 |
+
6e2m
|
2433 |
+
5wh6
|
2434 |
+
3kf4
|
2435 |
+
4lnp
|
2436 |
+
3el5
|
2437 |
+
1w84
|
2438 |
+
4gm8
|
2439 |
+
3o6t
|
2440 |
+
1q83
|
2441 |
+
6fut
|
2442 |
+
2ycm
|
2443 |
+
3cqw
|
2444 |
+
5ot3
|
2445 |
+
5dp8
|
2446 |
+
1g53
|
2447 |
+
5va9
|
2448 |
+
4wx7
|
2449 |
+
5kww
|
2450 |
+
6bu1
|
2451 |
+
1q6t
|
2452 |
+
1uto
|
2453 |
+
2bks
|
2454 |
+
4fmq
|
2455 |
+
5opr
|
2456 |
+
3ies
|
2457 |
+
6hti
|
2458 |
+
5u66
|
2459 |
+
4qz6
|
2460 |
+
6b1o
|
2461 |
+
4gy5
|
2462 |
+
5mrb
|
2463 |
+
2xml
|
2464 |
+
3skk
|
2465 |
+
1c2t
|
2466 |
+
4in9
|
2467 |
+
4mss
|
2468 |
+
4kju
|
2469 |
+
1hti
|
2470 |
+
5l6o
|
2471 |
+
4wkb
|
2472 |
+
4dus
|
2473 |
+
2am1
|
2474 |
+
3t5i
|
2475 |
+
1dkd
|
2476 |
+
2onc
|
2477 |
+
6hvh
|
2478 |
+
1ypg
|
2479 |
+
6cvf
|
2480 |
+
6bkw
|
2481 |
+
2jt5
|
2482 |
+
3fdt
|
2483 |
+
4wh7
|
2484 |
+
5i3m
|
2485 |
+
1azx
|
2486 |
+
3fck
|
2487 |
+
5u6c
|
2488 |
+
4ded
|
2489 |
+
4k0u
|
2490 |
+
5xmu
|
2491 |
+
3wk9
|
2492 |
+
4kz0
|
2493 |
+
5a7c
|
2494 |
+
6g9j
|
2495 |
+
3iw6
|
2496 |
+
4ddk
|
2497 |
+
1icj
|
2498 |
+
6eyt
|
2499 |
+
4z2o
|
2500 |
+
4e3h
|
2501 |
+
4c70
|
2502 |
+
2y57
|
2503 |
+
3dzt
|
2504 |
+
5e0g
|
2505 |
+
4nrb
|
2506 |
+
4qr3
|
2507 |
+
5ltn
|
2508 |
+
3omg
|
2509 |
+
6bod
|
2510 |
+
4jpa
|
2511 |
+
3fzs
|
2512 |
+
6f5l
|
2513 |
+
5edd
|
2514 |
+
2oyl
|
2515 |
+
2bmc
|
2516 |
+
2xqq
|
2517 |
+
3kqy
|
2518 |
+
1oiy
|
2519 |
+
5y13
|
2520 |
+
4d1s
|
2521 |
+
3ked
|
2522 |
+
5djp
|
2523 |
+
3bxe
|
2524 |
+
4bo0
|
2525 |
+
3oy3
|
2526 |
+
4o2a
|
2527 |
+
5em6
|
2528 |
+
5tfx
|
2529 |
+
4d9p
|
2530 |
+
3tku
|
2531 |
+
4p1r
|
2532 |
+
5nwz
|
2533 |
+
4bs4
|
2534 |
+
3oys
|
2535 |
+
5lgs
|
2536 |
+
4nyi
|
2537 |
+
3l58
|
2538 |
+
2vxn
|
2539 |
+
1y98
|
2540 |
+
3ck7
|
2541 |
+
1nh0
|
2542 |
+
4an0
|
2543 |
+
1mcz
|
2544 |
+
2h9n
|
2545 |
+
3h0s
|
2546 |
+
2ycq
|
2547 |
+
2x4s
|
2548 |
+
4acc
|
2549 |
+
5ows
|
2550 |
+
3rxa
|
2551 |
+
4dhm
|
2552 |
+
5lhi
|
2553 |
+
5l8c
|
2554 |
+
3rxi
|
2555 |
+
3r00
|
2556 |
+
5oq5
|
2557 |
+
1jev
|
2558 |
+
4ztn
|
2559 |
+
4yb7
|
2560 |
+
4a7j
|
2561 |
+
4os7
|
2562 |
+
3e3c
|
2563 |
+
4acu
|
2564 |
+
5hvt
|
2565 |
+
3lf0
|
2566 |
+
4jfj
|
2567 |
+
4p44
|
2568 |
+
5dxh
|
2569 |
+
1d4k
|
2570 |
+
5ewk
|
2571 |
+
1gx8
|
2572 |
+
1x6u
|
2573 |
+
3g2z
|
2574 |
+
1i7c
|
2575 |
+
5opb
|
2576 |
+
4y85
|
2577 |
+
6fii
|
2578 |
+
6c7q
|
2579 |
+
4jkt
|
2580 |
+
4lbl
|
2581 |
+
1w76
|
2582 |
+
5dgz
|
2583 |
+
3run
|
2584 |
+
4qoc
|
2585 |
+
456c
|
2586 |
+
5twz
|
2587 |
+
4a4h
|
2588 |
+
6gl9
|
2589 |
+
6h7z
|
2590 |
+
4fxz
|
2591 |
+
2hu6
|
2592 |
+
2ohp
|
2593 |
+
4ayt
|
2594 |
+
4fgx
|
2595 |
+
1x8b
|
2596 |
+
2y7x
|
2597 |
+
4yb6
|
2598 |
+
5i8c
|
2599 |
+
2aoi
|
2600 |
+
3kgt
|
2601 |
+
3g2h
|
2602 |
+
3gwx
|
2603 |
+
5lyr
|
2604 |
+
3nk8
|
2605 |
+
1mrx
|
2606 |
+
1pf8
|
2607 |
+
6dj1
|
2608 |
+
4jss
|
2609 |
+
3tu9
|
2610 |
+
5cqt
|
2611 |
+
1yds
|
2612 |
+
3hy9
|
2613 |
+
5y5u
|
2614 |
+
6dko
|
2615 |
+
3s0j
|
2616 |
+
5hm0
|
2617 |
+
3s3o
|
2618 |
+
5om7
|
2619 |
+
2j9n
|
2620 |
+
4bfd
|
2621 |
+
5wzw
|
2622 |
+
1d3v
|
2623 |
+
4pvv
|
2624 |
+
4i0s
|
2625 |
+
4pmm
|
2626 |
+
6ftp
|
2627 |
+
4hct
|
2628 |
+
1c5t
|
2629 |
+
5i3v
|
2630 |
+
5urk
|
2631 |
+
5q0f
|
2632 |
+
5xv7
|
2633 |
+
4bj9
|
2634 |
+
1css
|
2635 |
+
4azc
|
2636 |
+
1hqf
|
2637 |
+
3kej
|
2638 |
+
2p8n
|
2639 |
+
5tg1
|
2640 |
+
3cvk
|
2641 |
+
6awp
|
2642 |
+
1e3g
|
2643 |
+
1t4e
|
2644 |
+
2nns
|
2645 |
+
5al5
|
2646 |
+
3cr5
|
2647 |
+
6equ
|
2648 |
+
5fl5
|
2649 |
+
2yex
|
2650 |
+
5lsh
|
2651 |
+
4fgz
|
2652 |
+
3mv0
|
2653 |
+
3l5d
|
2654 |
+
1q6m
|
2655 |
+
5khh
|
2656 |
+
5c85
|
2657 |
+
2f3e
|
2658 |
+
1npw
|
2659 |
+
5w1e
|
2660 |
+
4j0a
|
2661 |
+
4mvn
|
2662 |
+
5ioz
|
2663 |
+
4yve
|
2664 |
+
5tbm
|
2665 |
+
2fx7
|
2666 |
+
4oex
|
2667 |
+
4pjt
|
2668 |
+
1nnu
|
2669 |
+
3c4h
|
2670 |
+
3vp1
|
2671 |
+
1bky
|
2672 |
+
5ajc
|
2673 |
+
1jcx
|
2674 |
+
8hvp
|
2675 |
+
4wvs
|
2676 |
+
2vcx
|
2677 |
+
5hkh
|
2678 |
+
2llo
|
2679 |
+
2jkm
|
2680 |
+
1q6p
|
2681 |
+
5mf6
|
2682 |
+
5afj
|
2683 |
+
4l50
|
2684 |
+
1o3e
|
2685 |
+
6evm
|
2686 |
+
1pyw
|
2687 |
+
3l3a
|
2688 |
+
4mnx
|
2689 |
+
4fll
|
2690 |
+
6hx5
|
2691 |
+
3ivc
|
2692 |
+
6mx8
|
2693 |
+
5wf5
|
2694 |
+
5a1f
|
2695 |
+
4c4g
|
2696 |
+
1w5w
|
2697 |
+
2w26
|
2698 |
+
4an9
|
2699 |
+
5n8j
|
2700 |
+
3aqt
|
2701 |
+
4dho
|
2702 |
+
4l7r
|
2703 |
+
4aro
|
2704 |
+
1stp
|
2705 |
+
6g07
|
2706 |
+
4hze
|
2707 |
+
2cbj
|
2708 |
+
5wbr
|
2709 |
+
5afx
|
2710 |
+
3bh3
|
2711 |
+
4ca8
|
2712 |
+
6aam
|
2713 |
+
1r78
|
2714 |
+
6aol
|
2715 |
+
1gcz
|
2716 |
+
3bjc
|
2717 |
+
1o2x
|
2718 |
+
1b40
|
2719 |
+
4u45
|
2720 |
+
5nat
|
2721 |
+
4qiy
|
2722 |
+
3v30
|
2723 |
+
3kyq
|
2724 |
+
3unn
|
2725 |
+
5elf
|
2726 |
+
1xoe
|
2727 |
+
2oqi
|
2728 |
+
5mpz
|
2729 |
+
4hxz
|
2730 |
+
4rfr
|
2731 |
+
3vp3
|
2732 |
+
6upj
|
2733 |
+
5xyy
|
2734 |
+
4wci
|
2735 |
+
2fwz
|
2736 |
+
6buu
|
2737 |
+
3ocz
|
2738 |
+
3v3v
|
2739 |
+
2yq6
|
2740 |
+
4m8e
|
2741 |
+
4r6e
|
2742 |
+
5ihh
|
2743 |
+
5ngs
|
2744 |
+
2v77
|
2745 |
+
3nzs
|
2746 |
+
5tyk
|
2747 |
+
4l7g
|
2748 |
+
3dne
|
2749 |
+
1m5f
|
2750 |
+
2xk8
|
2751 |
+
4urx
|
2752 |
+
3ft5
|
2753 |
+
4br3
|
2754 |
+
1bgq
|
2755 |
+
3fa3
|
2756 |
+
2y07
|
2757 |
+
4lpb
|
2758 |
+
5k0m
|
2759 |
+
4tlr
|
2760 |
+
1ocq
|
2761 |
+
4j5c
|
2762 |
+
4awm
|
2763 |
+
1ado
|
2764 |
+
2n3k
|
2765 |
+
4mf1
|
2766 |
+
4oho
|
2767 |
+
2xv1
|
2768 |
+
5hh6
|
2769 |
+
5kmh
|
2770 |
+
4lkt
|
2771 |
+
3n2v
|
2772 |
+
3o7u
|
2773 |
+
2ieo
|
2774 |
+
1wbo
|
2775 |
+
5i25
|
2776 |
+
4mhz
|
2777 |
+
5mmp
|
2778 |
+
3qs8
|
2779 |
+
2ykj
|
2780 |
+
5igm
|
2781 |
+
4zji
|
2782 |
+
3zxz
|
2783 |
+
4b71
|
2784 |
+
1fpp
|
2785 |
+
2y76
|
2786 |
+
6eya
|
2787 |
+
5lch
|
2788 |
+
5gp7
|
2789 |
+
3mmr
|
2790 |
+
4qc1
|
2791 |
+
3sbi
|
2792 |
+
4bsq
|
2793 |
+
5yhe
|
2794 |
+
5hj9
|
2795 |
+
4qw1
|
2796 |
+
1px4
|
2797 |
+
1q5l
|
2798 |
+
4i9z
|
2799 |
+
1pbk
|
2800 |
+
1o5b
|
2801 |
+
1ryf
|
2802 |
+
3oeu
|
2803 |
+
3nx7
|
2804 |
+
4izy
|
2805 |
+
5lvf
|
2806 |
+
3hll
|
2807 |
+
4jbp
|
2808 |
+
5icv
|
2809 |
+
2yln
|
2810 |
+
5om3
|
2811 |
+
1e2l
|
2812 |
+
2oyk
|
2813 |
+
2c0o
|
2814 |
+
5w5v
|
2815 |
+
1b2i
|
2816 |
+
3w8o
|
2817 |
+
4x60
|
2818 |
+
6h2z
|
2819 |
+
2a3i
|
2820 |
+
5jnl
|
2821 |
+
6m9d
|
2822 |
+
4twp
|
2823 |
+
5gmu
|
2824 |
+
5wg4
|
2825 |
+
2mkr
|
2826 |
+
5e89
|
2827 |
+
2j78
|
2828 |
+
3elc
|
2829 |
+
3eb1
|
2830 |
+
5wlv
|
2831 |
+
3udk
|
2832 |
+
4p0v
|
2833 |
+
5ahu
|
2834 |
+
5two
|
2835 |
+
2jf4
|
2836 |
+
1mm6
|
2837 |
+
3c4c
|
2838 |
+
5a2j
|
2839 |
+
3ti4
|
2840 |
+
3pd9
|
2841 |
+
4rx8
|
2842 |
+
4yhz
|
2843 |
+
2vr0
|
2844 |
+
6mim
|
2845 |
+
2k00
|
2846 |
+
3fr2
|
2847 |
+
5q0o
|
2848 |
+
5dgw
|
2849 |
+
3tiy
|
2850 |
+
4jxs
|
2851 |
+
5xst
|
2852 |
+
5tpx
|
2853 |
+
4j1h
|
2854 |
+
5xva
|
2855 |
+
1o49
|
2856 |
+
2mlm
|
2857 |
+
4alu
|
2858 |
+
1tv6
|
2859 |
+
4g2f
|
2860 |
+
2xp4
|
2861 |
+
1lhg
|
2862 |
+
5aoi
|
2863 |
+
2bz8
|
2864 |
+
4kbc
|
2865 |
+
1h22
|
2866 |
+
5tho
|
2867 |
+
1wun
|
2868 |
+
1d8m
|
2869 |
+
3m17
|
2870 |
+
1slg
|
2871 |
+
3pcc
|
2872 |
+
1oh4
|
2873 |
+
2vio
|
2874 |
+
3v6r
|
2875 |
+
4n7h
|
2876 |
+
3fv8
|
2877 |
+
4f08
|
2878 |
+
2p33
|
2879 |
+
5a5d
|
2880 |
+
3n1v
|
2881 |
+
4j4o
|
2882 |
+
5o1d
|
2883 |
+
5ewm
|
2884 |
+
3ds4
|
2885 |
+
4b3b
|
2886 |
+
1sqi
|
2887 |
+
2nmx
|
2888 |
+
1gai
|
2889 |
+
1fax
|
2890 |
+
4deg
|
2891 |
+
3suu
|
2892 |
+
4rcd
|
2893 |
+
6f6s
|
2894 |
+
1juf
|
2895 |
+
4zx3
|
2896 |
+
1m48
|
2897 |
+
5ttf
|
2898 |
+
4man
|
2899 |
+
5ljt
|
2900 |
+
1y0l
|
2901 |
+
6hsk
|
2902 |
+
1gyy
|
2903 |
+
3bi6
|
2904 |
+
3fue
|
2905 |
+
1c87
|
2906 |
+
4byj
|
2907 |
+
4r18
|
2908 |
+
6bnh
|
2909 |
+
3qpn
|
2910 |
+
4r4i
|
2911 |
+
4e5h
|
2912 |
+
4ojq
|
2913 |
+
5aqt
|
2914 |
+
3fu3
|
2915 |
+
3oap
|
2916 |
+
3d1x
|
2917 |
+
4j48
|
2918 |
+
5uig
|
2919 |
+
5vcz
|
2920 |
+
5tzd
|
2921 |
+
4hva
|
2922 |
+
3mvl
|
2923 |
+
6b1c
|
2924 |
+
4e96
|
2925 |
+
4d88
|
2926 |
+
4ufi
|
2927 |
+
4uvu
|
2928 |
+
3met
|
2929 |
+
5aeh
|
2930 |
+
6dh5
|
2931 |
+
4mrh
|
2932 |
+
5fqv
|
2933 |
+
5t8q
|
2934 |
+
6f7c
|
2935 |
+
5l17
|
2936 |
+
3zim
|
2937 |
+
3k83
|
2938 |
+
2p3a
|
2939 |
+
4wsj
|
2940 |
+
4cd1
|
2941 |
+
2xk7
|
2942 |
+
5w6u
|
2943 |
+
4zs3
|
2944 |
+
4u58
|
2945 |
+
2qn1
|
2946 |
+
6f5m
|
2947 |
+
2c8y
|
2948 |
+
3vw6
|
2949 |
+
1o42
|
2950 |
+
5uor
|
2951 |
+
2ycs
|
2952 |
+
2i4z
|
2953 |
+
4q1d
|
2954 |
+
5m0s
|
2955 |
+
3qup
|
2956 |
+
1tr7
|
2957 |
+
5xpn
|
2958 |
+
2aa6
|
2959 |
+
5uv2
|
2960 |
+
3pgl
|
2961 |
+
4mk7
|
2962 |
+
5uir
|
2963 |
+
1p57
|
2964 |
+
4ezx
|
2965 |
+
3shj
|
2966 |
+
5csw
|
2967 |
+
3ibn
|
2968 |
+
4ag8
|
2969 |
+
6ceh
|
2970 |
+
2p98
|
2971 |
+
4yht
|
2972 |
+
3k0k
|
2973 |
+
5neb
|
2974 |
+
4ysi
|
2975 |
+
1bo5
|
2976 |
+
1a28
|
2977 |
+
3wha
|
2978 |
+
4nq6
|
2979 |
+
1czc
|
2980 |
+
1ckb
|
2981 |
+
5j6d
|
2982 |
+
3hr1
|
2983 |
+
4acm
|
2984 |
+
6hrq
|
2985 |
+
1py5
|
2986 |
+
3km4
|
2987 |
+
4c66
|
2988 |
+
1sr7
|
2989 |
+
1rnm
|
2990 |
+
3krx
|
2991 |
+
3d25
|
2992 |
+
5d6e
|
2993 |
+
5w4v
|
2994 |
+
1xbc
|
2995 |
+
2x8e
|
2996 |
+
4cmu
|
2997 |
+
4f09
|
2998 |
+
5afv
|
2999 |
+
6bkx
|
3000 |
+
3lqj
|
3001 |
+
2hug
|
3002 |
+
5dnu
|
3003 |
+
2woa
|
3004 |
+
5xvw
|
3005 |
+
3fi3
|
3006 |
+
4yho
|
3007 |
+
1h1s
|
3008 |
+
1w3j
|
3009 |
+
5y59
|
3010 |
+
1sdv
|
3011 |
+
5tmn
|
3012 |
+
5myk
|
3013 |
+
5f29
|
3014 |
+
1efy
|
3015 |
+
4ayy
|
3016 |
+
4ykk
|
3017 |
+
3m6p
|
3018 |
+
1utl
|
3019 |
+
3zls
|
3020 |
+
4ff8
|
3021 |
+
5f6d
|
3022 |
+
4k8s
|
3023 |
+
2mpa
|
3024 |
+
2gfs
|
3025 |
+
1c86
|
3026 |
+
5e5g
|
3027 |
+
3zvy
|
3028 |
+
2f3r
|
3029 |
+
4e5j
|
3030 |
+
3l5r
|
3031 |
+
5l01
|
3032 |
+
2vj8
|
3033 |
+
4b9w
|
3034 |
+
4i7m
|
3035 |
+
4qwu
|
3036 |
+
3rpr
|
3037 |
+
4i7k
|
3038 |
+
2c1n
|
3039 |
+
4ret
|
3040 |
+
1owk
|
3041 |
+
4mxc
|
3042 |
+
2ohs
|
3043 |
+
1akw
|
3044 |
+
5tyh
|
3045 |
+
5huw
|
3046 |
+
5w14
|
3047 |
+
5lb7
|
3048 |
+
1f8e
|
3049 |
+
4ciy
|
3050 |
+
5etm
|
3051 |
+
2pwr
|
3052 |
+
5o1f
|
3053 |
+
4r1e
|
3054 |
+
4ncg
|
3055 |
+
4abf
|
3056 |
+
1my4
|
3057 |
+
4jib
|
3058 |
+
4nxr
|
3059 |
+
2jbo
|
3060 |
+
1njd
|
3061 |
+
1pdq
|
3062 |
+
1qj7
|
3063 |
+
5fi6
|
3064 |
+
2vtp
|
3065 |
+
5dro
|
3066 |
+
1o3b
|
3067 |
+
4jln
|
3068 |
+
2yis
|
3069 |
+
1rt2
|
3070 |
+
4feq
|
3071 |
+
3gjs
|
3072 |
+
5eef
|
3073 |
+
2zx8
|
3074 |
+
3ujd
|
3075 |
+
1fkf
|
3076 |
+
5eto
|
3077 |
+
1c5p
|
3078 |
+
5tys
|
3079 |
+
6ayo
|
3080 |
+
4eh4
|
3081 |
+
3djv
|
3082 |
+
3mhm
|
3083 |
+
2pow
|
3084 |
+
1w0y
|
3085 |
+
4dbm
|
3086 |
+
2ywp
|
3087 |
+
5uhi
|
3088 |
+
1mj7
|
3089 |
+
5am3
|
3090 |
+
1pxp
|
3091 |
+
4uff
|
3092 |
+
2bq6
|
3093 |
+
1n1g
|
3094 |
+
5nxq
|
3095 |
+
966c
|
3096 |
+
3vws
|
3097 |
+
2of2
|
3098 |
+
2ydf
|
3099 |
+
4nbk
|
3100 |
+
1l0a
|
3101 |
+
4u43
|
3102 |
+
5trh
|
3103 |
+
1rpa
|
3104 |
+
5etv
|
3105 |
+
1h61
|
3106 |
+
2vcb
|
3107 |
+
3d1v
|
3108 |
+
1xq0
|
3109 |
+
1b3h
|
3110 |
+
3svj
|
3111 |
+
5fun
|
3112 |
+
4bw1
|
3113 |
+
1kti
|
3114 |
+
4jof
|
3115 |
+
4izm
|
3116 |
+
4phu
|
3117 |
+
3jy9
|
3118 |
+
4urw
|
3119 |
+
5ael
|
3120 |
+
4irx
|
3121 |
+
3avn
|
3122 |
+
5mm9
|
3123 |
+
5twl
|
3124 |
+
4w9l
|
3125 |
+
2ad5
|
3126 |
+
4b4g
|
3127 |
+
4a22
|
3128 |
+
5vfc
|
3129 |
+
3l3q
|
3130 |
+
6fn9
|
3131 |
+
4m14
|
3132 |
+
2gl0
|
3133 |
+
4c35
|
3134 |
+
3iob
|
3135 |
+
6apr
|
3136 |
+
6g3v
|
3137 |
+
4cik
|
3138 |
+
2xpb
|
3139 |
+
3loo
|
3140 |
+
3drr
|
3141 |
+
3e4a
|
3142 |
+
5thi
|
3143 |
+
5mgm
|
3144 |
+
3mrv
|
3145 |
+
2c4v
|
3146 |
+
4i8n
|
3147 |
+
5obr
|
3148 |
+
2qyl
|
3149 |
+
6ee4
|
3150 |
+
2wzx
|
3151 |
+
5j8z
|
3152 |
+
2itz
|
3153 |
+
5t2i
|
3154 |
+
4mdn
|
3155 |
+
5nw0
|
3156 |
+
5l9o
|
3157 |
+
1c5n
|
3158 |
+
3bel
|
3159 |
+
1nt1
|
3160 |
+
4g69
|
3161 |
+
5ovv
|
3162 |
+
1i9n
|
3163 |
+
1hlk
|
3164 |
+
5hh4
|
3165 |
+
2hhn
|
3166 |
+
5v13
|
3167 |
+
2ww0
|
3168 |
+
2rcx
|
3169 |
+
5zms
|
3170 |
+
2ncz
|
3171 |
+
1a86
|
3172 |
+
4uuq
|
3173 |
+
5g2n
|
3174 |
+
1o5g
|
3175 |
+
2gfj
|
3176 |
+
5d3j
|
3177 |
+
3dpe
|
3178 |
+
5ldp
|
3179 |
+
3veu
|
3180 |
+
2vaq
|
3181 |
+
4ui5
|
3182 |
+
1hp5
|
3183 |
+
5g1a
|
3184 |
+
3f39
|
3185 |
+
4owm
|
3186 |
+
1dl7
|
3187 |
+
3ce3
|
3188 |
+
2qmg
|
3189 |
+
4poh
|
3190 |
+
5azg
|
3191 |
+
6by8
|
3192 |
+
5l7f
|
3193 |
+
4awo
|
3194 |
+
6fh7
|
3195 |
+
4ifi
|
3196 |
+
6b7e
|
3197 |
+
5i3x
|
3198 |
+
5lws
|
3199 |
+
5sve
|
3200 |
+
3kn0
|
3201 |
+
3q2h
|
3202 |
+
5eoc
|
3203 |
+
6b7h
|
3204 |
+
5ekn
|
3205 |
+
3rqw
|
3206 |
+
4erk
|
3207 |
+
5fso
|
3208 |
+
5e80
|
3209 |
+
2bpx
|
3210 |
+
1yw8
|
3211 |
+
3sc1
|
3212 |
+
5o4t
|
3213 |
+
5c2o
|
3214 |
+
4u0f
|
3215 |
+
2w17
|
3216 |
+
5nxy
|
3217 |
+
1oy7
|
3218 |
+
6dvm
|
3219 |
+
3k00
|
3220 |
+
1py2
|
3221 |
+
4zx0
|
3222 |
+
4nkt
|
3223 |
+
3s1h
|
3224 |
+
2ym5
|
3225 |
+
6cis
|
3226 |
+
3hdm
|
3227 |
+
2yj2
|
3228 |
+
4ef4
|
3229 |
+
3kvw
|
3230 |
+
5cu2
|
3231 |
+
6c1s
|
3232 |
+
4j6i
|
3233 |
+
6bij
|
3234 |
+
5xgh
|
3235 |
+
5u2c
|
3236 |
+
3m3e
|
3237 |
+
1yid
|
3238 |
+
1b6k
|
3239 |
+
4gd6
|
3240 |
+
5lp1
|
3241 |
+
4ww6
|
3242 |
+
1zhy
|
3243 |
+
3eky
|
3244 |
+
2q38
|
3245 |
+
4jym
|
3246 |
+
2ymt
|
3247 |
+
3gur
|
3248 |
+
3suv
|
3249 |
+
1njs
|
3250 |
+
4na8
|
3251 |
+
4msa
|
3252 |
+
5nk8
|
3253 |
+
1o4k
|
3254 |
+
3l6h
|
3255 |
+
1i5h
|
3256 |
+
3t6b
|
3257 |
+
5e1s
|
3258 |
+
6gzd
|
3259 |
+
2eum
|
3260 |
+
1z71
|
3261 |
+
2yc5
|
3262 |
+
6hai
|
3263 |
+
2a14
|
3264 |
+
4aa4
|
3265 |
+
4ask
|
3266 |
+
4ea1
|
3267 |
+
3pxz
|
3268 |
+
4n4s
|
3269 |
+
5wkm
|
3270 |
+
4jg0
|
3271 |
+
3sie
|
3272 |
+
3pkc
|
3273 |
+
1w1g
|
3274 |
+
5y8c
|
3275 |
+
2c6m
|
3276 |
+
5ou3
|
3277 |
+
6d50
|
3278 |
+
5v3y
|
3279 |
+
5lzj
|
3280 |
+
5tya
|
3281 |
+
4c9x
|
3282 |
+
3eyu
|
3283 |
+
4xtm
|
3284 |
+
3agl
|
3285 |
+
2brh
|
3286 |
+
4mbf
|
3287 |
+
5d4a
|
3288 |
+
2zz6
|
3289 |
+
2gbi
|
3290 |
+
1t5f
|
3291 |
+
5jiy
|
3292 |
+
1nw7
|
3293 |
+
3hl7
|
3294 |
+
6h7f
|
3295 |
+
1zd4
|
3296 |
+
3suw
|
3297 |
+
5fdc
|
3298 |
+
3cct
|
3299 |
+
4pm0
|
3300 |
+
2y1x
|
3301 |
+
5n9n
|
3302 |
+
4gj2
|
3303 |
+
5d6f
|
3304 |
+
4joj
|
3305 |
+
5klz
|
3306 |
+
4jju
|
3307 |
+
2gg7
|
3308 |
+
5hn9
|
3309 |
+
4tjy
|
3310 |
+
4r91
|
3311 |
+
6ffn
|
3312 |
+
5usf
|
3313 |
+
2clk
|
3314 |
+
5n70
|
3315 |
+
2ohu
|
3316 |
+
3eka
|
3317 |
+
5eq1
|
3318 |
+
4qlq
|
3319 |
+
6eis
|
3320 |
+
4acf
|
3321 |
+
5t35
|
3322 |
+
4orx
|
3323 |
+
2hmw
|
3324 |
+
3fz1
|
3325 |
+
3qx5
|
3326 |
+
4zhm
|
3327 |
+
3rxo
|
3328 |
+
1atl
|
3329 |
+
5t1k
|
3330 |
+
3np7
|
3331 |
+
3zt4
|
3332 |
+
1bdl
|
3333 |
+
4u6y
|
3334 |
+
2jbk
|
3335 |
+
5l13
|
3336 |
+
5mob
|
3337 |
+
2igy
|
3338 |
+
5jlz
|
3339 |
+
4flj
|
3340 |
+
2zu4
|
3341 |
+
2w70
|
3342 |
+
5d6y
|
3343 |
+
4kip
|
3344 |
+
2uw0
|
3345 |
+
4msg
|
3346 |
+
6f8x
|
3347 |
+
1r2b
|
3348 |
+
4qvm
|
3349 |
+
2ydo
|
3350 |
+
1w4q
|
3351 |
+
5okt
|
3352 |
+
5op4
|
3353 |
+
3al3
|
3354 |
+
2rvn
|
3355 |
+
3dp1
|
3356 |
+
4luz
|
3357 |
+
3o87
|
3358 |
+
1w2h
|
3359 |
+
1fiv
|
3360 |
+
1uh1
|
3361 |
+
6c8p
|
3362 |
+
4g8m
|
3363 |
+
4hai
|
3364 |
+
2evc
|
3365 |
+
2q2z
|
3366 |
+
4yyt
|
3367 |
+
4od0
|
3368 |
+
5k9w
|
3369 |
+
3fyj
|
3370 |
+
5vh0
|
3371 |
+
5ale
|
3372 |
+
3th8
|
3373 |
+
4yhp
|
3374 |
+
4pvo
|
3375 |
+
4whs
|
3376 |
+
1c4v
|
3377 |
+
5hed
|
3378 |
+
5qbv
|
3379 |
+
2oei
|
3380 |
+
4y2s
|
3381 |
+
1z6q
|
3382 |
+
4px6
|
3383 |
+
2knh
|
3384 |
+
5kns
|
3385 |
+
1m4h
|
3386 |
+
2g96
|
3387 |
+
3cm7
|
3388 |
+
4gcj
|
3389 |
+
1qft
|
3390 |
+
3ztd
|
3391 |
+
4yzu
|
3392 |
+
1vwl
|
3393 |
+
4kiq
|
3394 |
+
6ax1
|
3395 |
+
3zyh
|
3396 |
+
2c1q
|
3397 |
+
6mx3
|
3398 |
+
5o9r
|
3399 |
+
1q8t
|
3400 |
+
4ue1
|
3401 |
+
2y7z
|
3402 |
+
3mdz
|
3403 |
+
4gtr
|
3404 |
+
6fh6
|
3405 |
+
4qvq
|
3406 |
+
3tti
|
3407 |
+
5ap6
|
3408 |
+
4pkt
|
3409 |
+
3tdj
|
3410 |
+
3qnd
|
3411 |
+
4lvt
|
3412 |
+
1xo2
|
3413 |
+
1pcg
|
3414 |
+
5fiv
|
3415 |
+
1g3e
|
3416 |
+
6gx3
|
3417 |
+
5dhj
|
3418 |
+
5ixt
|
3419 |
+
1xhm
|
3420 |
+
4po7
|
3421 |
+
1a5g
|
3422 |
+
1haa
|
3423 |
+
6egs
|
3424 |
+
3iw8
|
3425 |
+
5qag
|
3426 |
+
5o1b
|
3427 |
+
5brz
|
3428 |
+
3mpt
|
3429 |
+
3ral
|
3430 |
+
1j14
|
3431 |
+
5wdj
|
3432 |
+
4io3
|
3433 |
+
2irz
|
3434 |
+
3f35
|
3435 |
+
5jan
|
3436 |
+
6mrg
|
3437 |
+
2oi3
|
3438 |
+
1onp
|
3439 |
+
4bjx
|
3440 |
+
2i0v
|
3441 |
+
4hmk
|
3442 |
+
5mat
|
3443 |
+
4h2m
|
3444 |
+
4agl
|
3445 |
+
4ayx
|
3446 |
+
5iwg
|
3447 |
+
2xez
|
3448 |
+
5em7
|
3449 |
+
5kdf
|
3450 |
+
3vv6
|
3451 |
+
4y59
|
3452 |
+
3ti6
|
3453 |
+
5gn6
|
3454 |
+
4u7v
|
3455 |
+
3rz7
|
3456 |
+
5wxo
|
3457 |
+
1o2w
|
3458 |
+
4r0i
|
3459 |
+
1a30
|
3460 |
+
5nz2
|
3461 |
+
3rf4
|
3462 |
+
6ee6
|
3463 |
+
4oiv
|
3464 |
+
1a9u
|
3465 |
+
3iop
|
3466 |
+
5x4p
|
3467 |
+
3gl6
|
3468 |
+
1hqg
|
3469 |
+
2oji
|
3470 |
+
4ps3
|
3471 |
+
2w05
|
3472 |
+
1tnh
|
3473 |
+
3djq
|
3474 |
+
2c9b
|
3475 |
+
2flb
|
3476 |
+
5itd
|
3477 |
+
5k00
|
3478 |
+
1t37
|
3479 |
+
3g0b
|
3480 |
+
6hdo
|
3481 |
+
2rfh
|
3482 |
+
1b5g
|
3483 |
+
4bdi
|
3484 |
+
4ikn
|
3485 |
+
3inf
|
3486 |
+
1rww
|
3487 |
+
4g68
|
3488 |
+
4djw
|
3489 |
+
5yum
|
3490 |
+
4hxl
|
3491 |
+
3dbd
|
3492 |
+
4hw7
|
3493 |
+
5mys
|
3494 |
+
3p7i
|
3495 |
+
2j7h
|
3496 |
+
2vvt
|
3497 |
+
3r2y
|
3498 |
+
5ng9
|
3499 |
+
1y2g
|
3500 |
+
2vwm
|
3501 |
+
3if7
|
3502 |
+
2hl4
|
3503 |
+
3ffp
|
3504 |
+
4qwg
|
3505 |
+
3g6z
|
3506 |
+
5dhf
|
3507 |
+
4y79
|
3508 |
+
3m57
|
3509 |
+
4oyi
|
3510 |
+
3s0b
|
3511 |
+
1yvx
|
3512 |
+
3v7c
|
3513 |
+
4md6
|
3514 |
+
4g9c
|
3515 |
+
2w6m
|
3516 |
+
5tt7
|
3517 |
+
3pkb
|
3518 |
+
3upi
|
3519 |
+
2va6
|
3520 |
+
2weh
|
3521 |
+
4bao
|
3522 |
+
5gid
|
3523 |
+
2w1g
|
3524 |
+
3mxc
|
3525 |
+
2fw6
|
3526 |
+
3diw
|
3527 |
+
1ind
|
3528 |
+
3i3d
|
3529 |
+
5k0i
|
3530 |
+
4npv
|
3531 |
+
2wf5
|
3532 |
+
2q7q
|
3533 |
+
4wyz
|
3534 |
+
5xaf
|
3535 |
+
1gj4
|
3536 |
+
5hf1
|
3537 |
+
2aw1
|
3538 |
+
3dbu
|
3539 |
+
3o9i
|
3540 |
+
4l34
|
3541 |
+
5j0d
|
3542 |
+
5afl
|
3543 |
+
2w3i
|
3544 |
+
5ew3
|
3545 |
+
5e0m
|
3546 |
+
5jfu
|
3547 |
+
4fm7
|
3548 |
+
1o4h
|
3549 |
+
4w9p
|
3550 |
+
6eyb
|
3551 |
+
4onf
|
3552 |
+
4zhl
|
3553 |
+
3mj2
|
3554 |
+
3k22
|
3555 |
+
2xxy
|
3556 |
+
5m5q
|
3557 |
+
4aci
|
3558 |
+
5kab
|
3559 |
+
4dpt
|
3560 |
+
4rsk
|
3561 |
+
1rsi
|
3562 |
+
5c42
|
3563 |
+
3tb6
|
3564 |
+
6bmi
|
3565 |
+
4myd
|
3566 |
+
2i40
|
3567 |
+
5nhj
|
3568 |
+
5moc
|
3569 |
+
1tom
|
3570 |
+
3ds6
|
3571 |
+
1lt6
|
3572 |
+
3eft
|
3573 |
+
2w8g
|
3574 |
+
4d1y
|
3575 |
+
4yrc
|
3576 |
+
1tu6
|
3577 |
+
5hmh
|
3578 |
+
5nw2
|
3579 |
+
1k9r
|
3580 |
+
3mxf
|
3581 |
+
2q1j
|
3582 |
+
1u0h
|
3583 |
+
4ye3
|
3584 |
+
4k60
|
3585 |
+
5zop
|
3586 |
+
6htg
|
3587 |
+
2fx9
|
3588 |
+
4q83
|
3589 |
+
4y8y
|
3590 |
+
4gr0
|
3591 |
+
3uqf
|
3592 |
+
3vha
|
3593 |
+
2yaz
|
3594 |
+
1k1m
|
3595 |
+
4i2w
|
3596 |
+
5ovx
|
3597 |
+
3db6
|
3598 |
+
1v2p
|
3599 |
+
5njx
|
3600 |
+
1wtg
|
3601 |
+
3uvn
|
3602 |
+
3h89
|
3603 |
+
2q7y
|
3604 |
+
4o2f
|
3605 |
+
3fv1
|
3606 |
+
4eu3
|
3607 |
+
3pwm
|
3608 |
+
4tmp
|
3609 |
+
5ulp
|
3610 |
+
6di1
|
3611 |
+
4iks
|
3612 |
+
4dhs
|
3613 |
+
5hg8
|
3614 |
+
6b1x
|
3615 |
+
5nw8
|
3616 |
+
3tjd
|
3617 |
+
5yve
|
3618 |
+
4uwg
|
3619 |
+
1jd5
|
3620 |
+
5km5
|
3621 |
+
2w4x
|
3622 |
+
3umx
|
3623 |
+
2ony
|
3624 |
+
1bm2
|
3625 |
+
4pku
|
3626 |
+
2pj9
|
3627 |
+
2m41
|
3628 |
+
4z8a
|
3629 |
+
2yjq
|
3630 |
+
6mwe
|
3631 |
+
1prl
|
3632 |
+
5y1y
|
3633 |
+
1c5y
|
3634 |
+
5ak6
|
3635 |
+
1ggn
|
3636 |
+
2usn
|
3637 |
+
2pv2
|
3638 |
+
1w25
|
3639 |
+
1c4u
|
3640 |
+
4ba3
|
3641 |
+
6c2x
|
3642 |
+
4ijl
|
3643 |
+
3gxy
|
3644 |
+
3f3u
|
3645 |
+
4io2
|
3646 |
+
4drm
|
3647 |
+
3cjo
|
3648 |
+
4dst
|
3649 |
+
5c87
|
3650 |
+
5ni8
|
3651 |
+
2ll7
|
3652 |
+
2pem
|
3653 |
+
2x7d
|
3654 |
+
3zc6
|
3655 |
+
1m2q
|
3656 |
+
4gk2
|
3657 |
+
3lqi
|
3658 |
+
3c1x
|
3659 |
+
2az9
|
3660 |
+
1fv0
|
3661 |
+
1gz3
|
3662 |
+
1gfy
|
3663 |
+
5mte
|
3664 |
+
2nxm
|
3665 |
+
4yml
|
3666 |
+
4yog
|
3667 |
+
2g6q
|
3668 |
+
1t79
|
3669 |
+
3hdk
|
3670 |
+
3uij
|
3671 |
+
5vl2
|
3672 |
+
4ufk
|
3673 |
+
4aph
|
3674 |
+
6d1u
|
3675 |
+
4rn2
|
3676 |
+
1zxv
|
3677 |
+
2p4i
|
3678 |
+
1w80
|
3679 |
+
3bl7
|
3680 |
+
2vh0
|
3681 |
+
3kqa
|
3682 |
+
5vdu
|
3683 |
+
4b2d
|
3684 |
+
5jgi
|
3685 |
+
4u0i
|
3686 |
+
3g9n
|
3687 |
+
5var
|
3688 |
+
4lnf
|
3689 |
+
3e9h
|
3690 |
+
2fzz
|
3691 |
+
3cfv
|
3692 |
+
1ws4
|
3693 |
+
5h21
|
3694 |
+
2p7z
|
3695 |
+
4j8s
|
3696 |
+
5fdr
|
3697 |
+
5z7b
|
3698 |
+
6cj1
|
3699 |
+
5tts
|
3700 |
+
6bmx
|
3701 |
+
1g49
|
3702 |
+
1mqd
|
3703 |
+
5ost
|
3704 |
+
2qhd
|
3705 |
+
6e4a
|
3706 |
+
3fur
|
3707 |
+
3v1r
|
3708 |
+
4wwn
|
3709 |
+
4hni
|
3710 |
+
6e83
|
3711 |
+
1gqs
|
3712 |
+
3eko
|
3713 |
+
1dmp
|
3714 |
+
2wnj
|
3715 |
+
4i6q
|
3716 |
+
4d8s
|
3717 |
+
2jb5
|
3718 |
+
4p58
|
3719 |
+
4usj
|
3720 |
+
6eq6
|
3721 |
+
3o0j
|
3722 |
+
5apj
|
3723 |
+
4ty1
|
3724 |
+
5avf
|
3725 |
+
2xef
|
3726 |
+
1way
|
3727 |
+
1a7c
|
3728 |
+
5f2r
|
3729 |
+
5k1f
|
3730 |
+
2c9d
|
3731 |
+
3a9i
|
3732 |
+
3deh
|
3733 |
+
3q3k
|
3734 |
+
4xtw
|
3735 |
+
6f0y
|
3736 |
+
2r3l
|
3737 |
+
4mra
|
3738 |
+
5qa4
|
3739 |
+
4zpg
|
3740 |
+
4ijp
|
3741 |
+
3wyx
|
3742 |
+
1s5z
|
3743 |
+
1y2h
|
3744 |
+
3qi1
|
3745 |
+
1c83
|
3746 |
+
5dts
|
3747 |
+
5e1d
|
3748 |
+
5j9k
|
3749 |
+
5o4f
|
3750 |
+
2wxi
|
3751 |
+
5f04
|
3752 |
+
2qmj
|
3753 |
+
3kvx
|
3754 |
+
4l7j
|
3755 |
+
1d5r
|
3756 |
+
2vyt
|
3757 |
+
4cfv
|
3758 |
+
1qcp
|
3759 |
+
4hlm
|
3760 |
+
5d48
|
3761 |
+
3snl
|
3762 |
+
5uwn
|
3763 |
+
4yll
|
3764 |
+
2brm
|
3765 |
+
4dzw
|
3766 |
+
4q7v
|
3767 |
+
5teh
|
3768 |
+
1c4y
|
3769 |
+
5mro
|
3770 |
+
4ymg
|
3771 |
+
3b1u
|
3772 |
+
2z9g
|
3773 |
+
2rt5
|
3774 |
+
3gxz
|
3775 |
+
6e0q
|
3776 |
+
6f7b
|
3777 |
+
4qz5
|
3778 |
+
5dh5
|
3779 |
+
3v3q
|
3780 |
+
4do5
|
3781 |
+
3k0h
|
3782 |
+
5dt2
|
3783 |
+
3l54
|
3784 |
+
3ebh
|
3785 |
+
2hd6
|
3786 |
+
5hbe
|
3787 |
+
4wri
|
3788 |
+
2qi7
|
3789 |
+
1jao
|
3790 |
+
5ajp
|
3791 |
+
6ej3
|
3792 |
+
3gjq
|
3793 |
+
6f8w
|
3794 |
+
5y20
|
3795 |
+
1rwx
|
3796 |
+
4ibj
|
3797 |
+
5op2
|
3798 |
+
3c6u
|
3799 |
+
2w0s
|
3800 |
+
1c7e
|
3801 |
+
5yyb
|
3802 |
+
3ni5
|
3803 |
+
3t8w
|
3804 |
+
5ntp
|
3805 |
+
4dfu
|
3806 |
+
1o4e
|
3807 |
+
5tqu
|
3808 |
+
2xyd
|
3809 |
+
4pl0
|
3810 |
+
5tl9
|
3811 |
+
2vpo
|
3812 |
+
4ov5
|
3813 |
+
4qps
|
3814 |
+
5wdc
|
3815 |
+
4awp
|
3816 |
+
4a9s
|
3817 |
+
3atk
|
3818 |
+
4nja
|
3819 |
+
4ms0
|
3820 |
+
3fzr
|
3821 |
+
1i9m
|
3822 |
+
4b5s
|
3823 |
+
2y71
|
3824 |
+
3f33
|
3825 |
+
5q0h
|
3826 |
+
5x9p
|
3827 |
+
4p4j
|
3828 |
+
5ajo
|
3829 |
+
3c56
|
3830 |
+
4pnl
|
3831 |
+
4fmu
|
3832 |
+
3uli
|
3833 |
+
5nlk
|
3834 |
+
4cs9
|
3835 |
+
6hkz
|
3836 |
+
2vo5
|
3837 |
+
2fts
|
3838 |
+
3sfc
|
3839 |
+
3pke
|
3840 |
+
4dk5
|
3841 |
+
1lor
|
3842 |
+
2jdn
|
3843 |
+
3jya
|
3844 |
+
6bqg
|
3845 |
+
3p9t
|
3846 |
+
3qkk
|
3847 |
+
6fnj
|
3848 |
+
6fmc
|
3849 |
+
5c0k
|
3850 |
+
1mmq
|
3851 |
+
4fck
|
3852 |
+
5npe
|
3853 |
+
4j59
|
3854 |
+
4eol
|
3855 |
+
5m57
|
3856 |
+
4efk
|
3857 |
+
3bt9
|
3858 |
+
1oiq
|
3859 |
+
5dwr
|
3860 |
+
3wyk
|
3861 |
+
4qf9
|
3862 |
+
4c5w
|
3863 |
+
5tuq
|
3864 |
+
3oqk
|
3865 |
+
4xj0
|
3866 |
+
5mwg
|
3867 |
+
2vwu
|
3868 |
+
6dpy
|
3869 |
+
4ara
|
3870 |
+
3wi6
|
3871 |
+
5owf
|
3872 |
+
3nw5
|
3873 |
+
4fhh
|
3874 |
+
3sna
|
3875 |
+
1uye
|
3876 |
+
2vcg
|
3877 |
+
5j7j
|
3878 |
+
4gtt
|
3879 |
+
5jc1
|
3880 |
+
2ph6
|
3881 |
+
4zpe
|
3882 |
+
2hz0
|
3883 |
+
5l4i
|
3884 |
+
1y1m
|
3885 |
+
5vo1
|
3886 |
+
4y2v
|
3887 |
+
1ecq
|
3888 |
+
6eeo
|
3889 |
+
5jrs
|
3890 |
+
4l23
|
3891 |
+
6f34
|
3892 |
+
4r4q
|
3893 |
+
4quo
|
3894 |
+
6dq6
|
3895 |
+
4e3k
|
3896 |
+
3zov
|
3897 |
+
1cet
|
3898 |
+
5e2k
|
3899 |
+
5jyy
|
3900 |
+
2jld
|
3901 |
+
5jna
|
3902 |
+
4qls
|
3903 |
+
4ksq
|
3904 |
+
4py4
|
3905 |
+
6biy
|
3906 |
+
2hqu
|
3907 |
+
4yk5
|
3908 |
+
4i12
|
3909 |
+
4km0
|
3910 |
+
5ttu
|
3911 |
+
2za3
|
3912 |
+
4o5g
|
3913 |
+
2y1g
|
3914 |
+
4cff
|
3915 |
+
4ztr
|
3916 |
+
4jps
|
3917 |
+
4uin
|
3918 |
+
2q93
|
3919 |
+
2x7t
|
3920 |
+
2q6c
|
3921 |
+
6ayr
|
3922 |
+
1pwy
|
3923 |
+
5lwe
|
3924 |
+
5cxi
|
3925 |
+
4n9b
|
3926 |
+
1fzo
|
3927 |
+
5ukm
|
3928 |
+
1ork
|
3929 |
+
4mk0
|
3930 |
+
1jbd
|
3931 |
+
1k2i
|
3932 |
+
4ifh
|
3933 |
+
4yh4
|
3934 |
+
3fee
|
3935 |
+
1flm
|
3936 |
+
5tqe
|
3937 |
+
1jj9
|
3938 |
+
4li5
|
3939 |
+
4jc1
|
3940 |
+
5i8p
|
3941 |
+
1lah
|
3942 |
+
1apw
|
3943 |
+
3ppm
|
3944 |
+
4kn7
|
3945 |
+
1m5w
|
3946 |
+
3vbx
|
3947 |
+
4ie2
|
3948 |
+
3sur
|
3949 |
+
1nz7
|
3950 |
+
4trw
|
3951 |
+
4qmu
|
3952 |
+
4qnu
|
3953 |
+
4os6
|
3954 |
+
2bge
|
3955 |
+
5xvg
|
3956 |
+
4o6w
|
3957 |
+
1nfu
|
3958 |
+
2zjf
|
3959 |
+
1fpi
|
3960 |
+
5id1
|
3961 |
+
3ccz
|
3962 |
+
2d3u
|
3963 |
+
5tyj
|
3964 |
+
1fls
|
3965 |
+
1ggd
|
3966 |
+
5ofx
|
3967 |
+
4o12
|
3968 |
+
4wf4
|
3969 |
+
3pck
|
3970 |
+
4ayv
|
3971 |
+
5jt9
|
3972 |
+
5nb7
|
3973 |
+
4b84
|
3974 |
+
5ggk
|
3975 |
+
6h5x
|
3976 |
+
1r5w
|
3977 |
+
4zw6
|
3978 |
+
5d6j
|
3979 |
+
5ep7
|
3980 |
+
4duh
|
3981 |
+
4ps0
|
3982 |
+
4drk
|
3983 |
+
1los
|
3984 |
+
3s6t
|
3985 |
+
3be9
|
3986 |
+
4ipi
|
3987 |
+
3wf7
|
3988 |
+
4pow
|
3989 |
+
4y46
|
3990 |
+
5izj
|
3991 |
+
1d4j
|
3992 |
+
4qg7
|
3993 |
+
2avm
|
3994 |
+
1g85
|
3995 |
+
1r1i
|
3996 |
+
3g1v
|
3997 |
+
3l7c
|
3998 |
+
5wyr
|
3999 |
+
4oti
|
4000 |
+
4a4o
|
4001 |
+
1fvv
|
4002 |
+
3uok
|
4003 |
+
5n3v
|
4004 |
+
4tim
|
4005 |
+
3tv8
|
4006 |
+
4a4g
|
4007 |
+
6c0s
|
4008 |
+
4fak
|
4009 |
+
1w12
|
4010 |
+
4jn2
|
4011 |
+
4oyp
|
4012 |
+
4zt7
|
4013 |
+
5emj
|
4014 |
+
2rc8
|
4015 |
+
2ypo
|
4016 |
+
3kmc
|
4017 |
+
4hwp
|
4018 |
+
3q2j
|
4019 |
+
4k5l
|
4020 |
+
3hwn
|
4021 |
+
5i83
|
4022 |
+
1j4r
|
4023 |
+
4fyh
|
4024 |
+
1kfy
|
4025 |
+
5g43
|
4026 |
+
4bnv
|
4027 |
+
5fpu
|
4028 |
+
1o48
|
4029 |
+
6ei4
|
4030 |
+
6ekd
|
4031 |
+
2k3w
|
4032 |
+
3ksq
|
4033 |
+
5wkl
|
4034 |
+
4hzz
|
4035 |
+
2f8g
|
4036 |
+
2uw3
|
4037 |
+
6mi6
|
4038 |
+
4u91
|
4039 |
+
3f7u
|
4040 |
+
3zk6
|
4041 |
+
5n2f
|
4042 |
+
2qx0
|
4043 |
+
3mrt
|
4044 |
+
2f0z
|
4045 |
+
3qvv
|
4046 |
+
1l7x
|
4047 |
+
2oc1
|
4048 |
+
3gbe
|
4049 |
+
5he3
|
4050 |
+
1pun
|
4051 |
+
5m4i
|
4052 |
+
3pp7
|
4053 |
+
5o91
|
4054 |
+
4mjo
|
4055 |
+
4fns
|
4056 |
+
4xnv
|
4057 |
+
3tay
|
4058 |
+
3ejs
|
4059 |
+
4c1w
|
4060 |
+
3njq
|
4061 |
+
6guc
|
4062 |
+
4dv8
|
4063 |
+
4el9
|
4064 |
+
1iep
|
4065 |
+
1ta2
|
4066 |
+
3h0e
|
4067 |
+
1bsk
|
4068 |
+
4pri
|
4069 |
+
3pcb
|
4070 |
+
4jg8
|
4071 |
+
3lbj
|
4072 |
+
1i8h
|
4073 |
+
4a4x
|
4074 |
+
1lhd
|
4075 |
+
2wa3
|
4076 |
+
5tcy
|
4077 |
+
3wth
|
4078 |
+
4baq
|
4079 |
+
1ylv
|
4080 |
+
5bve
|
4081 |
+
4g34
|
4082 |
+
5u28
|
4083 |
+
1qbv
|
4084 |
+
5z5f
|
4085 |
+
4ot6
|
4086 |
+
2g97
|
4087 |
+
5n16
|
4088 |
+
1m5e
|
4089 |
+
3efk
|
4090 |
+
4h7q
|
4091 |
+
2v5a
|
4092 |
+
5vs6
|
4093 |
+
2cne
|
4094 |
+
1pxn
|
4095 |
+
1jqy
|
4096 |
+
5j6s
|
4097 |
+
4abv
|
4098 |
+
6d6t
|
4099 |
+
1t4s
|
4100 |
+
3zsx
|
4101 |
+
1p01
|
4102 |
+
2f4j
|
4103 |
+
2gh7
|
4104 |
+
3f78
|
4105 |
+
5i38
|
4106 |
+
3h0w
|
4107 |
+
5d3x
|
4108 |
+
3zst
|
4109 |
+
2lbm
|
4110 |
+
6fil
|
4111 |
+
2vk2
|
4112 |
+
6ew7
|
4113 |
+
2iu0
|
4114 |
+
3t0l
|
4115 |
+
5ai9
|
4116 |
+
5wbm
|
4117 |
+
4ark
|
4118 |
+
3hlo
|
4119 |
+
1np0
|
4120 |
+
2w6c
|
4121 |
+
6dk1
|
4122 |
+
5xih
|
4123 |
+
5hk2
|
4124 |
+
1qhc
|
4125 |
+
3v5l
|
4126 |
+
1vr1
|
4127 |
+
4no8
|
4128 |
+
5hmy
|
4129 |
+
2jql
|
4130 |
+
1a46
|
4131 |
+
3kf7
|
4132 |
+
4lv4
|
4133 |
+
5hbh
|
4134 |
+
3wf9
|
4135 |
+
4ieh
|
4136 |
+
2vr3
|
4137 |
+
5dyw
|
4138 |
+
4xuz
|
4139 |
+
1mmr
|
4140 |
+
5ar0
|
4141 |
+
4h4b
|
4142 |
+
5knj
|
4143 |
+
5elv
|
4144 |
+
2g79
|
4145 |
+
4w52
|
4146 |
+
2rnx
|
4147 |
+
4rgd
|
4148 |
+
2az8
|
4149 |
+
3c1k
|
4150 |
+
5ick
|
4151 |
+
4lv3
|
4152 |
+
4mwb
|
4153 |
+
5a83
|
4154 |
+
1prm
|
4155 |
+
4gg5
|
4156 |
+
1rlq
|
4157 |
+
1rq2
|
4158 |
+
5fbn
|
4159 |
+
4e49
|
4160 |
+
1f47
|
4161 |
+
4yfi
|
4162 |
+
2v10
|
4163 |
+
3pa3
|
4164 |
+
4j1f
|
4165 |
+
4jvi
|
4166 |
+
4gmy
|
4167 |
+
2v3d
|
4168 |
+
4cft
|
4169 |
+
1epp
|
4170 |
+
2hoc
|
4171 |
+
4r5g
|
4172 |
+
4k0y
|
4173 |
+
5zz2
|
4174 |
+
1d3p
|
4175 |
+
4ng9
|
4176 |
+
6fav
|
4177 |
+
5hor
|
4178 |
+
3qci
|
4179 |
+
4mbp
|
4180 |
+
4msu
|
4181 |
+
5hg1
|
4182 |
+
1pyn
|
4183 |
+
1hmt
|
4184 |
+
2lpr
|
4185 |
+
4yha
|
4186 |
+
5hoa
|
4187 |
+
1sln
|
4188 |
+
4h3c
|
4189 |
+
4k64
|
4190 |
+
2w0d
|
4191 |
+
4lmu
|
4192 |
+
3tf6
|
4193 |
+
4z2p
|
4194 |
+
2hny
|
4195 |
+
5ctc
|
4196 |
+
6cck
|
4197 |
+
5vd1
|
4198 |
+
3qcf
|
4199 |
+
5ia0
|
4200 |
+
3l7g
|
4201 |
+
1eld
|
4202 |
+
1xh9
|
4203 |
+
1h3c
|
4204 |
+
4urm
|
4205 |
+
4j7i
|
4206 |
+
4ly9
|
4207 |
+
1nu1
|
4208 |
+
5sz5
|
4209 |
+
6cdl
|
4210 |
+
1uvu
|
4211 |
+
2wl4
|
4212 |
+
4eo4
|
4213 |
+
5lj2
|
4214 |
+
2qrl
|
4215 |
+
3kc1
|
4216 |
+
5nqe
|
4217 |
+
6gon
|
4218 |
+
2xs8
|
4219 |
+
5gmj
|
4220 |
+
5eyd
|
4221 |
+
6c42
|
4222 |
+
4wks
|
4223 |
+
3ka2
|
4224 |
+
4p6e
|
4225 |
+
4nnn
|
4226 |
+
3zvw
|
4227 |
+
4q6r
|
4228 |
+
5v8v
|
4229 |
+
2jdv
|
4230 |
+
4lxm
|
4231 |
+
5qcm
|
4232 |
+
5e8f
|
4233 |
+
5y80
|
4234 |
+
3ud5
|
4235 |
+
4n70
|
4236 |
+
1jwt
|
4237 |
+
4cgi
|
4238 |
+
2uw8
|
4239 |
+
4ajw
|
4240 |
+
4ivb
|
4241 |
+
4m6u
|
4242 |
+
2xu1
|
4243 |
+
6bxy
|
4244 |
+
4ud7
|
4245 |
+
3k5f
|
4246 |
+
2arm
|
4247 |
+
5jin
|
4248 |
+
3fmq
|
4249 |
+
2nt7
|
4250 |
+
1p4r
|
4251 |
+
3hxf
|
4252 |
+
4zwx
|
4253 |
+
4xx3
|
4254 |
+
4yee
|
4255 |
+
6aak
|
4256 |
+
2xae
|
4257 |
+
5t31
|
4258 |
+
3bhb
|
4259 |
+
5llh
|
4260 |
+
5nge
|
4261 |
+
4b9h
|
4262 |
+
5oxl
|
4263 |
+
5ipa
|
4264 |
+
1q3w
|
4265 |
+
6d56
|
4266 |
+
6df1
|
4267 |
+
3ole
|
4268 |
+
2v16
|
4269 |
+
3g2s
|
4270 |
+
4led
|
4271 |
+
2uz6
|
4272 |
+
4pnu
|
4273 |
+
3nrz
|
4274 |
+
1f7b
|
4275 |
+
1j4k
|
4276 |
+
5ku9
|
4277 |
+
1a4g
|
4278 |
+
4uia
|
4279 |
+
5kv8
|
4280 |
+
2rke
|
4281 |
+
4e8z
|
4282 |
+
5ykp
|
4283 |
+
4z1n
|
4284 |
+
5sz1
|
4285 |
+
4oak
|
4286 |
+
3twu
|
4287 |
+
2r3p
|
4288 |
+
5cf6
|
4289 |
+
1ym4
|
4290 |
+
5l4j
|
4291 |
+
4exs
|
4292 |
+
4qpa
|
4293 |
+
2k1q
|
4294 |
+
4eny
|
4295 |
+
4i0r
|
4296 |
+
2xz5
|
4297 |
+
5fxq
|
4298 |
+
3re4
|
4299 |
+
6cf5
|
4300 |
+
2cbr
|
4301 |
+
5ece
|
4302 |
+
5t2t
|
4303 |
+
1x8r
|
4304 |
+
4n3w
|
4305 |
+
1klu
|
4306 |
+
5nxx
|
4307 |
+
5jcb
|
4308 |
+
5klt
|
4309 |
+
4usw
|
4310 |
+
5ek9
|
4311 |
+
2mov
|
4312 |
+
6bid
|
4313 |
+
1mjj
|
4314 |
+
1tlo
|
4315 |
+
2hb9
|
4316 |
+
2f94
|
4317 |
+
4luv
|
4318 |
+
5gu4
|
4319 |
+
3wf8
|
4320 |
+
5ufo
|
4321 |
+
4n5t
|
4322 |
+
5hcx
|
4323 |
+
5mtw
|
4324 |
+
1o38
|
4325 |
+
5z1c
|
4326 |
+
4w4z
|
4327 |
+
4v27
|
4328 |
+
1k21
|
4329 |
+
3jrx
|
4330 |
+
5l96
|
4331 |
+
1esz
|
4332 |
+
2m3m
|
4333 |
+
5ivf
|
4334 |
+
1o3p
|
4335 |
+
6std
|
4336 |
+
4auj
|
4337 |
+
2lyb
|
4338 |
+
2w87
|
4339 |
+
5j3l
|
4340 |
+
2fgu
|
4341 |
+
3snd
|
4342 |
+
2w5g
|
4343 |
+
2wsx
|
4344 |
+
4qfl
|
4345 |
+
2vuk
|
4346 |
+
4a23
|
4347 |
+
5iu6
|
4348 |
+
1siv
|
4349 |
+
4ht2
|
4350 |
+
2ltz
|
4351 |
+
1o39
|
4352 |
+
4p0w
|
4353 |
+
3p8p
|
4354 |
+
5ypy
|
4355 |
+
3zvt
|
4356 |
+
2c5y
|
4357 |
+
1ayv
|
4358 |
+
3erk
|
4359 |
+
6g4y
|
4360 |
+
4ucd
|
4361 |
+
3e16
|
4362 |
+
4i7p
|
4363 |
+
5alv
|
4364 |
+
1osg
|
4365 |
+
6gw1
|
4366 |
+
5wxg
|
4367 |
+
4bvb
|
4368 |
+
1nc1
|
4369 |
+
5ugg
|
4370 |
+
5t1w
|
4371 |
+
3tvw
|
4372 |
+
5hkb
|
4373 |
+
2r3n
|
4374 |
+
2iog
|
4375 |
+
1h1r
|
4376 |
+
5eyc
|
4377 |
+
1ogx
|
4378 |
+
3er3
|
4379 |
+
5q0p
|
4380 |
+
3rlq
|
4381 |
+
5itp
|
4382 |
+
4nuc
|
4383 |
+
4w9j
|
4384 |
+
2b8l
|
4385 |
+
5khj
|
4386 |
+
4mz4
|
4387 |
+
3zlv
|
4388 |
+
3okh
|
4389 |
+
2epn
|
4390 |
+
1pwq
|
4391 |
+
3gsm
|
4392 |
+
3hzv
|
4393 |
+
6dpx
|
4394 |
+
4hvg
|
4395 |
+
1s17
|
4396 |
+
6arm
|
4397 |
+
5jq7
|
4398 |
+
2v88
|
4399 |
+
5lay
|
4400 |
+
5nn4
|
4401 |
+
4hj2
|
4402 |
+
3pp0
|
4403 |
+
1rst
|
4404 |
+
3qcq
|
4405 |
+
3rx8
|
4406 |
+
5ewz
|
4407 |
+
5mgx
|
4408 |
+
4c1t
|
4409 |
+
3cso
|
4410 |
+
4wq2
|
4411 |
+
4gxl
|
4412 |
+
5isz
|
4413 |
+
2xj2
|
4414 |
+
4y5h
|
4415 |
+
3zcw
|
4416 |
+
1l8g
|
4417 |
+
5vex
|
4418 |
+
4tky
|
4419 |
+
4elh
|
4420 |
+
4ejn
|
4421 |
+
4pgh
|
4422 |
+
2wuf
|
4423 |
+
2xbp
|
4424 |
+
6gw4
|
4425 |
+
3d7g
|
4426 |
+
5ksu
|
4427 |
+
2qrp
|
4428 |
+
4jg6
|
4429 |
+
4eqf
|
4430 |
+
3hbo
|
4431 |
+
5yjy
|
4432 |
+
2gv7
|
4433 |
+
4hdf
|
4434 |
+
1yi3
|
4435 |
+
5edr
|
4436 |
+
5nmf
|
4437 |
+
4w7p
|
4438 |
+
4fz6
|
4439 |
+
1g4j
|
4440 |
+
4a2a
|
4441 |
+
5kx8
|
4442 |
+
5a0b
|
4443 |
+
4qta
|
4444 |
+
4mho
|
4445 |
+
4fn5
|
4446 |
+
1gj8
|
4447 |
+
3d94
|
4448 |
+
1kdw
|
4449 |
+
6euw
|
4450 |
+
6gpb
|
4451 |
+
6glb
|
4452 |
+
2xaq
|
4453 |
+
3vh9
|
4454 |
+
1aku
|
4455 |
+
5j4v
|
4456 |
+
2f1g
|
4457 |
+
2vfk
|
4458 |
+
2r5a
|
4459 |
+
1g1e
|
4460 |
+
3buf
|
4461 |
+
1bzj
|
4462 |
+
4abg
|
4463 |
+
3cho
|
4464 |
+
5t6j
|
4465 |
+
4jda
|
4466 |
+
5ywy
|
4467 |
+
6cdo
|
4468 |
+
6fo9
|
4469 |
+
1g74
|
4470 |
+
3oxi
|
4471 |
+
5t8p
|
4472 |
+
3pcu
|
4473 |
+
1fyr
|
4474 |
+
1fm9
|
4475 |
+
5ddc
|
4476 |
+
5hwu
|
4477 |
+
1xud
|
4478 |
+
5ai1
|
4479 |
+
4e9u
|
4480 |
+
4uyn
|
4481 |
+
5k05
|
4482 |
+
6fgl
|
4483 |
+
5iha
|
4484 |
+
4aa2
|
4485 |
+
1wzy
|
4486 |
+
2w85
|
4487 |
+
3s2v
|
4488 |
+
4yuy
|
4489 |
+
6dud
|
4490 |
+
1xdg
|
4491 |
+
3bgs
|
4492 |
+
4hiq
|
4493 |
+
3rqf
|
4494 |
+
1jmg
|
4495 |
+
2xeg
|
4496 |
+
4g93
|
4497 |
+
6c7b
|
4498 |
+
3zso
|
4499 |
+
4xjt
|
4500 |
+
4rsc
|
4501 |
+
5q0u
|
4502 |
+
5iyv
|
4503 |
+
1qxy
|
4504 |
+
5n20
|
4505 |
+
1you
|
4506 |
+
5c7e
|
4507 |
+
4x9v
|
4508 |
+
5tjx
|
4509 |
+
3rtm
|
4510 |
+
4b05
|
4511 |
+
3tg5
|
4512 |
+
1b52
|
4513 |
+
1w1v
|
4514 |
+
5lg3
|
4515 |
+
2bmg
|
4516 |
+
5wii
|
4517 |
+
5wew
|
4518 |
+
5iua
|
4519 |
+
2g00
|
4520 |
+
1nm6
|
4521 |
+
4wef
|
4522 |
+
1i7m
|
4523 |
+
4hrc
|
4524 |
+
6at0
|
4525 |
+
1biw
|
4526 |
+
4uhg
|
4527 |
+
5hvp
|
4528 |
+
1ugy
|
4529 |
+
3ery
|
4530 |
+
5ll4
|
4531 |
+
5v6y
|
4532 |
+
1ru1
|
4533 |
+
2o4l
|
4534 |
+
2evo
|
4535 |
+
5lvn
|
4536 |
+
2rc9
|
4537 |
+
2fci
|
4538 |
+
6evq
|
4539 |
+
3rah
|
4540 |
+
3g2v
|
4541 |
+
5ny1
|
4542 |
+
1p10
|
4543 |
+
3o96
|
4544 |
+
5vsd
|
4545 |
+
4cxx
|
4546 |
+
5kcb
|
4547 |
+
4g2l
|
4548 |
+
5vqi
|
4549 |
+
5svl
|
4550 |
+
5qax
|
4551 |
+
5h6v
|
4552 |
+
4aa0
|
4553 |
+
6g1w
|
4554 |
+
3ddu
|
4555 |
+
1pzi
|
4556 |
+
3sax
|
4557 |
+
4nmr
|
4558 |
+
4c1f
|
4559 |
+
5d26
|
4560 |
+
1elr
|
4561 |
+
3gc7
|
4562 |
+
3c84
|
4563 |
+
2y1d
|
4564 |
+
3vd4
|
4565 |
+
2uzo
|
4566 |
+
3v8s
|
4567 |
+
5mqv
|
4568 |
+
4zly
|
4569 |
+
4p0a
|
4570 |
+
5dlv
|
4571 |
+
3qqa
|
4572 |
+
4g3g
|
4573 |
+
3h9f
|
4574 |
+
4wr8
|
4575 |
+
5win
|
4576 |
+
4hzm
|
4577 |
+
3rqe
|
4578 |
+
4j1c
|
4579 |
+
4kii
|
4580 |
+
5mw6
|
4581 |
+
5mwj
|
4582 |
+
1xap
|
4583 |
+
4zv2
|
4584 |
+
1ol1
|
4585 |
+
1a69
|
4586 |
+
4btt
|
4587 |
+
5t4h
|
4588 |
+
2oi2
|
4589 |
+
6bbs
|
4590 |
+
6aaj
|
4591 |
+
2y4a
|
4592 |
+
5i80
|
4593 |
+
1hte
|
4594 |
+
6cfd
|
4595 |
+
1o4l
|
4596 |
+
5kbe
|
4597 |
+
3saz
|
4598 |
+
3kqr
|
4599 |
+
2b07
|
4600 |
+
3iue
|
4601 |
+
3bxf
|
4602 |
+
1is0
|
4603 |
+
5a4t
|
4604 |
+
5ktu
|
4605 |
+
4agd
|
4606 |
+
3nf8
|
4607 |
+
2nd0
|
4608 |
+
5yyz
|
4609 |
+
2ay4
|
4610 |
+
6fhq
|
4611 |
+
3f3t
|
4612 |
+
1zhl
|
4613 |
+
3vbv
|
4614 |
+
1g9s
|
4615 |
+
5aut
|
4616 |
+
4u71
|
4617 |
+
1q66
|
4618 |
+
5vb9
|
4619 |
+
3qtr
|
4620 |
+
4nw2
|
4621 |
+
3qin
|
4622 |
+
5mzg
|
4623 |
+
1d9i
|
4624 |
+
5h08
|
4625 |
+
3rv7
|
4626 |
+
3rv8
|
4627 |
+
6ckx
|
4628 |
+
2itk
|
4629 |
+
4ij1
|
4630 |
+
1pxo
|
4631 |
+
5nt0
|
4632 |
+
5x62
|
4633 |
+
4oc4
|
4634 |
+
5qao
|
4635 |
+
3le9
|
4636 |
+
5dtr
|
4637 |
+
4a6s
|
4638 |
+
3bls
|
4639 |
+
1em6
|
4640 |
+
1pus
|
4641 |
+
3asx
|
4642 |
+
4lng
|
4643 |
+
3mvj
|
4644 |
+
4q3q
|
4645 |
+
3s9t
|
4646 |
+
4gfd
|
4647 |
+
2r8q
|
4648 |
+
5wqc
|
4649 |
+
3ri1
|
4650 |
+
5ih8
|
4651 |
+
6g6w
|
4652 |
+
3cjf
|
4653 |
+
6duh
|
4654 |
+
3shv
|
4655 |
+
4pda
|
4656 |
+
3cpb
|
4657 |
+
1bp0
|
4658 |
+
4lmn
|
4659 |
+
1zm6
|
4660 |
+
2kup
|
4661 |
+
3ij0
|
4662 |
+
6cz3
|
4663 |
+
3v3b
|
4664 |
+
3vru
|
4665 |
+
3arg
|
4666 |
+
2o64
|
4667 |
+
6ayi
|
4668 |
+
4qab
|
4669 |
+
4xu2
|
4670 |
+
5wzu
|
4671 |
+
4lh2
|
4672 |
+
1w6y
|
4673 |
+
5eis
|
4674 |
+
1czr
|
4675 |
+
5jzy
|
4676 |
+
4ejf
|
4677 |
+
4ufe
|
4678 |
+
5wqd
|
4679 |
+
5f0f
|
4680 |
+
4aw5
|
4681 |
+
3iqg
|
4682 |
+
4p90
|
4683 |
+
2ank
|
4684 |
+
4n1u
|
4685 |
+
6eku
|
4686 |
+
2h23
|
4687 |
+
1j5i
|
4688 |
+
2y7w
|
4689 |
+
5alj
|
4690 |
+
5jfr
|
4691 |
+
5eak
|
4692 |
+
2gfk
|
4693 |
+
3be2
|
4694 |
+
5hln
|
4695 |
+
5uc1
|
4696 |
+
3ax5
|
4697 |
+
4f3k
|
4698 |
+
5qb0
|
4699 |
+
4llj
|
4700 |
+
5ldk
|
4701 |
+
4eyr
|
4702 |
+
5v3x
|
4703 |
+
4fys
|
4704 |
+
4crl
|
4705 |
+
2zxd
|
4706 |
+
2etk
|
4707 |
+
3ddp
|
4708 |
+
4q0a
|
4709 |
+
3el0
|
4710 |
+
2ica
|
4711 |
+
4yv8
|
4712 |
+
4jin
|
4713 |
+
5enc
|
4714 |
+
1pb9
|
4715 |
+
5jur
|
4716 |
+
5n1z
|
4717 |
+
5ou2
|
4718 |
+
4y8d
|
4719 |
+
4gby
|
4720 |
+
5acw
|
4721 |
+
4r76
|
4722 |
+
5hrv
|
4723 |
+
2jt6
|
4724 |
+
4hhz
|
4725 |
+
3ocb
|
4726 |
+
4qxj
|
4727 |
+
5er5
|
4728 |
+
3hu2
|
4729 |
+
1v2l
|
4730 |
+
3dz5
|
4731 |
+
4j8b
|
4732 |
+
5vqs
|
4733 |
+
5khd
|
4734 |
+
5fho
|
4735 |
+
2f71
|
4736 |
+
3kdt
|
4737 |
+
5gmm
|
4738 |
+
3sd5
|
4739 |
+
5fck
|
4740 |
+
3q8h
|
4741 |
+
4h36
|
4742 |
+
6bm6
|
4743 |
+
4qmz
|
4744 |
+
4ks5
|
4745 |
+
4dew
|
4746 |
+
1nf8
|
4747 |
+
5ap0
|
4748 |
+
3s73
|
4749 |
+
6chp
|
4750 |
+
4r3b
|
4751 |
+
2oag
|
4752 |
+
2w06
|
4753 |
+
5j74
|
4754 |
+
2a2g
|
4755 |
+
4ju7
|
4756 |
+
3i81
|
4757 |
+
5aol
|
4758 |
+
1af2
|
4759 |
+
5hda
|
4760 |
+
3nu3
|
4761 |
+
6das
|
4762 |
+
1swp
|
4763 |
+
5njz
|
4764 |
+
1b74
|
4765 |
+
1sts
|
4766 |
+
2co0
|
4767 |
+
5od1
|
4768 |
+
3pab
|
4769 |
+
5u06
|
4770 |
+
2gnh
|
4771 |
+
3uig
|
4772 |
+
2uw5
|
4773 |
+
2vrx
|
4774 |
+
1ele
|
4775 |
+
3hp9
|
4776 |
+
3fqa
|
4777 |
+
4mh7
|
4778 |
+
2xkc
|
4779 |
+
2w3l
|
4780 |
+
5w73
|
4781 |
+
5hip
|
4782 |
+
4xv2
|
4783 |
+
1fch
|
4784 |
+
2j4k
|
4785 |
+
1o33
|
4786 |
+
2v57
|
4787 |
+
1kqb
|
4788 |
+
1bhx
|
4789 |
+
4a4w
|
4790 |
+
5bmm
|
4791 |
+
3dcw
|
4792 |
+
4i9o
|
4793 |
+
4ydn
|
4794 |
+
5xii
|
4795 |
+
5duf
|
4796 |
+
5j1r
|
4797 |
+
4no1
|
4798 |
+
1gvu
|
4799 |
+
1ycm
|
4800 |
+
2l3r
|
4801 |
+
4wnp
|
4802 |
+
4yzn
|
4803 |
+
4p75
|
4804 |
+
1b1h
|
4805 |
+
5hwv
|
4806 |
+
1s4d
|
4807 |
+
3rlb
|
4808 |
+
1c5f
|
4809 |
+
4fqo
|
4810 |
+
1iau
|
4811 |
+
5mim
|
4812 |
+
5y93
|
4813 |
+
5qa6
|
4814 |
+
3wk5
|
4815 |
+
4mcb
|
4816 |
+
4qms
|
4817 |
+
6b5m
|
4818 |
+
6fba
|
4819 |
+
2q8z
|
4820 |
+
3r92
|
4821 |
+
5mo0
|
4822 |
+
3wvm
|
4823 |
+
4qh8
|
4824 |
+
6dgz
|
4825 |
+
2w66
|
4826 |
+
2joa
|
4827 |
+
6gih
|
4828 |
+
5fqt
|
4829 |
+
2viw
|
4830 |
+
4o76
|
4831 |
+
2j83
|
4832 |
+
3cm2
|
4833 |
+
3ion
|
4834 |
+
4y2u
|
4835 |
+
3fhb
|
4836 |
+
2rip
|
4837 |
+
2q94
|
4838 |
+
6eiz
|
4839 |
+
3ieo
|
4840 |
+
1uyg
|
4841 |
+
1vsn
|
4842 |
+
5fnf
|
4843 |
+
2vgp
|
4844 |
+
2pk5
|
4845 |
+
2f6t
|
4846 |
+
1zfq
|
4847 |
+
5ypo
|
4848 |
+
2nnv
|
4849 |
+
4jvj
|
4850 |
+
2cej
|
4851 |
+
3hqw
|
4852 |
+
2boj
|
4853 |
+
2h21
|
4854 |
+
3bzi
|
4855 |
+
5ut6
|
4856 |
+
2toh
|
4857 |
+
5urm
|
4858 |
+
5ml8
|
4859 |
+
2qpu
|
4860 |
+
6f5u
|
4861 |
+
3t3y
|
4862 |
+
2zx5
|
4863 |
+
5alu
|
4864 |
+
2vxa
|
4865 |
+
1z4n
|
4866 |
+
1c8k
|
4867 |
+
4w53
|
4868 |
+
5cf8
|
4869 |
+
4hcz
|
4870 |
+
1jik
|
4871 |
+
4b81
|
4872 |
+
5y86
|
4873 |
+
5ul6
|
4874 |
+
5l2n
|
4875 |
+
3dhk
|
4876 |
+
5vio
|
4877 |
+
2piz
|
4878 |
+
3jyj
|
4879 |
+
5ly2
|
4880 |
+
6do4
|
4881 |
+
1v2s
|
4882 |
+
4ezo
|
4883 |
+
1iht
|
4884 |
+
3hl8
|
4885 |
+
4q1c
|
4886 |
+
3sk2
|
4887 |
+
2xjj
|
4888 |
+
6cdj
|
4889 |
+
4w4w
|
4890 |
+
1bm7
|
4891 |
+
5lca
|
4892 |
+
3rxf
|
4893 |
+
4q7w
|
4894 |
+
5ceq
|
4895 |
+
5aen
|
4896 |
+
3kjf
|
4897 |
+
2psj
|
4898 |
+
4avt
|
4899 |
+
5nxo
|
4900 |
+
3qn7
|
4901 |
+
1d6w
|
4902 |
+
5ory
|
4903 |
+
3ckr
|
4904 |
+
6eyz
|
4905 |
+
4lxa
|
4906 |
+
2chz
|
4907 |
+
6eqw
|
4908 |
+
3nzc
|
4909 |
+
5umw
|
4910 |
+
1ilh
|
4911 |
+
1o4j
|
4912 |
+
2pks
|
4913 |
+
6evp
|
4914 |
+
2wks
|
4915 |
+
2yc0
|
4916 |
+
4xy8
|
4917 |
+
2jg0
|
4918 |
+
1u33
|
4919 |
+
5iez
|
4920 |
+
2zxb
|
4921 |
+
2qnz
|
4922 |
+
5wfz
|
4923 |
+
3ob0
|
4924 |
+
1g36
|
4925 |
+
4at3
|
4926 |
+
3pd3
|
4927 |
+
5jjr
|
4928 |
+
6eo8
|
4929 |
+
4omc
|
4930 |
+
1k3t
|
4931 |
+
2vl8
|
4932 |
+
4y8x
|
4933 |
+
3l4t
|
4934 |
+
3s2a
|
4935 |
+
6f4x
|
4936 |
+
2qrm
|
4937 |
+
4u68
|
4938 |
+
4o3f
|
4939 |
+
4rpn
|
4940 |
+
2zns
|
4941 |
+
4zvi
|
4942 |
+
5ul1
|
4943 |
+
3fwv
|
4944 |
+
1exw
|
4945 |
+
2vvv
|
4946 |
+
2aof
|
4947 |
+
5vfd
|
4948 |
+
2qcf
|
4949 |
+
3bl0
|
4950 |
+
3gk1
|
4951 |
+
5i2i
|
4952 |
+
5w8v
|
4953 |
+
4ptc
|
4954 |
+
3piy
|
4955 |
+
1nlj
|
4956 |
+
4ddy
|
4957 |
+
2vwo
|
4958 |
+
3kdu
|
4959 |
+
6bt0
|
4960 |
+
5l99
|
4961 |
+
3rtn
|
4962 |
+
2yk1
|
4963 |
+
6f28
|
4964 |
+
1zh7
|
4965 |
+
5uiu
|
4966 |
+
4eh7
|
4967 |
+
5epp
|
4968 |
+
1o6h
|
4969 |
+
1b05
|
4970 |
+
5t5g
|
4971 |
+
6b1k
|
4972 |
+
4k75
|
4973 |
+
5hva
|
4974 |
+
3ips
|
4975 |
+
5obg
|
4976 |
+
5a3o
|
4977 |
+
2q89
|
4978 |
+
5owc
|
4979 |
+
5ggo
|
4980 |
+
4xk9
|
4981 |
+
3cf9
|
4982 |
+
1czl
|
4983 |
+
2ewy
|
4984 |
+
3a1e
|
4985 |
+
1xlz
|
4986 |
+
5k0b
|
4987 |
+
2nta
|
4988 |
+
4gvc
|
4989 |
+
1axr
|
4990 |
+
5fou
|
4991 |
+
1kkq
|
4992 |
+
4u7o
|
4993 |
+
5i4o
|
4994 |
+
4cwr
|
4995 |
+
5fa7
|
4996 |
+
1i5d
|
4997 |
+
5hdu
|
4998 |
+
2zg3
|
4999 |
+
2pmk
|
5000 |
+
3mrx
|
5001 |
+
3s1g
|
5002 |
+
6mvu
|
5003 |
+
1wkm
|
5004 |
+
6dvl
|
5005 |
+
5fe9
|
5006 |
+
5odx
|
5007 |
+
3sbh
|
5008 |
+
2jiw
|
5009 |
+
2r43
|
5010 |
+
4ibb
|
5011 |
+
4o05
|
5012 |
+
2v13
|
5013 |
+
4io8
|
5014 |
+
4z2h
|
5015 |
+
2vmc
|
5016 |
+
5ggn
|
5017 |
+
2afx
|
5018 |
+
1g3c
|
5019 |
+
2cn0
|
5020 |
+
3oki
|
5021 |
+
4xty
|
5022 |
+
1xgi
|
5023 |
+
3mmf
|
5024 |
+
5v1d
|
5025 |
+
2uxz
|
5026 |
+
4wwo
|
5027 |
+
4kpz
|
5028 |
+
4xbb
|
5029 |
+
5up0
|
5030 |
+
2gzl
|
5031 |
+
4r5x
|
5032 |
+
3iet
|
5033 |
+
1oq5
|
5034 |
+
6afd
|
5035 |
+
1b55
|
5036 |
+
6chl
|
5037 |
+
1xp0
|
5038 |
+
2q5k
|
5039 |
+
5ti7
|
5040 |
+
5uqx
|
5041 |
+
6bm5
|
5042 |
+
5w94
|
5043 |
+
1k1o
|
5044 |
+
4lm3
|
5045 |
+
1ek1
|
5046 |
+
4ayr
|
5047 |
+
2xxn
|
5048 |
+
5lsc
|
5049 |
+
1o0m
|
5050 |
+
4ui7
|
5051 |
+
1ppl
|
5052 |
+
6beh
|
5053 |
+
3ud7
|
5054 |
+
4zxx
|
5055 |
+
6gzh
|
5056 |
+
1uu9
|
5057 |
+
5jgq
|
5058 |
+
2q95
|
5059 |
+
5l2y
|
5060 |
+
3v3l
|
5061 |
+
2gmv
|
5062 |
+
5bvo
|
5063 |
+
3snb
|
5064 |
+
5q13
|
5065 |
+
5upf
|
5066 |
+
5tq3
|
5067 |
+
3gw5
|
5068 |
+
4wwp
|
5069 |
+
5wbo
|
5070 |
+
2j7g
|
5071 |
+
3rmf
|
5072 |
+
1fhd
|
5073 |
+
2w2u
|
5074 |
+
4flk
|
5075 |
+
2r0y
|
5076 |
+
2wbb
|
5077 |
+
3da6
|
5078 |
+
3l4z
|
5079 |
+
1v2w
|
5080 |
+
2azb
|
5081 |
+
2bz5
|
5082 |
+
2oxn
|
5083 |
+
3f8w
|
5084 |
+
1w7g
|
5085 |
+
3moh
|
5086 |
+
5m3a
|
5087 |
+
5aqq
|
5088 |
+
3tz0
|
5089 |
+
3zyu
|
5090 |
+
2pzy
|
5091 |
+
5usy
|
5092 |
+
4mx0
|
5093 |
+
4cpq
|
5094 |
+
4aq6
|
5095 |
+
5eld
|
5096 |
+
5gmv
|
5097 |
+
3qbn
|
5098 |
+
6rsa
|
5099 |
+
3u5j
|
5100 |
+
5h1t
|
5101 |
+
1ms0
|
5102 |
+
1ctr
|
5103 |
+
5lub
|
5104 |
+
4h5d
|
5105 |
+
4n99
|
5106 |
+
4cc2
|
5107 |
+
4hzw
|
5108 |
+
5lbq
|
5109 |
+
3ati
|
5110 |
+
3pd2
|
5111 |
+
1f74
|
5112 |
+
1qyg
|
5113 |
+
5dhg
|
5114 |
+
4mwx
|
5115 |
+
5ohy
|
5116 |
+
4ob2
|
5117 |
+
2b2v
|
5118 |
+
3c0z
|
5119 |
+
2gtv
|
5120 |
+
4r75
|
5121 |
+
5w2s
|
5122 |
+
3wsy
|
5123 |
+
1rs2
|
5124 |
+
2r6w
|
5125 |
+
4agn
|
5126 |
+
4gk4
|
5127 |
+
4qq5
|
5128 |
+
6bfa
|
5129 |
+
1n7t
|
5130 |
+
1ocn
|
5131 |
+
1gnj
|
5132 |
+
4u79
|
5133 |
+
3hmm
|
5134 |
+
2vl1
|
5135 |
+
1ec1
|
5136 |
+
5f4u
|
5137 |
+
2zsc
|
5138 |
+
4u5j
|
5139 |
+
4jfk
|
5140 |
+
5kew
|
5141 |
+
4btw
|
5142 |
+
2cbu
|
5143 |
+
1vkj
|
5144 |
+
4jnc
|
5145 |
+
1nli
|
5146 |
+
6bw3
|
5147 |
+
3fyk
|
5148 |
+
3cl2
|
5149 |
+
6f3i
|
5150 |
+
1w3l
|
5151 |
+
3gv9
|
5152 |
+
4h4e
|
5153 |
+
2ylc
|
5154 |
+
2fgi
|
5155 |
+
2ha5
|
5156 |
+
5sz9
|
5157 |
+
5gjg
|
5158 |
+
2q1q
|
5159 |
+
4aza
|
5160 |
+
5yia
|
5161 |
+
2rny
|
5162 |
+
1o30
|
5163 |
+
3m1k
|
5164 |
+
6dj5
|
5165 |
+
1pfu
|
5166 |
+
4awf
|
5167 |
+
5oqu
|
5168 |
+
4k42
|
5169 |
+
2wcg
|
5170 |
+
3oj8
|
5171 |
+
4ngs
|
5172 |
+
4lq9
|
5173 |
+
1jzs
|
5174 |
+
6g9h
|
5175 |
+
6g9u
|
5176 |
+
3axm
|
5177 |
+
4qp7
|
5178 |
+
4mma
|
5179 |
+
1g98
|
5180 |
+
5wi0
|
5181 |
+
5iep
|
5182 |
+
2opy
|
5183 |
+
6eq1
|
5184 |
+
2pri
|
5185 |
+
4y2j
|
5186 |
+
4x1s
|
5187 |
+
1bux
|
5188 |
+
4cjn
|
5189 |
+
2vnn
|
5190 |
+
5d2a
|
5191 |
+
6cms
|
5192 |
+
3g72
|
5193 |
+
4wz4
|
5194 |
+
2las
|
5195 |
+
4his
|
5196 |
+
5ohi
|
5197 |
+
1apv
|
5198 |
+
2v86
|
5199 |
+
5nap
|
5200 |
+
3wdc
|
5201 |
+
3d9m
|
5202 |
+
4kzl
|
5203 |
+
5ixf
|
5204 |
+
1fd7
|
5205 |
+
5f25
|
5206 |
+
5js3
|
5207 |
+
3d7h
|
5208 |
+
4ceb
|
5209 |
+
3dst
|
5210 |
+
4yym
|
5211 |
+
4x7n
|
5212 |
+
4cr5
|
5213 |
+
1gar
|
5214 |
+
4z2b
|
5215 |
+
3iph
|
5216 |
+
5t37
|
5217 |
+
3zqe
|
5218 |
+
6m9t
|
5219 |
+
3m54
|
5220 |
+
3szm
|
5221 |
+
2oxx
|
5222 |
+
4mlx
|
5223 |
+
3uxg
|
5224 |
+
3qri
|
5225 |
+
4l0v
|
5226 |
+
1a07
|
5227 |
+
5qay
|
5228 |
+
4cwo
|
5229 |
+
3r0y
|
5230 |
+
1wbs
|
5231 |
+
8gpb
|
5232 |
+
6bgz
|
5233 |
+
1ecv
|
5234 |
+
1ha2
|
5235 |
+
2kfx
|
5236 |
+
2be2
|
5237 |
+
6cjw
|
5238 |
+
2p94
|
5239 |
+
5tq7
|
5240 |
+
5fsc
|
5241 |
+
4btb
|
5242 |
+
5yov
|
5243 |
+
6eox
|
5244 |
+
5am2
|
5245 |
+
2pvm
|
5246 |
+
3gn7
|
5247 |
+
2ql7
|
5248 |
+
5j58
|
5249 |
+
1msm
|
5250 |
+
2bjm
|
5251 |
+
3rt8
|
5252 |
+
3ds3
|
5253 |
+
1m13
|
5254 |
+
4nxo
|
5255 |
+
2vj9
|
5256 |
+
3fqe
|
5257 |
+
2m0v
|
5258 |
+
3so9
|
5259 |
+
4r5b
|
5260 |
+
1v2j
|
5261 |
+
4bks
|
5262 |
+
4tkj
|
5263 |
+
1jld
|
5264 |
+
2ojf
|
5265 |
+
1z5m
|
5266 |
+
3m1s
|
5267 |
+
4lpf
|
5268 |
+
4zls
|
5269 |
+
4af3
|
5270 |
+
5eue
|
5271 |
+
2jh6
|
5272 |
+
2kvm
|
5273 |
+
5etl
|
5274 |
+
5hn0
|
5275 |
+
3f6g
|
5276 |
+
3fdm
|
5277 |
+
2jj3
|
5278 |
+
2zjw
|
5279 |
+
3sfh
|
5280 |
+
1ong
|
5281 |
+
1noi
|
5282 |
+
3cen
|
5283 |
+
2p4j
|
5284 |
+
4rvr
|
5285 |
+
4az5
|
5286 |
+
2wqp
|
5287 |
+
6fnt
|
5288 |
+
3ejt
|
5289 |
+
5c2h
|
5290 |
+
3sow
|
5291 |
+
3ml2
|
5292 |
+
1ld7
|
5293 |
+
1yz3
|
5294 |
+
3m2u
|
5295 |
+
2wcx
|
5296 |
+
1ec2
|
5297 |
+
3iqj
|
5298 |
+
3ccn
|
5299 |
+
3r1v
|
5300 |
+
5foo
|
5301 |
+
3cn0
|
5302 |
+
2z4w
|
5303 |
+
4ks1
|
5304 |
+
3rtf
|
5305 |
+
4bfr
|
5306 |
+
2pvk
|
5307 |
+
3ppr
|
5308 |
+
3r93
|
5309 |
+
4x9w
|
5310 |
+
2z7i
|
5311 |
+
4hdb
|
5312 |
+
4bti
|
5313 |
+
1eef
|
5314 |
+
6bln
|
5315 |
+
4wyy
|
5316 |
+
4bw3
|
5317 |
+
3mks
|
5318 |
+
3iit
|
5319 |
+
2axi
|
5320 |
+
4urz
|
5321 |
+
3q2a
|
5322 |
+
2w12
|
5323 |
+
3aho
|
5324 |
+
6e06
|
5325 |
+
5dy7
|
5326 |
+
1gi1
|
5327 |
+
3az8
|
5328 |
+
4ew2
|
5329 |
+
3tgs
|
5330 |
+
3zc5
|
5331 |
+
2ggx
|
5332 |
+
4ih3
|
5333 |
+
5u00
|
5334 |
+
4qkx
|
5335 |
+
4oef
|
5336 |
+
6gjn
|
5337 |
+
1ewj
|
5338 |
+
2xii
|
5339 |
+
5al2
|
5340 |
+
1o4p
|
5341 |
+
2xck
|
5342 |
+
3dcs
|
5343 |
+
2g0h
|
5344 |
+
5adr
|
5345 |
+
1kv1
|
5346 |
+
6h33
|
5347 |
+
2wl5
|
5348 |
+
6h3k
|
5349 |
+
1qq9
|
5350 |
+
5vdr
|
5351 |
+
5x4q
|
5352 |
+
2xk3
|
5353 |
+
3p4f
|
5354 |
+
5prc
|
5355 |
+
4gxs
|
5356 |
+
1qm5
|
5357 |
+
4aw8
|
5358 |
+
2eep
|
5359 |
+
5l15
|
5360 |
+
3tk2
|
5361 |
+
5heb
|
5362 |
+
5aia
|
5363 |
+
4nh9
|
5364 |
+
5nki
|
5365 |
+
3eos
|
5366 |
+
4m8y
|
5367 |
+
5u49
|
5368 |
+
5yh8
|
5369 |
+
5ylu
|
5370 |
+
6f8r
|
5371 |
+
3nxq
|
5372 |
+
2x3t
|
5373 |
+
5exl
|
5374 |
+
4x0z
|
5375 |
+
4rj6
|
5376 |
+
5ly1
|
5377 |
+
3zo4
|
5378 |
+
2nw4
|
5379 |
+
3upx
|
5380 |
+
5btv
|
5381 |
+
4n3r
|
5382 |
+
5ek0
|
5383 |
+
3otx
|
5384 |
+
4r4c
|
5385 |
+
1y3n
|
5386 |
+
5cal
|
5387 |
+
4dld
|
5388 |
+
5z89
|
5389 |
+
5sys
|
5390 |
+
1ybo
|
5391 |
+
2cmo
|
5392 |
+
1k3q
|
5393 |
+
2ima
|
5394 |
+
3wv2
|
5395 |
+
3caj
|
5396 |
+
3vv7
|
5397 |
+
1xug
|
5398 |
+
4l2k
|
5399 |
+
3aya
|
5400 |
+
3gs6
|
5401 |
+
5alg
|
5402 |
+
4b4n
|
5403 |
+
3zyr
|
5404 |
+
4hxm
|
5405 |
+
2ov4
|
5406 |
+
3n9s
|
5407 |
+
4n07
|
5408 |
+
2jnp
|
5409 |
+
3zxr
|
5410 |
+
3v7x
|
5411 |
+
1aid
|
5412 |
+
2zis
|
5413 |
+
4u8w
|
5414 |
+
6e2o
|
5415 |
+
5yqn
|
5416 |
+
3oc0
|
5417 |
+
4b1d
|
5418 |
+
3g9e
|
5419 |
+
4qw7
|
5420 |
+
1c1r
|
5421 |
+
1zsf
|
5422 |
+
2nm1
|
5423 |
+
3cs7
|
5424 |
+
2x24
|
5425 |
+
5d7c
|
5426 |
+
1bji
|
5427 |
+
4yl3
|
5428 |
+
4k78
|
5429 |
+
2f9u
|
5430 |
+
4kab
|
5431 |
+
3rl7
|
5432 |
+
4n8r
|
5433 |
+
5etu
|
5434 |
+
5drs
|
5435 |
+
6es0
|
5436 |
+
2g8n
|
5437 |
+
5ol3
|
5438 |
+
2i6a
|
5439 |
+
5gvk
|
5440 |
+
2qrk
|
5441 |
+
3sx4
|
5442 |
+
4q4r
|
5443 |
+
5nq5
|
5444 |
+
3ctt
|
5445 |
+
5kxc
|
5446 |
+
1tyr
|
5447 |
+
4j0z
|
5448 |
+
5z4h
|
5449 |
+
2uzn
|
5450 |
+
4oon
|
5451 |
+
2ohr
|
5452 |
+
4re4
|
5453 |
+
3prs
|
5454 |
+
1f8c
|
5455 |
+
4jvb
|
5456 |
+
3eig
|
5457 |
+
1dbk
|
5458 |
+
4p74
|
5459 |
+
4zg9
|
5460 |
+
3wtn
|
5461 |
+
3l7a
|
5462 |
+
4cdr
|
5463 |
+
4fli
|
5464 |
+
2am9
|
5465 |
+
2jkp
|
5466 |
+
2bts
|
5467 |
+
1u9q
|
5468 |
+
5ea6
|
5469 |
+
6db3
|
5470 |
+
4b6o
|
5471 |
+
3nnw
|
5472 |
+
3p5k
|
5473 |
+
2c4f
|
5474 |
+
1rbp
|
5475 |
+
2xuc
|
5476 |
+
4hvd
|
5477 |
+
3ijz
|
5478 |
+
5n4t
|
5479 |
+
4jr5
|
5480 |
+
6e9w
|
5481 |
+
5f63
|
5482 |
+
4cjq
|
5483 |
+
1b46
|
5484 |
+
4j4n
|
5485 |
+
4kcx
|
5486 |
+
2a2x
|
5487 |
+
4h3i
|
5488 |
+
4k4f
|
5489 |
+
6bky
|
5490 |
+
2bak
|
5491 |
+
5csd
|
5492 |
+
4mgc
|
5493 |
+
4mwv
|
5494 |
+
1mzs
|
5495 |
+
4ym2
|
5496 |
+
4ztm
|
5497 |
+
5epn
|
5498 |
+
5v7w
|
5499 |
+
5hes
|
5500 |
+
3n49
|
5501 |
+
2zlg
|
5502 |
+
2kbr
|
5503 |
+
5fng
|
5504 |
+
2fgv
|
5505 |
+
1f4e
|
5506 |
+
2gd8
|
5507 |
+
3g6h
|
5508 |
+
5u0f
|
5509 |
+
4j44
|
5510 |
+
5v35
|
5511 |
+
1c9d
|
5512 |
+
6g6y
|
5513 |
+
4azi
|
5514 |
+
5kpk
|
5515 |
+
4ui8
|
5516 |
+
1no9
|
5517 |
+
4p3h
|
5518 |
+
3gcs
|
5519 |
+
5ngu
|
5520 |
+
6bl1
|
5521 |
+
1q6j
|
5522 |
+
2zda
|
5523 |
+
3b27
|
5524 |
+
1o2j
|
5525 |
+
3u2k
|
5526 |
+
6mil
|
5527 |
+
1n7i
|
5528 |
+
2wec
|
5529 |
+
1h6h
|
5530 |
+
3owl
|
5531 |
+
3g34
|
5532 |
+
1ec9
|
5533 |
+
4crf
|
5534 |
+
3hha
|
5535 |
+
3qiy
|
5536 |
+
4dh6
|
5537 |
+
4pid
|
5538 |
+
2y55
|
5539 |
+
5hhx
|
5540 |
+
5etf
|
5541 |
+
4xar
|
5542 |
+
2pvu
|
5543 |
+
5ito
|
5544 |
+
1li3
|
5545 |
+
3dya
|
5546 |
+
1xsc
|
5547 |
+
3ti3
|
5548 |
+
1tze
|
5549 |
+
6fmf
|
5550 |
+
1di9
|
5551 |
+
2yke
|
5552 |
+
5f4p
|
5553 |
+
5sz7
|
5554 |
+
1m2p
|
5555 |
+
1uu8
|
5556 |
+
4y64
|
5557 |
+
3rt6
|
5558 |
+
3vs3
|
5559 |
+
3nfl
|
5560 |
+
4bdg
|
5561 |
+
5jv0
|
5562 |
+
3wd1
|
5563 |
+
4pge
|
5564 |
+
5cxz
|
5565 |
+
5ak4
|
5566 |
+
4mdt
|
5567 |
+
2j27
|
5568 |
+
4lte
|
5569 |
+
2ayr
|
5570 |
+
5m6f
|
5571 |
+
5dv4
|
5572 |
+
2qbu
|
5573 |
+
6ciy
|
5574 |
+
3ekq
|
5575 |
+
3c7q
|
5576 |
+
2osc
|
5577 |
+
4r6w
|
5578 |
+
2ph9
|
5579 |
+
3qkm
|
5580 |
+
3hhu
|
5581 |
+
4xqb
|
5582 |
+
5jr6
|
5583 |
+
2uwl
|
5584 |
+
5ezz
|
5585 |
+
1y3y
|
5586 |
+
1i8i
|
5587 |
+
3sxf
|
5588 |
+
2i7c
|
5589 |
+
4m1j
|
5590 |
+
6rnt
|
5591 |
+
3g5y
|
5592 |
+
3hwx
|
5593 |
+
2p83
|
5594 |
+
1mik
|
5595 |
+
1mrn
|
5596 |
+
1sm3
|
5597 |
+
3py1
|
5598 |
+
5fah
|
5599 |
+
4pnn
|
5600 |
+
3tza
|
5601 |
+
3zmp
|
5602 |
+
2wxl
|
5603 |
+
5qaz
|
5604 |
+
4odf
|
5605 |
+
1eix
|
5606 |
+
5b2d
|
5607 |
+
5kdr
|
5608 |
+
3hcm
|
5609 |
+
2x91
|
5610 |
+
3frg
|
5611 |
+
6gch
|
5612 |
+
4qz2
|
5613 |
+
1hvh
|
5614 |
+
1g3m
|
5615 |
+
1tnl
|
5616 |
+
3s7f
|
5617 |
+
6cpa
|
5618 |
+
6g0w
|
5619 |
+
6ffh
|
5620 |
+
3kec
|
5621 |
+
1nj5
|
5622 |
+
6afr
|
5623 |
+
5kup
|
5624 |
+
6ftn
|
5625 |
+
4o97
|
5626 |
+
2i5f
|
5627 |
+
5nzf
|
5628 |
+
2f89
|
5629 |
+
5fsn
|
5630 |
+
3nex
|
5631 |
+
6b2c
|
5632 |
+
4zt5
|
5633 |
+
3gt9
|
5634 |
+
3sud
|
5635 |
+
5btx
|
5636 |
+
4fab
|
5637 |
+
3fxb
|
5638 |
+
2x4z
|
5639 |
+
3l4x
|
5640 |
+
5svx
|
5641 |
+
5u98
|
5642 |
+
1oim
|
5643 |
+
3lpr
|
5644 |
+
4pqa
|
5645 |
+
4pnk
|
5646 |
+
4ogj
|
5647 |
+
5k0s
|
5648 |
+
4oba
|
5649 |
+
6h7m
|
5650 |
+
3aas
|
5651 |
+
4zae
|
5652 |
+
5u5t
|
5653 |
+
4n6h
|
5654 |
+
4dsy
|
5655 |
+
1ywh
|
5656 |
+
4w9o
|
5657 |
+
2qbp
|
5658 |
+
5d45
|
5659 |
+
5lhu
|
5660 |
+
2bro
|
5661 |
+
1uz4
|
5662 |
+
1ugx
|
5663 |
+
6avi
|
5664 |
+
2aox
|
5665 |
+
5nb6
|
5666 |
+
4he9
|
5667 |
+
2oz5
|
5668 |
+
5n24
|
5669 |
+
1h8l
|
5670 |
+
3pwd
|
5671 |
+
1it6
|
5672 |
+
4rvk
|
5673 |
+
6b27
|
5674 |
+
2qu5
|
5675 |
+
4x7j
|
5676 |
+
5tyo
|
5677 |
+
2ym3
|
5678 |
+
5mjn
|
5679 |
+
3h26
|
5680 |
+
5ufs
|
5681 |
+
2wj1
|
5682 |
+
1rt1
|
5683 |
+
1kz8
|
5684 |
+
2zbk
|
5685 |
+
4krs
|
5686 |
+
5j87
|
5687 |
+
3u3u
|
5688 |
+
3g1d
|
5689 |
+
5bms
|
5690 |
+
1u9w
|
5691 |
+
2z7g
|
5692 |
+
4xv1
|
5693 |
+
4ngm
|
5694 |
+
4j8t
|
5695 |
+
5d11
|
5696 |
+
5c11
|
5697 |
+
3f17
|
5698 |
+
4alw
|
5699 |
+
3q3b
|
5700 |
+
3rwd
|
5701 |
+
1c70
|
5702 |
+
3iiw
|
5703 |
+
1hww
|
5704 |
+
5kv9
|
5705 |
+
4wey
|
5706 |
+
4ok3
|
5707 |
+
2ctc
|
5708 |
+
4bcb
|
5709 |
+
6e8m
|
5710 |
+
3shy
|
5711 |
+
4mnw
|
5712 |
+
5ut0
|
5713 |
+
3lcd
|
5714 |
+
5yc3
|
5715 |
+
2vwz
|
5716 |
+
2xbx
|
5717 |
+
1o0o
|
5718 |
+
2vj1
|
5719 |
+
6b33
|
5720 |
+
4hnp
|
5721 |
+
1w70
|
5722 |
+
4bh3
|
5723 |
+
4gng
|
5724 |
+
2q8m
|
5725 |
+
4rrr
|
5726 |
+
4rqv
|
5727 |
+
1hih
|
5728 |
+
3u1i
|
5729 |
+
5ovr
|
5730 |
+
4ach
|
5731 |
+
6c0u
|
5732 |
+
4qiz
|
5733 |
+
4k18
|
5734 |
+
1e72
|
5735 |
+
4ocq
|
5736 |
+
1b11
|
5737 |
+
3gds
|
5738 |
+
3mwu
|
5739 |
+
5ivs
|
5740 |
+
3bux
|
5741 |
+
3qc4
|
5742 |
+
5ovc
|
5743 |
+
1pu7
|
5744 |
+
1y3w
|
5745 |
+
4v01
|
5746 |
+
6e7j
|
5747 |
+
1uu3
|
5748 |
+
5dh3
|
5749 |
+
3tu1
|
5750 |
+
4q3s
|
5751 |
+
4r5a
|
5752 |
+
4z16
|
5753 |
+
3uyr
|
5754 |
+
5wir
|
5755 |
+
4exg
|
5756 |
+
5kby
|
5757 |
+
4iur
|
5758 |
+
4zv1
|
5759 |
+
5xsu
|
5760 |
+
4gtp
|
5761 |
+
2o8h
|
5762 |
+
3wqw
|
5763 |
+
5th7
|
5764 |
+
5tv3
|
5765 |
+
1tfz
|
5766 |
+
2v3e
|
5767 |
+
5ntw
|
5768 |
+
3cyy
|
5769 |
+
1ny2
|
5770 |
+
4q6f
|
5771 |
+
2pjt
|
5772 |
+
5w7x
|
5773 |
+
5jap
|
5774 |
+
3b68
|
5775 |
+
5tyl
|
5776 |
+
2a4w
|
5777 |
+
2v00
|
5778 |
+
4nks
|
5779 |
+
1ets
|
5780 |
+
2fq6
|
5781 |
+
5hbs
|
5782 |
+
4r59
|
5783 |
+
2ama
|
5784 |
+
2web
|
5785 |
+
6e4t
|
5786 |
+
4xm6
|
5787 |
+
3bkl
|
5788 |
+
6fty
|
5789 |
+
5v0n
|
5790 |
+
6ge7
|
5791 |
+
2boh
|
5792 |
+
1ikt
|
5793 |
+
2r5d
|
5794 |
+
5alh
|
5795 |
+
5szc
|
5796 |
+
1cr6
|
5797 |
+
4zzy
|
5798 |
+
2p1c
|
5799 |
+
1phw
|
5800 |
+
5w92
|
5801 |
+
3l9n
|
5802 |
+
3k8q
|
5803 |
+
3eml
|
5804 |
+
3nij
|
5805 |
+
5amg
|
5806 |
+
3bv2
|
5807 |
+
2w73
|
5808 |
+
1h35
|
5809 |
+
3tne
|
5810 |
+
3jyr
|
5811 |
+
5l9g
|
5812 |
+
2xsb
|
5813 |
+
4f70
|
5814 |
+
2iuz
|
5815 |
+
1ml1
|
5816 |
+
3ewj
|
5817 |
+
4mk9
|
5818 |
+
2lo6
|
5819 |
+
2jiu
|
5820 |
+
4es0
|
5821 |
+
6dqa
|
5822 |
+
3kab
|
5823 |
+
5mxk
|
5824 |
+
2i0y
|
5825 |
+
4zy2
|
5826 |
+
6cqt
|
5827 |
+
2i47
|
5828 |
+
2i0d
|
5829 |
+
2i80
|
5830 |
+
1nfw
|
5831 |
+
5uzk
|
5832 |
+
6hd6
|
5833 |
+
1y6a
|
5834 |
+
1vcu
|
5835 |
+
1e2k
|
5836 |
+
4wz6
|
5837 |
+
1nc6
|
5838 |
+
4zyv
|
5839 |
+
1wcc
|
5840 |
+
4og4
|
5841 |
+
3il6
|
5842 |
+
1kzk
|
5843 |
+
4frk
|
5844 |
+
1nms
|
5845 |
+
5kax
|
5846 |
+
1fwu
|
5847 |
+
5djr
|
5848 |
+
3a1c
|
5849 |
+
1hdq
|
5850 |
+
5ml6
|
5851 |
+
5l4h
|
5852 |
+
4rj3
|
5853 |
+
2x4t
|
5854 |
+
5nk9
|
5855 |
+
2xj1
|
5856 |
+
3mfw
|
5857 |
+
3gy3
|
5858 |
+
5nvv
|
5859 |
+
4rh5
|
5860 |
+
4jxv
|
5861 |
+
4zs2
|
5862 |
+
5ivv
|
5863 |
+
4axa
|
5864 |
+
5lli
|
5865 |
+
3q5h
|
5866 |
+
4wmu
|
5867 |
+
2z50
|
5868 |
+
4lkf
|
5869 |
+
1rjk
|
5870 |
+
6g93
|
5871 |
+
4nni
|
5872 |
+
6exs
|
5873 |
+
1nki
|
5874 |
+
3i7g
|
5875 |
+
6ei5
|
5876 |
+
6erv
|
5877 |
+
1z3c
|
5878 |
+
3r5n
|
5879 |
+
1lol
|
5880 |
+
3qk5
|
5881 |
+
1rhm
|
5882 |
+
4jfe
|
5883 |
+
1xm4
|
5884 |
+
4gny
|
5885 |
+
3ti1
|
5886 |
+
4hhy
|
5887 |
+
5b5b
|
5888 |
+
4fjz
|
5889 |
+
3w2o
|
5890 |
+
1oxq
|
5891 |
+
3wk8
|
5892 |
+
6bl2
|
5893 |
+
3oe8
|
5894 |
+
3f7z
|
5895 |
+
4j3i
|
5896 |
+
5ogl
|
5897 |
+
4my6
|
5898 |
+
6fob
|
5899 |
+
4o1l
|
5900 |
+
2uy0
|
5901 |
+
5dqc
|
5902 |
+
1g46
|
5903 |
+
5orl
|
5904 |
+
1uwu
|
5905 |
+
185l
|
5906 |
+
4z07
|
5907 |
+
2w8w
|
5908 |
+
3l3l
|
5909 |
+
3vvy
|
5910 |
+
3jwq
|
5911 |
+
1o2z
|
5912 |
+
5lsy
|
5913 |
+
3iok
|
5914 |
+
3g6m
|
5915 |
+
1sdu
|
5916 |
+
4xtp
|
5917 |
+
4qt2
|
5918 |
+
5fdd
|
5919 |
+
5ia2
|
5920 |
+
1ux7
|
5921 |
+
5jhk
|
5922 |
+
4ca4
|
5923 |
+
3qfz
|
5924 |
+
1qvt
|
5925 |
+
3t9t
|
5926 |
+
4j0y
|
5927 |
+
4x49
|
5928 |
+
3lpf
|
5929 |
+
2bpv
|
5930 |
+
3jzr
|
5931 |
+
1fcz
|
5932 |
+
3qps
|
5933 |
+
4p7m
|
5934 |
+
4hvb
|
5935 |
+
3cp9
|
5936 |
+
5jm4
|
5937 |
+
2q9y
|
5938 |
+
3eid
|
5939 |
+
4o4y
|
5940 |
+
3cid
|
5941 |
+
3nc4
|
5942 |
+
6b1f
|
5943 |
+
3rth
|
5944 |
+
3rxe
|
5945 |
+
1sl3
|
5946 |
+
4ap0
|
5947 |
+
4mu7
|
5948 |
+
1pvn
|
5949 |
+
4jfm
|
5950 |
+
1rej
|
5951 |
+
3ens
|
5952 |
+
3e9b
|
5953 |
+
4hby
|
5954 |
+
6guf
|
5955 |
+
3iiy
|
5956 |
+
2z4y
|
5957 |
+
4to8
|
5958 |
+
5t1i
|
5959 |
+
5upj
|
5960 |
+
3c89
|
5961 |
+
4dju
|
5962 |
+
3pcg
|
5963 |
+
6gu2
|
5964 |
+
2euk
|
5965 |
+
3vbw
|
5966 |
+
3px8
|
5967 |
+
3g4k
|
5968 |
+
6dh0
|
5969 |
+
1ukh
|
5970 |
+
4rxh
|
5971 |
+
2ien
|
5972 |
+
2upj
|
5973 |
+
5m44
|
5974 |
+
3gzn
|
5975 |
+
3eio
|
5976 |
+
2hk5
|
5977 |
+
3emh
|
5978 |
+
1o3f
|
5979 |
+
5ipj
|
5980 |
+
6dai
|
5981 |
+
3su5
|
5982 |
+
3sh1
|
5983 |
+
4iic
|
5984 |
+
5e0h
|
5985 |
+
4fs4
|
5986 |
+
4m3q
|
5987 |
+
4wf2
|
5988 |
+
2osf
|
5989 |
+
2pj3
|
5990 |
+
2r0z
|
5991 |
+
1jrs
|
5992 |
+
1i9q
|
5993 |
+
2zgx
|
5994 |
+
2jfh
|
5995 |
+
2ow9
|
5996 |
+
2aa9
|
5997 |
+
5vt1
|
5998 |
+
5l0c
|
5999 |
+
4ybk
|
6000 |
+
3zmt
|
6001 |
+
5kr1
|
6002 |
+
2r7b
|
6003 |
+
2lh8
|
6004 |
+
2wyn
|
6005 |
+
3ckz
|
6006 |
+
6lpr
|
6007 |
+
1usn
|
6008 |
+
3v2n
|
6009 |
+
5oq8
|
6010 |
+
6bhd
|
6011 |
+
2pym
|
6012 |
+
4xaq
|
6013 |
+
3puj
|
6014 |
+
4ek9
|
6015 |
+
1eb1
|
6016 |
+
5o1a
|
6017 |
+
5k5c
|
6018 |
+
2rnw
|
6019 |
+
5qa8
|
6020 |
+
2zg1
|
6021 |
+
4gtm
|
6022 |
+
3uec
|
6023 |
+
4ncm
|
6024 |
+
4alg
|
6025 |
+
5hvs
|
6026 |
+
1lxh
|
6027 |
+
1y6r
|
6028 |
+
5aux
|
6029 |
+
2qwb
|
6030 |
+
2h2d
|
6031 |
+
4qir
|
6032 |
+
1s89
|
6033 |
+
1qwf
|
6034 |
+
2avv
|
6035 |
+
5knt
|
6036 |
+
4odn
|
6037 |
+
3o1e
|
6038 |
+
3lj7
|
6039 |
+
3eov
|
6040 |
+
6cpw
|
6041 |
+
1qca
|
6042 |
+
1jii
|
6043 |
+
3lkh
|
6044 |
+
3rul
|
6045 |
+
4g4p
|
6046 |
+
1qk4
|
6047 |
+
5nkh
|
6048 |
+
1w0z
|
6049 |
+
1jlq
|
6050 |
+
4ngt
|
6051 |
+
4meo
|
6052 |
+
4pmt
|
6053 |
+
2v2h
|
6054 |
+
4lm2
|
6055 |
+
3bu6
|
6056 |
+
1bzs
|
6057 |
+
2vvc
|
6058 |
+
1v0n
|
6059 |
+
5a7y
|
6060 |
+
3d67
|
6061 |
+
4u0c
|
6062 |
+
4uxj
|
6063 |
+
4b78
|
6064 |
+
4bo2
|
6065 |
+
2jsd
|
6066 |
+
4aa1
|
6067 |
+
3ga5
|
6068 |
+
5hka
|
6069 |
+
3vtd
|
6070 |
+
2gm1
|
6071 |
+
4x6x
|
6072 |
+
6ma2
|
6073 |
+
2ces
|
6074 |
+
4ayq
|
6075 |
+
1tpw
|
6076 |
+
2uxi
|
6077 |
+
3gc4
|
6078 |
+
5ye7
|
6079 |
+
2cbv
|
6080 |
+
1v0p
|
6081 |
+
2uzb
|
6082 |
+
5xvq
|
6083 |
+
3r7b
|
6084 |
+
3umo
|
6085 |
+
3b8q
|
6086 |
+
2y6c
|
6087 |
+
3bc5
|
6088 |
+
2bes
|
6089 |
+
5wa7
|
6090 |
+
4f6x
|
6091 |
+
3uvk
|
6092 |
+
1hgt
|
6093 |
+
6m8y
|
6094 |
+
5twg
|
6095 |
+
4avu
|
6096 |
+
5vwi
|
6097 |
+
1ms6
|
6098 |
+
5xo7
|
6099 |
+
3dcq
|
6100 |
+
5km9
|
6101 |
+
2ygf
|
6102 |
+
1zsr
|
6103 |
+
1f40
|
6104 |
+
5m2q
|
6105 |
+
1bl7
|
6106 |
+
4k7n
|
6107 |
+
4hvs
|
6108 |
+
4z2i
|
6109 |
+
5voj
|
6110 |
+
3ck8
|
6111 |
+
5d6q
|
6112 |
+
3g0e
|
6113 |
+
5y0f
|
6114 |
+
3dpk
|
6115 |
+
1bjv
|
6116 |
+
6bw5
|
6117 |
+
3dow
|
6118 |
+
2zif
|
6119 |
+
1mzc
|
6120 |
+
2nng
|
6121 |
+
2xnm
|
6122 |
+
3f8e
|
6123 |
+
2ndg
|
6124 |
+
4lh5
|
6125 |
+
3e8r
|
6126 |
+
2e9o
|
6127 |
+
3uih
|
6128 |
+
4hlc
|
6129 |
+
5moo
|
6130 |
+
4epy
|
6131 |
+
2i3h
|
6132 |
+
6fby
|
6133 |
+
6ew6
|
6134 |
+
3ama
|
6135 |
+
4l0t
|
6136 |
+
1vj9
|
6137 |
+
3pup
|
6138 |
+
2xct
|
6139 |
+
5fh8
|
6140 |
+
5ivz
|
6141 |
+
3pxq
|
6142 |
+
1str
|
6143 |
+
2xxx
|
6144 |
+
2pqj
|
6145 |
+
5mra
|
6146 |
+
4o28
|
6147 |
+
1d6n
|
6148 |
+
1pr5
|
6149 |
+
1rpf
|
6150 |
+
4tt2
|
6151 |
+
3bhx
|
6152 |
+
2cma
|
6153 |
+
3dct
|
6154 |
+
4qt0
|
6155 |
+
6f1j
|
6156 |
+
3gvu
|
6157 |
+
5yy9
|
6158 |
+
2x81
|
6159 |
+
2cv3
|
6160 |
+
6fa4
|
6161 |
+
5jo0
|
6162 |
+
3l0e
|
6163 |
+
3p3j
|
6164 |
+
1eed
|
6165 |
+
5aib
|
6166 |
+
3qbc
|
6167 |
+
1n7j
|
6168 |
+
5fpi
|
6169 |
+
6bnl
|
6170 |
+
5v8q
|
6171 |
+
6gxw
|
6172 |
+
1rw8
|
6173 |
+
5zw6
|
6174 |
+
4e3d
|
6175 |
+
2mji
|
6176 |
+
6ayh
|
6177 |
+
3lcv
|
6178 |
+
1w2k
|
6179 |
+
3zns
|
6180 |
+
5mty
|
6181 |
+
6c3u
|
6182 |
+
4ks4
|
6183 |
+
3ds9
|
6184 |
+
4hld
|
6185 |
+
3elj
|
6186 |
+
4j45
|
6187 |
+
5v41
|
6188 |
+
2yne
|
6189 |
+
5nad
|
6190 |
+
5lvq
|
6191 |
+
3h0a
|
6192 |
+
3d9p
|
6193 |
+
4tu4
|
6194 |
+
3ip5
|
6195 |
+
1w22
|
6196 |
+
4kbk
|
6197 |
+
5lqq
|
6198 |
+
5wyx
|
6199 |
+
3ps1
|
6200 |
+
5ou1
|
6201 |
+
5j9x
|
6202 |
+
2xru
|
6203 |
+
3t4p
|
6204 |
+
3uzp
|
6205 |
+
2o2u
|
6206 |
+
3dei
|
6207 |
+
3u93
|
6208 |
+
4z8m
|
6209 |
+
3lhs
|
6210 |
+
2f81
|
6211 |
+
3fn0
|
6212 |
+
4iqt
|
6213 |
+
5laz
|
6214 |
+
1xot
|
6215 |
+
2z52
|
6216 |
+
1zs0
|
6217 |
+
1oau
|
6218 |
+
5d47
|
6219 |
+
3o4k
|
6220 |
+
6dcg
|
6221 |
+
1o4q
|
6222 |
+
1csi
|
6223 |
+
3tpp
|
6224 |
+
5nwd
|
6225 |
+
2wca
|
6226 |
+
4ie5
|
6227 |
+
1u1w
|
6228 |
+
2w92
|
6229 |
+
3r4n
|
6230 |
+
5aae
|
6231 |
+
4gja
|
6232 |
+
2pj2
|
6233 |
+
5f2p
|
6234 |
+
5hjq
|
6235 |
+
2yme
|
6236 |
+
3cbs
|
6237 |
+
5u0y
|
6238 |
+
5w3i
|
6239 |
+
5qaw
|
6240 |
+
5d3h
|
6241 |
+
3sb0
|
6242 |
+
5alx
|
6243 |
+
5g57
|
6244 |
+
3uhm
|
6245 |
+
6afj
|
6246 |
+
5jf5
|
6247 |
+
4ccd
|
6248 |
+
5mhq
|
6249 |
+
5etx
|
6250 |
+
1clu
|
6251 |
+
4k6u
|
6252 |
+
6g28
|
6253 |
+
4zyz
|
6254 |
+
1sj0
|
6255 |
+
4eh3
|
6256 |
+
2r5b
|
6257 |
+
4pyn
|
6258 |
+
5eq0
|
6259 |
+
1cil
|
6260 |
+
5le1
|
6261 |
+
5nyh
|
6262 |
+
6bdy
|
6263 |
+
2auz
|
6264 |
+
5vm0
|
6265 |
+
2ff1
|
6266 |
+
3f8f
|
6267 |
+
2rka
|
6268 |
+
3dda
|
6269 |
+
4iu4
|
6270 |
+
5bs4
|
6271 |
+
5a0a
|
6272 |
+
2qn2
|
6273 |
+
4fyo
|
6274 |
+
1p2a
|
6275 |
+
2uze
|
6276 |
+
1x38
|
6277 |
+
4ps8
|
6278 |
+
2g19
|
6279 |
+
3nzu
|
6280 |
+
3gi6
|
6281 |
+
5dtt
|
6282 |
+
1gaf
|
6283 |
+
3nii
|
6284 |
+
2xm8
|
6285 |
+
4att
|
6286 |
+
2vex
|
6287 |
+
4jx7
|
6288 |
+
6h34
|
6289 |
+
4tvj
|
6290 |
+
4lh3
|
6291 |
+
3pvw
|
6292 |
+
1ai7
|
6293 |
+
1kc7
|
6294 |
+
2rl5
|
6295 |
+
6c0r
|
6296 |
+
4rcp
|
6297 |
+
1nhv
|
6298 |
+
5mw2
|
6299 |
+
4mg7
|
6300 |
+
1drk
|
6301 |
+
4mzh
|
6302 |
+
1r6g
|
6303 |
+
5xpl
|
6304 |
+
4o74
|
6305 |
+
3bu8
|
6306 |
+
3cgf
|
6307 |
+
4nie
|
6308 |
+
2a3b
|
6309 |
+
1xos
|
6310 |
+
2wlz
|
6311 |
+
1a37
|
6312 |
+
5lpj
|
6313 |
+
1yvh
|
6314 |
+
4xhe
|
6315 |
+
2lct
|
6316 |
+
3lau
|
6317 |
+
3zki
|
6318 |
+
1g2l
|
6319 |
+
4uiv
|
6320 |
+
6b4u
|
6321 |
+
3jqf
|
6322 |
+
3ixk
|
6323 |
+
4pvt
|
6324 |
+
5lpl
|
6325 |
+
3sdk
|
6326 |
+
5km3
|
6327 |
+
1t7f
|
6328 |
+
4z2l
|
6329 |
+
4tk1
|
6330 |
+
2j9a
|
6331 |
+
3bbt
|
6332 |
+
3tjc
|
6333 |
+
2qi4
|
6334 |
+
4acg
|
6335 |
+
5tuz
|
6336 |
+
4lbo
|
6337 |
+
5uuu
|
6338 |
+
5ckr
|
6339 |
+
2h2e
|
6340 |
+
5qai
|
6341 |
+
1qxk
|
6342 |
+
2wyf
|
6343 |
+
3f0r
|
6344 |
+
1rd4
|
6345 |
+
2ipo
|
6346 |
+
1ukt
|
6347 |
+
2xx2
|
6348 |
+
3hvh
|
6349 |
+
2bmz
|
6350 |
+
1jqd
|
6351 |
+
5d24
|
6352 |
+
4cpy
|
6353 |
+
4bdk
|
6354 |
+
2xu4
|
6355 |
+
2evm
|
6356 |
+
6alc
|
6357 |
+
4r5y
|
6358 |
+
4oc5
|
6359 |
+
3kdm
|
6360 |
+
4gk3
|
6361 |
+
5wvd
|
6362 |
+
4pz5
|
6363 |
+
1x1z
|
6364 |
+
2duv
|
6365 |
+
6fnx
|
6366 |
+
5u4b
|
6367 |
+
4dfn
|
6368 |
+
4agp
|
6369 |
+
1n9a
|
6370 |
+
5mny
|
6371 |
+
3hqh
|
6372 |
+
3o8h
|
6373 |
+
4qem
|
6374 |
+
3l81
|
6375 |
+
4c0r
|
6376 |
+
1utp
|
6377 |
+
5z68
|
6378 |
+
5tuy
|
6379 |
+
5fb7
|
6380 |
+
3wv3
|
6381 |
+
3n7r
|
6382 |
+
3bze
|
6383 |
+
2bvd
|
6384 |
+
2fx6
|
6385 |
+
5vcw
|
6386 |
+
4ibf
|
6387 |
+
1zom
|
6388 |
+
4f6w
|
6389 |
+
2fdp
|
6390 |
+
1i91
|
6391 |
+
1d2s
|
6392 |
+
3ikd
|
6393 |
+
4w9e
|
6394 |
+
3fej
|
6395 |
+
4ntj
|
6396 |
+
4wk7
|
6397 |
+
2a29
|
6398 |
+
3f15
|
6399 |
+
4u6c
|
6400 |
+
1ing
|
6401 |
+
3wq6
|
6402 |
+
4ock
|
6403 |
+
2yb0
|
6404 |
+
3wtl
|
6405 |
+
5yl2
|
6406 |
+
2hz4
|
6407 |
+
2gbf
|
6408 |
+
3r8z
|
6409 |
+
5cso
|
6410 |
+
2j95
|
6411 |
+
5jxq
|
6412 |
+
4ofb
|
6413 |
+
2fr3
|
6414 |
+
5b4l
|
6415 |
+
3ovx
|
6416 |
+
6cha
|
6417 |
+
4qwl
|
6418 |
+
1tl9
|
6419 |
+
3mo2
|
6420 |
+
3c8e
|
6421 |
+
3k5x
|
6422 |
+
1uw6
|
6423 |
+
3fhr
|
6424 |
+
1b3f
|
6425 |
+
5a8z
|
6426 |
+
5bvk
|
6427 |
+
4o62
|
6428 |
+
2hb1
|
6429 |
+
3qxd
|
6430 |
+
3i4y
|
6431 |
+
6g9d
|
6432 |
+
6gop
|
6433 |
+
5ajv
|
6434 |
+
1oar
|
6435 |
+
5flt
|
6436 |
+
2zhd
|
6437 |
+
2xey
|
6438 |
+
4ikr
|
6439 |
+
4ckr
|
6440 |
+
4ufg
|
6441 |
+
5xvk
|
6442 |
+
2vmd
|
6443 |
+
5oci
|
6444 |
+
1syo
|
6445 |
+
4lq3
|
6446 |
+
1dtq
|
6447 |
+
5bpp
|
6448 |
+
6fg6
|
6449 |
+
4cki
|
6450 |
+
5wei
|
6451 |
+
3fl9
|
6452 |
+
5cnj
|
6453 |
+
4os5
|
6454 |
+
6awn
|
6455 |
+
3atm
|
6456 |
+
1ypj
|
6457 |
+
1odj
|
6458 |
+
5msb
|
6459 |
+
4f2w
|
6460 |
+
2h5a
|
6461 |
+
2w3k
|
6462 |
+
5w1v
|
6463 |
+
1pi4
|
6464 |
+
4kx8
|
6465 |
+
5m25
|
6466 |
+
1dhj
|
6467 |
+
2qki
|
6468 |
+
4b72
|
6469 |
+
1n0t
|
6470 |
+
3oag
|
6471 |
+
5dyo
|
6472 |
+
1ql9
|
6473 |
+
5u7k
|
6474 |
+
5mod
|
6475 |
+
5mtx
|
6476 |
+
4u6w
|
6477 |
+
1yk7
|
6478 |
+
3d8z
|
6479 |
+
2pnc
|
6480 |
+
5em8
|
6481 |
+
5cil
|
6482 |
+
3iny
|
6483 |
+
5l2t
|
6484 |
+
3u6a
|
6485 |
+
5fow
|
6486 |
+
2owb
|
6487 |
+
1k1y
|
6488 |
+
5nf9
|
6489 |
+
3ijg
|
6490 |
+
1qan
|
6491 |
+
4ad2
|
6492 |
+
2p09
|
6493 |
+
4xir
|
6494 |
+
4tqn
|
6495 |
+
5q11
|
6496 |
+
3zzh
|
6497 |
+
3qel
|
6498 |
+
5jha
|
6499 |
+
3rxh
|
6500 |
+
2ha0
|
6501 |
+
5xqx
|
6502 |
+
3q2g
|
6503 |
+
5wl0
|
6504 |
+
4bic
|
6505 |
+
6ccn
|
6506 |
+
1mh5
|
6507 |
+
2ai8
|
6508 |
+
1xp9
|
6509 |
+
4ef6
|
6510 |
+
5jzb
|
6511 |
+
2h8h
|
6512 |
+
5sxm
|
6513 |
+
3dm6
|
6514 |
+
2ym8
|
6515 |
+
6fmi
|
6516 |
+
5f1h
|
6517 |
+
4qyg
|
6518 |
+
2qtu
|
6519 |
+
3vfb
|
6520 |
+
1vwf
|
6521 |
+
1ivp
|
6522 |
+
3vf7
|
6523 |
+
5typ
|
6524 |
+
5igq
|
6525 |
+
4h1j
|
6526 |
+
3sug
|
6527 |
+
3h85
|
6528 |
+
2viy
|
6529 |
+
6hf5
|
6530 |
+
2poq
|
6531 |
+
5q17
|
6532 |
+
6afa
|
6533 |
+
4mpc
|
6534 |
+
6c0t
|
6535 |
+
4zsh
|
6536 |
+
5dit
|
6537 |
+
6aom
|
6538 |
+
3h8c
|
6539 |
+
2e9v
|
6540 |
+
2hfp
|
6541 |
+
4u5n
|
6542 |
+
5caq
|
6543 |
+
4m2w
|
6544 |
+
4tv3
|
6545 |
+
3oy8
|
6546 |
+
1pot
|
6547 |
+
3owk
|
6548 |
+
3arn
|
6549 |
+
2dri
|
6550 |
+
4ymj
|
6551 |
+
3qto
|
6552 |
+
5ix0
|
6553 |
+
4jr0
|
6554 |
+
5i5x
|
6555 |
+
1nzl
|
6556 |
+
5u4a
|
6557 |
+
4eg4
|
6558 |
+
1wbw
|
6559 |
+
3nee
|
6560 |
+
5fdp
|
6561 |
+
4cqe
|
6562 |
+
1hvs
|
6563 |
+
2w6q
|
6564 |
+
1n8v
|
6565 |
+
5ct7
|
6566 |
+
5dx4
|
6567 |
+
2fdd
|
6568 |
+
4ydf
|
6569 |
+
5c2e
|
6570 |
+
3qsb
|
6571 |
+
5zk3
|
6572 |
+
5vgy
|
6573 |
+
5ot8
|
6574 |
+
6boe
|
6575 |
+
1c29
|
6576 |
+
2pjl
|
6577 |
+
2euf
|
6578 |
+
6cnk
|
6579 |
+
3as1
|
6580 |
+
3abu
|
6581 |
+
3dpd
|
6582 |
+
5aku
|
6583 |
+
4k6w
|
6584 |
+
4j3l
|
6585 |
+
4nau
|
6586 |
+
3fpm
|
6587 |
+
5w7u
|
6588 |
+
3c3q
|
6589 |
+
3mg7
|
6590 |
+
1c12
|
6591 |
+
3buo
|
6592 |
+
3rhx
|
6593 |
+
5lyh
|
6594 |
+
1b0h
|
6595 |
+
4ynd
|
6596 |
+
5y0x
|
6597 |
+
5enb
|
6598 |
+
2a5b
|
6599 |
+
5mqe
|
6600 |
+
3l5e
|
6601 |
+
1tl1
|
6602 |
+
3way
|
6603 |
+
3gs7
|
6604 |
+
3ex3
|
6605 |
+
4np9
|
6606 |
+
5mxq
|
6607 |
+
2cnh
|
6608 |
+
1swr
|
6609 |
+
3t1m
|
6610 |
+
4eyj
|
6611 |
+
6mj7
|
6612 |
+
5f01
|
6613 |
+
3rkz
|
6614 |
+
4ln2
|
6615 |
+
4jia
|
6616 |
+
4l4z
|
6617 |
+
4qr4
|
6618 |
+
2er9
|
6619 |
+
5vnb
|
6620 |
+
5xff
|
6621 |
+
4prp
|
6622 |
+
2jqk
|
6623 |
+
1gi8
|
6624 |
+
2ynr
|
6625 |
+
1gfz
|
6626 |
+
5nk2
|
6627 |
+
1rsd
|
6628 |
+
5umz
|
6629 |
+
3jzf
|
6630 |
+
4k69
|
6631 |
+
6b5o
|
6632 |
+
4o4k
|
6633 |
+
4jal
|
6634 |
+
3nht
|
6635 |
+
4j1i
|
6636 |
+
5xof
|
6637 |
+
4ie7
|
6638 |
+
4f9w
|
6639 |
+
5tvn
|
6640 |
+
2qoh
|
6641 |
+
2jdy
|
6642 |
+
3wym
|
6643 |
+
1w31
|
6644 |
+
5c6o
|
6645 |
+
3nim
|
6646 |
+
1vso
|
6647 |
+
4z2g
|
6648 |
+
1o37
|
6649 |
+
3lbz
|
6650 |
+
4bqs
|
6651 |
+
3tfv
|
6652 |
+
5i8g
|
6653 |
+
3utu
|
6654 |
+
3msl
|
6655 |
+
1bra
|
6656 |
+
2k46
|
6657 |
+
4mg9
|
6658 |
+
2w76
|
6659 |
+
4wyp
|
6660 |
+
5jcj
|
6661 |
+
3b92
|
6662 |
+
3zha
|
6663 |
+
2i4x
|
6664 |
+
3wbl
|
6665 |
+
5trk
|
6666 |
+
2n8t
|
6667 |
+
3ge7
|
6668 |
+
4unn
|
6669 |
+
2ria
|
6670 |
+
4wgi
|
6671 |
+
4bds
|
6672 |
+
2y06
|
6673 |
+
6bhh
|
6674 |
+
4raq
|
6675 |
+
5i56
|
6676 |
+
3vv8
|
6677 |
+
2xk4
|
6678 |
+
4az0
|
6679 |
+
3ov1
|
6680 |
+
4ycw
|
6681 |
+
5ei4
|
6682 |
+
4u1b
|
6683 |
+
3bv3
|
6684 |
+
5etp
|
6685 |
+
3kcf
|
6686 |
+
6fod
|
6687 |
+
3eq9
|
6688 |
+
1awf
|
6689 |
+
1eat
|
6690 |
+
4giu
|
6691 |
+
3vyd
|
6692 |
+
2pvh
|
6693 |
+
5aaf
|
6694 |
+
2hdr
|
6695 |
+
1lgw
|
6696 |
+
2lsp
|
6697 |
+
4l02
|
6698 |
+
6b7b
|
6699 |
+
3ioe
|
6700 |
+
4c1m
|
6701 |
+
5kxi
|
6702 |
+
5yof
|
6703 |
+
4obv
|
6704 |
+
3r6t
|
6705 |
+
1uj6
|
6706 |
+
1a09
|
6707 |
+
4yk6
|
6708 |
+
1rzx
|
6709 |
+
3cy2
|
6710 |
+
6f8v
|
6711 |
+
1xor
|
6712 |
+
4la7
|
6713 |
+
1qwe
|
6714 |
+
5mxo
|
6715 |
+
2opb
|
6716 |
+
3psl
|
6717 |
+
1aqi
|
6718 |
+
5y5w
|
6719 |
+
2j4q
|
6720 |
+
5vfn
|
6721 |
+
3e37
|
6722 |
+
4fzg
|
6723 |
+
5qim
|
6724 |
+
6da4
|
6725 |
+
1oxr
|
6726 |
+
5hgc
|
6727 |
+
3at3
|
6728 |
+
5ieg
|
6729 |
+
6cq0
|
6730 |
+
2ioa
|
6731 |
+
3lpg
|
6732 |
+
4mzo
|
6733 |
+
1w7x
|
6734 |
+
2aia
|
6735 |
+
5v2l
|
6736 |
+
5abg
|
6737 |
+
5x5o
|
6738 |
+
2xcn
|
6739 |
+
5toz
|
6740 |
+
5tp0
|
6741 |
+
4z22
|
6742 |
+
4wlb
|
6743 |
+
4pd5
|
6744 |
+
3zbx
|
6745 |
+
3pb9
|
6746 |
+
3f5l
|
6747 |
+
6bke
|
6748 |
+
4p7s
|
6749 |
+
6dhc
|
6750 |
+
5enh
|
6751 |
+
4m3p
|
6752 |
+
4jmg
|
6753 |
+
1k03
|
6754 |
+
4pni
|
6755 |
+
4asy
|
6756 |
+
1a4r
|
6757 |
+
4deu
|
6758 |
+
4hy9
|
6759 |
+
4g0p
|
6760 |
+
5b5p
|
6761 |
+
3wqv
|
6762 |
+
2r3m
|
6763 |
+
6q73
|
6764 |
+
5ar5
|
6765 |
+
1drv
|
6766 |
+
4ua8
|
6767 |
+
4loy
|
6768 |
+
5eh8
|
6769 |
+
4wy3
|
6770 |
+
3jzh
|
6771 |
+
2aov
|
6772 |
+
6dj2
|
6773 |
+
5t27
|
6774 |
+
1kdk
|
6775 |
+
2og8
|
6776 |
+
10gs
|
6777 |
+
4uw1
|
6778 |
+
4hge
|
6779 |
+
5qcn
|
6780 |
+
6c4d
|
6781 |
+
1bai
|
6782 |
+
3i5n
|
6783 |
+
6epa
|
6784 |
+
3dgq
|
6785 |
+
5tzx
|
6786 |
+
4h3b
|
6787 |
+
5a4q
|
6788 |
+
1e5a
|
6789 |
+
5n93
|
6790 |
+
2exg
|
6791 |
+
5k4l
|
6792 |
+
1qpb
|
6793 |
+
1f3e
|
6794 |
+
4a0j
|
6795 |
+
5ula
|
6796 |
+
4cc3
|
6797 |
+
2oym
|
6798 |
+
1dis
|
6799 |
+
3ns7
|
6800 |
+
3uz5
|
6801 |
+
3ewz
|
6802 |
+
5q0r
|
6803 |
+
1qbo
|
6804 |
+
1nd5
|
6805 |
+
2qzr
|
6806 |
+
4oq3
|
6807 |
+
6e9l
|
6808 |
+
2n0w
|
6809 |
+
2hr6
|
6810 |
+
5vse
|
6811 |
+
5jsm
|
6812 |
+
1ssq
|
6813 |
+
3l4u
|
6814 |
+
1y2k
|
6815 |
+
2r3k
|
6816 |
+
3e3u
|
6817 |
+
4ibi
|
6818 |
+
3kgu
|
6819 |
+
1tni
|
6820 |
+
5hfj
|
6821 |
+
1dva
|
6822 |
+
5mno
|
6823 |
+
1qbu
|
6824 |
+
3px9
|
6825 |
+
5xpm
|
6826 |
+
5q1b
|
6827 |
+
4zjw
|
6828 |
+
4gqp
|
6829 |
+
3r21
|
6830 |
+
3lpp
|
6831 |
+
4bdt
|
6832 |
+
4ks2
|
6833 |
+
2v58
|
6834 |
+
3bft
|
6835 |
+
1il5
|
6836 |
+
5yco
|
6837 |
+
4p5e
|
6838 |
+
3rhk
|
6839 |
+
5fq9
|
6840 |
+
5ko1
|
6841 |
+
5bwc
|
6842 |
+
4q7p
|
6843 |
+
1ro7
|
6844 |
+
3lil
|
6845 |
+
4mwq
|
6846 |
+
3wf6
|
6847 |
+
1tft
|
6848 |
+
3hpt
|
6849 |
+
5t3n
|
6850 |
+
4oo9
|
6851 |
+
2b5j
|
6852 |
+
2bet
|
6853 |
+
3nuy
|
6854 |
+
5nea
|
6855 |
+
3kdd
|
6856 |
+
5ls6
|
6857 |
+
6f2n
|
6858 |
+
4rac
|
6859 |
+
4j47
|
6860 |
+
3iut
|
6861 |
+
4uvv
|
6862 |
+
2i4v
|
6863 |
+
1a8i
|
6864 |
+
5k48
|
6865 |
+
2hpa
|
6866 |
+
1mrs
|
6867 |
+
6fv4
|
6868 |
+
1q8u
|
6869 |
+
5aqz
|
6870 |
+
4ytc
|
6871 |
+
1ibc
|
6872 |
+
4eft
|
6873 |
+
2v95
|
6874 |
+
3me9
|
6875 |
+
4o0b
|
6876 |
+
4kn0
|
6877 |
+
3g2j
|
6878 |
+
1ai5
|
6879 |
+
1n51
|
6880 |
+
1gnm
|
6881 |
+
4zur
|
6882 |
+
4zsj
|
6883 |
+
3v8w
|
6884 |
+
4tzm
|
6885 |
+
1swn
|
6886 |
+
5ih9
|
6887 |
+
3gen
|
6888 |
+
4r6t
|
6889 |
+
2ykb
|
6890 |
+
5u7i
|
6891 |
+
4e81
|
6892 |
+
3v01
|
6893 |
+
3n4b
|
6894 |
+
1jmi
|
6895 |
+
4dcx
|
6896 |
+
3at4
|
6897 |
+
2c6c
|
6898 |
+
4mzl
|
6899 |
+
5ybi
|
6900 |
+
5tcj
|
6901 |
+
2w54
|
6902 |
+
4o13
|
6903 |
+
5ufc
|
6904 |
+
2xs0
|
6905 |
+
4flp
|
6906 |
+
4yqm
|
6907 |
+
3o8p
|
6908 |
+
3tpu
|
6909 |
+
5yft
|
6910 |
+
5mql
|
6911 |
+
5w6e
|
6912 |
+
2yjx
|
6913 |
+
4pqn
|
6914 |
+
4m48
|
6915 |
+
2iiv
|
6916 |
+
4ohm
|
6917 |
+
4a9c
|
6918 |
+
6en4
|
6919 |
+
3wk4
|
6920 |
+
3p50
|
6921 |
+
3bpr
|
6922 |
+
5gwz
|
6923 |
+
1mai
|
6924 |
+
5wys
|
6925 |
+
4oel
|
6926 |
+
1uy8
|
6927 |
+
4u01
|
6928 |
+
4ibc
|
6929 |
+
1qti
|
6930 |
+
4jpy
|
6931 |
+
1q41
|
6932 |
+
2gvd
|
6933 |
+
5aip
|
6934 |
+
5i0b
|
6935 |
+
4zyt
|
6936 |
+
4yxd
|
6937 |
+
4qt1
|
6938 |
+
4w4y
|
6939 |
+
1c8l
|
6940 |
+
3e5u
|
6941 |
+
3kqd
|
6942 |
+
4uj2
|
6943 |
+
3k4q
|
6944 |
+
4o42
|
6945 |
+
5o1h
|
6946 |
+
3b0w
|
6947 |
+
3t64
|
6948 |
+
1hty
|
6949 |
+
5dgm
|
6950 |
+
3bjm
|
6951 |
+
1b8o
|
6952 |
+
4l3p
|
6953 |
+
2b1z
|
6954 |
+
4yyi
|
6955 |
+
5ceh
|
6956 |
+
3l3m
|
6957 |
+
3ebl
|
6958 |
+
4bo8
|
6959 |
+
4fvq
|
6960 |
+
3fup
|
6961 |
+
5ot9
|
6962 |
+
3eax
|
6963 |
+
3vhk
|
6964 |
+
3cda
|
6965 |
+
5c1y
|
6966 |
+
3r2a
|
6967 |
+
1obx
|
6968 |
+
4tzn
|
6969 |
+
1d7i
|
6970 |
+
3qd3
|
6971 |
+
3wka
|
6972 |
+
3ovz
|
6973 |
+
3ihz
|
6974 |
+
5iis
|
6975 |
+
5vo6
|
6976 |
+
5tc0
|
6977 |
+
3fqk
|
6978 |
+
1dm2
|
6979 |
+
4y63
|
6980 |
+
6mvx
|
6981 |
+
4ucu
|
6982 |
+
5oht
|
6983 |
+
4jff
|
6984 |
+
1n8u
|
6985 |
+
4xua
|
6986 |
+
2ybp
|
6987 |
+
2cgf
|
6988 |
+
3d4q
|
6989 |
+
4gsy
|
6990 |
+
4i32
|
6991 |
+
2psv
|
6992 |
+
2ych
|
6993 |
+
5lck
|
6994 |
+
1xxe
|
6995 |
+
5wrs
|
6996 |
+
5trg
|
6997 |
+
5dp6
|
6998 |
+
2lnw
|
6999 |
+
5kr2
|
7000 |
+
4utx
|
7001 |
+
1a8t
|
7002 |
+
4qw5
|
7003 |
+
6emu
|
7004 |
+
2itt
|
7005 |
+
4m7y
|
7006 |
+
3kqo
|
7007 |
+
5ku3
|
7008 |
+
4n7u
|
7009 |
+
1oit
|
7010 |
+
1w1t
|
7011 |
+
4j26
|
7012 |
+
4nrp
|
7013 |
+
4yh3
|
7014 |
+
3nzw
|
7015 |
+
5zh2
|
7016 |
+
3vw9
|
7017 |
+
2hyy
|
7018 |
+
1qj1
|
7019 |
+
1csr
|
7020 |
+
2we3
|
7021 |
+
6mnf
|
7022 |
+
4ijh
|
7023 |
+
2jdk
|
7024 |
+
4kcg
|
7025 |
+
1kmv
|
7026 |
+
3buh
|
7027 |
+
4ovh
|
7028 |
+
1mxu
|
7029 |
+
4mg8
|
7030 |
+
3lka
|
7031 |
+
4twy
|
7032 |
+
5vsb
|
7033 |
+
4ofl
|
7034 |
+
6cdm
|
7035 |
+
2f3k
|
7036 |
+
5aqp
|
7037 |
+
4tkg
|
7038 |
+
5w4e
|
7039 |
+
3zot
|
7040 |
+
2yak
|
7041 |
+
3qkd
|
7042 |
+
2pv1
|
7043 |
+
5mz8
|
7044 |
+
5gut
|
7045 |
+
3avz
|
7046 |
+
2q8g
|
7047 |
+
3ilq
|
7048 |
+
3zw3
|
7049 |
+
4ckj
|
7050 |
+
1qbr
|
7051 |
+
4q08
|
7052 |
+
3zpu
|
7053 |
+
5u8f
|
7054 |
+
2ydv
|
7055 |
+
3rtp
|
7056 |
+
4b95
|
7057 |
+
2f9b
|
7058 |
+
2uz9
|
7059 |
+
4ehg
|
7060 |
+
4xsz
|
7061 |
+
1bkj
|
7062 |
+
6f22
|
7063 |
+
1tet
|
7064 |
+
3f3w
|
7065 |
+
4abd
|
7066 |
+
3sjf
|
7067 |
+
2byh
|
7068 |
+
5jsg
|
7069 |
+
4op3
|
7070 |
+
6fsy
|
7071 |
+
3twv
|
7072 |
+
5d25
|
7073 |
+
2vto
|
7074 |
+
2oa0
|
7075 |
+
6csq
|
7076 |
+
6dh3
|
7077 |
+
5jq9
|
7078 |
+
4xkx
|
7079 |
+
4tmf
|
7080 |
+
4brx
|
7081 |
+
2ghg
|
7082 |
+
2gvj
|
7083 |
+
4wnm
|
7084 |
+
5ayf
|
7085 |
+
4osf
|
7086 |
+
1u65
|
7087 |
+
3lzs
|
7088 |
+
1i90
|
7089 |
+
3gdt
|
7090 |
+
6eru
|
7091 |
+
5ops
|
7092 |
+
2mpm
|
7093 |
+
4cc7
|
7094 |
+
3ckp
|
7095 |
+
1o4d
|
7096 |
+
2vvs
|
7097 |
+
6ep4
|
7098 |
+
4bkz
|
7099 |
+
4aom
|
7100 |
+
1wc6
|
7101 |
+
1mpa
|
7102 |
+
2pl9
|
7103 |
+
2p53
|
7104 |
+
4zyr
|
7105 |
+
3gqz
|
7106 |
+
4og8
|
7107 |
+
4mlt
|
7108 |
+
1mf4
|
7109 |
+
1xxh
|
7110 |
+
3p3g
|
7111 |
+
3g0c
|
7112 |
+
5dbm
|
7113 |
+
4xhk
|
7114 |
+
5lny
|
7115 |
+
3g8i
|
7116 |
+
5g60
|
7117 |
+
2zas
|
7118 |
+
2z7h
|
7119 |
+
3kfa
|
7120 |
+
4a9u
|
7121 |
+
4gj7
|
7122 |
+
4nwd
|
7123 |
+
4ei4
|
7124 |
+
5yjf
|
7125 |
+
2won
|
7126 |
+
2f2c
|
7127 |
+
3mg8
|
7128 |
+
3i06
|
7129 |
+
2wa4
|
7130 |
+
3hzm
|
7131 |
+
3wkc
|
7132 |
+
4j7e
|
7133 |
+
3dxm
|
7134 |
+
3m9f
|
7135 |
+
1gzv
|
7136 |
+
4clp
|
7137 |
+
5a09
|
7138 |
+
5tg5
|
7139 |
+
4wkn
|
7140 |
+
1njf
|
7141 |
+
3ce0
|
7142 |
+
1tpz
|
7143 |
+
6bh0
|
7144 |
+
3vfa
|
7145 |
+
3su1
|
7146 |
+
2vtn
|
7147 |
+
5yp6
|
7148 |
+
5twj
|
7149 |
+
4i74
|
7150 |
+
5zk8
|
7151 |
+
2al5
|
7152 |
+
3bh9
|
7153 |
+
4djo
|
7154 |
+
4oi6
|
7155 |
+
5m4u
|
7156 |
+
1wva
|
7157 |
+
3uvx
|
7158 |
+
2aod
|
7159 |
+
1pqc
|
7160 |
+
4n4t
|
7161 |
+
5fdi
|
7162 |
+
1lcp
|
7163 |
+
4ere
|
7164 |
+
1ci7
|
7165 |
+
1ykp
|
7166 |
+
2qju
|
7167 |
+
1ftj
|
7168 |
+
5hk9
|
7169 |
+
5y3o
|
7170 |
+
5q0v
|
7171 |
+
6ayn
|
7172 |
+
5os1
|
7173 |
+
2j9l
|
7174 |
+
2qm9
|
7175 |
+
2x6j
|
7176 |
+
5ei2
|
7177 |
+
5izc
|
7178 |
+
3u18
|
7179 |
+
4zek
|
7180 |
+
4s1g
|
7181 |
+
2wq4
|
7182 |
+
1nfy
|
7183 |
+
6bnt
|
7184 |
+
4jai
|
7185 |
+
2jb6
|
7186 |
+
5ahw
|
7187 |
+
4uit
|
7188 |
+
3bmn
|
7189 |
+
4gzx
|
7190 |
+
6gxu
|
7191 |
+
4gki
|
7192 |
+
3ccb
|
7193 |
+
4ezq
|
7194 |
+
5v7a
|
7195 |
+
6dzq
|
7196 |
+
4az3
|
7197 |
+
4ucr
|
7198 |
+
4pnt
|
7199 |
+
2wtj
|
7200 |
+
5amn
|
7201 |
+
4ux6
|
7202 |
+
3t8v
|
7203 |
+
1i33
|
7204 |
+
3r7n
|
7205 |
+
5f00
|
7206 |
+
5nvy
|
7207 |
+
3k41
|
7208 |
+
4aq3
|
7209 |
+
3tdh
|
7210 |
+
3wdz
|
7211 |
+
5nib
|
7212 |
+
6b8y
|
7213 |
+
1v2h
|
7214 |
+
5jpt
|
7215 |
+
1xge
|
7216 |
+
4umn
|
7217 |
+
2xrw
|
7218 |
+
2vvn
|
7219 |
+
3t07
|
7220 |
+
2vpp
|
7221 |
+
1ghv
|
7222 |
+
4ydq
|
7223 |
+
2dbl
|
7224 |
+
3ho9
|
7225 |
+
5w88
|
7226 |
+
2g71
|
7227 |
+
2lk1
|
7228 |
+
2pwg
|
7229 |
+
4ai5
|
7230 |
+
1o41
|
7231 |
+
1tsv
|
7232 |
+
5al3
|
7233 |
+
4fk7
|
7234 |
+
2o4z
|
7235 |
+
4a51
|
7236 |
+
4gwk
|
7237 |
+
3ay0
|
7238 |
+
3own
|
7239 |
+
4e5g
|
7240 |
+
1lcj
|
7241 |
+
1hk3
|
7242 |
+
4rhy
|
7243 |
+
4yoi
|
7244 |
+
3prf
|
7245 |
+
5z99
|
7246 |
+
3slz
|
7247 |
+
4tmk
|
7248 |
+
1au0
|
7249 |
+
2qwg
|
7250 |
+
1bdq
|
7251 |
+
5h8b
|
7252 |
+
4emt
|
7253 |
+
6bec
|
7254 |
+
1g9d
|
7255 |
+
1qf2
|
7256 |
+
2r0u
|
7257 |
+
1f2o
|
7258 |
+
1b9t
|
7259 |
+
2c1p
|
7260 |
+
1hn4
|
7261 |
+
3skg
|
7262 |
+
4ee0
|
7263 |
+
6c2y
|
7264 |
+
4pg3
|
7265 |
+
3uw4
|
7266 |
+
1wdn
|
7267 |
+
3mho
|
7268 |
+
4yl1
|
7269 |
+
6cex
|
7270 |
+
3b7r
|
7271 |
+
4pop
|
7272 |
+
5f02
|
7273 |
+
3d7b
|
7274 |
+
1xbb
|
7275 |
+
2zft
|
7276 |
+
4i8z
|
7277 |
+
4oya
|
7278 |
+
3otf
|
7279 |
+
2xhm
|
7280 |
+
5c20
|
7281 |
+
1zrz
|
7282 |
+
4rqk
|
7283 |
+
5k8o
|
7284 |
+
1tvo
|
7285 |
+
6fnr
|
7286 |
+
1dwd
|
7287 |
+
4zlo
|
7288 |
+
1nyx
|
7289 |
+
5aad
|
7290 |
+
3kqw
|
7291 |
+
3nw7
|
7292 |
+
5ti6
|
7293 |
+
6e59
|
7294 |
+
1ywr
|
7295 |
+
2xn5
|
7296 |
+
4cy1
|
7297 |
+
1yfz
|
7298 |
+
5e3a
|
7299 |
+
4a7c
|
7300 |
+
5ljq
|
7301 |
+
5h9r
|
7302 |
+
1gi6
|
7303 |
+
2b1p
|
7304 |
+
1kc5
|
7305 |
+
3kpw
|
7306 |
+
1q5k
|
7307 |
+
4aml
|
7308 |
+
4ibg
|
7309 |
+
6e49
|
7310 |
+
2w8y
|
7311 |
+
3kmm
|
7312 |
+
2w6o
|
7313 |
+
3hdn
|
7314 |
+
6cef
|
7315 |
+
1u8t
|
7316 |
+
4e8y
|
7317 |
+
4gj6
|
7318 |
+
4hbm
|
7319 |
+
4g3f
|
7320 |
+
4eok
|
7321 |
+
2rox
|
7322 |
+
1t48
|
7323 |
+
2xd6
|
7324 |
+
2fjn
|
7325 |
+
5ndb
|
7326 |
+
4j77
|
7327 |
+
1n43
|
7328 |
+
3ui7
|
7329 |
+
5e73
|
7330 |
+
1h1h
|
7331 |
+
4mhs
|
7332 |
+
3ohf
|
7333 |
+
3kdc
|
7334 |
+
4edy
|
7335 |
+
2wzs
|
7336 |
+
5h9s
|
7337 |
+
3cth
|
7338 |
+
2j34
|
7339 |
+
1h62
|
7340 |
+
4jnm
|
7341 |
+
6bil
|
7342 |
+
3mhc
|
7343 |
+
4zw8
|
7344 |
+
3g90
|
7345 |
+
4f7v
|
7346 |
+
4eh8
|
7347 |
+
5wkh
|
7348 |
+
4ycm
|
7349 |
+
4mk8
|
7350 |
+
2xj0
|
7351 |
+
2tpi
|
7352 |
+
4clz
|
7353 |
+
4ko8
|
7354 |
+
5qaj
|
7355 |
+
5dus
|
7356 |
+
4xm7
|
7357 |
+
2uzl
|
7358 |
+
1k1l
|
7359 |
+
4g95
|
7360 |
+
1c3e
|
7361 |
+
5g10
|
7362 |
+
4nnr
|
7363 |
+
3e64
|
7364 |
+
1fq8
|
7365 |
+
4c71
|
7366 |
+
4b0c
|
7367 |
+
3ft3
|
7368 |
+
1ybg
|
7369 |
+
4y2t
|
7370 |
+
5dk4
|
7371 |
+
4dds
|
7372 |
+
3ggw
|
7373 |
+
5axi
|
7374 |
+
3ueo
|
7375 |
+
2r9b
|
7376 |
+
3ppj
|
7377 |
+
1meu
|
7378 |
+
4z7o
|
7379 |
+
3n8k
|
7380 |
+
2jup
|
7381 |
+
3p9j
|
7382 |
+
3hxe
|
7383 |
+
1e06
|
7384 |
+
3ika
|
7385 |
+
5yyf
|
7386 |
+
4kc4
|
7387 |
+
3su3
|
7388 |
+
4z7h
|
7389 |
+
4x2l
|
7390 |
+
5hcv
|
7391 |
+
5ir1
|
7392 |
+
1f9g
|
7393 |
+
5law
|
7394 |
+
3o99
|
7395 |
+
1yci
|
7396 |
+
3g3d
|
7397 |
+
3aje
|
7398 |
+
2o5d
|
7399 |
+
3b7i
|
7400 |
+
6af9
|
7401 |
+
2gvz
|
7402 |
+
4qmt
|
7403 |
+
3qj0
|
7404 |
+
2y9q
|
7405 |
+
1nw5
|
7406 |
+
5wg8
|
7407 |
+
4bzr
|
7408 |
+
1k6t
|
7409 |
+
5hd0
|
7410 |
+
3fui
|
7411 |
+
1lek
|
7412 |
+
5kql
|
7413 |
+
5d21
|
7414 |
+
1iig
|
7415 |
+
5ewh
|
7416 |
+
2vhq
|
7417 |
+
2gh6
|
7418 |
+
4x6y
|
7419 |
+
4mbl
|
7420 |
+
2v54
|
7421 |
+
5ug9
|
7422 |
+
3hvk
|
7423 |
+
3qts
|
7424 |
+
3q43
|
7425 |
+
4nvq
|
7426 |
+
3co9
|
7427 |
+
4uxh
|
7428 |
+
2gj4
|
7429 |
+
4dwb
|
7430 |
+
5q16
|
7431 |
+
1uyf
|
7432 |
+
5jbi
|
7433 |
+
2il2
|
7434 |
+
1yt9
|
7435 |
+
3t6j
|
7436 |
+
2zu5
|
7437 |
+
5buj
|
7438 |
+
2xiy
|
7439 |
+
2fs9
|
7440 |
+
1al8
|
7441 |
+
4cig
|
7442 |
+
3cgy
|
7443 |
+
4mdq
|
7444 |
+
3st6
|
7445 |
+
4dzy
|
7446 |
+
6fcl
|
7447 |
+
1m0o
|
7448 |
+
3spf
|
7449 |
+
1lkk
|
7450 |
+
4uu7
|
7451 |
+
1zky
|
7452 |
+
5d9l
|
7453 |
+
1zd3
|
7454 |
+
5t6f
|
7455 |
+
1g2o
|
7456 |
+
2i1m
|
7457 |
+
3khv
|
7458 |
+
3o88
|
7459 |
+
5fi2
|
7460 |
+
3idp
|
7461 |
+
2pov
|
7462 |
+
4x11
|
7463 |
+
2qe4
|
7464 |
+
3qtz
|
7465 |
+
5alm
|
7466 |
+
4pli
|
7467 |
+
3fts
|
7468 |
+
2x4u
|
7469 |
+
4o45
|
7470 |
+
1tkx
|
7471 |
+
2q8h
|
7472 |
+
1mue
|
7473 |
+
4eop
|
7474 |
+
2j7e
|
7475 |
+
5akk
|
7476 |
+
5wtt
|
7477 |
+
3h9o
|
7478 |
+
3v4x
|
7479 |
+
5b6c
|
7480 |
+
5boy
|
7481 |
+
5hdz
|
7482 |
+
5nkg
|
7483 |
+
6ajg
|
7484 |
+
4dum
|
7485 |
+
3whw
|
7486 |
+
6b59
|
7487 |
+
5aan
|
7488 |
+
6fo5
|
7489 |
+
4pmp
|
7490 |
+
5i0l
|
7491 |
+
2xk9
|
7492 |
+
5mon
|
7493 |
+
3d4y
|
7494 |
+
2xib
|
7495 |
+
3c2r
|
7496 |
+
5mfr
|
7497 |
+
2ra6
|
7498 |
+
2xl2
|
7499 |
+
4w5a
|
7500 |
+
3zm6
|
7501 |
+
3zm5
|
7502 |
+
3zhz
|
7503 |
+
3ogq
|
7504 |
+
4rrq
|
7505 |
+
4wxi
|
7506 |
+
4asd
|
7507 |
+
5txy
|
7508 |
+
5u0w
|
7509 |
+
4xta
|
7510 |
+
3t2v
|
7511 |
+
2q9m
|
7512 |
+
5lyw
|
7513 |
+
4kon
|
7514 |
+
3sv2
|
7515 |
+
2j7d
|
7516 |
+
3hmv
|
7517 |
+
6g92
|
7518 |
+
1z6f
|
7519 |
+
5a46
|
7520 |
+
3gnw
|
7521 |
+
5k03
|
7522 |
+
2bgn
|
7523 |
+
3ohi
|
7524 |
+
3acw
|
7525 |
+
3hng
|
7526 |
+
4j06
|
7527 |
+
1owj
|
7528 |
+
4fbe
|
7529 |
+
1gbt
|
7530 |
+
4fmo
|
7531 |
+
4g8v
|
7532 |
+
2fzc
|
7533 |
+
2vx0
|
7534 |
+
2o1c
|
7535 |
+
5unp
|
7536 |
+
4o7c
|
7537 |
+
4rxe
|
7538 |
+
5t90
|
7539 |
+
5jyo
|
7540 |
+
2wzy
|
7541 |
+
1tfq
|
7542 |
+
1tqf
|
7543 |
+
3s78
|
7544 |
+
6g0v
|
7545 |
+
2ei6
|
7546 |
+
4r95
|
7547 |
+
3peq
|
7548 |
+
3o9f
|
7549 |
+
1mq6
|
7550 |
+
1k6v
|
7551 |
+
6gfs
|
7552 |
+
6q6y
|
7553 |
+
5m39
|
7554 |
+
3wz7
|
7555 |
+
1nwl
|
7556 |
+
3ard
|
7557 |
+
5e3d
|
7558 |
+
2woq
|
7559 |
+
4gq6
|
7560 |
+
3iw5
|
7561 |
+
2h15
|
7562 |
+
3avh
|
7563 |
+
2azr
|
7564 |
+
5vsk
|
7565 |
+
6ckr
|
7566 |
+
4n84
|
7567 |
+
4eh2
|
7568 |
+
4cpw
|
7569 |
+
5f91
|
7570 |
+
4k3r
|
7571 |
+
4dgn
|
7572 |
+
2yer
|
7573 |
+
5ayt
|
7574 |
+
4cpz
|
7575 |
+
4y29
|
7576 |
+
5tq6
|
7577 |
+
3bcn
|
7578 |
+
3roc
|
7579 |
+
5lwm
|
7580 |
+
3gjd
|
7581 |
+
3k5v
|
7582 |
+
4zip
|
7583 |
+
4und
|
7584 |
+
6exm
|
7585 |
+
5qak
|
7586 |
+
4u0n
|
7587 |
+
5wo4
|
7588 |
+
1rrw
|
7589 |
+
6b2p
|
7590 |
+
5hls
|
7591 |
+
3pjc
|
7592 |
+
1cin
|
7593 |
+
3b2w
|
7594 |
+
1kmy
|
7595 |
+
4ys7
|
7596 |
+
4f0c
|
7597 |
+
1zgi
|
7598 |
+
3vqu
|
7599 |
+
3uoh
|
7600 |
+
1qr3
|
7601 |
+
5i8b
|
7602 |
+
4l7h
|
7603 |
+
2aay
|
7604 |
+
4jlm
|
7605 |
+
3wnr
|
7606 |
+
4en4
|
7607 |
+
5w0f
|
7608 |
+
4lxz
|
7609 |
+
4cjr
|
7610 |
+
4jj7
|
7611 |
+
2h5i
|
7612 |
+
2avi
|
7613 |
+
3ezv
|
7614 |
+
4j09
|
7615 |
+
3hkw
|
7616 |
+
3uxm
|
7617 |
+
4b5d
|
7618 |
+
5vcv
|
7619 |
+
2vtt
|
7620 |
+
3bl9
|
7621 |
+
2y1n
|
7622 |
+
5nin
|
7623 |
+
3uvo
|
7624 |
+
5anw
|
7625 |
+
5nvw
|
7626 |
+
4b9k
|
7627 |
+
1j4p
|
7628 |
+
4io5
|
7629 |
+
4dkp
|
7630 |
+
2jdt
|
7631 |
+
1iem
|
7632 |
+
4lm0
|
7633 |
+
5wyq
|
7634 |
+
5nr8
|
7635 |
+
6f7t
|
7636 |
+
5a81
|
7637 |
+
3lnk
|
7638 |
+
2xuf
|
7639 |
+
5ort
|
7640 |
+
1h1q
|
7641 |
+
4twd
|
7642 |
+
1e1y
|
7643 |
+
5lo5
|
7644 |
+
4anm
|
7645 |
+
1e1v
|
7646 |
+
4tki
|
7647 |
+
4wv6
|
7648 |
+
4htx
|
7649 |
+
1t13
|
7650 |
+
4euo
|
7651 |
+
6gy1
|
7652 |
+
4civ
|
7653 |
+
3dux
|
7654 |
+
5knv
|
7655 |
+
5hn7
|
7656 |
+
6gi6
|
7657 |
+
5vb5
|
7658 |
+
3f5p
|
7659 |
+
2kfh
|
7660 |
+
4b3u
|
7661 |
+
5nf5
|
7662 |
+
5mes
|
7663 |
+
4w55
|
7664 |
+
1sv3
|
7665 |
+
3p7a
|
7666 |
+
6frf
|
7667 |
+
6eks
|
7668 |
+
5afm
|
7669 |
+
5z4o
|
7670 |
+
3cow
|
7671 |
+
5hu1
|
7672 |
+
6f9g
|
7673 |
+
3ds1
|
7674 |
+
6a6w
|
7675 |
+
2g8r
|
7676 |
+
2ze1
|
7677 |
+
5q18
|
7678 |
+
5cau
|
7679 |
+
1s38
|
7680 |
+
1zge
|
7681 |
+
1me4
|
7682 |
+
3cj4
|
7683 |
+
4pr5
|
7684 |
+
4gzf
|
7685 |
+
1q54
|
7686 |
+
5l9i
|
7687 |
+
1z6j
|
7688 |
+
2ez5
|
7689 |
+
3unk
|
7690 |
+
3qwc
|
7691 |
+
3o86
|
7692 |
+
4j51
|
7693 |
+
6fyi
|
7694 |
+
3cj2
|
7695 |
+
2viz
|
7696 |
+
5ekm
|
7697 |
+
3f9y
|
7698 |
+
2uy5
|
7699 |
+
2brb
|
7700 |
+
5g45
|
7701 |
+
5jgd
|
7702 |
+
4j1e
|
7703 |
+
4ikt
|
7704 |
+
5opu
|
7705 |
+
4mwc
|
7706 |
+
1t7d
|
7707 |
+
2viq
|
7708 |
+
3ocp
|
7709 |
+
3wuv
|
7710 |
+
4yay
|
7711 |
+
3d7f
|
7712 |
+
2vh6
|
7713 |
+
4foc
|
7714 |
+
2ra0
|
7715 |
+
5fwg
|
7716 |
+
1o3c
|
7717 |
+
4bi0
|
7718 |
+
1kll
|
7719 |
+
3qtq
|
7720 |
+
3cl0
|
7721 |
+
3ho2
|
7722 |
+
3vw7
|
7723 |
+
6h37
|
7724 |
+
4rlw
|
7725 |
+
6dak
|
7726 |
+
3p3t
|
7727 |
+
3m11
|
7728 |
+
6fdp
|
7729 |
+
4c73
|
7730 |
+
5ksx
|
7731 |
+
6bcy
|
7732 |
+
1okl
|
7733 |
+
4gqq
|
7734 |
+
3sji
|
7735 |
+
2x2i
|
7736 |
+
1hkj
|
7737 |
+
5hu9
|
7738 |
+
5vom
|
7739 |
+
5fdo
|
7740 |
+
1uu7
|
7741 |
+
5iay
|
7742 |
+
5nu5
|
7743 |
+
6ghh
|
7744 |
+
4q06
|
7745 |
+
3apc
|
7746 |
+
1re8
|
7747 |
+
5uey
|
7748 |
+
2ha6
|
7749 |
+
4aaw
|
7750 |
+
1tcx
|
7751 |
+
3lpj
|
7752 |
+
3w0l
|
7753 |
+
3s45
|
7754 |
+
3n5j
|
7755 |
+
1rhj
|
7756 |
+
5d0r
|
7757 |
+
2qp6
|
7758 |
+
2vqj
|
7759 |
+
2zaz
|
7760 |
+
2zir
|
7761 |
+
4mq1
|
7762 |
+
5alt
|
7763 |
+
5he5
|
7764 |
+
3atp
|
7765 |
+
5w5j
|
7766 |
+
3ekw
|
7767 |
+
4xas
|
7768 |
+
5mwy
|
7769 |
+
4mwy
|
7770 |
+
2wzf
|
7771 |
+
2z1w
|
7772 |
+
1d4t
|
7773 |
+
4yk0
|
7774 |
+
3hnb
|
7775 |
+
4h3j
|
7776 |
+
6g36
|
7777 |
+
1rhr
|
7778 |
+
2r3f
|
7779 |
+
6bcr
|
7780 |
+
5owh
|
7781 |
+
5idp
|
7782 |
+
1odi
|
7783 |
+
3vw1
|
7784 |
+
4n6z
|
7785 |
+
3qcx
|
7786 |
+
4z89
|
7787 |
+
4pkb
|
7788 |
+
2ewp
|
7789 |
+
3d9z
|
7790 |
+
4c5d
|
7791 |
+
1xoz
|
7792 |
+
4meq
|
7793 |
+
3so6
|
7794 |
+
3tiw
|
7795 |
+
6h7u
|
7796 |
+
3u0d
|
7797 |
+
1ur9
|
7798 |
+
4lar
|
7799 |
+
4css
|
7800 |
+
2a3c
|
7801 |
+
1h3a
|
7802 |
+
4aqc
|
7803 |
+
5l2s
|
7804 |
+
5vi6
|
7805 |
+
6cmr
|
7806 |
+
2wf4
|
7807 |
+
3chs
|
7808 |
+
5uc4
|
7809 |
+
5tca
|
7810 |
+
2x6e
|
7811 |
+
4gne
|
7812 |
+
5ey9
|
7813 |
+
4ih5
|
7814 |
+
1mto
|
7815 |
+
4qwi
|
7816 |
+
5nai
|
7817 |
+
4ym4
|
7818 |
+
3prz
|
7819 |
+
2nnp
|
7820 |
+
1vij
|
7821 |
+
5bvd
|
7822 |
+
5swf
|
7823 |
+
3pn3
|
7824 |
+
2pql
|
7825 |
+
3ekv
|
7826 |
+
3nq9
|
7827 |
+
5c7n
|
7828 |
+
1els
|
7829 |
+
4k5m
|
7830 |
+
6bq0
|
7831 |
+
1o2k
|
7832 |
+
2aux
|
7833 |
+
4x69
|
7834 |
+
5mts
|
7835 |
+
1e9h
|
7836 |
+
4ykj
|
7837 |
+
1mkd
|
7838 |
+
6i3s
|
7839 |
+
1zpb
|
7840 |
+
5mo8
|
7841 |
+
2q92
|
7842 |
+
4u70
|
7843 |
+
4wph
|
7844 |
+
4xy9
|
7845 |
+
4ith
|
7846 |
+
5aph
|
7847 |
+
5cy3
|
7848 |
+
3fat
|
7849 |
+
4ly1
|
7850 |
+
2vti
|
7851 |
+
1f0q
|
7852 |
+
4wsy
|
7853 |
+
3ej1
|
7854 |
+
3ine
|
7855 |
+
3rux
|
7856 |
+
2vvu
|
7857 |
+
5a3t
|
7858 |
+
4qtd
|
7859 |
+
5a5s
|
7860 |
+
3t7g
|
7861 |
+
1xon
|
7862 |
+
4gah
|
7863 |
+
5flq
|
7864 |
+
2hw2
|
7865 |
+
3aig
|
7866 |
+
4hl5
|
7867 |
+
5wzr
|
7868 |
+
2imd
|
7869 |
+
3oxz
|
7870 |
+
1ndv
|
7871 |
+
5yji
|
7872 |
+
2hxm
|
7873 |
+
3l59
|
7874 |
+
4jpx
|
7875 |
+
1ws5
|
7876 |
+
4uix
|
7877 |
+
2iv9
|
7878 |
+
4dwk
|
7879 |
+
4qvp
|
7880 |
+
2c1b
|
7881 |
+
5cw8
|
7882 |
+
2r6n
|
7883 |
+
4cws
|
7884 |
+
2d3z
|
7885 |
+
2oc9
|
7886 |
+
4ehz
|
7887 |
+
1ett
|
7888 |
+
1fdq
|
7889 |
+
2avo
|
7890 |
+
4r0a
|
7891 |
+
1zzz
|
7892 |
+
3moe
|
7893 |
+
4mmp
|
7894 |
+
5muc
|
7895 |
+
5zh5
|
7896 |
+
3zqi
|
7897 |
+
6f08
|
7898 |
+
6elo
|
7899 |
+
6dif
|
7900 |
+
3mf5
|
7901 |
+
5qas
|
7902 |
+
3fu5
|
7903 |
+
3rv9
|
7904 |
+
4jne
|
7905 |
+
5urj
|
7906 |
+
5oxk
|
7907 |
+
4y3y
|
7908 |
+
5hki
|
7909 |
+
4tyb
|
7910 |
+
2glm
|
7911 |
+
2xnb
|
7912 |
+
3tt0
|
7913 |
+
6gmq
|
7914 |
+
4i5p
|
7915 |
+
1f92
|
7916 |
+
3psd
|
7917 |
+
5hcy
|
7918 |
+
1q6n
|
7919 |
+
4tmn
|
7920 |
+
1tmn
|
7921 |
+
2gg0
|
7922 |
+
3zep
|
7923 |
+
1c88
|
7924 |
+
4fea
|
7925 |
+
5nwb
|
7926 |
+
1ppc
|
7927 |
+
5myx
|
7928 |
+
4ci3
|
7929 |
+
1z6d
|
7930 |
+
4kww
|
7931 |
+
4ixu
|
7932 |
+
1leg
|
7933 |
+
3a5y
|
7934 |
+
4bo3
|
7935 |
+
5cyi
|
7936 |
+
5uzj
|
7937 |
+
4mw0
|
7938 |
+
5j18
|
7939 |
+
5ml3
|
7940 |
+
2bmk
|
7941 |
+
1e66
|
7942 |
+
2brc
|
7943 |
+
2fwy
|
7944 |
+
5oxm
|
7945 |
+
1bn1
|
7946 |
+
4qlv
|
7947 |
+
4qip
|
7948 |
+
3ms2
|
7949 |
+
5wxf
|
7950 |
+
5yib
|
7951 |
+
3ig7
|
7952 |
+
4pgb
|
7953 |
+
4p73
|
7954 |
+
2y4s
|
7955 |
+
5zh4
|
7956 |
+
4ch2
|
7957 |
+
5tex
|
7958 |
+
3b4f
|
7959 |
+
3poa
|
7960 |
+
4zyx
|
7961 |
+
4m0y
|
7962 |
+
2ot1
|
7963 |
+
5e91
|
7964 |
+
1yc5
|
7965 |
+
3iqi
|
7966 |
+
2xpc
|
7967 |
+
1o2s
|
7968 |
+
1pmu
|
7969 |
+
4l58
|
7970 |
+
4mx1
|
7971 |
+
5am4
|
7972 |
+
2hs2
|
7973 |
+
4yne
|
7974 |
+
1ctt
|
7975 |
+
3l5c
|
7976 |
+
2zm1
|
7977 |
+
1lxf
|
7978 |
+
2f1b
|
7979 |
+
4zcs
|
7980 |
+
4zw5
|
7981 |
+
2oh0
|
7982 |
+
5n2z
|
7983 |
+
3f19
|
7984 |
+
2obf
|
7985 |
+
6f9t
|
7986 |
+
2f01
|
7987 |
+
6euc
|
7988 |
+
5vee
|
7989 |
+
4oyo
|
7990 |
+
5moq
|
7991 |
+
3ft4
|
7992 |
+
6cbg
|
7993 |
+
5wuu
|
7994 |
+
5f5b
|
7995 |
+
4xs2
|
7996 |
+
1ype
|
7997 |
+
4rwl
|
7998 |
+
4hpi
|
7999 |
+
4e34
|
8000 |
+
1yc1
|
8001 |
+
5jy0
|
8002 |
+
2fxr
|
8003 |
+
5e1m
|
8004 |
+
5oq6
|
8005 |
+
1nhz
|
8006 |
+
3pjt
|
8007 |
+
5jzi
|
8008 |
+
4elf
|
8009 |
+
4fxy
|
8010 |
+
6dpz
|
8011 |
+
5a6a
|
8012 |
+
2waj
|
8013 |
+
2fqt
|
8014 |
+
3mxy
|
8015 |
+
1y91
|
8016 |
+
6biv
|
8017 |
+
4j1k
|
8018 |
+
3zmi
|
8019 |
+
5xjm
|
8020 |
+
2fv5
|
8021 |
+
5db3
|
8022 |
+
3ryj
|
8023 |
+
3b95
|
8024 |
+
3i5r
|
8025 |
+
2ajl
|
8026 |
+
6c99
|
8027 |
+
3bx5
|
8028 |
+
5ave
|
8029 |
+
3muz
|
8030 |
+
2ye9
|
8031 |
+
2rf2
|
8032 |
+
2j2i
|
8033 |
+
5g0q
|
8034 |
+
4yuw
|
8035 |
+
2r3g
|
8036 |
+
4cwf
|
8037 |
+
3t3h
|
8038 |
+
5ajz
|
8039 |
+
2bgr
|
8040 |
+
4l9i
|
8041 |
+
4igk
|
8042 |
+
6cz4
|
8043 |
+
4qfp
|
8044 |
+
5ty8
|
8045 |
+
4odm
|
8046 |
+
3hs8
|
8047 |
+
4ele
|
8048 |
+
5zia
|
8049 |
+
2pvj
|
8050 |
+
5w5k
|
8051 |
+
4m5l
|
8052 |
+
3wz8
|
8053 |
+
4egh
|
8054 |
+
5w7j
|
8055 |
+
4jfw
|
8056 |
+
6eda
|
8057 |
+
5tpb
|
8058 |
+
5m5d
|
8059 |
+
4o71
|
8060 |
+
3kag
|
8061 |
+
4u93
|
8062 |
+
6eed
|
8063 |
+
4zam
|
8064 |
+
2jbp
|
8065 |
+
4z3v
|
8066 |
+
2pu0
|
8067 |
+
4zzd
|
8068 |
+
4f14
|
8069 |
+
4h4d
|
8070 |
+
1pxh
|
8071 |
+
2hwp
|
8072 |
+
1u9e
|
8073 |
+
4wko
|
8074 |
+
5kqx
|
8075 |
+
1tog
|
8076 |
+
4yqu
|
8077 |
+
2yi0
|
8078 |
+
2xf0
|
8079 |
+
4uof
|
8080 |
+
4io7
|
8081 |
+
4ds1
|
8082 |
+
5diq
|
8083 |
+
3ti5
|
8084 |
+
4x8u
|
8085 |
+
2lp8
|
8086 |
+
3avm
|
8087 |
+
3kqm
|
8088 |
+
4zph
|
8089 |
+
2wou
|
8090 |
+
4jyu
|
8091 |
+
3ip8
|
8092 |
+
5ti3
|
8093 |
+
4cku
|
8094 |
+
3h78
|
8095 |
+
3vdb
|
8096 |
+
3chd
|
8097 |
+
4i5h
|
8098 |
+
5i2r
|
8099 |
+
3tyv
|
8100 |
+
4uwk
|
8101 |
+
5j6a
|
8102 |
+
3lk0
|
8103 |
+
5k13
|
8104 |
+
2hj4
|
8105 |
+
3bfu
|
8106 |
+
4ajk
|
8107 |
+
3n45
|
8108 |
+
3te5
|
8109 |
+
3ujb
|
8110 |
+
5v9p
|
8111 |
+
2bzz
|
8112 |
+
3a6t
|
8113 |
+
2y6o
|
8114 |
+
3b28
|
8115 |
+
1hvl
|
8116 |
+
5a2i
|
8117 |
+
4mx9
|
8118 |
+
4g8y
|
8119 |
+
4dko
|
8120 |
+
3kdb
|
8121 |
+
1lf9
|
8122 |
+
4qmp
|
8123 |
+
5q10
|
8124 |
+
3hqr
|
8125 |
+
4d2d
|
8126 |
+
3w32
|
8127 |
+
4ksp
|
8128 |
+
6f8b
|
8129 |
+
3h6z
|
8130 |
+
5k0h
|
8131 |
+
3h2n
|
8132 |
+
5ke0
|
8133 |
+
5w4w
|
8134 |
+
5mxr
|
8135 |
+
5igl
|
8136 |
+
2h9p
|
8137 |
+
4iuu
|
8138 |
+
4d8a
|
8139 |
+
3dvp
|
8140 |
+
1lox
|
8141 |
+
3ao4
|
8142 |
+
4h38
|
8143 |
+
4bdb
|
8144 |
+
4j1p
|
8145 |
+
1o4b
|
8146 |
+
4mro
|
8147 |
+
5eel
|
8148 |
+
2ay3
|
8149 |
+
3e8n
|
8150 |
+
6g8m
|
8151 |
+
2pyy
|
8152 |
+
4m0z
|
8153 |
+
2mas
|
8154 |
+
4ks3
|
8155 |
+
4p72
|
8156 |
+
6ccx
|
8157 |
+
3ttn
|
8158 |
+
4jsr
|
8159 |
+
6aqq
|
8160 |
+
6em6
|
8161 |
+
5o3r
|
8162 |
+
4rqz
|
8163 |
+
4hkk
|
8164 |
+
4qll
|
8165 |
+
2q6f
|
8166 |
+
5he1
|
8167 |
+
4fe9
|
8168 |
+
2wu6
|
8169 |
+
2pj7
|
8170 |
+
1bty
|
8171 |
+
1ule
|
8172 |
+
6dry
|
8173 |
+
5ezg
|
8174 |
+
5h17
|
8175 |
+
3s7b
|
8176 |
+
4x48
|
8177 |
+
3atw
|
8178 |
+
1kug
|
8179 |
+
2hdu
|
8180 |
+
3odu
|
8181 |
+
3l9m
|
8182 |
+
1d1p
|
8183 |
+
2ihj
|
8184 |
+
5mgk
|
8185 |
+
2n1g
|
8186 |
+
6hk6
|
8187 |
+
1mq5
|
8188 |
+
4kp5
|
8189 |
+
1yyr
|
8190 |
+
5al4
|
8191 |
+
1pzj
|
8192 |
+
6axl
|
8193 |
+
2z4b
|
8194 |
+
5mym
|
8195 |
+
4gv8
|
8196 |
+
2cni
|
8197 |
+
4xub
|
8198 |
+
6cjh
|
8199 |
+
3ig1
|
8200 |
+
4m2r
|
8201 |
+
1tt1
|
8202 |
+
5ime
|
8203 |
+
5oei
|
8204 |
+
6d6u
|
8205 |
+
1utj
|
8206 |
+
1dfo
|
8207 |
+
3ixj
|
8208 |
+
5anu
|
8209 |
+
2ogz
|
8210 |
+
5bwb
|
8211 |
+
5vad
|
8212 |
+
2x9e
|
8213 |
+
6epz
|
8214 |
+
4yv2
|
8215 |
+
2jdh
|
8216 |
+
1w13
|
8217 |
+
4eos
|
8218 |
+
4x1f
|
8219 |
+
4gao
|
8220 |
+
5c8k
|
8221 |
+
4k5n
|
8222 |
+
3pj1
|
8223 |
+
5hz5
|
8224 |
+
1x7a
|
8225 |
+
1h9z
|
8226 |
+
6gjm
|
8227 |
+
3ipe
|
8228 |
+
3fuj
|
8229 |
+
4m3d
|
8230 |
+
5g11
|
8231 |
+
4asj
|
8232 |
+
5xig
|
8233 |
+
4ybs
|
8234 |
+
5gmi
|
8235 |
+
3d04
|
8236 |
+
3dv1
|
8237 |
+
2fie
|
8238 |
+
4twt
|
8239 |
+
3ary
|
8240 |
+
4anb
|
8241 |
+
6hmg
|
8242 |
+
4n9c
|
8243 |
+
2lsk
|
8244 |
+
2ksb
|
8245 |
+
5mwd
|
8246 |
+
1gfw
|
8247 |
+
5gja
|
8248 |
+
3u3z
|
8249 |
+
2f7o
|
8250 |
+
3mzc
|
8251 |
+
5w9g
|
8252 |
+
5yz2
|
8253 |
+
4nmq
|
8254 |
+
2y2k
|
8255 |
+
5lz5
|
8256 |
+
4qz7
|
8257 |
+
1bug
|
8258 |
+
4zmf
|
8259 |
+
1o8b
|
8260 |
+
5jf3
|
8261 |
+
2qft
|
8262 |
+
5jop
|
8263 |
+
4jaj
|
8264 |
+
3s9i
|
8265 |
+
6cvy
|
8266 |
+
3oaf
|
8267 |
+
4hlw
|
8268 |
+
5ta6
|
8269 |
+
5mae
|
8270 |
+
2yg2
|
8271 |
+
5m2v
|
8272 |
+
4zxy
|
8273 |
+
1g9r
|
8274 |
+
3iqu
|
8275 |
+
5i9y
|
8276 |
+
3pch
|
8277 |
+
5kkt
|
8278 |
+
2fqo
|
8279 |
+
5mn1
|
8280 |
+
3e3b
|
8281 |
+
4jlj
|
8282 |
+
4tq3
|
8283 |
+
4zga
|
8284 |
+
4jlg
|
8285 |
+
1pf7
|
8286 |
+
5ewd
|
8287 |
+
4dhf
|
8288 |
+
4ywa
|
8289 |
+
5fxr
|
8290 |
+
4e1k
|
8291 |
+
2zmd
|
8292 |
+
4jyv
|
8293 |
+
1fkg
|
8294 |
+
2lwi
|
8295 |
+
6iik
|
8296 |
+
3zxe
|
8297 |
+
6dgx
|
8298 |
+
2vx1
|
8299 |
+
3hav
|
8300 |
+
3pkn
|
8301 |
+
1trd
|
8302 |
+
3u10
|
8303 |
+
2a0c
|
8304 |
+
3ly2
|
8305 |
+
2xn6
|
8306 |
+
1irs
|
8307 |
+
2ntf
|
8308 |
+
3rum
|
8309 |
+
6iin
|
8310 |
+
5hzx
|
8311 |
+
1urw
|
8312 |
+
2xb7
|
8313 |
+
4umr
|
8314 |
+
5apr
|
8315 |
+
5ngt
|
8316 |
+
3q71
|
8317 |
+
3og7
|
8318 |
+
4oeg
|
8319 |
+
4tte
|
8320 |
+
2ow6
|
8321 |
+
3sff
|
8322 |
+
3eu7
|
8323 |
+
2zju
|
8324 |
+
5tx5
|
8325 |
+
3v8t
|
8326 |
+
1nqc
|
8327 |
+
3t2c
|
8328 |
+
4afh
|
8329 |
+
3vhu
|
8330 |
+
2d1x
|
8331 |
+
2h2h
|
8332 |
+
5nvz
|
8333 |
+
4qy8
|
8334 |
+
3w2s
|
8335 |
+
4w9h
|
8336 |
+
4r6v
|
8337 |
+
5esq
|
8338 |
+
5v5d
|
8339 |
+
3rbu
|
8340 |
+
3d51
|
8341 |
+
4q07
|
8342 |
+
4jrv
|
8343 |
+
2in6
|
8344 |
+
3bki
|
8345 |
+
5ov9
|
8346 |
+
6ayd
|
8347 |
+
4zyc
|
8348 |
+
4ybm
|
8349 |
+
4xip
|
8350 |
+
3ibu
|
8351 |
+
5kde
|
8352 |
+
1br5
|
8353 |
+
1lan
|
8354 |
+
1gwq
|
8355 |
+
3ggv
|
8356 |
+
3cke
|
8357 |
+
4av0
|
8358 |
+
4qpd
|
8359 |
+
4urk
|
8360 |
+
4o04
|
8361 |
+
3d4z
|
8362 |
+
4uct
|
8363 |
+
5uwj
|
8364 |
+
4b8y
|
8365 |
+
5nvc
|
8366 |
+
6f23
|
8367 |
+
5w0e
|
8368 |
+
4m84
|
8369 |
+
2hdq
|
8370 |
+
5c6p
|
8371 |
+
2amt
|
8372 |
+
2rgu
|
8373 |
+
4ax9
|
8374 |
+
6g9n
|
8375 |
+
6hu2
|
8376 |
+
6cho
|
8377 |
+
3v7d
|
8378 |
+
5iz9
|
8379 |
+
2vev
|
8380 |
+
3dej
|
8381 |
+
2hxq
|
8382 |
+
4mvx
|
8383 |
+
2c3l
|
8384 |
+
5c29
|
8385 |
+
1we2
|
8386 |
+
6f9u
|
8387 |
+
1m6p
|
8388 |
+
2f80
|
8389 |
+
2ooz
|
8390 |
+
4py2
|
8391 |
+
4zcw
|
8392 |
+
5kx7
|
8393 |
+
4m13
|
8394 |
+
4dhp
|
8395 |
+
4kz6
|
8396 |
+
5ypw
|
8397 |
+
2zdn
|
8398 |
+
1qf5
|
8399 |
+
2i4w
|
8400 |
+
2xu3
|
8401 |
+
1wbn
|
8402 |
+
5lt9
|
8403 |
+
3zmv
|
8404 |
+
4efs
|
8405 |
+
7cpa
|
8406 |
+
2i72
|
8407 |
+
4rpo
|
8408 |
+
2h13
|
8409 |
+
4obo
|
8410 |
+
3f88
|
8411 |
+
6g47
|
8412 |
+
2y6d
|
8413 |
+
3o57
|
8414 |
+
5a0c
|
8415 |
+
2fl6
|
8416 |
+
5mja
|
8417 |
+
5jal
|
8418 |
+
3aqa
|
8419 |
+
3g9l
|
8420 |
+
5g22
|
8421 |
+
5znp
|
8422 |
+
1hi4
|
8423 |
+
1y2a
|
8424 |
+
6ay5
|
8425 |
+
3cf8
|
8426 |
+
3f5k
|
8427 |
+
1a0q
|
8428 |
+
3et7
|
8429 |
+
4eky
|
8430 |
+
6bvb
|
8431 |
+
5u94
|
8432 |
+
1m1b
|
8433 |
+
3ryv
|
8434 |
+
2peh
|
8435 |
+
3vw2
|
8436 |
+
5e1e
|
8437 |
+
3i51
|
8438 |
+
5fb0
|
8439 |
+
1rtl
|
8440 |
+
2i4p
|
8441 |
+
1a9m
|
8442 |
+
6au5
|
8443 |
+
4jyt
|
8444 |
+
4k3k
|
8445 |
+
2c5o
|
8446 |
+
2qu6
|
8447 |
+
4hwr
|
8448 |
+
6bqk
|
8449 |
+
4bqh
|
8450 |
+
5cs6
|
8451 |
+
4dea
|
8452 |
+
4x3r
|
8453 |
+
4iid
|
8454 |
+
6gzm
|
8455 |
+
2y2n
|
8456 |
+
3fuk
|
8457 |
+
2ypi
|
8458 |
+
1b3l
|
8459 |
+
4zsq
|
8460 |
+
4o44
|
8461 |
+
2e1w
|
8462 |
+
3rdo
|
8463 |
+
4zme
|
8464 |
+
4zz2
|
8465 |
+
4ucs
|
8466 |
+
3sl0
|
8467 |
+
6ey9
|
8468 |
+
5arg
|
8469 |
+
3p3r
|
8470 |
+
6an1
|
8471 |
+
3eor
|
8472 |
+
2uue
|
8473 |
+
1n4h
|
8474 |
+
3gk2
|
8475 |
+
3oot
|
8476 |
+
5i5z
|
8477 |
+
3hv3
|
8478 |
+
2hzi
|
8479 |
+
5yc2
|
8480 |
+
1g48
|
8481 |
+
3bxg
|
8482 |
+
5wbq
|
8483 |
+
4a1w
|
8484 |
+
5q0q
|
8485 |
+
4axm
|
8486 |
+
6g91
|
8487 |
+
4q0l
|
8488 |
+
1d8e
|
8489 |
+
1bb0
|
8490 |
+
1lpg
|
8491 |
+
1gmy
|
8492 |
+
6gin
|
8493 |
+
5yy4
|
8494 |
+
2pvv
|
8495 |
+
6ht8
|
8496 |
+
5j82
|
8497 |
+
2x5o
|
8498 |
+
3orn
|
8499 |
+
2nmb
|
8500 |
+
1pk0
|
8501 |
+
3rik
|
8502 |
+
4lkd
|
8503 |
+
1v2n
|
8504 |
+
4ufl
|
8505 |
+
6ahi
|
8506 |
+
5bsk
|
8507 |
+
3uza
|
8508 |
+
2w8f
|
8509 |
+
4nka
|
8510 |
+
6bef
|
8511 |
+
5abw
|
8512 |
+
6bkh
|
8513 |
+
5l30
|
8514 |
+
2clx
|
8515 |
+
4an1
|
8516 |
+
4ufz
|
8517 |
+
5nk6
|
8518 |
+
1syi
|
8519 |
+
3zsy
|
8520 |
+
5ul5
|
8521 |
+
3irx
|
8522 |
+
5ux4
|
8523 |
+
4r5n
|
8524 |
+
4bdc
|
8525 |
+
5fut
|
8526 |
+
3e2m
|
8527 |
+
3lgp
|
8528 |
+
2ivz
|
8529 |
+
1akv
|
8530 |
+
2ydi
|
8531 |
+
4i11
|
8532 |
+
3zxv
|
8533 |
+
4m3e
|
8534 |
+
4kwg
|
8535 |
+
4g2w
|
8536 |
+
3o95
|
8537 |
+
6gu4
|
8538 |
+
2doo
|
8539 |
+
5yun
|
8540 |
+
3n5e
|
8541 |
+
3mqf
|
8542 |
+
2y5k
|
8543 |
+
2vnm
|
8544 |
+
3g0g
|
8545 |
+
1qfs
|
8546 |
+
4o7b
|
8547 |
+
3ty0
|
8548 |
+
4uil
|
8549 |
+
3st5
|
8550 |
+
3f36
|
8551 |
+
6fqo
|
8552 |
+
4pkw
|
8553 |
+
5j6m
|
8554 |
+
4xbo
|
8555 |
+
1hxk
|
8556 |
+
6ghj
|
8557 |
+
1h8y
|
8558 |
+
2pq9
|
8559 |
+
5em3
|
8560 |
+
1rlp
|
8561 |
+
1yvf
|
8562 |
+
4cqg
|
8563 |
+
3srb
|
8564 |
+
6fmk
|
8565 |
+
4o6e
|
8566 |
+
5xmv
|
8567 |
+
4agq
|
8568 |
+
2j3q
|
8569 |
+
1ke9
|
8570 |
+
1mfd
|
8571 |
+
1a5h
|
8572 |
+
4b1j
|
8573 |
+
4i0f
|
8574 |
+
3up2
|
8575 |
+
2ay5
|
8576 |
+
5mqx
|
8577 |
+
3lpu
|
8578 |
+
3bmq
|
8579 |
+
5wfw
|
8580 |
+
4j5b
|
8581 |
+
5alp
|
8582 |
+
5ee8
|
8583 |
+
4qj0
|
8584 |
+
1ka7
|
8585 |
+
3k3h
|
8586 |
+
4np2
|
8587 |
+
3bwj
|
8588 |
+
5osl
|
8589 |
+
5all
|
8590 |
+
4jze
|
8591 |
+
3b3x
|
8592 |
+
3sm0
|
8593 |
+
2xa4
|
8594 |
+
3t3v
|
8595 |
+
3t1n
|
8596 |
+
4yp8
|
8597 |
+
4bc5
|
8598 |
+
5f08
|
8599 |
+
4qw6
|
8600 |
+
5ofv
|
8601 |
+
2bdl
|
8602 |
+
4y83
|
8603 |
+
4y4j
|
8604 |
+
2prj
|
8605 |
+
6cfc
|
8606 |
+
5eth
|
8607 |
+
1oky
|
8608 |
+
2ban
|
8609 |
+
4blb
|
8610 |
+
3f38
|
8611 |
+
2uy3
|
8612 |
+
6fdq
|
8613 |
+
4qmx
|
8614 |
+
4bo5
|
8615 |
+
5wh5
|
8616 |
+
6cvv
|
8617 |
+
2oph
|
8618 |
+
3owb
|
8619 |
+
1xlx
|
8620 |
+
2cf9
|
8621 |
+
4av4
|
8622 |
+
2wxv
|
8623 |
+
5v8p
|
8624 |
+
4eqj
|
8625 |
+
4aoc
|
8626 |
+
5jk3
|
8627 |
+
4xtx
|
8628 |
+
2aoj
|
8629 |
+
1v7a
|
8630 |
+
3lzv
|
8631 |
+
3bum
|
8632 |
+
3fxw
|
8633 |
+
4qhc
|
8634 |
+
1b6j
|
8635 |
+
3f80
|
8636 |
+
4or0
|
8637 |
+
6dq5
|
8638 |
+
5lsx
|
8639 |
+
4bdd
|
8640 |
+
4x8v
|
8641 |
+
4od9
|
8642 |
+
3vye
|
8643 |
+
2yix
|
8644 |
+
1i7i
|
8645 |
+
4eoy
|
8646 |
+
2k4i
|
8647 |
+
2bv4
|
8648 |
+
4z0f
|
8649 |
+
5dp7
|
8650 |
+
4xiq
|
8651 |
+
3d20
|
8652 |
+
5llo
|
8653 |
+
2ymd
|
8654 |
+
4hn2
|
8655 |
+
5n31
|
8656 |
+
4ffs
|
8657 |
+
4b5b
|
8658 |
+
5jf1
|
8659 |
+
4i73
|
8660 |
+
2pqb
|
8661 |
+
2i19
|
8662 |
+
1cbx
|
8663 |
+
1gsz
|
8664 |
+
5ws3
|
8665 |
+
4h3q
|
8666 |
+
5a5q
|
8667 |
+
4uvy
|
8668 |
+
4guj
|
8669 |
+
1i7g
|
8670 |
+
3c8a
|
8671 |
+
4ll3
|
8672 |
+
4pp0
|
8673 |
+
5hk1
|
8674 |
+
4rux
|
8675 |
+
3coj
|
8676 |
+
3d6p
|
8677 |
+
1ndj
|
8678 |
+
1o79
|
8679 |
+
3nsh
|
8680 |
+
5hl9
|
8681 |
+
2e27
|
8682 |
+
5iui
|
8683 |
+
4og5
|
8684 |
+
3wdd
|
8685 |
+
1lnm
|
8686 |
+
3igb
|
8687 |
+
4x24
|
8688 |
+
4tsx
|
8689 |
+
2gmk
|
8690 |
+
5ox5
|
8691 |
+
1bqn
|
8692 |
+
4e8w
|
8693 |
+
5xyf
|
8694 |
+
4uco
|
8695 |
+
1eas
|
8696 |
+
2b7f
|
8697 |
+
4m5u
|
8698 |
+
5evk
|
8699 |
+
3ipu
|
8700 |
+
4p5d
|
8701 |
+
2fsa
|
8702 |
+
4ay5
|
8703 |
+
4bcp
|
8704 |
+
5thj
|
8705 |
+
3tam
|
8706 |
+
4jsc
|
8707 |
+
3ug2
|
8708 |
+
5e7n
|
8709 |
+
1ofz
|
8710 |
+
3uo4
|
8711 |
+
5clm
|
8712 |
+
3gr2
|
8713 |
+
2m0u
|
8714 |
+
6f7q
|
8715 |
+
3sdg
|
8716 |
+
1sme
|
8717 |
+
3g2i
|
8718 |
+
1oyt
|
8719 |
+
3h3c
|
8720 |
+
1xff
|
8721 |
+
4oc6
|
8722 |
+
3b3c
|
8723 |
+
1xa5
|
8724 |
+
1fe3
|
8725 |
+
1g32
|
8726 |
+
5olb
|
8727 |
+
5a85
|
8728 |
+
2oz2
|
8729 |
+
4d8i
|
8730 |
+
5swh
|
8731 |
+
1y2d
|
8732 |
+
1inc
|
8733 |
+
4obz
|
8734 |
+
1c7f
|
8735 |
+
2clh
|
8736 |
+
1qkn
|
8737 |
+
2etm
|
8738 |
+
4i5c
|
8739 |
+
3vd7
|
8740 |
+
1p28
|
8741 |
+
5j7s
|
8742 |
+
1y2j
|
8743 |
+
1aht
|
8744 |
+
4iq6
|
8745 |
+
2pe2
|
8746 |
+
4f3c
|
8747 |
+
4ih7
|
8748 |
+
1hkk
|
8749 |
+
4puj
|
8750 |
+
3o1g
|
8751 |
+
4w9i
|
8752 |
+
3qrj
|
8753 |
+
1qj6
|
8754 |
+
4azg
|
8755 |
+
4joo
|
8756 |
+
6dxx
|
8757 |
+
4sga
|
8758 |
+
1gja
|
8759 |
+
5k4j
|
8760 |
+
4yef
|
8761 |
+
1sbg
|
8762 |
+
3s00
|
8763 |
+
5fcw
|
8764 |
+
4txe
|
8765 |
+
4mr5
|
8766 |
+
1bxo
|
8767 |
+
5xxf
|
8768 |
+
5jic
|
8769 |
+
4abh
|
8770 |
+
3nzx
|
8771 |
+
5edl
|
8772 |
+
3pcf
|
8773 |
+
3k98
|
8774 |
+
3qqu
|
8775 |
+
1hgj
|
8776 |
+
2qch
|
8777 |
+
2yim
|
8778 |
+
4dtt
|
8779 |
+
4l09
|
8780 |
+
3f07
|
8781 |
+
4hki
|
8782 |
+
4cl6
|
8783 |
+
2z5o
|
8784 |
+
4e7r
|
8785 |
+
5amd
|
8786 |
+
1c1v
|
8787 |
+
1ym1
|
8788 |
+
1s64
|
8789 |
+
2w6t
|
8790 |
+
3tl5
|
8791 |
+
1w1y
|
8792 |
+
4eoh
|
8793 |
+
5i58
|
8794 |
+
4z5w
|
8795 |
+
1u2y
|
8796 |
+
6hu1
|
8797 |
+
3wav
|
8798 |
+
1nxy
|
8799 |
+
3n4c
|
8800 |
+
5c91
|
8801 |
+
2kzu
|
8802 |
+
5kre
|
8803 |
+
2jkk
|
8804 |
+
4hkp
|
8805 |
+
4y2y
|
8806 |
+
4w54
|
8807 |
+
4bnu
|
8808 |
+
3lp7
|
8809 |
+
3bla
|
8810 |
+
1gni
|
8811 |
+
2idw
|
8812 |
+
2xy9
|
8813 |
+
2q6b
|
8814 |
+
3uxd
|
8815 |
+
5o9p
|
8816 |
+
3ao1
|
8817 |
+
3v2o
|
8818 |
+
1i00
|
8819 |
+
5ewj
|
8820 |
+
2rgp
|
8821 |
+
2xln
|
8822 |
+
6ma5
|
8823 |
+
4d2w
|
8824 |
+
6eww
|
8825 |
+
4lkq
|
8826 |
+
4o7a
|
8827 |
+
5m4k
|
8828 |
+
5g3n
|
8829 |
+
1wm1
|
8830 |
+
4fzj
|
8831 |
+
2nyr
|
8832 |
+
2mc1
|
8833 |
+
2qky
|
8834 |
+
6eh2
|
8835 |
+
5v1y
|
8836 |
+
4glw
|
8837 |
+
3arb
|
8838 |
+
4gq4
|
8839 |
+
2vin
|
8840 |
+
4rss
|
8841 |
+
3q7j
|
8842 |
+
2h4g
|
8843 |
+
2x2c
|
8844 |
+
1gt4
|
8845 |
+
1fo0
|
8846 |
+
1ftk
|
8847 |
+
4kby
|
8848 |
+
1ch8
|
8849 |
+
5fnu
|
8850 |
+
3sv7
|
8851 |
+
2vvo
|
8852 |
+
5uah
|
8853 |
+
3k97
|
8854 |
+
2wpa
|
8855 |
+
1a4h
|
8856 |
+
5lhg
|
8857 |
+
6eeh
|
8858 |
+
4mse
|
8859 |
+
3nnv
|
8860 |
+
6eq4
|
8861 |
+
5f1l
|
8862 |
+
3q0z
|
8863 |
+
3elm
|
8864 |
+
2uzd
|
8865 |
+
3p2e
|
8866 |
+
1r0p
|
8867 |
+
1j16
|
8868 |
+
2qhz
|
8869 |
+
5h0b
|
8870 |
+
4nyt
|
8871 |
+
5ij7
|
8872 |
+
4l2l
|
8873 |
+
1afl
|
8874 |
+
5vd0
|
8875 |
+
4i10
|
8876 |
+
1opi
|
8877 |
+
2ves
|
8878 |
+
5tyn
|
8879 |
+
3gf2
|
8880 |
+
3nuo
|
8881 |
+
5w2p
|
8882 |
+
4uv9
|
8883 |
+
3sut
|
8884 |
+
2f3f
|
8885 |
+
1dmb
|
8886 |
+
3wd2
|
8887 |
+
4xm8
|
8888 |
+
4kp4
|
8889 |
+
1hy7
|
8890 |
+
4xbd
|
8891 |
+
5m6h
|
8892 |
+
1g05
|
8893 |
+
4zh3
|
8894 |
+
5d0c
|
8895 |
+
2e7l
|
8896 |
+
3kba
|
8897 |
+
5nhh
|
8898 |
+
2pax
|
8899 |
+
1p0y
|
8900 |
+
2l7u
|
8901 |
+
3wns
|
8902 |
+
5u4d
|
8903 |
+
3axk
|
8904 |
+
4qpl
|
8905 |
+
5jt2
|
8906 |
+
2rk7
|
8907 |
+
5lss
|
8908 |
+
3sni
|
8909 |
+
5aaa
|
8910 |
+
5wfm
|
8911 |
+
4pb1
|
8912 |
+
3oe4
|
8913 |
+
5m63
|
8914 |
+
5xg5
|
8915 |
+
3lle
|
8916 |
+
2yac
|
8917 |
+
4odk
|
8918 |
+
2x95
|
8919 |
+
2ig0
|
8920 |
+
2zdl
|
8921 |
+
4ay6
|
8922 |
+
2c1a
|
8923 |
+
1nny
|
8924 |
+
1nw4
|
8925 |
+
2fj0
|
8926 |
+
3kah
|
8927 |
+
4db7
|
8928 |
+
1bxq
|
8929 |
+
3ifl
|
8930 |
+
5f9e
|
8931 |
+
4p2t
|
8932 |
+
4exh
|
8933 |
+
6d2o
|
8934 |
+
5t2b
|
8935 |
+
6eee
|
8936 |
+
2oi0
|
8937 |
+
3lpl
|
8938 |
+
4tk3
|
8939 |
+
1o6i
|
8940 |
+
6eux
|
8941 |
+
2ojj
|
8942 |
+
3pyy
|
8943 |
+
4edz
|
8944 |
+
3jy0
|
8945 |
+
3r5t
|
8946 |
+
4xdo
|
8947 |
+
3qo9
|
8948 |
+
4u2w
|
8949 |
+
5nme
|
8950 |
+
6hdn
|
8951 |
+
4mre
|
8952 |
+
4ryg
|
8953 |
+
5ez0
|
8954 |
+
3c14
|
8955 |
+
5kzi
|
8956 |
+
6bix
|
8957 |
+
3uug
|
8958 |
+
5ldm
|
8959 |
+
1o2v
|
8960 |
+
4llx
|
8961 |
+
3lw0
|
8962 |
+
2op9
|
8963 |
+
4nhc
|
8964 |
+
5wqj
|
8965 |
+
5wi1
|
8966 |
+
4e20
|
8967 |
+
6fjf
|
8968 |
+
2x2m
|
8969 |
+
5l98
|
8970 |
+
3qsd
|
8971 |
+
5lcj
|
8972 |
+
5t23
|
8973 |
+
1adl
|
8974 |
+
2wa8
|
8975 |
+
4q9y
|
8976 |
+
2rkg
|
8977 |
+
4gid
|
8978 |
+
3f70
|
8979 |
+
2xk6
|
8980 |
+
5t8e
|
8981 |
+
4lxb
|
8982 |
+
2xp2
|
8983 |
+
3juk
|
8984 |
+
5uf0
|
8985 |
+
3l1s
|
8986 |
+
6evr
|
8987 |
+
1lag
|
8988 |
+
1awi
|
8989 |
+
6ej4
|
8990 |
+
1pmx
|
8991 |
+
4kln
|
8992 |
+
3wgg
|
8993 |
+
5g61
|
8994 |
+
5n69
|
8995 |
+
4o9v
|
8996 |
+
3kqc
|
8997 |
+
1him
|
8998 |
+
3cd0
|
8999 |
+
2kbs
|
9000 |
+
1moq
|
9001 |
+
2f10
|
9002 |
+
2zb0
|
9003 |
+
2d41
|
9004 |
+
4bdh
|
9005 |
+
1ebz
|
9006 |
+
5lcf
|
9007 |
+
5u13
|
9008 |
+
4qwk
|
9009 |
+
4cd8
|
9010 |
+
4d85
|
9011 |
+
1tvr
|
9012 |
+
4l6s
|
9013 |
+
3pd4
|
9014 |
+
1hq5
|
9015 |
+
5tiu
|
9016 |
+
1o44
|
9017 |
+
6g22
|
9018 |
+
2ckm
|
9019 |
+
4btk
|
9020 |
+
2cli
|
9021 |
+
6cb5
|
9022 |
+
3o0u
|
9023 |
+
5u4x
|
9024 |
+
4lp6
|
9025 |
+
5afk
|
9026 |
+
2o3p
|
9027 |
+
1zpc
|
9028 |
+
3qo3
|
9029 |
+
3d1z
|
9030 |
+
2z3h
|
9031 |
+
1hms
|
9032 |
+
5ox6
|
9033 |
+
5fpp
|
9034 |
+
3f3d
|
9035 |
+
5t78
|
9036 |
+
5hg5
|
9037 |
+
3mxe
|
9038 |
+
4i7l
|
9039 |
+
1tuf
|
9040 |
+
5lmk
|
9041 |
+
3nu9
|
9042 |
+
5om9
|
9043 |
+
2qi3
|
9044 |
+
3l5b
|
9045 |
+
4v0i
|
9046 |
+
2nv7
|
9047 |
+
2wkt
|
9048 |
+
4ndu
|
9049 |
+
1aq1
|
9050 |
+
3ddq
|
9051 |
+
1vyj
|
9052 |
+
5ods
|
9053 |
+
1b8n
|
9054 |
+
4xhl
|
9055 |
+
4jft
|
9056 |
+
3n7o
|
9057 |
+
4og6
|
9058 |
+
5j9z
|
9059 |
+
5ufr
|
9060 |
+
4qjm
|
9061 |
+
3g4g
|
9062 |
+
5jox
|
9063 |
+
2std
|
9064 |
+
4uvx
|
9065 |
+
2yb9
|
9066 |
+
3qaa
|
9067 |
+
5mwo
|
9068 |
+
2onz
|
9069 |
+
2hiw
|
9070 |
+
1xnz
|
9071 |
+
2agv
|
9072 |
+
4qgg
|
9073 |
+
5x28
|
9074 |
+
2dw7
|
9075 |
+
2ohk
|
9076 |
+
4oue
|
9077 |
+
1o4a
|
9078 |
+
6ds0
|
9079 |
+
3t5u
|
9080 |
+
3ij1
|
9081 |
+
4klv
|
9082 |
+
3lgl
|
9083 |
+
2wey
|
9084 |
+
1qk3
|
9085 |
+
4i0d
|
9086 |
+
1rti
|
9087 |
+
3clp
|
9088 |
+
4f8h
|
9089 |
+
4qwj
|
9090 |
+
1bmb
|
9091 |
+
5jar
|
9092 |
+
5a5z
|
9093 |
+
5ofu
|
9094 |
+
2yiu
|
9095 |
+
2z5t
|
9096 |
+
5emm
|
9097 |
+
4ibm
|
9098 |
+
5lzh
|
9099 |
+
4xh2
|
9100 |
+
3t09
|
9101 |
+
2p95
|
9102 |
+
1fmb
|
9103 |
+
1gj5
|
9104 |
+
3s72
|
9105 |
+
5ia5
|
9106 |
+
4kp6
|
9107 |
+
1s9t
|
9108 |
+
2fhy
|
9109 |
+
4del
|
9110 |
+
3ao5
|
9111 |
+
4xii
|
9112 |
+
5cp9
|
9113 |
+
3vb4
|
9114 |
+
3sha
|
9115 |
+
5el2
|
9116 |
+
2uup
|
9117 |
+
6bfe
|
9118 |
+
4jv6
|
9119 |
+
3e8u
|
9120 |
+
3ubd
|
9121 |
+
1tys
|
9122 |
+
4p10
|
9123 |
+
5ekj
|
9124 |
+
1d5j
|
9125 |
+
4bpi
|
9126 |
+
3n23
|
9127 |
+
3amb
|
9128 |
+
4gue
|
9129 |
+
4n8q
|
9130 |
+
1o0d
|
9131 |
+
4d1j
|
9132 |
+
1a9q
|
9133 |
+
2vtq
|
9134 |
+
1h1d
|
9135 |
+
5uw5
|
9136 |
+
6bfp
|
9137 |
+
3tfu
|
9138 |
+
5xyz
|
9139 |
+
2q1l
|
9140 |
+
4m7j
|
9141 |
+
3m8u
|
9142 |
+
5kbf
|
9143 |
+
3btl
|
9144 |
+
4ctj
|
9145 |
+
1koj
|
9146 |
+
2ajb
|
9147 |
+
3unz
|
9148 |
+
2xgs
|
9149 |
+
4pd9
|
9150 |
+
5g1c
|
9151 |
+
5w19
|
9152 |
+
5vqw
|
9153 |
+
5yc8
|
9154 |
+
4ufd
|
9155 |
+
1w83
|
9156 |
+
4qdk
|
9157 |
+
1tyn
|
9158 |
+
6buv
|
9159 |
+
4amw
|
9160 |
+
3dnd
|
9161 |
+
1d7j
|
9162 |
+
1nzv
|
9163 |
+
4ryl
|
9164 |
+
2f6j
|
9165 |
+
6bbx
|
9166 |
+
5lgp
|
9167 |
+
6ay3
|
9168 |
+
1fwv
|
9169 |
+
2qg0
|
9170 |
+
3mg4
|
9171 |
+
3qmk
|
9172 |
+
4dma
|
9173 |
+
2r3c
|
9174 |
+
1d6s
|
9175 |
+
5dsx
|
9176 |
+
1tg5
|
9177 |
+
6do3
|
9178 |
+
5n7v
|
9179 |
+
1g5f
|
9180 |
+
1c5q
|
9181 |
+
1lb6
|
9182 |
+
4pv7
|
9183 |
+
3ii5
|
9184 |
+
4rab
|
9185 |
+
4eke
|
9186 |
+
2w10
|
9187 |
+
5i86
|
9188 |
+
1uho
|
9189 |
+
5vsf
|
9190 |
+
3g08
|
9191 |
+
2zxg
|
9192 |
+
4btl
|
9193 |
+
3hb4
|
9194 |
+
5j4y
|
9195 |
+
5lgt
|
9196 |
+
6boy
|
9197 |
+
5kva
|
9198 |
+
5mka
|
9199 |
+
5wa8
|
9200 |
+
2i0e
|
9201 |
+
3ptg
|
9202 |
+
5vp9
|
9203 |
+
4mw2
|
9204 |
+
3djf
|
9205 |
+
6b7d
|
9206 |
+
5t1a
|
9207 |
+
5hrw
|
9208 |
+
5e2o
|
9209 |
+
4xuc
|
9210 |
+
3vg1
|
9211 |
+
6c4g
|
9212 |
+
2csn
|
9213 |
+
3q32
|
9214 |
+
4q9m
|
9215 |
+
3vry
|
9216 |
+
3fv7
|
9217 |
+
5lhh
|
9218 |
+
3fh5
|
9219 |
+
2qry
|
9220 |
+
4f9g
|
9221 |
+
4c8r
|
9222 |
+
4m6p
|
9223 |
+
4riu
|
9224 |
+
3dp3
|
9225 |
+
2r3i
|
9226 |
+
3bwk
|
9227 |
+
6ew3
|
9228 |
+
4bs5
|
9229 |
+
4g3e
|
9230 |
+
2wvz
|
9231 |
+
3wc5
|
9232 |
+
4nb6
|
9233 |
+
5xmr
|
9234 |
+
4ps5
|
9235 |
+
4dvi
|
9236 |
+
3uvm
|
9237 |
+
5os7
|
9238 |
+
2xix
|
9239 |
+
5alw
|
9240 |
+
3iaw
|
9241 |
+
2xnp
|
9242 |
+
6dvo
|
9243 |
+
1cgl
|
9244 |
+
4xv3
|
9245 |
+
5dya
|
9246 |
+
3c79
|
9247 |
+
2e9a
|
9248 |
+
6dil
|
9249 |
+
4caf
|
9250 |
+
4tpw
|
9251 |
+
5fov
|
9252 |
+
5n3w
|
9253 |
+
5ttv
|
9254 |
+
6f3b
|
9255 |
+
5cas
|
9256 |
+
5aqg
|
9257 |
+
3dz2
|
9258 |
+
1xhy
|
9259 |
+
3t01
|
9260 |
+
5th4
|
9261 |
+
4i80
|
9262 |
+
4q3t
|
9263 |
+
2ceq
|
9264 |
+
4yff
|
9265 |
+
3bti
|
9266 |
+
5vll
|
9267 |
+
4hy4
|
9268 |
+
6g3y
|
9269 |
+
4ykn
|
9270 |
+
5lu2
|
9271 |
+
5wg7
|
9272 |
+
3fnu
|
9273 |
+
6g84
|
9274 |
+
6ap6
|
9275 |
+
6hpg
|
9276 |
+
1c3x
|
9277 |
+
5if4
|
9278 |
+
5wgp
|
9279 |
+
3d6q
|
9280 |
+
2wer
|
9281 |
+
2qrq
|
9282 |
+
4cfl
|
9283 |
+
3uib
|
9284 |
+
6fgf
|
9285 |
+
5tx3
|
9286 |
+
3plu
|
9287 |
+
1zzl
|
9288 |
+
6db4
|
9289 |
+
5tpg
|
9290 |
+
3k8o
|
9291 |
+
2fxv
|
9292 |
+
3c2u
|
9293 |
+
1w8l
|
9294 |
+
1di8
|
9295 |
+
3udh
|
9296 |
+
4cu1
|
9297 |
+
5gvl
|
9298 |
+
5nvx
|
9299 |
+
1bt6
|
9300 |
+
6d9x
|
9301 |
+
1vjb
|
9302 |
+
6b31
|
9303 |
+
2qo1
|
9304 |
+
3daz
|
9305 |
+
1v0l
|
9306 |
+
5nuu
|
9307 |
+
2qtb
|
9308 |
+
5ewy
|
9309 |
+
4i9u
|
9310 |
+
4afj
|
9311 |
+
5hzn
|
9312 |
+
2ohq
|
9313 |
+
4eqc
|
9314 |
+
3p8h
|
9315 |
+
5y53
|
9316 |
+
1kat
|
9317 |
+
4kwo
|
9318 |
+
2hiz
|
9319 |
+
2cmf
|
9320 |
+
4bgx
|
9321 |
+
4hys
|
9322 |
+
4lww
|
9323 |
+
3k39
|
9324 |
+
3rdq
|
9325 |
+
4ega
|
9326 |
+
5fsl
|
9327 |
+
3ehw
|
9328 |
+
5gnk
|
9329 |
+
5n8b
|
9330 |
+
6h29
|
9331 |
+
1dy4
|
9332 |
+
3nu6
|
9333 |
+
5dxu
|
9334 |
+
5jf8
|
9335 |
+
2qd9
|
9336 |
+
5zaj
|
9337 |
+
1oif
|
9338 |
+
2v8w
|
9339 |
+
1ywi
|
9340 |
+
5uiq
|
9341 |
+
1xr8
|
9342 |
+
4yvz
|
9343 |
+
2y82
|
9344 |
+
1pkx
|
9345 |
+
2qbw
|
9346 |
+
1ebg
|
9347 |
+
3a4p
|
9348 |
+
3ful
|
9349 |
+
4d62
|
9350 |
+
5qb2
|
9351 |
+
6bgx
|
9352 |
+
1ela
|
9353 |
+
5j59
|
9354 |
+
2q63
|
9355 |
+
6cmj
|
9356 |
+
2p9a
|
9357 |
+
5nwk
|
9358 |
+
3w54
|
9359 |
+
4rrg
|
9360 |
+
2l1r
|
9361 |
+
2gsu
|
9362 |
+
2wva
|
9363 |
+
2vpn
|
9364 |
+
1qji
|
9365 |
+
4gts
|
9366 |
+
6gnw
|
9367 |
+
4afg
|
9368 |
+
5ty9
|
9369 |
+
4ps7
|
9370 |
+
3r2f
|
9371 |
+
3qak
|
9372 |
+
4dgg
|
9373 |
+
5f67
|
9374 |
+
1kak
|
9375 |
+
4mc9
|
9376 |
+
4dpu
|
9377 |
+
4u5o
|
9378 |
+
3h06
|
9379 |
+
2b4m
|
9380 |
+
4q99
|
9381 |
+
4dgb
|
9382 |
+
4hw2
|
9383 |
+
5uvc
|
9384 |
+
1yxd
|
9385 |
+
4cix
|
9386 |
+
4ehm
|
9387 |
+
5his
|
9388 |
+
2ihq
|
9389 |
+
4kmd
|
9390 |
+
5cin
|
9391 |
+
5v7i
|
9392 |
+
3itz
|
9393 |
+
3il5
|
9394 |
+
3brn
|
9395 |
+
1h4w
|
9396 |
+
2ilp
|
9397 |
+
6bnk
|
9398 |
+
1me3
|
9399 |
+
5fh7
|
9400 |
+
1rgk
|
9401 |
+
3iub
|
9402 |
+
3p4q
|
9403 |
+
1njt
|
9404 |
+
1ya4
|
9405 |
+
2x6i
|
9406 |
+
3e81
|
9407 |
+
4yl0
|
9408 |
+
1at6
|
9409 |
+
3pr0
|
9410 |
+
5wf3
|
9411 |
+
4uzh
|
9412 |
+
5f2k
|
9413 |
+
4j93
|
9414 |
+
4dwg
|
9415 |
+
5ti2
|
9416 |
+
4pcs
|
9417 |
+
3qcj
|
9418 |
+
4qjo
|
9419 |
+
4dpf
|
9420 |
+
4qer
|
9421 |
+
2kp8
|
9422 |
+
4o2p
|
9423 |
+
4pd6
|
9424 |
+
2op3
|
9425 |
+
6got
|
9426 |
+
2weq
|
9427 |
+
4lh7
|
9428 |
+
5l97
|
9429 |
+
6bed
|
9430 |
+
5o1e
|
9431 |
+
4ezt
|
9432 |
+
5y8w
|
9433 |
+
1err
|
9434 |
+
4rj7
|
9435 |
+
2yol
|
9436 |
+
5t68
|
9437 |
+
2ltx
|
9438 |
+
5g17
|
9439 |
+
1mxl
|
9440 |
+
4c7t
|
9441 |
+
3uvu
|
9442 |
+
5a3r
|
9443 |
+
4yuz
|
9444 |
+
3nf9
|
9445 |
+
2fix
|
9446 |
+
3pgu
|
9447 |
+
4kn1
|
9448 |
+
3mi3
|
9449 |
+
5dpw
|
9450 |
+
3e5a
|
9451 |
+
1y1z
|
9452 |
+
5j8i
|
9453 |
+
4e5d
|
9454 |
+
3cd8
|
9455 |
+
6ccl
|
9456 |
+
4x9r
|
9457 |
+
3rtx
|
9458 |
+
2zmj
|
9459 |
+
1xp6
|
9460 |
+
6cks
|
9461 |
+
3fw3
|
9462 |
+
4znx
|
9463 |
+
4nyj
|
9464 |
+
1q1g
|
9465 |
+
2ews
|
9466 |
+
5o5m
|
9467 |
+
4w4v
|
9468 |
+
2w1d
|
9469 |
+
5d1j
|
9470 |
+
5fbe
|
9471 |
+
3ipq
|
9472 |
+
2qk5
|
9473 |
+
2ydj
|
9474 |
+
3gv6
|
9475 |
+
1mxo
|
9476 |
+
5l9h
|
9477 |
+
3odk
|
9478 |
+
6cze
|
9479 |
+
6c98
|
9480 |
+
2wmx
|
9481 |
+
3qa2
|
9482 |
+
5oax
|
9483 |
+
6gnm
|
9484 |
+
3q6z
|
9485 |
+
2oqv
|
9486 |
+
5exn
|
9487 |
+
3s53
|
9488 |
+
5lzg
|
9489 |
+
3mo5
|
9490 |
+
6drz
|
9491 |
+
5nn5
|
9492 |
+
4x1q
|
9493 |
+
2mow
|
9494 |
+
3ow3
|
9495 |
+
4ebw
|
9496 |
+
4a4c
|
9497 |
+
6ema
|
9498 |
+
2h6q
|
9499 |
+
2fjm
|
9500 |
+
5uez
|
9501 |
+
6et8
|
9502 |
+
6ep9
|
9503 |
+
1avd
|
9504 |
+
2q80
|
9505 |
+
4nj3
|
9506 |
+
4mdr
|
9507 |
+
5ely
|
9508 |
+
5dri
|
9509 |
+
1v2r
|
9510 |
+
1hk4
|
9511 |
+
5xfj
|
9512 |
+
4z0q
|
9513 |
+
4heg
|
9514 |
+
5h3q
|
9515 |
+
2buv
|
9516 |
+
4l7d
|
9517 |
+
3nb5
|
9518 |
+
1g9b
|
9519 |
+
3oay
|
9520 |
+
4aj4
|
9521 |
+
1bxr
|
9522 |
+
2w9h
|
9523 |
+
2iws
|
9524 |
+
3oy1
|
9525 |
+
3qpo
|
9526 |
+
2hog
|
9527 |
+
3rl8
|
9528 |
+
1zgb
|
9529 |
+
1a4w
|
9530 |
+
3vvz
|
9531 |
+
5ia4
|
9532 |
+
6f1n
|
9533 |
+
1x70
|
9534 |
+
3q5u
|
9535 |
+
4do4
|
9536 |
+
2pcp
|
9537 |
+
5m77
|
9538 |
+
4a50
|
9539 |
+
1elb
|
9540 |
+
1rri
|
9541 |
+
2ydm
|
9542 |
+
3ldp
|
9543 |
+
4k9g
|
9544 |
+
2ptz
|
9545 |
+
3uo6
|
9546 |
+
2qwd
|
9547 |
+
5fdz
|
9548 |
+
6fiv
|
9549 |
+
1hqh
|
9550 |
+
5q12
|
9551 |
+
5anv
|
9552 |
+
5k5e
|
9553 |
+
5aer
|
9554 |
+
1jys
|
9555 |
+
2zu3
|
9556 |
+
2oiq
|
9557 |
+
5lwn
|
9558 |
+
1i9o
|
9559 |
+
1npv
|
9560 |
+
4piq
|
9561 |
+
2w0j
|
9562 |
+
6c5f
|
9563 |
+
1w8m
|
9564 |
+
5gjd
|
9565 |
+
5yql
|
9566 |
+
1m83
|
9567 |
+
4djv
|
9568 |
+
3ns9
|
9569 |
+
3zn1
|
9570 |
+
4eg7
|
9571 |
+
3u4r
|
9572 |
+
6hu0
|
9573 |
+
4awq
|
9574 |
+
4l6q
|
9575 |
+
1ad8
|
9576 |
+
3d9k
|
9577 |
+
5ucj
|
9578 |
+
3piz
|
9579 |
+
3ekt
|
9580 |
+
1g9a
|
9581 |
+
3m2w
|
9582 |
+
5q1c
|
9583 |
+
1mv0
|
9584 |
+
6emh
|
9585 |
+
1ttv
|
9586 |
+
5u12
|
9587 |
+
1lhf
|
9588 |
+
1w1p
|
9589 |
+
2i4t
|
9590 |
+
4z68
|
9591 |
+
4gqr
|
9592 |
+
3uqp
|
9593 |
+
1rhq
|
9594 |
+
3oxc
|
9595 |
+
4mc6
|
9596 |
+
3adt
|
9597 |
+
3ivi
|
9598 |
+
3r8u
|
9599 |
+
1udt
|
9600 |
+
1o36
|
9601 |
+
4ou3
|
9602 |
+
6apz
|
9603 |
+
5gmp
|
9604 |
+
2l84
|
9605 |
+
2gg9
|
9606 |
+
3o64
|
9607 |
+
3uo9
|
9608 |
+
4qht
|
9609 |
+
6f6r
|
9610 |
+
3hy7
|
9611 |
+
1nox
|
9612 |
+
5u6v
|
9613 |
+
3ans
|
9614 |
+
1mdl
|
9615 |
+
3d2e
|
9616 |
+
2fsv
|
9617 |
+
5t2m
|
9618 |
+
3p79
|
9619 |
+
4je7
|
9620 |
+
3gta
|
9621 |
+
4q9z
|
9622 |
+
6f55
|
9623 |
+
1gu1
|
9624 |
+
5y6k
|
9625 |
+
3ert
|
9626 |
+
3ant
|
9627 |
+
5a3h
|
9628 |
+
3zdv
|
9629 |
+
3o1d
|
9630 |
+
6ar4
|
9631 |
+
2ym4
|
9632 |
+
3s3v
|
9633 |
+
3fk1
|
9634 |
+
3pbb
|
9635 |
+
3r6c
|
9636 |
+
1xh8
|
9637 |
+
5lh4
|
9638 |
+
5q0w
|
9639 |
+
2psu
|
9640 |
+
5gty
|
9641 |
+
2qi0
|
9642 |
+
2nn7
|
9643 |
+
5vb6
|
9644 |
+
4b8o
|
9645 |
+
1zp8
|
9646 |
+
5uqv
|
9647 |
+
4pci
|
9648 |
+
5f5z
|
9649 |
+
4rj4
|
9650 |
+
6dh4
|
9651 |
+
3lce
|
9652 |
+
4ea2
|
9653 |
+
4y6m
|
9654 |
+
5d3p
|
9655 |
+
1gsf
|
9656 |
+
4l7l
|
9657 |
+
1tkt
|
9658 |
+
3a29
|
9659 |
+
5ljj
|
9660 |
+
4gpk
|
9661 |
+
3ayc
|
9662 |
+
3qkv
|
9663 |
+
3ern
|
9664 |
+
3zhf
|
9665 |
+
1f4y
|
9666 |
+
6bgg
|
9667 |
+
5uz0
|
9668 |
+
2znt
|
9669 |
+
5du4
|
9670 |
+
1utn
|
9671 |
+
5ayy
|
9672 |
+
1lzo
|
9673 |
+
1gym
|
9674 |
+
5k8s
|
9675 |
+
3kb3
|
9676 |
+
3ijy
|
9677 |
+
5oa2
|
9678 |
+
5wio
|
9679 |
+
1yei
|
9680 |
+
4hlh
|
9681 |
+
2eg8
|
9682 |
+
5tkd
|
9683 |
+
1kpm
|
9684 |
+
3tpr
|
9685 |
+
3mt9
|
9686 |
+
3tcy
|
9687 |
+
4qxr
|
9688 |
+
3uyt
|
9689 |
+
3o9l
|
9690 |
+
5ejv
|
9691 |
+
6ekn
|
9692 |
+
2fky
|
9693 |
+
5vp0
|
9694 |
+
4rxa
|
9695 |
+
2xpa
|
9696 |
+
1kav
|
9697 |
+
3ecn
|
9698 |
+
5vlh
|
9699 |
+
4lko
|
9700 |
+
2g83
|
9701 |
+
4m5r
|
9702 |
+
5iql
|
9703 |
+
5g53
|
9704 |
+
3fhe
|
9705 |
+
2xj7
|
9706 |
+
3u78
|
9707 |
+
3zt3
|
9708 |
+
4hkn
|
9709 |
+
4h58
|
9710 |
+
4f1l
|
9711 |
+
5q0t
|
9712 |
+
2jkh
|
9713 |
+
5w13
|
9714 |
+
3r88
|
9715 |
+
1yvz
|
9716 |
+
4qmq
|
9717 |
+
5aag
|
9718 |
+
1b6m
|
9719 |
+
4i47
|
9720 |
+
6d5e
|
9721 |
+
6c91
|
9722 |
+
1z95
|
9723 |
+
4ca6
|
9724 |
+
4ysl
|
9725 |
+
4gbz
|
9726 |
+
1aj7
|
9727 |
+
1wcq
|
9728 |
+
3m96
|
9729 |
+
5t92
|
9730 |
+
6gjl
|
9731 |
+
4yxo
|
9732 |
+
5l2m
|
9733 |
+
4wov
|
9734 |
+
3l2y
|
9735 |
+
5v5y
|
9736 |
+
3a3y
|
9737 |
+
2gmx
|
9738 |
+
2fo4
|
9739 |
+
2h5j
|
9740 |
+
2r05
|
9741 |
+
2qtt
|
9742 |
+
4jn4
|
9743 |
+
5npf
|
9744 |
+
1gt5
|
9745 |
+
4jfd
|
9746 |
+
2qhr
|
9747 |
+
2sfp
|
9748 |
+
3rx5
|
9749 |
+
4e4l
|
9750 |
+
4mao
|
9751 |
+
1zkl
|
9752 |
+
3syr
|
9753 |
+
3jzj
|
9754 |
+
5h9q
|
9755 |
+
5one
|
9756 |
+
4io6
|
9757 |
+
3lp2
|
9758 |
+
2i4j
|
9759 |
+
3rlp
|
9760 |
+
5eta
|
9761 |
+
4yth
|
9762 |
+
3r24
|
9763 |
+
3gsg
|
9764 |
+
2of4
|
9765 |
+
5inh
|
9766 |
+
3ed0
|
9767 |
+
3zlr
|
9768 |
+
5llp
|
9769 |
+
6esj
|
9770 |
+
5c8m
|
9771 |
+
3dkf
|
9772 |
+
4z6h
|
9773 |
+
4x6o
|
9774 |
+
2j47
|
9775 |
+
1usk
|
9776 |
+
5w8j
|
9777 |
+
4x1p
|
9778 |
+
1xb7
|
9779 |
+
1lqe
|
9780 |
+
4apr
|
9781 |
+
5khm
|
9782 |
+
2ga2
|
9783 |
+
2ly0
|
9784 |
+
4zro
|
9785 |
+
4e26
|
9786 |
+
4g16
|
9787 |
+
4uvw
|
9788 |
+
1f5l
|
9789 |
+
4ipn
|
9790 |
+
4hwt
|
9791 |
+
4g90
|
9792 |
+
1kds
|
9793 |
+
4bck
|
9794 |
+
5k6s
|
9795 |
+
5eqp
|
9796 |
+
1vwn
|
9797 |
+
4uye
|
9798 |
+
4gtq
|
9799 |
+
6fe1
|
9800 |
+
6gjj
|
9801 |
+
3hb8
|
9802 |
+
2zdm
|
9803 |
+
5alz
|
9804 |
+
3eyg
|
9805 |
+
4lkk
|
9806 |
+
4os2
|
9807 |
+
1j4q
|
9808 |
+
4o36
|
9809 |
+
5dtm
|
9810 |
+
2wgi
|
9811 |
+
6faf
|
9812 |
+
1mx1
|
9813 |
+
3lfn
|
9814 |
+
2i1r
|
9815 |
+
3hzy
|
9816 |
+
1a4k
|
9817 |
+
4zl4
|
9818 |
+
1dub
|
9819 |
+
3qi3
|
9820 |
+
3i90
|
9821 |
+
3qgy
|
9822 |
+
6gfy
|
9823 |
+
1o2u
|
9824 |
+
4xyn
|
9825 |
+
3rk7
|
9826 |
+
6atv
|
9827 |
+
2wu7
|
9828 |
+
4tnw
|
9829 |
+
2uwo
|
9830 |
+
1z6p
|
9831 |
+
3p8o
|
9832 |
+
3my1
|
9833 |
+
3s3q
|
9834 |
+
5w0l
|
9835 |
+
4tw8
|
9836 |
+
6b8u
|
9837 |
+
5jg1
|
9838 |
+
2azm
|
9839 |
+
4qw3
|
9840 |
+
5ntk
|
9841 |
+
5jq8
|
9842 |
+
3gcq
|
9843 |
+
2zcs
|
9844 |
+
2pvw
|
9845 |
+
1o0n
|
9846 |
+
1ph0
|
9847 |
+
3nu5
|
9848 |
+
5loh
|
9849 |
+
1t08
|
9850 |
+
4m7b
|
9851 |
+
1qpl
|
9852 |
+
4ge5
|
9853 |
+
4w9s
|
9854 |
+
5fat
|
9855 |
+
5l2w
|
9856 |
+
5nx2
|
9857 |
+
2gst
|
9858 |
+
2pix
|
9859 |
+
5myn
|
9860 |
+
3ump
|
9861 |
+
2xoi
|
9862 |
+
4r7m
|
9863 |
+
5ful
|
9864 |
+
1kf6
|
9865 |
+
2on3
|
9866 |
+
5wa9
|
9867 |
+
5tw3
|
9868 |
+
1q4k
|
9869 |
+
6fu4
|
9870 |
+
5umx
|
9871 |
+
2bdy
|
9872 |
+
4ezy
|
9873 |
+
4crj
|
9874 |
+
4pyx
|
9875 |
+
5t97
|
9876 |
+
2cet
|
9877 |
+
1fao
|
9878 |
+
1n46
|
9879 |
+
2ooh
|
9880 |
+
3dgo
|
9881 |
+
4io4
|
9882 |
+
1xjd
|
9883 |
+
1q72
|
9884 |
+
3mag
|
9885 |
+
6euv
|
9886 |
+
4g5f
|
9887 |
+
4dgm
|
9888 |
+
5o1c
|
9889 |
+
3ken
|
9890 |
+
4d2r
|
9891 |
+
5fnq
|
9892 |
+
4z7f
|
9893 |
+
2o3z
|
9894 |
+
4xgz
|
9895 |
+
4i2z
|
9896 |
+
6g15
|
9897 |
+
5ypp
|
9898 |
+
2x09
|
9899 |
+
5lt6
|
9900 |
+
3k5g
|
9901 |
+
2xej
|
9902 |
+
1uyh
|
9903 |
+
4tln
|
9904 |
+
4mrw
|
9905 |
+
3c10
|
9906 |
+
3sdi
|
9907 |
+
4tw6
|
9908 |
+
3pa4
|
9909 |
+
3q4k
|
9910 |
+
5l3a
|
9911 |
+
3b9g
|
9912 |
+
4ohp
|
9913 |
+
3nq3
|
9914 |
+
5vfj
|
9915 |
+
4rqi
|
9916 |
+
4x7k
|
9917 |
+
2q8s
|
9918 |
+
1ca8
|
9919 |
+
5a3x
|
9920 |
+
4wf6
|
9921 |
+
5oh4
|
9922 |
+
2qu3
|
9923 |
+
5dq8
|
9924 |
+
6ffs
|
9925 |
+
4loq
|
9926 |
+
4prb
|
9927 |
+
5vwk
|
9928 |
+
2yhw
|
9929 |
+
5eob
|
9930 |
+
5dgj
|
9931 |
+
2i4d
|
9932 |
+
5wlo
|
9933 |
+
5lo6
|
9934 |
+
5aln
|
9935 |
+
3p5l
|
9936 |
+
4q1y
|
9937 |
+
6c4u
|
9938 |
+
1gi7
|
9939 |
+
2jkt
|
9940 |
+
4yv1
|
9941 |
+
3ctj
|
9942 |
+
4qfr
|
9943 |
+
4wmy
|
9944 |
+
5c84
|
9945 |
+
3ie3
|
9946 |
+
5mnn
|
9947 |
+
3l8v
|
9948 |
+
6eij
|
9949 |
+
1o2n
|
9950 |
+
4nmv
|
9951 |
+
5ok6
|
9952 |
+
4yab
|
9953 |
+
2vnf
|
9954 |
+
3r0w
|
9955 |
+
2uyq
|
9956 |
+
5j19
|
9957 |
+
1y2c
|
9958 |
+
3nth
|
9959 |
+
5ni0
|
9960 |
+
4tpk
|
9961 |
+
1vyq
|
9962 |
+
4txs
|
9963 |
+
2wgs
|
9964 |
+
5gv2
|
9965 |
+
1b3g
|
9966 |
+
3kad
|
9967 |
+
6hgz
|
9968 |
+
3dng
|
9969 |
+
4u7q
|
9970 |
+
5fnd
|
9971 |
+
2c5x
|
9972 |
+
5ho6
|
9973 |
+
2aqu
|
9974 |
+
1ke6
|
9975 |
+
5g5f
|
9976 |
+
3wff
|
9977 |
+
3m36
|
9978 |
+
4bb4
|
9979 |
+
3ai8
|
9980 |
+
3ee2
|
9981 |
+
5u14
|
9982 |
+
4xe1
|
9983 |
+
4ggz
|
9984 |
+
4av5
|
9985 |
+
3bgc
|
9986 |
+
5i4v
|
9987 |
+
3g0d
|
9988 |
+
4bkj
|
9989 |
+
2aei
|
9990 |
+
4hup
|
9991 |
+
4yv9
|
9992 |
+
4uwf
|
9993 |
+
2ovy
|
9994 |
+
2oo8
|
9995 |
+
4dlj
|
9996 |
+
2v83
|
9997 |
+
1ct8
|
9998 |
+
5qan
|
9999 |
+
4nwc
|
10000 |
+
4msc
|
10001 |
+
4iti
|
10002 |
+
3guz
|
10003 |
+
6i8l
|
10004 |
+
2yof
|
10005 |
+
1oyn
|
10006 |
+
3qti
|
10007 |
+
5nf6
|
10008 |
+
5n7x
|
10009 |
+
3t0t
|
10010 |
+
3oyw
|
10011 |
+
4ab9
|
10012 |
+
3aw0
|
10013 |
+
2x2l
|
10014 |
+
2lkk
|
10015 |
+
3oyq
|
10016 |
+
6c28
|
10017 |
+
2ofv
|
10018 |
+
1b58
|
10019 |
+
4cpt
|
10020 |
+
4em7
|
10021 |
+
1t5a
|
10022 |
+
4xyf
|
10023 |
+
3duy
|
10024 |
+
4xh6
|
10025 |
+
1j15
|
10026 |
+
3b7j
|
10027 |
+
2isw
|
10028 |
+
3eqs
|
10029 |
+
3tkz
|
10030 |
+
3dgl
|
10031 |
+
3qw5
|
10032 |
+
6df4
|
10033 |
+
2jjb
|
10034 |
+
5auy
|
10035 |
+
2rcu
|
10036 |
+
5mqy
|
10037 |
+
2aoe
|
10038 |
+
1d8f
|
10039 |
+
1kl5
|
10040 |
+
4zsg
|
10041 |
+
3e0p
|
10042 |
+
3su6
|
10043 |
+
5tz3
|
10044 |
+
4hco
|
10045 |
+
3i6c
|
10046 |
+
2ow1
|
10047 |
+
2yjw
|
10048 |
+
4nue
|
10049 |
+
1uyd
|
10050 |
+
4hod
|
10051 |
+
3oik
|
10052 |
+
2viv
|
10053 |
+
4wtu
|
10054 |
+
4gih
|
10055 |
+
1b9s
|
10056 |
+
5i40
|
10057 |
+
4zb6
|
10058 |
+
5fns
|
10059 |
+
4x6h
|
10060 |
+
5hg9
|
10061 |
+
5naw
|
10062 |
+
1h37
|
10063 |
+
1uj0
|
10064 |
+
3e9i
|
10065 |
+
3i5z
|
10066 |
+
1v2v
|
10067 |
+
5wb3
|
10068 |
+
3lpt
|
10069 |
+
3k4d
|
10070 |
+
3nhi
|
10071 |
+
1cbr
|
10072 |
+
5uis
|
10073 |
+
3f68
|
10074 |
+
5nk3
|
10075 |
+
3okv
|
10076 |
+
3krr
|
10077 |
+
4gnf
|
10078 |
+
3zyf
|
10079 |
+
3ivg
|
10080 |
+
5d3n
|
10081 |
+
4rs0
|
10082 |
+
5oxn
|
10083 |
+
1owd
|
10084 |
+
1w7h
|
10085 |
+
5o4s
|
10086 |
+
3hrf
|
10087 |
+
2r3h
|
10088 |
+
1yp9
|
10089 |
+
5oyd
|
10090 |
+
4iif
|
10091 |
+
4uvb
|
10092 |
+
1b9j
|
10093 |
+
2bgd
|
10094 |
+
6giu
|
10095 |
+
5eek
|
10096 |
+
3tnh
|
10097 |
+
3gp0
|
10098 |
+
3bxs
|
10099 |
+
2ay1
|
10100 |
+
5cap
|
10101 |
+
3ta0
|
10102 |
+
3mkf
|
10103 |
+
4uyf
|
10104 |
+
4zx6
|
10105 |
+
5a3n
|
10106 |
+
3hek
|
10107 |
+
6b5r
|
10108 |
+
1fbm
|
10109 |
+
5wou
|
10110 |
+
3g76
|
10111 |
+
2rkf
|
10112 |
+
5j86
|
10113 |
+
5lav
|
10114 |
+
2rkn
|
10115 |
+
3jzo
|
10116 |
+
3kr5
|
10117 |
+
2vo4
|
10118 |
+
4lzr
|
10119 |
+
2srt
|
10120 |
+
4wbg
|
10121 |
+
1vyz
|
10122 |
+
3ebi
|
10123 |
+
2qbx
|
10124 |
+
3gbb
|
10125 |
+
3vnt
|
10126 |
+
3erd
|
10127 |
+
1o34
|
10128 |
+
1lbk
|
10129 |
+
6czi
|
10130 |
+
4d1c
|
10131 |
+
1k1p
|
10132 |
+
2bmv
|
10133 |
+
1jlr
|
10134 |
+
5hx6
|
10135 |
+
2igw
|
10136 |
+
4o0r
|
10137 |
+
2isv
|
10138 |
+
3kr8
|
10139 |
+
4k3m
|
10140 |
+
5xiw
|
10141 |
+
2z5s
|
10142 |
+
2w97
|
10143 |
+
4u03
|
10144 |
+
4p4d
|
10145 |
+
1pwp
|
10146 |
+
5j27
|
10147 |
+
3w5e
|
10148 |
+
5a3s
|
10149 |
+
1zz3
|
10150 |
+
4y5i
|
10151 |
+
4rx9
|
10152 |
+
4ty7
|
10153 |
+
6g4z
|
10154 |
+
4j3e
|
10155 |
+
1s3k
|
10156 |
+
6ajh
|
10157 |
+
2wei
|
10158 |
+
5v5o
|
10159 |
+
4p45
|
10160 |
+
4nbl
|
10161 |
+
4rxd
|
10162 |
+
1cp6
|
10163 |
+
1r5h
|
10164 |
+
4nnw
|
10165 |
+
4cga
|
10166 |
+
3kb7
|
10167 |
+
4phw
|
10168 |
+
3zpq
|
10169 |
+
4b3c
|
10170 |
+
1wv7
|
10171 |
+
5hja
|
10172 |
+
1mfi
|
10173 |
+
3jzk
|
10174 |
+
1hsh
|
10175 |
+
6aro
|
10176 |
+
3vyf
|
10177 |
+
2v7d
|
10178 |
+
4k66
|
10179 |
+
5eeq
|
10180 |
+
5mos
|
10181 |
+
3ska
|
10182 |
+
4bg1
|
10183 |
+
4ql8
|
10184 |
+
4lgg
|
10185 |
+
4anw
|
10186 |
+
6gr7
|
10187 |
+
2x7s
|
10188 |
+
4ie4
|
10189 |
+
1p05
|
10190 |
+
4zbi
|
10191 |
+
5c6v
|
10192 |
+
3qzv
|
10193 |
+
5etq
|
10194 |
+
1nhw
|
10195 |
+
2xx4
|
10196 |
+
1uys
|
10197 |
+
3zsq
|
10198 |
+
4h75
|
10199 |
+
4d0w
|
10200 |
+
4pml
|
10201 |
+
3gyn
|
10202 |
+
2fm5
|
10203 |
+
4r93
|
10204 |
+
5usq
|
10205 |
+
4e3b
|
10206 |
+
2hwi
|
10207 |
+
3kl8
|
10208 |
+
2vr4
|
10209 |
+
3o0e
|
10210 |
+
3dab
|
10211 |
+
5h8g
|
10212 |
+
4ynb
|
10213 |
+
1kr3
|
10214 |
+
4w9d
|
10215 |
+
4msl
|
10216 |
+
5k8v
|
10217 |
+
5ix1
|
10218 |
+
5zaf
|
10219 |
+
6cve
|
10220 |
+
4h85
|
10221 |
+
3d5m
|
10222 |
+
3v78
|
10223 |
+
5uox
|
10224 |
+
5d1u
|
10225 |
+
4fcm
|
10226 |
+
2zz1
|
10227 |
+
4i1r
|
10228 |
+
5hkm
|
10229 |
+
4y8c
|
10230 |
+
1fkn
|
10231 |
+
5he2
|
10232 |
+
3n3g
|
10233 |
+
3g5v
|
10234 |
+
2evl
|
10235 |
+
3k3j
|
10236 |
+
1utr
|
10237 |
+
3ixg
|
10238 |
+
4u44
|
10239 |
+
4ahs
|
10240 |
+
1o2y
|
10241 |
+
3fcf
|
10242 |
+
5dde
|
10243 |
+
3bgm
|
10244 |
+
2nxd
|
10245 |
+
4yhq
|
10246 |
+
4k19
|
10247 |
+
5y7w
|
10248 |
+
3v3m
|
10249 |
+
4ph4
|
10250 |
+
1nja
|
10251 |
+
5i23
|
10252 |
+
3rsv
|
10253 |
+
5n17
|
10254 |
+
4bt5
|
10255 |
+
2ojg
|
10256 |
+
5x72
|
10257 |
+
6eq7
|
10258 |
+
3ehx
|
10259 |
+
1a5v
|
10260 |
+
6clv
|
10261 |
+
3qcs
|
10262 |
+
5cy9
|
10263 |
+
3bgp
|
10264 |
+
3nf7
|
10265 |
+
4dmn
|
10266 |
+
2dxs
|
10267 |
+
4msk
|
10268 |
+
2wmu
|
10269 |
+
4hws
|
10270 |
+
5c2a
|
10271 |
+
3lco
|
10272 |
+
4x3u
|
10273 |
+
5c7a
|
10274 |
+
1pa9
|
10275 |
+
5he7
|
10276 |
+
3m67
|
10277 |
+
1j7z
|
10278 |
+
3s5y
|
10279 |
+
3oe0
|
10280 |
+
4kql
|
10281 |
+
5l8y
|
10282 |
+
5cks
|
10283 |
+
4cc5
|
10284 |
+
2rcb
|
10285 |
+
3bi1
|
10286 |
+
3jzc
|
10287 |
+
2qzx
|
10288 |
+
4u73
|
10289 |
+
2an5
|
10290 |
+
2uvm
|
10291 |
+
6g2n
|
10292 |
+
1dzj
|
10293 |
+
6b97
|
10294 |
+
5y6d
|
10295 |
+
1qvu
|
10296 |
+
4ymx
|
10297 |
+
1yej
|
10298 |
+
6f3d
|
10299 |
+
5tg7
|
10300 |
+
2w1i
|
10301 |
+
3dv5
|
10302 |
+
1vyw
|
10303 |
+
3sw9
|
10304 |
+
4qz3
|
10305 |
+
8a3h
|
10306 |
+
3o3j
|
10307 |
+
5gn9
|
10308 |
+
4b7j
|
10309 |
+
2i4u
|
10310 |
+
3m8q
|
10311 |
+
2fu8
|
10312 |
+
4hfp
|
10313 |
+
1swi
|
10314 |
+
2vd0
|
10315 |
+
3pz1
|
10316 |
+
2jo9
|
10317 |
+
3q4c
|
10318 |
+
4bzo
|
10319 |
+
4tyl
|
10320 |
+
6fuj
|
10321 |
+
2x7c
|
10322 |
+
3hg1
|
10323 |
+
3pty
|
10324 |
+
5f3i
|
10325 |
+
4q9o
|
10326 |
+
3e1r
|
10327 |
+
4j78
|
10328 |
+
4ucv
|
10329 |
+
6h38
|
10330 |
+
3wtk
|
10331 |
+
4lno
|
10332 |
+
2h65
|
10333 |
+
3s4q
|
10334 |
+
3lp0
|
10335 |
+
4ajo
|
10336 |
+
5maj
|
10337 |
+
3d7d
|
10338 |
+
4xe0
|
10339 |
+
6hpw
|
10340 |
+
4p0b
|
10341 |
+
5fsb
|
10342 |
+
4f6u
|
10343 |
+
5h0g
|
10344 |
+
2zdk
|
10345 |
+
6hoy
|
10346 |
+
6bib
|
10347 |
+
3rpv
|
10348 |
+
1kel
|
10349 |
+
4v24
|
10350 |
+
5k1i
|
10351 |
+
4j4v
|
10352 |
+
3kai
|
10353 |
+
3c9e
|
10354 |
+
2v59
|
10355 |
+
5cs5
|
10356 |
+
5jqb
|
10357 |
+
6as8
|
10358 |
+
5dw2
|
10359 |
+
1mq1
|
10360 |
+
4gw1
|
10361 |
+
4gj9
|
10362 |
+
6e2n
|
10363 |
+
4qlu
|
10364 |
+
5jog
|
10365 |
+
4iu1
|
10366 |
+
3tyq
|
10367 |
+
3r2b
|
10368 |
+
5alr
|
10369 |
+
5c4s
|
10370 |
+
3pa8
|
10371 |
+
2qq7
|
10372 |
+
4qn9
|
10373 |
+
2uwd
|
10374 |
+
1yye
|
10375 |
+
1oir
|
10376 |
+
1gpy
|
10377 |
+
6ert
|
10378 |
+
3d7z
|
10379 |
+
6dq8
|
10380 |
+
4lsj
|
10381 |
+
2wxm
|
10382 |
+
3pj2
|
10383 |
+
3nwb
|
10384 |
+
3qxc
|
10385 |
+
4hwo
|
10386 |
+
3afk
|
10387 |
+
2rk8
|
10388 |
+
6acb
|
10389 |
+
6g85
|
10390 |
+
1kna
|
10391 |
+
4pvx
|
10392 |
+
5hex
|
10393 |
+
3jqa
|
10394 |
+
5xms
|
10395 |
+
4an2
|
10396 |
+
3lcu
|
10397 |
+
3rdh
|
10398 |
+
2r3y
|
10399 |
+
4w7t
|
10400 |
+
6few
|
10401 |
+
4cd4
|
10402 |
+
2gg2
|
10403 |
+
4ga3
|
10404 |
+
6anl
|
10405 |
+
1yyy
|
10406 |
+
3r16
|
10407 |
+
4al4
|
10408 |
+
4uru
|
10409 |
+
2ovv
|
10410 |
+
4ya8
|
10411 |
+
4re3
|
10412 |
+
3bgq
|
10413 |
+
5lpr
|
10414 |
+
5fap
|
10415 |
+
5cei
|
10416 |
+
3v5q
|
10417 |
+
1maw
|
10418 |
+
4p4f
|
10419 |
+
4jx9
|
10420 |
+
4xqa
|
10421 |
+
3ghe
|
10422 |
+
3fci
|
10423 |
+
1zfp
|
10424 |
+
2l12
|
10425 |
+
4lil
|
10426 |
+
6eq2
|
10427 |
+
5vdv
|
10428 |
+
6b0v
|
10429 |
+
4l0i
|
10430 |
+
4zsl
|
10431 |
+
5yu9
|
10432 |
+
1p04
|
10433 |
+
1rnt
|
10434 |
+
2chm
|
10435 |
+
1nhx
|
10436 |
+
3ckb
|
10437 |
+
2vot
|
10438 |
+
5n1p
|
10439 |
+
2jke
|
10440 |
+
5ztn
|
10441 |
+
4j82
|
10442 |
+
3hxb
|
10443 |
+
3qvu
|
10444 |
+
1hk5
|
10445 |
+
4pyo
|
10446 |
+
3atl
|
10447 |
+
3jzi
|
10448 |
+
4ad3
|
10449 |
+
4b6r
|
10450 |
+
3g8o
|
10451 |
+
4kc2
|
10452 |
+
7upj
|
10453 |
+
5eyz
|
10454 |
+
6do5
|
10455 |
+
5wfj
|
10456 |
+
2j4a
|
10457 |
+
3kmx
|
10458 |
+
5oy3
|
10459 |
+
4o55
|
10460 |
+
2qi5
|
10461 |
+
4jfs
|
10462 |
+
4h3g
|
10463 |
+
2y68
|
10464 |
+
3fv2
|
10465 |
+
3ioc
|
10466 |
+
5jyp
|
10467 |
+
2gde
|
10468 |
+
4mm8
|
10469 |
+
4jjm
|
10470 |
+
5ccl
|
10471 |
+
5umy
|
10472 |
+
4n7e
|
10473 |
+
4f64
|
10474 |
+
3p9h
|
10475 |
+
4hz5
|
10476 |
+
4kin
|
10477 |
+
6cqf
|
10478 |
+
3feg
|
10479 |
+
3aaq
|
10480 |
+
3sl1
|
10481 |
+
1uxb
|
10482 |
+
4oee
|
10483 |
+
4i7d
|
10484 |
+
5ll5
|
10485 |
+
4qlk
|
10486 |
+
3s9y
|
10487 |
+
3t3g
|
10488 |
+
2p3b
|
10489 |
+
2jbj
|
10490 |
+
2x8i
|
10491 |
+
4ui3
|
10492 |
+
3po1
|
10493 |
+
5ji6
|
10494 |
+
3u90
|
10495 |
+
4lts
|
10496 |
+
4xrq
|
10497 |
+
4jzr
|
10498 |
+
5nkb
|
10499 |
+
1km3
|
10500 |
+
2qnx
|
10501 |
+
3myg
|
10502 |
+
2va7
|
10503 |
+
4ymh
|
10504 |
+
4nms
|
10505 |
+
5ar7
|
10506 |
+
2h3e
|
10507 |
+
4lp0
|
10508 |
+
2ay9
|
10509 |
+
5trs
|
10510 |
+
4fse
|
10511 |
+
6cdg
|
10512 |
+
6ful
|
10513 |
+
4x8n
|
10514 |
+
4w4x
|
10515 |
+
5m29
|
10516 |
+
4ocx
|
10517 |
+
3sov
|
10518 |
+
4fxp
|
10519 |
+
3ex2
|
10520 |
+
5uwl
|
10521 |
+
4wpn
|
10522 |
+
3bi0
|
10523 |
+
5nwh
|
10524 |
+
1vik
|
10525 |
+
4uj9
|
10526 |
+
5tg4
|
10527 |
+
5hrx
|
10528 |
+
3wz6
|
10529 |
+
1mm7
|
10530 |
+
5v37
|
10531 |
+
5eol
|
10532 |
+
4egi
|
10533 |
+
5n21
|
10534 |
+
3vhe
|
10535 |
+
3cj3
|
10536 |
+
4w9q
|
10537 |
+
2qtg
|
10538 |
+
4z93
|
10539 |
+
3jqb
|
10540 |
+
5f3c
|
10541 |
+
5ll9
|
10542 |
+
4zts
|
10543 |
+
5aei
|
10544 |
+
1o9d
|
10545 |
+
2iw9
|
10546 |
+
5b5g
|
10547 |
+
1g54
|
10548 |
+
3v5p
|
10549 |
+
2yk9
|
10550 |
+
1ez9
|
10551 |
+
4c6x
|
10552 |
+
2g24
|
10553 |
+
1m9n
|
10554 |
+
5f60
|
10555 |
+
1vzq
|
10556 |
+
1rt9
|
10557 |
+
5jq5
|
10558 |
+
3ha6
|
10559 |
+
2yj9
|
10560 |
+
4nra
|
10561 |
+
2h9t
|
10562 |
+
6afi
|
10563 |
+
3el8
|
10564 |
+
4kni
|
10565 |
+
5v79
|
10566 |
+
4fxf
|
10567 |
+
3ncg
|
10568 |
+
4x3s
|
10569 |
+
1dif
|
10570 |
+
4aa7
|
10571 |
+
4d1b
|
10572 |
+
5av0
|
10573 |
+
2clm
|
10574 |
+
4l10
|
10575 |
+
1exv
|
10576 |
+
2ltv
|
10577 |
+
6g1v
|
10578 |
+
3rwh
|
10579 |
+
5yfs
|
10580 |
+
5xkm
|
10581 |
+
5mjb
|
10582 |
+
2i03
|
10583 |
+
2v0z
|
10584 |
+
3udm
|
10585 |
+
3i3b
|
10586 |
+
1h1b
|
10587 |
+
6esa
|
10588 |
+
4ai8
|
10589 |
+
5ak3
|
10590 |
+
5j20
|
10591 |
+
5jjm
|
10592 |
+
3wto
|
10593 |
+
1std
|
10594 |
+
1jjt
|
10595 |
+
4kxb
|
10596 |
+
1jdj
|
10597 |
+
2chw
|
10598 |
+
3ll8
|
10599 |
+
5j79
|
10600 |
+
5adq
|
10601 |
+
4r74
|
10602 |
+
5n53
|
10603 |
+
3ljg
|
10604 |
+
2lsr
|
10605 |
+
3rk9
|
10606 |
+
1add
|
10607 |
+
5ja0
|
10608 |
+
5x02
|
10609 |
+
5cc2
|
10610 |
+
3u9c
|
10611 |
+
5d12
|
10612 |
+
1o6q
|
10613 |
+
1xn0
|
10614 |
+
5f20
|
10615 |
+
4lgh
|
10616 |
+
5etr
|
10617 |
+
3mj5
|
10618 |
+
4km2
|
10619 |
+
4f9u
|
10620 |
+
6el5
|
10621 |
+
1hmr
|
10622 |
+
5n9k
|
10623 |
+
3are
|
10624 |
+
1lv8
|
10625 |
+
5n99
|
10626 |
+
4gly
|
10627 |
+
1sh9
|
10628 |
+
4uns
|
10629 |
+
4cpu
|
10630 |
+
2or4
|
10631 |
+
2rkd
|
10632 |
+
4psq
|
10633 |
+
5wcm
|
10634 |
+
5vsc
|
10635 |
+
4nl1
|
10636 |
+
4um9
|
10637 |
+
4wa9
|
10638 |
+
3fxv
|
10639 |
+
2obj
|
10640 |
+
2ohm
|
10641 |
+
4zw3
|
10642 |
+
5jao
|
10643 |
+
6htz
|
10644 |
+
3n2p
|
10645 |
+
5dda
|
10646 |
+
2vwy
|
10647 |
+
4ge2
|
10648 |
+
5d7e
|
10649 |
+
4wx4
|
10650 |
+
3sgv
|
10651 |
+
5w12
|
10652 |
+
4gmc
|
10653 |
+
4dij
|
10654 |
+
1r5g
|
10655 |
+
4r3w
|
10656 |
+
5hn8
|
10657 |
+
4fk6
|
10658 |
+
5ggl
|
10659 |
+
2ks9
|
10660 |
+
1tq4
|
10661 |
+
2qu2
|
10662 |
+
4oyk
|
10663 |
+
1my8
|
10664 |
+
6mv3
|
10665 |
+
3kqs
|
10666 |
+
3gz9
|
10667 |
+
3eta
|
10668 |
+
1uv5
|
10669 |
+
2bok
|
10670 |
+
1b42
|
10671 |
+
5mlw
|
10672 |
+
5d29
|
10673 |
+
4qr5
|
10674 |
+
1r6n
|
10675 |
+
6f6u
|
10676 |
+
4pio
|
10677 |
+
6cee
|
10678 |
+
3mp1
|
10679 |
+
4pz8
|
10680 |
+
6fgy
|
10681 |
+
5moe
|
10682 |
+
5yfz
|
10683 |
+
5zwh
|
10684 |
+
4kb9
|
10685 |
+
2wmw
|
10686 |
+
1nax
|
10687 |
+
1o4n
|
10688 |
+
2znu
|
10689 |
+
5gvp
|
10690 |
+
3ma3
|
10691 |
+
3k15
|
10692 |
+
5qae
|
10693 |
+
1v48
|
10694 |
+
2psx
|
10695 |
+
4d8e
|
10696 |
+
1m5d
|
10697 |
+
2v2c
|
10698 |
+
2ql5
|
10699 |
+
3h0y
|
10700 |
+
3wpn
|
10701 |
+
2qa8
|
10702 |
+
1rs4
|
10703 |
+
5tgy
|
10704 |
+
2b7d
|
10705 |
+
4pl6
|
10706 |
+
2w8j
|
10707 |
+
3tdz
|
10708 |
+
2wxj
|
10709 |
+
5g2b
|
10710 |
+
4nrk
|
10711 |
+
3gwv
|
10712 |
+
1kne
|
10713 |
+
3kqe
|
10714 |
+
5khg
|
10715 |
+
4uiu
|
10716 |
+
4kyh
|
10717 |
+
4e93
|
10718 |
+
2qg2
|
10719 |
+
1a4m
|
10720 |
+
4byi
|
10721 |
+
5ngz
|
10722 |
+
4c1c
|
10723 |
+
6fam
|
10724 |
+
5lgq
|
10725 |
+
2hb3
|
10726 |
+
4c1h
|
10727 |
+
3ms9
|
10728 |
+
2pnx
|
10729 |
+
4qmw
|
10730 |
+
1lzq
|
10731 |
+
3aid
|
10732 |
+
3psb
|
10733 |
+
5w6r
|
10734 |
+
4c4e
|
10735 |
+
4jxw
|
10736 |
+
5ngr
|
10737 |
+
1utz
|
10738 |
+
3r7o
|
10739 |
+
3umq
|
10740 |
+
3hw1
|
10741 |
+
1tkc
|
10742 |
+
1abt
|
10743 |
+
3mbp
|
10744 |
+
3i9g
|
10745 |
+
1rwq
|
10746 |
+
4iz0
|
10747 |
+
6dh2
|
10748 |
+
4rx7
|
10749 |
+
4kwf
|
10750 |
+
2cn8
|
10751 |
+
3bar
|
10752 |
+
1cny
|
10753 |
+
1npz
|
10754 |
+
2bys
|
10755 |
+
4y6p
|
10756 |
+
4y6s
|
10757 |
+
5q0s
|
10758 |
+
2uxx
|
10759 |
+
6eaa
|
10760 |
+
5cs2
|
10761 |
+
4c1e
|
10762 |
+
4mgv
|
10763 |
+
2wxf
|
10764 |
+
5q1e
|
10765 |
+
5o83
|
10766 |
+
3r4o
|
10767 |
+
6fyk
|
10768 |
+
1x8s
|
10769 |
+
5b25
|
10770 |
+
4f39
|
10771 |
+
4tk5
|
10772 |
+
5nhp
|
10773 |
+
4lov
|
10774 |
+
1kui
|
10775 |
+
3art
|
10776 |
+
4d2v
|
10777 |
+
1bnv
|
10778 |
+
4kov
|
10779 |
+
6cyc
|
10780 |
+
4fkk
|
10781 |
+
6hvj
|
10782 |
+
2j4z
|
10783 |
+
2p3c
|
10784 |
+
1f0s
|
10785 |
+
3dy6
|
10786 |
+
5lz7
|
10787 |
+
3mww
|
10788 |
+
1hvk
|
10789 |
+
1x76
|
10790 |
+
2aez
|
10791 |
+
1bio
|
10792 |
+
1lhe
|
10793 |
+
3k48
|
10794 |
+
2krd
|
10795 |
+
4bbg
|
10796 |
+
5otc
|
10797 |
+
3kqp
|
10798 |
+
4esi
|
10799 |
+
2rku
|
10800 |
+
2kpl
|
10801 |
+
1erb
|
10802 |
+
2xx5
|
10803 |
+
2fl2
|
10804 |
+
4a4v
|
10805 |
+
1lqd
|
10806 |
+
1lfo
|
10807 |
+
3hf6
|
10808 |
+
3bm8
|
10809 |
+
1a99
|
10810 |
+
3zly
|
10811 |
+
6cwn
|
10812 |
+
3d8y
|
10813 |
+
5icz
|
10814 |
+
1hgi
|
10815 |
+
4qgf
|
10816 |
+
6fug
|
10817 |
+
3tn8
|
10818 |
+
6f3g
|
10819 |
+
5kq5
|
10820 |
+
3tz2
|
10821 |
+
1xws
|
10822 |
+
5uov
|
10823 |
+
2o9j
|
10824 |
+
3coh
|
10825 |
+
3h98
|
10826 |
+
1mes
|
10827 |
+
3ot3
|
10828 |
+
6f1x
|
10829 |
+
5gs9
|
10830 |
+
2hha
|
10831 |
+
1pfy
|
10832 |
+
4j3j
|
10833 |
+
4rn1
|
10834 |
+
4ze6
|
10835 |
+
3zpt
|
10836 |
+
4f9y
|
10837 |
+
4lbu
|
10838 |
+
2nno
|
10839 |
+
5v42
|
10840 |
+
2fyv
|
10841 |
+
4j8m
|
10842 |
+
6hjk
|
10843 |
+
4ha5
|
10844 |
+
3tu7
|
10845 |
+
1izh
|
10846 |
+
3o9d
|
10847 |
+
6g4m
|
10848 |
+
2r2b
|
10849 |
+
2xc0
|
10850 |
+
1g30
|
10851 |
+
3anq
|
10852 |
+
5uv5
|
10853 |
+
4ty8
|
10854 |
+
2vew
|
10855 |
+
3br9
|
10856 |
+
1df8
|
10857 |
+
3fgc
|
10858 |
+
1utt
|
10859 |
+
6cd8
|
10860 |
+
6f4w
|
10861 |
+
3l8x
|
10862 |
+
4fe6
|
10863 |
+
5adt
|
10864 |
+
5nzq
|
10865 |
+
6htt
|
10866 |
+
5k0t
|
10867 |
+
3pn1
|
10868 |
+
4ryc
|
10869 |
+
4nga
|
10870 |
+
4crc
|
10871 |
+
4xcu
|
10872 |
+
3f3c
|
10873 |
+
3obx
|
10874 |
+
6agg
|
10875 |
+
6cq5
|
10876 |
+
3w2r
|
10877 |
+
3dsu
|
10878 |
+
3zs0
|
10879 |
+
4wkv
|
10880 |
+
3w07
|
10881 |
+
1ntk
|
10882 |
+
4dk8
|
10883 |
+
3kgq
|
10884 |
+
4anv
|
10885 |
+
4ery
|
10886 |
+
4jzd
|
10887 |
+
3tjh
|
10888 |
+
4jwk
|
10889 |
+
4hyi
|
10890 |
+
4kne
|
10891 |
+
3u9q
|
10892 |
+
5ih2
|
10893 |
+
2h02
|
10894 |
+
4c6u
|
10895 |
+
1i8z
|
10896 |
+
4bid
|
10897 |
+
3lmp
|
10898 |
+
5ohj
|
10899 |
+
4j81
|
10900 |
+
5dey
|
10901 |
+
5k8n
|
10902 |
+
1pz5
|
10903 |
+
1shd
|
10904 |
+
3hhm
|
10905 |
+
5n0f
|
10906 |
+
5kh3
|
10907 |
+
3nba
|
10908 |
+
4u5s
|
10909 |
+
2ndo
|
10910 |
+
3shc
|
10911 |
+
3vid
|
10912 |
+
1ik4
|
10913 |
+
1al7
|
10914 |
+
1fq7
|
10915 |
+
2x4r
|
10916 |
+
4kz3
|
10917 |
+
6cen
|
10918 |
+
3s8l
|
10919 |
+
2aoc
|
10920 |
+
2xh5
|
10921 |
+
2p93
|
10922 |
+
4qfg
|
10923 |
+
5huy
|
10924 |
+
3ebo
|
10925 |
+
1agm
|
10926 |
+
1fv9
|
10927 |
+
4jnj
|
10928 |
+
4c72
|
10929 |
+
1vfn
|
10930 |
+
4xg3
|
10931 |
+
3hl5
|
10932 |
+
2xah
|
10933 |
+
5n58
|
10934 |
+
3mof
|
10935 |
+
3r22
|
10936 |
+
5o45
|
10937 |
+
1utm
|
10938 |
+
3p8e
|
10939 |
+
1kl3
|
10940 |
+
5o5h
|
10941 |
+
5lpk
|
10942 |
+
2zdx
|
10943 |
+
6q74
|
10944 |
+
3miy
|
10945 |
+
5bpe
|
10946 |
+
2vta
|
10947 |
+
1bnq
|
10948 |
+
6f90
|
10949 |
+
4myh
|
10950 |
+
5llm
|
10951 |
+
4poj
|
10952 |
+
1q6s
|
10953 |
+
1jws
|
10954 |
+
5xmp
|
10955 |
+
4ahv
|
10956 |
+
4e4n
|
10957 |
+
4qgi
|
10958 |
+
4o75
|
10959 |
+
3ogp
|
10960 |
+
3dk1
|
10961 |
+
4bdf
|
10962 |
+
2ybs
|
10963 |
+
4ght
|
10964 |
+
1e5j
|
10965 |
+
1veb
|
10966 |
+
4wrq
|
10967 |
+
5cqu
|
10968 |
+
1ow7
|
10969 |
+
5nsp
|
10970 |
+
2wtx
|
10971 |
+
2rqu
|
10972 |
+
5kpl
|
10973 |
+
3g19
|
10974 |
+
3gy7
|
10975 |
+
4bhi
|
10976 |
+
3rjm
|
10977 |
+
3f3v
|
10978 |
+
4h42
|
10979 |
+
4y16
|
10980 |
+
1o3g
|
10981 |
+
1utc
|
10982 |
+
3wzu
|
10983 |
+
6b5q
|
10984 |
+
1u2r
|
10985 |
+
3sx9
|
10986 |
+
1nju
|
10987 |
+
3drp
|
10988 |
+
6azk
|
10989 |
+
3r9d
|
10990 |
+
4awi
|
10991 |
+
1ce5
|
10992 |
+
5vd2
|
10993 |
+
5kzq
|
10994 |
+
2bal
|
10995 |
+
1y2f
|
10996 |
+
2xxt
|
10997 |
+
5hlp
|
10998 |
+
2y8c
|
10999 |
+
5auu
|
11000 |
+
1bwa
|
11001 |
+
6gbe
|
11002 |
+
2zv2
|
11003 |
+
3f7b
|
11004 |
+
1e4h
|
11005 |
+
6arn
|
11006 |
+
3ryw
|
11007 |
+
6fr0
|
11008 |
+
5wbz
|
11009 |
+
1c8v
|
11010 |
+
5kau
|
11011 |
+
1v41
|
11012 |
+
4oew
|
11013 |
+
5fbo
|
11014 |
+
3l9h
|
11015 |
+
5hi7
|
11016 |
+
3igg
|
11017 |
+
4hy0
|
11018 |
+
5enf
|
11019 |
+
1cwc
|
11020 |
+
5yjo
|
11021 |
+
2e92
|
11022 |
+
186l
|
11023 |
+
6epy
|
11024 |
+
3qk0
|
11025 |
+
6cq4
|
11026 |
+
2jkq
|
11027 |
+
3gb2
|
11028 |
+
5xmt
|
11029 |
+
2ybu
|
11030 |
+
3arz
|
11031 |
+
2o5k
|
11032 |
+
5c13
|
11033 |
+
2amv
|
11034 |
+
4std
|
11035 |
+
4gfm
|
11036 |
+
2fm2
|
11037 |
+
4pv0
|
11038 |
+
3qx9
|
11039 |
+
1hnn
|
11040 |
+
3bl2
|
11041 |
+
5dhp
|
11042 |
+
6c7i
|
11043 |
+
5pzn
|
11044 |
+
5ur9
|
11045 |
+
1pye
|
11046 |
+
3upf
|
11047 |
+
3ooz
|
11048 |
+
3zcl
|
11049 |
+
2vkm
|
11050 |
+
2jdl
|
11051 |
+
2uyi
|
11052 |
+
1usi
|
11053 |
+
1ezq
|
11054 |
+
4qz0
|
11055 |
+
3g5d
|
11056 |
+
3ry8
|
11057 |
+
2vnt
|
11058 |
+
5ehy
|
11059 |
+
1mqj
|
11060 |
+
5gs4
|
11061 |
+
5xg4
|
11062 |
+
3h59
|
11063 |
+
1bv7
|
11064 |
+
1br6
|
11065 |
+
1mns
|
11066 |
+
2ybk
|
11067 |
+
1bcj
|
11068 |
+
3ktr
|
11069 |
+
1e02
|
11070 |
+
1ykr
|
11071 |
+
5vja
|
11072 |
+
3r5j
|
11073 |
+
5edu
|
11074 |
+
3kga
|
11075 |
+
6b5t
|
11076 |
+
5f74
|
11077 |
+
5qaq
|
11078 |
+
1jpl
|
11079 |
+
5hmi
|
11080 |
+
3mjl
|
11081 |
+
1eei
|
11082 |
+
4n8e
|
11083 |
+
1hrn
|
11084 |
+
2o4s
|
11085 |
+
1agw
|
11086 |
+
4yz5
|
11087 |
+
4wn1
|
11088 |
+
3tc5
|
11089 |
+
2pjb
|
11090 |
+
6ea1
|
11091 |
+
5epy
|
11092 |
+
3vc4
|
11093 |
+
2i0g
|
11094 |
+
3ah8
|
11095 |
+
1ogg
|
11096 |
+
1onh
|
11097 |
+
1tmb
|
11098 |
+
6bau
|
11099 |
+
4ad6
|
11100 |
+
1a3e
|
11101 |
+
4drn
|
11102 |
+
1aw1
|
11103 |
+
5fl1
|
11104 |
+
2h2j
|
11105 |
+
4prg
|
11106 |
+
4ibe
|
11107 |
+
2yem
|
11108 |
+
3fql
|
11109 |
+
5zwf
|
11110 |
+
1x0n
|
11111 |
+
3pi5
|
11112 |
+
6ehh
|
11113 |
+
1cps
|
11114 |
+
5akl
|
11115 |
+
3g2t
|
11116 |
+
3vsx
|
11117 |
+
4dhl
|
11118 |
+
1hsg
|
11119 |
+
3vhv
|
11120 |
+
3ro4
|
11121 |
+
5myl
|
11122 |
+
4lyw
|
11123 |
+
3sl5
|
11124 |
+
3e92
|
11125 |
+
4o91
|
11126 |
+
3ipa
|
11127 |
+
1imx
|
11128 |
+
1u71
|
11129 |
+
5dx3
|
11130 |
+
4hvi
|
11131 |
+
1h5v
|
11132 |
+
3p7b
|
11133 |
+
5v8o
|
11134 |
+
2rg5
|
11135 |
+
5nx9
|
11136 |
+
4i8x
|
11137 |
+
4rcf
|
11138 |
+
4yrd
|
11139 |
+
4bcn
|
11140 |
+
4d09
|
11141 |
+
5f8y
|
11142 |
+
5mwp
|
11143 |
+
3n76
|
11144 |
+
3gba
|
11145 |
+
4lyn
|
11146 |
+
1unl
|
11147 |
+
3e6v
|
11148 |
+
4dce
|
11149 |
+
3rsr
|
11150 |
+
1nlp
|
11151 |
+
5dxg
|
11152 |
+
3rcd
|
11153 |
+
2cji
|
11154 |
+
5zwi
|
11155 |
+
3o9a
|
11156 |
+
2x2k
|
11157 |
+
4n5d
|
11158 |
+
5l4f
|
11159 |
+
5gx7
|
11160 |
+
5yqo
|
11161 |
+
4gzt
|
11162 |
+
3tki
|
11163 |
+
5dd0
|
11164 |
+
5ivt
|
11165 |
+
5mnr
|
11166 |
+
3asl
|
11167 |
+
2oc0
|
11168 |
+
3l3n
|
11169 |
+
5izf
|
11170 |
+
1i6v
|
11171 |
+
2y56
|
11172 |
+
4x0f
|
11173 |
+
2h4k
|
11174 |
+
3ivh
|
11175 |
+
4yy6
|
11176 |
+
1drj
|
11177 |
+
3hku
|
11178 |
+
3kfn
|
11179 |
+
6gmd
|
11180 |
+
2c3k
|
11181 |
+
1w5v
|
11182 |
+
5oha
|
11183 |
+
4myq
|
11184 |
+
3new
|
11185 |
+
1o5c
|
11186 |
+
4k5y
|
11187 |
+
5kbi
|
11188 |
+
5of0
|
11189 |
+
5dhs
|
11190 |
+
1y19
|
11191 |
+
3hky
|
11192 |
+
5nka
|
11193 |
+
1wax
|
11194 |
+
6h9b
|
11195 |
+
3i7i
|
11196 |
+
4b6c
|
11197 |
+
1h3h
|
11198 |
+
5xw6
|
11199 |
+
4jql
|
11200 |
+
4cra
|
11201 |
+
3d4l
|
11202 |
+
2nwn
|
11203 |
+
2zyb
|
11204 |
+
3rm9
|
11205 |
+
3q6s
|
11206 |
+
3g4i
|
11207 |
+
3zqt
|
11208 |
+
4bbe
|
11209 |
+
3olf
|
11210 |
+
6gxa
|
11211 |
+
5h4j
|
11212 |
+
4ljh
|
11213 |
+
4a4f
|
11214 |
+
4nw5
|
11215 |
+
2vi5
|
11216 |
+
3eqy
|
11217 |
+
4tpp
|
11218 |
+
1pi5
|
11219 |
+
4bt3
|
11220 |
+
3kiv
|
11221 |
+
1pb8
|
11222 |
+
4xyc
|
11223 |
+
1zd2
|
11224 |
+
2vur
|
11225 |
+
2k2r
|
11226 |
+
5j1x
|
11227 |
+
3pfp
|
11228 |
+
6g37
|
11229 |
+
3nsq
|
11230 |
+
6eq8
|
11231 |
+
2wi6
|
11232 |
+
1bxl
|
11233 |
+
5eci
|
11234 |
+
5jrq
|
11235 |
+
5ehr
|
11236 |
+
4qz1
|
11237 |
+
1nmk
|
11238 |
+
5zkb
|
11239 |
+
4f65
|
11240 |
+
5a7b
|
11241 |
+
5sym
|
11242 |
+
3wti
|
11243 |
+
1j1a
|
11244 |
+
4nwk
|
11245 |
+
5l8t
|
11246 |
+
5k0f
|
11247 |
+
1mqh
|
11248 |
+
1h3b
|
11249 |
+
1wxz
|
11250 |
+
3tt4
|
11251 |
+
5k0x
|
11252 |
+
2ez7
|
11253 |
+
5wbp
|
11254 |
+
4ddl
|
11255 |
+
2ygu
|
11256 |
+
3e7a
|
11257 |
+
1aqj
|
11258 |
+
5m7s
|
11259 |
+
2odd
|
11260 |
+
4eon
|
11261 |
+
3fq7
|
11262 |
+
3vf9
|
11263 |
+
1pxm
|
11264 |
+
4umt
|
11265 |
+
4rlt
|
11266 |
+
4f8j
|
11267 |
+
5dp9
|
11268 |
+
1ung
|
11269 |
+
4r5w
|
11270 |
+
5ais
|
11271 |
+
4btu
|
11272 |
+
4hyb
|
11273 |
+
3nyx
|
11274 |
+
3nif
|
11275 |
+
5hmk
|
11276 |
+
2qyk
|
11277 |
+
3tz4
|
11278 |
+
3qxm
|
11279 |
+
6isd
|
11280 |
+
6g97
|
11281 |
+
5ccm
|
11282 |
+
5u0z
|
11283 |
+
2wbd
|
11284 |
+
3aav
|
11285 |
+
5vzu
|
11286 |
+
2hai
|
11287 |
+
6evn
|
11288 |
+
2yga
|
11289 |
+
1p17
|
11290 |
+
5fus
|
11291 |
+
5elw
|
11292 |
+
4azt
|
11293 |
+
6ea2
|
11294 |
+
1xbo
|
11295 |
+
2yhy
|
11296 |
+
4u0m
|
11297 |
+
6b3e
|
11298 |
+
5hff
|
11299 |
+
3iu8
|
11300 |
+
1dqx
|
11301 |
+
4o0v
|
11302 |
+
5t1u
|
11303 |
+
4gs6
|
11304 |
+
2xei
|
11305 |
+
6gn1
|
11306 |
+
2pze
|
11307 |
+
2j87
|
11308 |
+
4hy1
|
11309 |
+
3udn
|
11310 |
+
5nmg
|
11311 |
+
2pgz
|
11312 |
+
1wdq
|
11313 |
+
4er1
|
11314 |
+
2l6j
|
11315 |
+
4cmo
|
11316 |
+
4gbd
|
11317 |
+
3itu
|
11318 |
+
5a7j
|
11319 |
+
3su4
|
11320 |
+
3r6g
|
11321 |
+
5ea7
|
11322 |
+
6eiq
|
11323 |
+
5qb1
|
11324 |
+
4o61
|
11325 |
+
3grj
|
11326 |
+
4xjs
|
11327 |
+
2x85
|
11328 |
+
3b66
|
11329 |
+
3le6
|
11330 |
+
5t19
|
11331 |
+
3itc
|
11332 |
+
5ett
|
11333 |
+
2esm
|
11334 |
+
3dc2
|
11335 |
+
3p2k
|
11336 |
+
3u7s
|
11337 |
+
3c6w
|
11338 |
+
4fcr
|
11339 |
+
2clo
|
11340 |
+
3d0e
|
11341 |
+
2jqi
|
11342 |
+
1ekb
|
11343 |
+
4ovz
|
11344 |
+
3soq
|
11345 |
+
1hef
|
11346 |
+
5os0
|
11347 |
+
4htp
|
11348 |
+
4tk2
|
11349 |
+
4j22
|
11350 |
+
4etz
|
11351 |
+
3gus
|
11352 |
+
3s76
|
11353 |
+
4pyv
|
11354 |
+
3c49
|
11355 |
+
1ktt
|
11356 |
+
2yz3
|
11357 |
+
1xnx
|
11358 |
+
1elc
|
11359 |
+
5i24
|
11360 |
+
6eif
|
11361 |
+
5t9z
|
11362 |
+
2qt5
|
11363 |
+
5h1e
|
11364 |
+
5ekh
|
11365 |
+
5vdw
|
11366 |
+
3fbr
|
11367 |
+
2za0
|
11368 |
+
5wej
|
11369 |
+
2yel
|
11370 |
+
4anx
|
11371 |
+
1rtf
|
11372 |
+
1r5y
|
11373 |
+
1pzo
|
11374 |
+
2ydw
|
11375 |
+
5kam
|
11376 |
+
5i13
|
11377 |
+
5exw
|
11378 |
+
2xyr
|
11379 |
+
3qs1
|
11380 |
+
2x9f
|
11381 |
+
2np8
|
11382 |
+
5ci7
|
11383 |
+
1m7y
|
11384 |
+
1fcx
|
11385 |
+
5ok3
|
11386 |
+
1hp0
|
11387 |
+
3l79
|
11388 |
+
4jq8
|
11389 |
+
4bhn
|
11390 |
+
1i9p
|
11391 |
+
4hyh
|
11392 |
+
1jil
|
11393 |
+
5f2s
|
11394 |
+
1bwn
|
11395 |
+
1xh7
|
11396 |
+
5kbg
|
11397 |
+
4bg6
|
11398 |
+
3qfy
|
11399 |
+
4ycu
|
11400 |
+
3lxk
|
11401 |
+
4w57
|
11402 |
+
4kxl
|
11403 |
+
5mk9
|
11404 |
+
6er4
|
11405 |
+
2rcw
|
11406 |
+
4jpc
|
11407 |
+
6h1u
|
11408 |
+
3iae
|
11409 |
+
3fnm
|
11410 |
+
3mxr
|
11411 |
+
3c2o
|
11412 |
+
5eva
|
11413 |
+
4kbi
|
11414 |
+
3ogx
|
11415 |
+
5owa
|
11416 |
+
6bmr
|
11417 |
+
4mgb
|
11418 |
+
5ka9
|
11419 |
+
2bza
|
11420 |
+
3sad
|
11421 |
+
4wj5
|
11422 |
+
4o1d
|
11423 |
+
4pnc
|
11424 |
+
4mzf
|
11425 |
+
1f9e
|
11426 |
+
4whl
|
11427 |
+
2imb
|
11428 |
+
4llk
|
11429 |
+
4ih6
|
11430 |
+
1vjd
|
11431 |
+
3stj
|
11432 |
+
3usn
|
11433 |
+
5tnt
|
11434 |
+
4i4e
|
11435 |
+
4hg7
|
11436 |
+
5dxe
|
11437 |
+
1hc9
|
11438 |
+
3dcc
|
11439 |
+
3d27
|
11440 |
+
5azf
|
11441 |
+
5c5h
|
11442 |
+
4m7x
|
11443 |
+
1ysg
|
11444 |
+
5nve
|
11445 |
+
4dcy
|
11446 |
+
2qrh
|
11447 |
+
1r9l
|
11448 |
+
3l0k
|
11449 |
+
4iuv
|
11450 |
+
5j31
|
11451 |
+
5ulg
|
11452 |
+
2wc3
|
11453 |
+
2jxr
|
11454 |
+
4qwx
|
11455 |
+
4joe
|
11456 |
+
4djh
|
11457 |
+
3sm1
|
11458 |
+
4prd
|
11459 |
+
5etn
|
11460 |
+
1ihy
|
11461 |
+
3ut5
|
11462 |
+
4gjc
|
11463 |
+
5c1x
|
11464 |
+
2oxy
|
11465 |
+
5can
|
11466 |
+
5hz9
|
11467 |
+
4uxq
|
11468 |
+
3nzi
|
11469 |
+
4hfz
|
11470 |
+
4mn3
|
11471 |
+
1jif
|
11472 |
+
1svh
|
11473 |
+
4zsa
|
11474 |
+
5y24
|
11475 |
+
5f9b
|
11476 |
+
4mka
|
11477 |
+
5wf7
|
11478 |
+
4o0y
|
11479 |
+
5w8h
|
11480 |
+
1t1s
|
11481 |
+
5w7i
|
11482 |
+
4o2e
|
11483 |
+
3g58
|
11484 |
+
4jmu
|
11485 |
+
3dg8
|
11486 |
+
5u7o
|
11487 |
+
5owt
|
11488 |
+
2oic
|
11489 |
+
3mt7
|
11490 |
+
5ka3
|
11491 |
+
2wgj
|
11492 |
+
1orw
|
11493 |
+
1vea
|
11494 |
+
1j01
|
11495 |
+
4yec
|
11496 |
+
6b7c
|
11497 |
+
5wg9
|
11498 |
+
2fv9
|
11499 |
+
1e55
|
11500 |
+
3cfs
|
11501 |
+
5nhy
|
11502 |
+
4x6s
|
11503 |
+
5ak0
|
11504 |
+
4q1w
|
11505 |
+
4o5b
|
11506 |
+
1b32
|
11507 |
+
2fzk
|
11508 |
+
2p3g
|
11509 |
+
1h24
|
11510 |
+
3qfd
|
11511 |
+
4xu0
|
11512 |
+
3pe2
|
11513 |
+
5ow1
|
11514 |
+
4uyg
|
11515 |
+
3du8
|
11516 |
+
4cby
|
11517 |
+
1mtr
|
11518 |
+
3bug
|
11519 |
+
4uj1
|
11520 |
+
4omj
|
11521 |
+
2y58
|
11522 |
+
1onz
|
11523 |
+
3esj
|
11524 |
+
1y2b
|
11525 |
+
1zyj
|
11526 |
+
1fig
|
11527 |
+
3cd7
|
11528 |
+
2hf8
|
11529 |
+
2v3u
|
11530 |
+
1o4f
|
11531 |
+
5w0q
|
11532 |
+
1ql7
|
11533 |
+
3kv2
|
11534 |
+
2wez
|
11535 |
+
2loz
|
11536 |
+
4zg6
|
11537 |
+
5f4l
|
11538 |
+
4mo4
|
11539 |
+
3mam
|
11540 |
+
2h44
|
11541 |
+
3que
|
11542 |
+
4y32
|
11543 |
+
5cwa
|
11544 |
+
5hyr
|
11545 |
+
4mnp
|
11546 |
+
3wix
|
11547 |
+
5tw5
|
11548 |
+
4dem
|
11549 |
+
5di1
|
11550 |
+
3zlq
|
11551 |
+
6en5
|
11552 |
+
4ogv
|
11553 |
+
2r6y
|
11554 |
+
4k8o
|
11555 |
+
6c7w
|
11556 |
+
6eqv
|
11557 |
+
3dx4
|
11558 |
+
5qa7
|
11559 |
+
2qlm
|
11560 |
+
4tn4
|
11561 |
+
5vm6
|
11562 |
+
4x5r
|
11563 |
+
3k23
|
11564 |
+
2q54
|
11565 |
+
2pe1
|
11566 |
+
4k2y
|
11567 |
+
4rfc
|
11568 |
+
6hqy
|
11569 |
+
4ie3
|
11570 |
+
2qbq
|
11571 |
+
5o07
|
11572 |
+
7std
|
11573 |
+
4mm7
|
11574 |
+
3axz
|
11575 |
+
1a85
|
11576 |
+
5etb
|
11577 |
+
4ylj
|
11578 |
+
2vpe
|
11579 |
+
2qln
|
11580 |
+
5zfi
|
11581 |
+
5wbk
|
11582 |
+
4bty
|
11583 |
+
1nvs
|
11584 |
+
5ftq
|
11585 |
+
3dyo
|
11586 |
+
2c9t
|
11587 |
+
2h6b
|
11588 |
+
5nz4
|
11589 |
+
5ar4
|
11590 |
+
1xfv
|
11591 |
+
6g6z
|
11592 |
+
4e1n
|
11593 |
+
2q2y
|
11594 |
+
2zwz
|
11595 |
+
2ozr
|
11596 |
+
3fei
|
11597 |
+
2xe4
|
11598 |
+
3nin
|
11599 |
+
4py1
|
11600 |
+
4j52
|
11601 |
+
4mrf
|
11602 |
+
1ngw
|
11603 |
+
1m7q
|
11604 |
+
4m8t
|
11605 |
+
4qhp
|
11606 |
+
1my3
|
11607 |
+
5fgk
|
11608 |
+
2ff2
|
11609 |
+
5qat
|
11610 |
+
3chf
|
11611 |
+
4kox
|
11612 |
+
2nsx
|
11613 |
+
5v1b
|
11614 |
+
1det
|
11615 |
+
4cq0
|
11616 |
+
2iwx
|
11617 |
+
4isi
|
11618 |
+
4bcg
|
11619 |
+
1pro
|
11620 |
+
4ebv
|
11621 |
+
2jh5
|
11622 |
+
4mm6
|
11623 |
+
4b82
|
11624 |
+
4m5m
|
11625 |
+
4pp3
|
11626 |
+
3v31
|
11627 |
+
4yt7
|
11628 |
+
3vp4
|
11629 |
+
3imy
|
11630 |
+
1rbo
|
11631 |
+
4b1c
|
11632 |
+
2w7y
|
11633 |
+
1k9q
|
11634 |
+
4erq
|
11635 |
+
5tzh
|
11636 |
+
2a3x
|
11637 |
+
5f61
|
11638 |
+
5orj
|
11639 |
+
3efr
|
11640 |
+
5g4o
|
11641 |
+
3el1
|
11642 |
+
5lkr
|
11643 |
+
1mn9
|
11644 |
+
5wdw
|
11645 |
+
4oym
|
11646 |
+
2iko
|
11647 |
+
1h39
|
11648 |
+
5ddd
|
11649 |
+
5nu1
|
11650 |
+
4qz4
|
11651 |
+
1o5p
|
11652 |
+
4i9c
|
11653 |
+
3wmc
|
11654 |
+
4ajl
|
11655 |
+
4zud
|
11656 |
+
3kig
|
11657 |
+
3wde
|
11658 |
+
6fdu
|
11659 |
+
4psb
|
11660 |
+
4bw2
|
11661 |
+
1hk1
|
11662 |
+
1pph
|
11663 |
+
3wut
|
11664 |
+
2ate
|
11665 |
+
3nw9
|
11666 |
+
5ceo
|
11667 |
+
1g2m
|
11668 |
+
1o3i
|
11669 |
+
5ald
|
11670 |
+
2hjb
|
11671 |
+
2cvd
|
11672 |
+
5za1
|
11673 |
+
4cnh
|
11674 |
+
4pnw
|
11675 |
+
4uwl
|
11676 |
+
5c1w
|
11677 |
+
1m0n
|
11678 |
+
2nsj
|
11679 |
+
4imz
|
11680 |
+
4x3k
|
11681 |
+
4zgk
|
11682 |
+
3pvu
|
11683 |
+
2fah
|
11684 |
+
6ex0
|
11685 |
+
6gz9
|
11686 |
+
1ke8
|
11687 |
+
3tkw
|
11688 |
+
2xfj
|
11689 |
+
4bo9
|
11690 |
+
4cqf
|
11691 |
+
5sy2
|
11692 |
+
3fh7
|
11693 |
+
5u4f
|
11694 |
+
1k27
|
11695 |
+
1msn
|
11696 |
+
5ow8
|
11697 |
+
5ekx
|
11698 |
+
4re2
|
11699 |
+
1dar
|
11700 |
+
6iil
|
11701 |
+
1bmm
|
11702 |
+
3tsk
|
11703 |
+
3tzm
|
11704 |
+
3ttz
|
11705 |
+
4ibd
|
11706 |
+
4zx5
|
11707 |
+
2c4w
|
11708 |
+
1qf4
|
11709 |
+
2xgo
|
11710 |
+
3bm6
|
11711 |
+
2zfp
|
11712 |
+
2uyw
|
11713 |
+
3h8b
|
11714 |
+
4acx
|
11715 |
+
3ouh
|
11716 |
+
4zy1
|
11717 |
+
1c1u
|
11718 |
+
3btc
|
11719 |
+
1azl
|
11720 |
+
4ivd
|
11721 |
+
1o4i
|
11722 |
+
5evb
|
11723 |
+
5dpx
|
11724 |
+
4k9y
|
11725 |
+
3wtm
|
11726 |
+
6mxe
|
11727 |
+
5ygf
|
11728 |
+
4mpe
|
11729 |
+
1o2q
|
11730 |
+
3ru1
|
11731 |
+
4qtb
|
11732 |
+
3qw6
|
11733 |
+
4yb5
|
11734 |
+
2hzl
|
11735 |
+
1b5i
|
11736 |
+
1dbb
|
11737 |
+
4gj3
|
11738 |
+
6bfw
|
11739 |
+
5y5n
|
11740 |
+
5jdi
|
11741 |
+
1kv5
|
11742 |
+
4der
|
11743 |
+
2xc4
|
11744 |
+
3s3r
|
11745 |
+
5lso
|
11746 |
+
5cu4
|
11747 |
+
1ysi
|
11748 |
+
1n2v
|
11749 |
+
4jje
|
11750 |
+
5akw
|
11751 |
+
5f3z
|
11752 |
+
6dl9
|
11753 |
+
5wgd
|
11754 |
+
3muk
|
11755 |
+
3uw9
|
11756 |
+
1o32
|
11757 |
+
1jq3
|
11758 |
+
2zpk
|
11759 |
+
3hk1
|
11760 |
+
2f1a
|
11761 |
+
2haw
|
11762 |
+
4psx
|
11763 |
+
4i54
|
11764 |
+
5d3s
|
11765 |
+
5m56
|
11766 |
+
2bkz
|
11767 |
+
5dxt
|
11768 |
+
1qw7
|
11769 |
+
4abu
|
11770 |
+
2ggb
|
11771 |
+
5fjw
|
11772 |
+
4k5p
|
11773 |
+
5als
|
11774 |
+
2xjg
|
11775 |
+
5eqy
|
11776 |
+
4g2j
|
11777 |
+
2a4g
|
11778 |
+
3hf8
|
11779 |
+
5em9
|
11780 |
+
4ztl
|
11781 |
+
2g1q
|
11782 |
+
4phv
|
11783 |
+
2ylq
|
11784 |
+
5tdb
|
11785 |
+
6dh7
|
11786 |
+
5kz0
|
11787 |
+
3rz3
|
11788 |
+
2vww
|
11789 |
+
5t4b
|
11790 |
+
5xs8
|
11791 |
+
5j7g
|
11792 |
+
1f4f
|
11793 |
+
5mev
|
11794 |
+
5cgd
|
11795 |
+
3vrw
|
11796 |
+
5t8j
|
11797 |
+
2o48
|
11798 |
+
4cgj
|
11799 |
+
4cts
|
11800 |
+
4cbt
|
11801 |
+
5ofw
|
11802 |
+
3q2m
|
11803 |
+
4ce2
|
11804 |
+
2qqs
|
11805 |
+
2j75
|
11806 |
+
4yw7
|
11807 |
+
5wip
|
11808 |
+
6afl
|
11809 |
+
6b16
|
11810 |
+
2cgu
|
11811 |
+
6exi
|
11812 |
+
3mt8
|
11813 |
+
4o24
|
11814 |
+
1z34
|
11815 |
+
3fvg
|
11816 |
+
1w6j
|
11817 |
+
3py0
|
11818 |
+
5nkc
|
11819 |
+
1os5
|
11820 |
+
3t70
|
11821 |
+
2nwl
|
11822 |
+
6dq4
|
11823 |
+
1n3z
|
11824 |
+
4rme
|
11825 |
+
5z95
|
11826 |
+
1tx7
|
11827 |
+
4yc8
|
11828 |
+
3t0m
|
11829 |
+
4e5w
|
11830 |
+
4f1s
|
11831 |
+
1hvr
|
11832 |
+
1xzx
|
11833 |
+
3fty
|
11834 |
+
6au9
|
11835 |
+
4eu0
|
11836 |
+
4d1a
|
11837 |
+
2p7a
|
11838 |
+
4z2k
|
11839 |
+
5ap7
|
11840 |
+
1sqb
|
11841 |
+
3wt5
|
11842 |
+
3eqb
|
11843 |
+
4o3c
|
11844 |
+
1rgl
|
11845 |
+
3r7q
|
11846 |
+
2ay8
|
11847 |
+
5enm
|
11848 |
+
2ha7
|
11849 |
+
5ak5
|
11850 |
+
6dug
|
11851 |
+
3wgw
|
11852 |
+
6bfn
|
11853 |
+
2fx8
|
11854 |
+
4rxc
|
11855 |
+
6bny
|
11856 |
+
6h36
|
11857 |
+
5ugm
|
11858 |
+
5trj
|
11859 |
+
5xpo
|
11860 |
+
1jmf
|
11861 |
+
3ugc
|
11862 |
+
4jhz
|
11863 |
+
3p44
|
11864 |
+
1zp5
|
11865 |
+
1v2o
|
11866 |
+
5tbe
|
11867 |
+
1o2r
|
11868 |
+
4wsk
|
11869 |
+
5vdk
|
11870 |
+
3rni
|
11871 |
+
3kc3
|
11872 |
+
4mi3
|
11873 |
+
4pb2
|
11874 |
+
5euk
|
11875 |
+
5ukk
|
11876 |
+
2k2g
|
11877 |
+
4a4q
|
11878 |
+
3m6q
|
11879 |
+
3btj
|
11880 |
+
4gtv
|
11881 |
+
5u0g
|
11882 |
+
4zh4
|
11883 |
+
3v2p
|
11884 |
+
3kqt
|
11885 |
+
4im0
|
11886 |
+
1ni1
|
11887 |
+
3wp0
|
11888 |
+
3vi7
|
11889 |
+
4tkn
|
11890 |
+
6bg3
|
11891 |
+
1o1s
|
11892 |
+
5d3l
|
11893 |
+
2qc6
|
11894 |
+
5lp6
|
11895 |
+
2br6
|
11896 |
+
5ku6
|
11897 |
+
5d3c
|
11898 |
+
5ny3
|
11899 |
+
5hjb
|
11900 |
+
4txc
|
11901 |
+
3waw
|
11902 |
+
5b1s
|
11903 |
+
4trz
|
11904 |
+
2pwc
|
11905 |
+
3nu4
|
11906 |
+
4x3i
|
11907 |
+
3djk
|
11908 |
+
3qw7
|
11909 |
+
3ivx
|
11910 |
+
6b8j
|
11911 |
+
1y0x
|
11912 |
+
1ros
|
11913 |
+
4rwj
|
11914 |
+
6bto
|
11915 |
+
3ztc
|
11916 |
+
1jlx
|
11917 |
+
5h13
|
11918 |
+
3l0v
|
11919 |
+
4ycn
|
11920 |
+
5qam
|
11921 |
+
4ke1
|
11922 |
+
3wv1
|
11923 |
+
4mep
|
11924 |
+
5tzc
|
11925 |
+
1bil
|
11926 |
+
4fl2
|
11927 |
+
4u6r
|
11928 |
+
4k6i
|
11929 |
+
4g2r
|
11930 |
+
4pg9
|
11931 |
+
2hzn
|
11932 |
+
3r8v
|
11933 |
+
5d9k
|
11934 |
+
4gg7
|
11935 |
+
3d9n
|
11936 |
+
6cct
|
11937 |
+
2c93
|
11938 |
+
1uxa
|
11939 |
+
3nfk
|
11940 |
+
5f27
|
11941 |
+
2w6n
|
11942 |
+
3k8d
|
11943 |
+
4pl4
|
11944 |
+
4b9z
|
11945 |
+
4uiy
|
11946 |
+
5fl4
|
11947 |
+
2bbb
|
11948 |
+
3b50
|
11949 |
+
1qon
|
11950 |
+
6ce8
|
11951 |
+
1ydk
|
11952 |
+
4jv8
|
11953 |
+
2bw7
|
11954 |
+
1li2
|
11955 |
+
4qag
|
11956 |
+
3hyg
|
11957 |
+
2qtr
|
11958 |
+
2cen
|
11959 |
+
4k3n
|
11960 |
+
2fes
|
11961 |
+
5kat
|
11962 |
+
1dzp
|
11963 |
+
3gcu
|
11964 |
+
4nbn
|
11965 |
+
4ctk
|
11966 |
+
1okx
|
11967 |
+
1nzq
|
11968 |
+
5fb1
|
11969 |
+
4r5v
|
11970 |
+
4b7n
|
11971 |
+
4det
|
11972 |
+
2xm2
|
11973 |
+
3exe
|
11974 |
+
1jje
|
11975 |
+
4wup
|
11976 |
+
3sjt
|
11977 |
+
6h8s
|
11978 |
+
6bx6
|
11979 |
+
5tqf
|
11980 |
+
3lpk
|
11981 |
+
3h1x
|
11982 |
+
4ps1
|
11983 |
+
3c72
|
11984 |
+
2dua
|
11985 |
+
4w97
|
11986 |
+
5diu
|
11987 |
+
2cbs
|
11988 |
+
4zy4
|
11989 |
+
4alx
|
11990 |
+
1y6b
|
11991 |
+
1tnj
|
11992 |
+
2vo7
|
11993 |
+
4qye
|
11994 |
+
4no9
|
11995 |
+
5ct1
|
11996 |
+
4elb
|
11997 |
+
5sz2
|
11998 |
+
4u0x
|
11999 |
+
4ztq
|
12000 |
+
2nnd
|
12001 |
+
1xom
|
12002 |
+
4u0a
|
12003 |
+
4abj
|
12004 |
+
3uh4
|
12005 |
+
1pop
|
12006 |
+
3hv5
|
12007 |
+
3zll
|
12008 |
+
4rak
|
12009 |
+
5u7m
|
12010 |
+
5tuo
|
12011 |
+
5ur1
|
12012 |
+
4iqu
|
12013 |
+
3kac
|
12014 |
+
1t7r
|
12015 |
+
4lqg
|
12016 |
+
4um1
|
12017 |
+
5mwa
|
12018 |
+
3djp
|
12019 |
+
4zeb
|
12020 |
+
3r91
|
12021 |
+
4o77
|
12022 |
+
4r5t
|
12023 |
+
4ijq
|
12024 |
+
4mxa
|
12025 |
+
3d0b
|
12026 |
+
5ld8
|
12027 |
+
3hdz
|
12028 |
+
4bxn
|
12029 |
+
3vb5
|
12030 |
+
5q0j
|
12031 |
+
3rx7
|
12032 |
+
1k9s
|
12033 |
+
6cjy
|
12034 |
+
4zjj
|
12035 |
+
5i3y
|
12036 |
+
2wos
|
12037 |
+
1bbz
|
12038 |
+
4rx5
|
12039 |
+
4nzm
|
12040 |
+
1m5c
|
12041 |
+
4djs
|
12042 |
+
5ect
|
12043 |
+
5ejw
|
12044 |
+
4fvr
|
12045 |
+
5vtb
|
12046 |
+
6f20
|
12047 |
+
1u9x
|
12048 |
+
1zea
|
12049 |
+
2zzu
|
12050 |
+
3rxp
|
12051 |
+
2z3z
|
12052 |
+
1oeb
|
12053 |
+
1gux
|
12054 |
+
4g8r
|
12055 |
+
1hk2
|
12056 |
+
1g4k
|
12057 |
+
5dfp
|
12058 |
+
5vc4
|
12059 |
+
4g55
|
12060 |
+
4o7d
|
12061 |
+
1nc3
|
12062 |
+
6cdp
|
12063 |
+
4gu9
|
12064 |
+
5gvn
|
12065 |
+
3l8s
|
12066 |
+
4bis
|
12067 |
+
4lwi
|
12068 |
+
2baj
|
12069 |
+
5wik
|
12070 |
+
5a7i
|
12071 |
+
4pnq
|
12072 |
+
2xde
|
12073 |
+
6e4u
|
12074 |
+
1b38
|
12075 |
+
3wzn
|
12076 |
+
5nn0
|
12077 |
+
4fl1
|
12078 |
+
3q6k
|
12079 |
+
6eab
|
12080 |
+
3s68
|
12081 |
+
2dq7
|
12082 |
+
1yw7
|
12083 |
+
4x8p
|
12084 |
+
5vgo
|
12085 |
+
2o9k
|
12086 |
+
4yo6
|
12087 |
+
4lv1
|
12088 |
+
5ose
|
12089 |
+
4ogt
|
12090 |
+
5e8a
|
12091 |
+
4k76
|
12092 |
+
2pr9
|
12093 |
+
1z3j
|
12094 |
+
2g72
|
12095 |
+
2l1b
|
12096 |
+
4gdy
|
12097 |
+
1lq2
|
12098 |
+
6g0q
|
12099 |
+
6cv8
|
12100 |
+
5tri
|
12101 |
+
1g7q
|
12102 |
+
1o4g
|
12103 |
+
4cg8
|
12104 |
+
2ohl
|
12105 |
+
1v2u
|
12106 |
+
4b83
|
12107 |
+
3wyj
|
12108 |
+
4hrd
|
12109 |
+
4kfq
|
12110 |
+
1no6
|
12111 |
+
5lax
|
12112 |
+
3egk
|
12113 |
+
3f7g
|
12114 |
+
4deh
|
12115 |
+
5tmp
|
12116 |
+
4rad
|
12117 |
+
3d78
|
12118 |
+
5l72
|
12119 |
+
3avj
|
12120 |
+
4rg0
|
12121 |
+
4qev
|
12122 |
+
5nt4
|
12123 |
+
5svk
|
12124 |
+
2w08
|
12125 |
+
3lxo
|
12126 |
+
3ljj
|
12127 |
+
4kif
|
12128 |
+
2jdo
|
12129 |
+
1v0o
|
12130 |
+
1k3n
|
12131 |
+
1rgj
|
12132 |
+
4zt8
|
12133 |
+
6dub
|
12134 |
+
1zdp
|
12135 |
+
187l
|
12136 |
+
6dkb
|
12137 |
+
3n6k
|
12138 |
+
1tnk
|
12139 |
+
2h2g
|
12140 |
+
4mjq
|
12141 |
+
4a9i
|
12142 |
+
4pre
|
12143 |
+
2gni
|
12144 |
+
3bgb
|
12145 |
+
4ddm
|
12146 |
+
2p99
|
12147 |
+
1mwt
|
12148 |
+
5nhl
|
12149 |
+
6b4w
|
12150 |
+
3sou
|
12151 |
+
3sm2
|
12152 |
+
5qik
|
12153 |
+
1loq
|
12154 |
+
4yqh
|
12155 |
+
5mi7
|
12156 |
+
4ynl
|
12157 |
+
2f9v
|
12158 |
+
1qbn
|
12159 |
+
2r2m
|
12160 |
+
3uod
|
12161 |
+
2w0z
|
12162 |
+
4ewo
|
12163 |
+
1fsy
|
12164 |
+
1tmm
|
12165 |
+
3va4
|
12166 |
+
6b0y
|
12167 |
+
2adu
|
12168 |
+
5dtj
|
12169 |
+
3k3a
|
12170 |
+
1sm2
|
12171 |
+
3ozs
|
12172 |
+
3o8g
|
12173 |
+
5g42
|
12174 |
+
4h3a
|
12175 |
+
2fwp
|
12176 |
+
6fbw
|
12177 |
+
5tzw
|
12178 |
+
1xkk
|
12179 |
+
3tdu
|
12180 |
+
3efj
|
12181 |
+
3as2
|
12182 |
+
2ity
|
12183 |
+
4zwy
|
12184 |
+
2nmy
|
12185 |
+
4amy
|
12186 |
+
5kad
|
12187 |
+
3qtv
|
12188 |
+
3ncq
|
12189 |
+
3p58
|
12190 |
+
6h1i
|
12191 |
+
5x13
|
12192 |
+
4d1d
|
12193 |
+
3zev
|
12194 |
+
6aum
|
12195 |
+
1ftm
|
12196 |
+
4dsu
|
12197 |
+
4hla
|
12198 |
+
2qoe
|
12199 |
+
5em5
|
12200 |
+
3u0p
|
12201 |
+
3dx2
|
12202 |
+
4kn2
|
12203 |
+
4ce1
|
12204 |
+
3np9
|
12205 |
+
3t2w
|
12206 |
+
4b7r
|
12207 |
+
5o9q
|
12208 |
+
1rth
|
12209 |
+
3eq7
|
12210 |
+
3i0s
|
12211 |
+
2pgl
|
12212 |
+
2yj8
|
12213 |
+
2z6w
|
12214 |
+
3v9b
|
12215 |
+
6fs0
|
12216 |
+
1dhi
|
12217 |
+
4hdp
|
12218 |
+
5svz
|
12219 |
+
4mz5
|
12220 |
+
1a1c
|
12221 |
+
4p0n
|
12222 |
+
3n7s
|
12223 |
+
2aow
|
12224 |
+
1j19
|
12225 |
+
4k3o
|
12226 |
+
1m7i
|
12227 |
+
3s9z
|
12228 |
+
1igb
|
12229 |
+
4o9s
|
12230 |
+
5xyx
|
12231 |
+
4mex
|
12232 |
+
5jy3
|
12233 |
+
4jht
|
12234 |
+
3hxc
|
12235 |
+
2c3i
|
12236 |
+
4itp
|
12237 |
+
2fl5
|
12238 |
+
4b12
|
12239 |
+
3o6m
|
12240 |
+
2vd4
|
12241 |
+
3tib
|
12242 |
+
5yj8
|
12243 |
+
1aze
|
12244 |
+
4yad
|
12245 |
+
3w37
|
12246 |
+
5e8z
|
12247 |
+
3pz4
|
12248 |
+
2p4y
|
12249 |
+
2xda
|
12250 |
+
3n4l
|
12251 |
+
1i1e
|
12252 |
+
1tbz
|
12253 |
+
2bxu
|
12254 |
+
1g6r
|
12255 |
+
4h5e
|
12256 |
+
3fuz
|
12257 |
+
1f2p
|
12258 |
+
1b51
|
12259 |
+
5lm6
|
12260 |
+
5gx6
|
12261 |
+
4wn0
|
12262 |
+
3h21
|
12263 |
+
3vd9
|
12264 |
+
1x39
|
12265 |
+
4bjc
|
12266 |
+
6d5g
|
12267 |
+
3nnu
|
12268 |
+
3d32
|
12269 |
+
3l9l
|
12270 |
+
5i3w
|
12271 |
+
4kqo
|
12272 |
+
5w38
|
12273 |
+
2p2i
|
12274 |
+
4ohk
|
12275 |
+
5l2i
|
12276 |
+
4jlh
|
12277 |
+
4whh
|
12278 |
+
3u6i
|
12279 |
+
2khh
|
12280 |
+
4gu6
|
12281 |
+
1snk
|
12282 |
+
1ogu
|
12283 |
+
2p0d
|
12284 |
+
1zeo
|
12285 |
+
1iq1
|
12286 |
+
4knb
|
12287 |
+
3lrh
|
12288 |
+
5a5r
|
12289 |
+
5iok
|
12290 |
+
5t6p
|
12291 |
+
4dx9
|
12292 |
+
2a0t
|
12293 |
+
1c5x
|
12294 |
+
1qxw
|
12295 |
+
3d83
|
12296 |
+
3pwh
|
12297 |
+
5g46
|
12298 |
+
4wy6
|
12299 |
+
1yw2
|
12300 |
+
1bm6
|
12301 |
+
4yhm
|
12302 |
+
1tka
|
12303 |
+
3qpp
|
12304 |
+
4g19
|
12305 |
+
1pdz
|
12306 |
+
4fnz
|
12307 |
+
5mby
|
12308 |
+
3zt1
|
12309 |
+
1y3v
|
12310 |
+
3tv4
|
12311 |
+
2qmd
|
12312 |
+
2phb
|
12313 |
+
1bzf
|
12314 |
+
1m2r
|
12315 |
+
6g46
|
12316 |
+
3hvj
|
12317 |
+
3mhl
|
12318 |
+
4w9c
|
12319 |
+
4imq
|
12320 |
+
5k4i
|
12321 |
+
3abt
|
12322 |
+
3vuc
|
12323 |
+
4oyt
|
12324 |
+
5qb3
|
12325 |
+
5yv5
|
12326 |
+
4n1b
|
12327 |
+
1pip
|
12328 |
+
5iu8
|
12329 |
+
3zke
|
12330 |
+
5f1z
|
12331 |
+
4qvx
|
12332 |
+
4zlz
|
12333 |
+
4qfs
|
12334 |
+
5ai0
|
12335 |
+
4op2
|
12336 |
+
3tfn
|
12337 |
+
5cnm
|
12338 |
+
6dge
|
12339 |
+
1htg
|
12340 |
+
3rey
|
12341 |
+
1o6r
|
12342 |
+
3w5n
|
12343 |
+
4l52
|
12344 |
+
4b76
|
12345 |
+
5qar
|
12346 |
+
4nj9
|
12347 |
+
2kaw
|
12348 |
+
4ezz
|
12349 |
+
3hkt
|
12350 |
+
5e1b
|
12351 |
+
3ufa
|
12352 |
+
4btx
|
12353 |
+
5mgj
|
12354 |
+
2ha2
|
12355 |
+
5cst
|
12356 |
+
5ea5
|
12357 |
+
5kgn
|
12358 |
+
3jq7
|
12359 |
+
1qy2
|
12360 |
+
4fpk
|
12361 |
+
3hq5
|
12362 |
+
1at5
|
12363 |
+
1hge
|
12364 |
+
5ty1
|
12365 |
+
4b3d
|
12366 |
+
1lyb
|
12367 |
+
5mrd
|
12368 |
+
4zt4
|
12369 |
+
4ovg
|
12370 |
+
4pp7
|
12371 |
+
2w5i
|
12372 |
+
6ced
|
12373 |
+
4elg
|
12374 |
+
5j71
|
12375 |
+
3i6o
|
12376 |
+
4mx5
|
12377 |
+
4pnm
|
12378 |
+
2g0g
|
12379 |
+
1x81
|
12380 |
+
4wkp
|
12381 |
+
4kxm
|
12382 |
+
1wht
|
12383 |
+
6q3q
|
12384 |
+
4gee
|
12385 |
+
2f70
|
12386 |
+
2wd1
|
12387 |
+
6aah
|
12388 |
+
4rfm
|
12389 |
+
2wvt
|
12390 |
+
3dx3
|
12391 |
+
5t4v
|
12392 |
+
1owh
|
12393 |
+
4k7o
|
12394 |
+
4z7n
|
12395 |
+
5lla
|
12396 |
+
5ehw
|
12397 |
+
3jsi
|
12398 |
+
1ohr
|
12399 |
+
4k3h
|
12400 |
+
5y8y
|
12401 |
+
1pu8
|
12402 |
+
2mg5
|
12403 |
+
3l5f
|
12404 |
+
3tfk
|
12405 |
+
1t31
|
12406 |
+
3t08
|
12407 |
+
4iho
|
12408 |
+
3i91
|
12409 |
+
5fdg
|
12410 |
+
5ntq
|
12411 |
+
5wa4
|
12412 |
+
2iqg
|
12413 |
+
5tol
|
12414 |
+
4tz2
|
12415 |
+
2d1o
|
12416 |
+
5ene
|
12417 |
+
4mc2
|
12418 |
+
6ax4
|
12419 |
+
4aoi
|
12420 |
+
1u3r
|
12421 |
+
4ngq
|
12422 |
+
3src
|
12423 |
+
5zzw
|
12424 |
+
1sw2
|
12425 |
+
6g2m
|
12426 |
+
5fwa
|
12427 |
+
2q7m
|
12428 |
+
1xn2
|
12429 |
+
5g6u
|
12430 |
+
1puq
|
12431 |
+
5ha9
|
12432 |
+
3s56
|
12433 |
+
3ckt
|
12434 |
+
2jaj
|
12435 |
+
2qlb
|
12436 |
+
1l6y
|
12437 |
+
4tzq
|
12438 |
+
5u9d
|
12439 |
+
4nzb
|
12440 |
+
3ccc
|
12441 |
+
3isj
|
12442 |
+
5kbr
|
12443 |
+
3u92
|
12444 |
+
5duw
|
12445 |
+
3ijh
|
12446 |
+
1uti
|
12447 |
+
5tw2
|
12448 |
+
2hd1
|
12449 |
+
4wuy
|
12450 |
+
1riw
|
12451 |
+
3u8n
|
12452 |
+
6flg
|
12453 |
+
2qzk
|
12454 |
+
5w6o
|
12455 |
+
2v2q
|
12456 |
+
6e86
|
12457 |
+
4e0w
|
12458 |
+
5jf4
|
12459 |
+
5a8y
|
12460 |
+
2nq6
|
12461 |
+
1tsy
|
12462 |
+
1rek
|
12463 |
+
2xht
|
12464 |
+
2gtk
|
12465 |
+
4kom
|
12466 |
+
6en6
|
12467 |
+
3zmz
|
12468 |
+
3efs
|
12469 |
+
4whr
|
12470 |
+
5j1v
|
12471 |
+
1ld8
|
12472 |
+
4o37
|
12473 |
+
5qa5
|
12474 |
+
4c9w
|
12475 |
+
2zdz
|
12476 |
+
1l5q
|
12477 |
+
3kek
|
12478 |
+
2olb
|
12479 |
+
4dru
|
12480 |
+
2h42
|
12481 |
+
5jnn
|
12482 |
+
1w0x
|
12483 |
+
6chh
|
12484 |
+
3av9
|
12485 |
+
3uzc
|
12486 |
+
1l83
|
12487 |
+
2osm
|
12488 |
+
5i89
|
12489 |
+
5wb6
|
12490 |
+
3vdc
|
12491 |
+
1b4h
|
12492 |
+
5e0a
|
12493 |
+
1nyy
|
12494 |
+
4bqg
|
12495 |
+
5otr
|
12496 |
+
5axp
|
12497 |
+
2w1f
|
12498 |
+
4z1q
|
12499 |
+
4q4q
|
12500 |
+
4o07
|
12501 |
+
3g0f
|
12502 |
+
4alv
|
12503 |
+
4jfx
|
12504 |
+
5kjn
|
12505 |
+
2jal
|
12506 |
+
4u0w
|
12507 |
+
2k0g
|
12508 |
+
3uwk
|
12509 |
+
3k26
|
12510 |
+
5iq6
|
12511 |
+
6hjj
|
12512 |
+
3o0g
|
12513 |
+
3iu9
|
12514 |
+
4xg8
|
12515 |
+
4xya
|
12516 |
+
1zfk
|
12517 |
+
3jvk
|
12518 |
+
5wxh
|
12519 |
+
3t0w
|
12520 |
+
5yg3
|
12521 |
+
1xpz
|
12522 |
+
4b60
|
12523 |
+
4j2t
|
12524 |
+
3ds0
|
12525 |
+
2l0i
|
12526 |
+
5y1u
|
12527 |
+
1pxk
|
12528 |
+
4da5
|
12529 |
+
1z6e
|
12530 |
+
6fi5
|
12531 |
+
4pry
|
12532 |
+
8lpr
|
12533 |
+
2ya7
|
12534 |
+
3zv7
|
12535 |
+
4bnz
|
12536 |
+
6bh5
|
12537 |
+
4x2s
|
12538 |
+
2vth
|
12539 |
+
3tvc
|
12540 |
+
5fky
|
12541 |
+
1i43
|
12542 |
+
5jau
|
12543 |
+
4qsw
|
12544 |
+
1m21
|
12545 |
+
4xsy
|
12546 |
+
2pvn
|
12547 |
+
5htl
|
12548 |
+
5o7i
|
12549 |
+
3skh
|
12550 |
+
5wic
|
12551 |
+
1fvt
|
12552 |
+
4rio
|
12553 |
+
3si3
|
12554 |
+
6dnp
|
12555 |
+
4c4n
|
12556 |
+
4ufu
|
12557 |
+
2ork
|
12558 |
+
5dkr
|
12559 |
+
3m59
|
12560 |
+
3tmk
|
12561 |
+
3btr
|
12562 |
+
5nps
|
12563 |
+
2oah
|
12564 |
+
5ywx
|
12565 |
+
4nxs
|
12566 |
+
3r8i
|
12567 |
+
1z1h
|
12568 |
+
4jik
|
12569 |
+
3oui
|
12570 |
+
4pzx
|
12571 |
+
5o1g
|
12572 |
+
5auw
|
12573 |
+
6cjv
|
12574 |
+
1t46
|
12575 |
+
1uwb
|
12576 |
+
4lgu
|
12577 |
+
5xvu
|
12578 |
+
4x3t
|
12579 |
+
5dtk
|
12580 |
+
3qkl
|
12581 |
+
3meu
|
12582 |
+
3ove
|
12583 |
+
5mw3
|
12584 |
+
2zcq
|
12585 |
+
4n7y
|
12586 |
+
4e4a
|
12587 |
+
2avs
|
12588 |
+
4e3l
|
12589 |
+
1hbv
|
12590 |
+
3tl0
|
12591 |
+
3g15
|
12592 |
+
6c5t
|
12593 |
+
4ayu
|
12594 |
+
4aba
|
12595 |
+
5ddb
|
12596 |
+
5mmg
|
12597 |
+
5k09
|
12598 |
+
3fj7
|
12599 |
+
4y3j
|
12600 |
+
3dxg
|
12601 |
+
5a6n
|
12602 |
+
5lvd
|
12603 |
+
3c2f
|
12604 |
+
1w51
|
12605 |
+
4m3m
|
12606 |
+
4x6k
|
12607 |
+
6h7b
|
12608 |
+
5gow
|
12609 |
+
5n6s
|
12610 |
+
2f18
|
12611 |
+
4kvm
|
12612 |
+
6d5j
|
12613 |
+
2qhn
|
12614 |
+
1ppm
|
12615 |
+
5y2f
|
12616 |
+
3fi2
|
12617 |
+
3vzv
|
12618 |
+
4r73
|
12619 |
+
5h5q
|
12620 |
+
5gic
|
12621 |
+
1g6g
|
12622 |
+
5j47
|
12623 |
+
4tmr
|
12624 |
+
4inb
|
12625 |
+
1w6h
|
12626 |
+
1inf
|
12627 |
+
5alk
|
12628 |
+
3u8l
|
12629 |
+
2bvr
|
12630 |
+
5bnj
|
12631 |
+
5nk4
|
12632 |
+
2c6g
|
12633 |
+
5tbn
|
12634 |
+
5ug8
|
12635 |
+
2wbg
|
12636 |
+
6bgv
|
12637 |
+
3fzc
|
12638 |
+
5mgf
|
12639 |
+
4ngp
|
12640 |
+
4akn
|
12641 |
+
3k27
|
12642 |
+
4gfn
|
12643 |
+
1vjc
|
12644 |
+
6ckc
|
12645 |
+
3bqc
|
12646 |
+
2k0x
|
12647 |
+
4o0a
|
12648 |
+
4m1d
|
12649 |
+
3cfn
|
12650 |
+
2ds1
|
12651 |
+
3wnt
|
12652 |
+
2ogy
|
12653 |
+
6d28
|
12654 |
+
6ffi
|
12655 |
+
6eu6
|
12656 |
+
2it4
|
12657 |
+
6h78
|
12658 |
+
3s0e
|
12659 |
+
3u1y
|
12660 |
+
3r04
|
12661 |
+
2nsl
|
12662 |
+
4knj
|
12663 |
+
5q14
|
12664 |
+
1e1x
|
12665 |
+
5cs3
|
12666 |
+
5hfc
|
12667 |
+
5zob
|
12668 |
+
4erz
|
12669 |
+
5ant
|
12670 |
+
6ft4
|
12671 |
+
3th0
|
12672 |
+
1ijr
|
12673 |
+
4lnw
|
12674 |
+
4pyq
|
12675 |
+
2r3t
|
12676 |
+
3ik3
|
12677 |
+
5mkr
|
12678 |
+
2gz7
|
12679 |
+
1joj
|
12680 |
+
1j17
|
12681 |
+
1c5o
|
12682 |
+
3avf
|
12683 |
+
3u0t
|
12684 |
+
1c85
|
12685 |
+
5w99
|
12686 |
+
6d4o
|
12687 |
+
2qic
|
12688 |
+
2tmn
|
12689 |
+
4cc6
|
12690 |
+
5q1h
|
12691 |
+
5k5n
|
12692 |
+
5n55
|
12693 |
+
3rxj
|
12694 |
+
3njy
|
12695 |
+
3srg
|
12696 |
+
4bgm
|
12697 |
+
4m0r
|
12698 |
+
5nxv
|
12699 |
+
5j1w
|
12700 |
+
4bbf
|
12701 |
+
4mot
|
12702 |
+
1tl7
|
12703 |
+
6gf9
|
12704 |
+
4ivs
|
12705 |
+
1bmn
|
12706 |
+
1bju
|
12707 |
+
1w4o
|
12708 |
+
2pmn
|
12709 |
+
1k6p
|
12710 |
+
5akz
|
12711 |
+
4ca7
|
12712 |
+
4joa
|
12713 |
+
1mfa
|
12714 |
+
4qqc
|
12715 |
+
5e2q
|
12716 |
+
1dgm
|
12717 |
+
2fxu
|
12718 |
+
3ejp
|
12719 |
+
1a1b
|
12720 |
+
5k0j
|
12721 |
+
3h5u
|
12722 |
+
5ha1
|
12723 |
+
2rg6
|
12724 |
+
4b77
|
12725 |
+
4hzt
|
12726 |
+
5fe7
|
12727 |
+
4pgd
|
12728 |
+
5uwm
|
12729 |
+
4rro
|
12730 |
+
4rr6
|
12731 |
+
4o70
|
12732 |
+
5cfa
|
12733 |
+
4ke0
|
12734 |
+
4ju3
|
12735 |
+
2wtw
|
12736 |
+
2qhm
|
12737 |
+
3m3z
|
12738 |
+
2vqt
|
12739 |
+
5q0d
|
12740 |
+
3gcv
|
12741 |
+
4fmn
|
12742 |
+
3s7l
|
12743 |
+
5kgx
|
12744 |
+
2n9e
|
12745 |
+
2vmf
|
12746 |
+
4x63
|
12747 |
+
3fc1
|
12748 |
+
1ok7
|
12749 |
+
4pzv
|
12750 |
+
5dd9
|
12751 |
+
4nru
|
12752 |
+
1udu
|
12753 |
+
6fmp
|
12754 |
+
5fxs
|
12755 |
+
4dk7
|
12756 |
+
4e5f
|
12757 |
+
5ml0
|
12758 |
+
3v6s
|
12759 |
+
4eeh
|
12760 |
+
5cjf
|
12761 |
+
5e1o
|
12762 |
+
6bw8
|
12763 |
+
3h2f
|
12764 |
+
1yly
|
12765 |
+
4avs
|
12766 |
+
1sri
|
12767 |
+
1avn
|
12768 |
+
3i25
|
12769 |
+
4fm8
|
12770 |
+
4jg7
|
12771 |
+
3fu6
|
12772 |
+
1g7f
|
12773 |
+
4l1u
|
12774 |
+
4dr9
|
12775 |
+
3ocg
|
12776 |
+
5wal
|
12777 |
+
4dq2
|
12778 |
+
1uz8
|
12779 |
+
4qjp
|
12780 |
+
2onb
|
12781 |
+
4hgc
|
12782 |
+
2lyw
|
12783 |
+
5xgl
|
12784 |
+
1ydr
|
12785 |
+
2r0h
|
12786 |
+
4q4s
|
12787 |
+
5j64
|
12788 |
+
4riv
|
12789 |
+
4cp7
|
12790 |
+
5d9p
|
12791 |
+
1il4
|
12792 |
+
2qaf
|
12793 |
+
1idb
|
12794 |
+
3ft8
|
12795 |
+
1hos
|
12796 |
+
2xnn
|
12797 |
+
5myv
|
12798 |
+
5ti4
|
12799 |
+
3gi5
|
12800 |
+
2wxh
|
12801 |
+
4eo6
|
12802 |
+
3spk
|
12803 |
+
1g3f
|
12804 |
+
5iy4
|
12805 |
+
5h1v
|
12806 |
+
1mem
|
12807 |
+
1rdt
|
12808 |
+
2c92
|
12809 |
+
1n7m
|
12810 |
+
5dif
|
12811 |
+
2py4
|
12812 |
+
4k9h
|
12813 |
+
4ehr
|
12814 |
+
1nfx
|
12815 |
+
4cst
|
12816 |
+
3h0v
|
12817 |
+
5z7j
|
12818 |
+
5ta2
|
12819 |
+
5nu3
|
12820 |
+
3k3i
|
12821 |
+
3gpe
|
12822 |
+
3zq9
|
12823 |
+
5cqj
|
12824 |
+
6axk
|
12825 |
+
4len
|
12826 |
+
4nmp
|
12827 |
+
3b25
|
12828 |
+
3ch9
|
12829 |
+
5djv
|
12830 |
+
4hxw
|
12831 |
+
4euc
|
12832 |
+
1hvy
|
12833 |
+
2jk9
|
12834 |
+
3ncz
|
12835 |
+
3bu1
|
12836 |
+
4bb2
|
12837 |
+
3wqh
|
12838 |
+
6alz
|
12839 |
+
3qch
|
12840 |
+
4jv7
|
12841 |
+
2jmj
|
12842 |
+
3nan
|
12843 |
+
5vds
|
12844 |
+
1oth
|
12845 |
+
2aie
|
12846 |
+
3dln
|
12847 |
+
3mv5
|
12848 |
+
5egu
|
12849 |
+
6dki
|
12850 |
+
5am0
|
12851 |
+
3vrt
|
12852 |
+
6dpt
|
12853 |
+
1ew9
|
12854 |
+
2w6u
|
12855 |
+
2ggu
|
12856 |
+
5jsj
|
12857 |
+
2xwd
|
12858 |
+
3zya
|
12859 |
+
5uwp
|
12860 |
+
2exc
|
12861 |
+
5e28
|
12862 |
+
5k32
|
12863 |
+
3g4f
|
12864 |
+
2xng
|
12865 |
+
4x5y
|
12866 |
+
6esm
|
12867 |
+
1gi4
|
12868 |
+
3d2t
|
12869 |
+
5ttw
|
12870 |
+
3ekx
|
12871 |
+
2uwp
|
12872 |
+
1klg
|
12873 |
+
4y2x
|
12874 |
+
2dwx
|
12875 |
+
5lrq
|
12876 |
+
1od8
|
12877 |
+
1ceb
|
12878 |
+
4ci2
|
12879 |
+
4m5i
|
12880 |
+
1o9e
|
12881 |
+
1nq7
|
12882 |
+
3ejr
|
12883 |
+
4wrs
|
12884 |
+
4eor
|
12885 |
+
1g1d
|
12886 |
+
5ofi
|
12887 |
+
2kce
|
12888 |
+
5eko
|
12889 |
+
4mhy
|
12890 |
+
1ndy
|
12891 |
+
2cc7
|
12892 |
+
2nnk
|
12893 |
+
5ybe
|
12894 |
+
1svg
|
12895 |
+
5aes
|
12896 |
+
4pkr
|
12897 |
+
5j5x
|
12898 |
+
1cka
|
12899 |
+
3n7h
|
12900 |
+
3pxe
|
12901 |
+
4kz7
|
12902 |
+
1tcw
|
12903 |
+
3v5j
|
12904 |
+
2xp8
|
12905 |
+
4bv2
|
12906 |
+
1gyx
|
12907 |
+
4i6b
|
12908 |
+
4oyb
|
12909 |
+
1ox9
|
12910 |
+
2wf2
|
12911 |
+
3zvv
|
12912 |
+
5f90
|
12913 |
+
1rdj
|
12914 |
+
4azb
|
12915 |
+
3o5n
|
12916 |
+
4uub
|
12917 |
+
3d1e
|
12918 |
+
1n5z
|
12919 |
+
6b1y
|
12920 |
+
2o7e
|
12921 |
+
3o9v
|
12922 |
+
4hf4
|
12923 |
+
6ety
|
12924 |
+
2qi6
|
12925 |
+
5jas
|
12926 |
+
3gss
|
12927 |
+
1c5c
|
12928 |
+
5l9l
|
12929 |
+
3ifp
|
12930 |
+
1czk
|
12931 |
+
4fi9
|
12932 |
+
1cs4
|
12933 |
+
5e88
|
12934 |
+
1mui
|
12935 |
+
5vp1
|
12936 |
+
3vbt
|
12937 |
+
3sh0
|
12938 |
+
4avw
|
12939 |
+
2asu
|
12940 |
+
1qf1
|
12941 |
+
3hjo
|
12942 |
+
1iiq
|
12943 |
+
2r2w
|
12944 |
+
1ztq
|
12945 |
+
2c8x
|
12946 |
+
3wtj
|
12947 |
+
4lys
|
12948 |
+
4lv2
|
12949 |
+
1u9v
|
12950 |
+
1dx6
|
12951 |
+
3mtd
|
12952 |
+
5ii1
|
12953 |
+
6d5h
|
12954 |
+
4nku
|
12955 |
+
1w1d
|
12956 |
+
1e37
|
12957 |
+
4pte
|
12958 |
+
3c7p
|
12959 |
+
4glx
|
12960 |
+
1hvi
|
12961 |
+
5f4n
|
12962 |
+
5f6u
|
12963 |
+
1y8p
|
12964 |
+
3kwb
|
12965 |
+
5ggj
|
12966 |
+
3gx0
|
12967 |
+
3ztx
|
12968 |
+
4uiz
|
12969 |
+
3ueu
|
12970 |
+
2vl4
|
12971 |
+
2wnl
|
12972 |
+
4cl9
|
12973 |
+
5aqn
|
12974 |
+
3ipx
|
12975 |
+
1i72
|
12976 |
+
3dsz
|
12977 |
+
3mhi
|
12978 |
+
4ap7
|
12979 |
+
2xcg
|
12980 |
+
7prc
|
12981 |
+
4e3o
|
12982 |
+
4int
|
12983 |
+
1zz1
|
12984 |
+
5bjt
|
12985 |
+
2xas
|
12986 |
+
4ny3
|
12987 |
+
5fi7
|
12988 |
+
1owi
|
12989 |
+
3qd4
|
12990 |
+
1ew8
|
12991 |
+
4hdc
|
12992 |
+
4ac3
|
12993 |
+
3h52
|
12994 |
+
5nzp
|
12995 |
+
1lbf
|
12996 |
+
1b6p
|
12997 |
+
2ylp
|
12998 |
+
3qxt
|
12999 |
+
3kyr
|
13000 |
+
1ksn
|
13001 |
+
3twp
|
13002 |
+
3ti8
|
13003 |
+
6ewe
|
13004 |
+
3t19
|
13005 |
+
3eu5
|
13006 |
+
4dvf
|
13007 |
+
2flr
|
13008 |
+
1oe7
|
13009 |
+
2or9
|
13010 |
+
1v2m
|
13011 |
+
5fjx
|
13012 |
+
1m2x
|
13013 |
+
2c80
|
13014 |
+
3nm6
|
13015 |
+
4nak
|
13016 |
+
5y12
|
13017 |
+
2vwn
|
13018 |
+
5chk
|
13019 |
+
4dv9
|
13020 |
+
5akg
|
13021 |
+
5x9h
|
13022 |
+
5m7u
|
13023 |
+
6axp
|
13024 |
+
1upk
|
13025 |
+
1j36
|
13026 |
+
1uv6
|
13027 |
+
3f2a
|
13028 |
+
1yet
|
13029 |
+
1ov3
|
13030 |
+
4kwp
|
13031 |
+
1eoj
|
13032 |
+
1yms
|
13033 |
+
4o4g
|
13034 |
+
3p0g
|
13035 |
+
3tsz
|
13036 |
+
2hrm
|
13037 |
+
4tz8
|
13038 |
+
5k4x
|
13039 |
+
3hzk
|
13040 |
+
5w5s
|
13041 |
+
4ekg
|
13042 |
+
6gh9
|
13043 |
+
5l26
|
13044 |
+
2lsv
|
13045 |
+
6eqa
|
13046 |
+
5fp0
|
13047 |
+
2zc9
|
13048 |
+
2jk7
|
13049 |
+
3h03
|
13050 |
+
3wb4
|
13051 |
+
1xow
|
13052 |
+
4hra
|
13053 |
+
4mk1
|
13054 |
+
1y20
|
13055 |
+
5yc1
|
13056 |
+
5lx6
|
13057 |
+
2er0
|
13058 |
+
5x4m
|
13059 |
+
4yih
|
13060 |
+
3mbl
|
13061 |
+
4a7i
|
13062 |
+
5koq
|
13063 |
+
3cx9
|
13064 |
+
4zom
|
13065 |
+
5sz6
|
13066 |
+
2vqm
|
13067 |
+
4yyn
|
13068 |
+
1syh
|
13069 |
+
1kwr
|
13070 |
+
6cyb
|
13071 |
+
3pm1
|
13072 |
+
2zym
|
13073 |
+
5fv7
|
13074 |
+
3shz
|
13075 |
+
4dmw
|
13076 |
+
6b5j
|
13077 |
+
1wn6
|
13078 |
+
5vd3
|
13079 |
+
1njc
|
13080 |
+
3ew2
|
13081 |
+
5ia3
|
13082 |
+
4a4e
|
13083 |
+
4a9n
|
13084 |
+
4iue
|
13085 |
+
2ewa
|
13086 |
+
1akq
|
13087 |
+
5ew9
|
13088 |
+
5n8e
|
13089 |
+
5a54
|
13090 |
+
4kow
|
13091 |
+
5w6i
|
13092 |
+
5mgg
|
13093 |
+
5oh3
|
13094 |
+
4hmh
|
13095 |
+
4f3i
|
13096 |
+
3kd7
|
13097 |
+
1w9u
|
13098 |
+
5da3
|
13099 |
+
4n6y
|
13100 |
+
5jid
|
13101 |
+
1juy
|
13102 |
+
1f0r
|
13103 |
+
5iw0
|
13104 |
+
4ui4
|
13105 |
+
3tkh
|
13106 |
+
2gc8
|
13107 |
+
5qc4
|
13108 |
+
3wzj
|
13109 |
+
5l7h
|
13110 |
+
2kdh
|
13111 |
+
1uyk
|
13112 |
+
3sv9
|
13113 |
+
3uex
|
13114 |
+
5os8
|
13115 |
+
4b7q
|
13116 |
+
5a6i
|
13117 |
+
5om2
|
13118 |
+
5lgu
|
13119 |
+
5uwk
|
13120 |
+
5u1q
|
13121 |
+
5unh
|
13122 |
+
5nw1
|
13123 |
+
4ck3
|
13124 |
+
1g42
|
13125 |
+
2e9d
|
13126 |
+
5k4z
|
13127 |
+
4l7b
|
13128 |
+
1so2
|
13129 |
+
6esn
|
13130 |
+
4pzw
|
13131 |
+
1ida
|
13132 |
+
3jzb
|
13133 |
+
1o2h
|
13134 |
+
5qby
|
13135 |
+
1nde
|
13136 |
+
6dne
|
13137 |
+
1f8d
|
13138 |
+
1nvr
|
13139 |
+
5ult
|
13140 |
+
1db5
|
13141 |
+
4fr3
|
13142 |
+
1g27
|
13143 |
+
5alo
|
13144 |
+
4o15
|
13145 |
+
4ryd
|
13146 |
+
4oar
|
13147 |
+
4zy0
|
13148 |
+
4pd7
|
13149 |
+
2aq7
|
13150 |
+
6etj
|
13151 |
+
2zga
|
13152 |
+
5luu
|
13153 |
+
2l8j
|
13154 |
+
2wky
|
13155 |
+
4yrg
|
13156 |
+
2v22
|
13157 |
+
2ndf
|
13158 |
+
1jsv
|
13159 |
+
4u6z
|
13160 |
+
5wdl
|
13161 |
+
5nxi
|
13162 |
+
6i8y
|
13163 |
+
4u6x
|
13164 |
+
4mw5
|
13165 |
+
4ufj
|
13166 |
+
3ith
|
13167 |
+
1wb0
|
13168 |
+
3arq
|
13169 |
+
3dp2
|
13170 |
+
1lst
|
13171 |
+
3fqh
|
13172 |
+
2ivu
|
13173 |
+
1s5q
|
13174 |
+
6ct7
|
13175 |
+
3pma
|
13176 |
+
2ay6
|
13177 |
+
5e90
|
13178 |
+
1re1
|
13179 |
+
4l32
|
13180 |
+
3g5k
|
13181 |
+
4bw4
|
13182 |
+
1pig
|
13183 |
+
2xne
|
13184 |
+
4qme
|
13185 |
+
5ugh
|
13186 |
+
1cpi
|
13187 |
+
3wd9
|
13188 |
+
1o5m
|
13189 |
+
5wfc
|
13190 |
+
4tun
|
13191 |
+
2y77
|
13192 |
+
5laq
|
13193 |
+
1ax2
|
13194 |
+
1b39
|
13195 |
+
3hrb
|
13196 |
+
5dah
|
13197 |
+
5iza
|
13198 |
+
3thb
|
13199 |
+
4bi1
|
13200 |
+
3arf
|
13201 |
+
4gwi
|
13202 |
+
6h1h
|
13203 |
+
5yzc
|
13204 |
+
5tg6
|
13205 |
+
3vap
|
13206 |
+
4lkh
|
13207 |
+
2q2a
|
13208 |
+
2fle
|
13209 |
+
2vwf
|
13210 |
+
1g2k
|
13211 |
+
2zz2
|
13212 |
+
5xhz
|
13213 |
+
4zim
|
13214 |
+
5fwr
|
13215 |
+
6g9i
|
13216 |
+
6bqa
|
13217 |
+
1g45
|
13218 |
+
2ao6
|
13219 |
+
3is9
|
13220 |
+
2qmf
|
13221 |
+
3wt7
|
13222 |
+
5vlr
|
13223 |
+
5fnr
|
13224 |
+
6cf6
|
13225 |
+
5z9e
|
13226 |
+
5t1m
|
13227 |
+
3uda
|
13228 |
+
3ur9
|
13229 |
+
3dp4
|
13230 |
+
6c7g
|
13231 |
+
5kmf
|
13232 |
+
4hev
|
13233 |
+
6d8e
|
13234 |
+
5acx
|
13235 |
+
5ouh
|
13236 |
+
2fde
|
13237 |
+
6c0n
|
13238 |
+
4wt2
|
13239 |
+
6cgp
|
13240 |
+
5zun
|
13241 |
+
5dyt
|
13242 |
+
4cwb
|
13243 |
+
2xcs
|
13244 |
+
4z1k
|
13245 |
+
4b11
|
13246 |
+
2i2c
|
13247 |
+
5ko5
|
13248 |
+
2ccc
|
13249 |
+
1xgj
|
13250 |
+
6ayt
|
13251 |
+
1ao8
|
13252 |
+
1c5z
|
13253 |
+
1b9v
|
13254 |
+
5toe
|
13255 |
+
4bup
|
13256 |
+
4pox
|
13257 |
+
1gnn
|
13258 |
+
3a4o
|
13259 |
+
5kqg
|
13260 |
+
5am1
|
13261 |
+
1i37
|
13262 |
+
5uln
|
13263 |
+
3gpo
|
13264 |
+
2g01
|
13265 |
+
3fx6
|
13266 |
+
5nba
|
13267 |
+
1ke7
|
13268 |
+
3my5
|
13269 |
+
4inr
|
13270 |
+
1jp5
|
13271 |
+
5eqe
|
13272 |
+
4muf
|
13273 |
+
5xhr
|
13274 |
+
2wmr
|
13275 |
+
3ebb
|
13276 |
+
4mwe
|
13277 |
+
5ap4
|
13278 |
+
5nwg
|
13279 |
+
4bde
|
13280 |
+
4x8t
|
13281 |
+
5tbp
|
13282 |
+
1nl6
|
13283 |
+
4oz1
|
13284 |
+
3hvc
|
13285 |
+
1flr
|
13286 |
+
3pz3
|
13287 |
+
4pkv
|
13288 |
+
4drp
|
13289 |
+
4awk
|
13290 |
+
2ww2
|
13291 |
+
4tw9
|
13292 |
+
5b4k
|
13293 |
+
4o3t
|
13294 |
+
4fev
|
13295 |
+
1o45
|
13296 |
+
4bcj
|
13297 |
+
3upz
|
13298 |
+
1qkb
|
13299 |
+
5nho
|
13300 |
+
2x8d
|
13301 |
+
1aq7
|
13302 |
+
5y21
|
13303 |
+
5i12
|
13304 |
+
3bsc
|
13305 |
+
4wki
|
13306 |
+
1ouy
|
13307 |
+
4jv9
|
13308 |
+
5o9h
|
13309 |
+
4ez3
|
13310 |
+
3dd8
|
13311 |
+
5h7g
|
13312 |
+
1sqt
|
13313 |
+
3pn4
|
13314 |
+
5aab
|
13315 |
+
2ha4
|
13316 |
+
4enx
|
13317 |
+
1bap
|
13318 |
+
6enm
|
13319 |
+
5za7
|
13320 |
+
3dbs
|
13321 |
+
4mvw
|
13322 |
+
3vrv
|
13323 |
+
2azc
|
13324 |
+
3mss
|
13325 |
+
3i60
|
13326 |
+
5hld
|
13327 |
+
1zkn
|
13328 |
+
2wxq
|
13329 |
+
4y87
|
13330 |
+
4m8x
|
13331 |
+
5f6v
|
13332 |
+
4fhi
|
13333 |
+
5auv
|
13334 |
+
4l7c
|
13335 |
+
3wcl
|
13336 |
+
3gqo
|
13337 |
+
5dhh
|
13338 |
+
5u7d
|
13339 |
+
6grp
|
13340 |
+
1xm6
|
13341 |
+
1lpz
|
13342 |
+
2wf3
|
13343 |
+
5cvd
|
13344 |
+
3zmj
|
13345 |
+
1g6s
|
13346 |
+
5eud
|
13347 |
+
3wyl
|
13348 |
+
4wh9
|
13349 |
+
2oq6
|
13350 |
+
2who
|
13351 |
+
2nmz
|
13352 |
+
2xiz
|
13353 |
+
4hbx
|
13354 |
+
6bee
|
13355 |
+
3ryx
|
13356 |
+
5ans
|
13357 |
+
5zvw
|
13358 |
+
4zwz
|
13359 |
+
3q96
|
13360 |
+
4v05
|
13361 |
+
2pyi
|
13362 |
+
5jf2
|
13363 |
+
1wbv
|
13364 |
+
6c7x
|
13365 |
+
4qsx
|
13366 |
+
5m6u
|
13367 |
+
1m0b
|
13368 |
+
3qg6
|
13369 |
+
3nyn
|
13370 |
+
1rm8
|
13371 |
+
3lhj
|
13372 |
+
3g86
|
13373 |
+
1ny0
|
13374 |
+
3zj8
|
13375 |
+
3o6l
|
13376 |
+
2vb8
|
13377 |
+
3p9l
|
13378 |
+
4bnx
|
13379 |
+
5uch
|
13380 |
+
3sv6
|
13381 |
+
4ynk
|
13382 |
+
223l
|
13383 |
+
5orr
|
13384 |
+
4o0j
|
13385 |
+
3rxm
|
13386 |
+
3rw9
|
13387 |
+
4po0
|
13388 |
+
4z84
|
13389 |
+
4j21
|
13390 |
+
5yjm
|
13391 |
+
5n25
|
13392 |
+
4bky
|
13393 |
+
5svy
|
13394 |
+
5gmn
|
13395 |
+
5u7l
|
13396 |
+
1f1j
|
13397 |
+
4aji
|
13398 |
+
2oj9
|
13399 |
+
3oli
|
13400 |
+
4r4o
|
13401 |
+
6ayq
|
13402 |
+
4ql1
|
13403 |
+
3f7h
|
13404 |
+
1skj
|
13405 |
+
2wfj
|
13406 |
+
1wc1
|
13407 |
+
2r3o
|
13408 |
+
3m5a
|
13409 |
+
4lwc
|
13410 |
+
4j5p
|
13411 |
+
3n46
|
13412 |
+
3ttp
|
13413 |
+
1jjk
|
13414 |
+
5vb7
|
13415 |
+
2pj0
|
13416 |
+
3dog
|
13417 |
+
2bve
|
13418 |
+
5vfm
|
13419 |
+
4l2x
|
13420 |
+
3uvp
|
13421 |
+
4wno
|
13422 |
+
4y38
|
13423 |
+
2c69
|
13424 |
+
6eol
|
13425 |
+
2zx9
|
13426 |
+
4q9s
|
13427 |
+
2alv
|
13428 |
+
3ip6
|
13429 |
+
3sio
|
13430 |
+
4xoe
|
13431 |
+
3sn8
|
13432 |
+
5y48
|
13433 |
+
5u7j
|
13434 |
+
2g9u
|
13435 |
+
5f3g
|
13436 |
+
1xh4
|
13437 |
+
4j79
|
13438 |
+
5ghv
|
13439 |
+
2i2b
|
13440 |
+
1gah
|
13441 |
+
3kr1
|
13442 |
+
5npd
|
13443 |
+
5mks
|
13444 |
+
1jwu
|
13445 |
+
4inh
|
13446 |
+
1tsl
|
13447 |
+
2wq5
|
13448 |
+
6hkj
|
13449 |
+
2yek
|
13450 |
+
1hpo
|
13451 |
+
2e9u
|
13452 |
+
3mwe
|
13453 |
+
6aff
|
13454 |
+
6e99
|
13455 |
+
5vlp
|
13456 |
+
2uxu
|
13457 |
+
4u5t
|
13458 |
+
2hwo
|
13459 |
+
4ury
|
13460 |
+
5byi
|
13461 |
+
4v04
|
13462 |
+
5e2s
|
13463 |
+
3lj3
|
13464 |
+
4bt9
|
13465 |
+
4jt9
|
13466 |
+
4rce
|
13467 |
+
6b5a
|
13468 |
+
4mk2
|
13469 |
+
4idv
|
13470 |
+
4bah
|
13471 |
+
5lj1
|
13472 |
+
3nal
|
13473 |
+
6d1m
|
13474 |
+
5kpm
|
13475 |
+
5sxn
|
13476 |
+
5doh
|
13477 |
+
3m6f
|
13478 |
+
3u81
|
13479 |
+
6bsk
|
13480 |
+
5nfa
|
13481 |
+
1gui
|
13482 |
+
5i1q
|
13483 |
+
4m4q
|
13484 |
+
4ow0
|
13485 |
+
5ur6
|
13486 |
+
5iu7
|
13487 |
+
6d55
|
13488 |
+
1bma
|
13489 |
+
5uxn
|
13490 |
+
1oiu
|
13491 |
+
4ln7
|
13492 |
+
2a5s
|
13493 |
+
5u5k
|
13494 |
+
5e4w
|
13495 |
+
6afg
|
13496 |
+
1oyq
|
13497 |
+
4xtv
|
13498 |
+
6eji
|
13499 |
+
2xdl
|
13500 |
+
3at1
|
13501 |
+
1njb
|
13502 |
+
4u0g
|
13503 |
+
1tou
|
13504 |
+
2pj5
|
13505 |
+
4q1a
|
13506 |
+
3avk
|
13507 |
+
6fmj
|
13508 |
+
2lto
|
13509 |
+
6czc
|
13510 |
+
3u8m
|
13511 |
+
2y5l
|
13512 |
+
3fjg
|
13513 |
+
5uwi
|
13514 |
+
6m9c
|
13515 |
+
5m3b
|
13516 |
+
3jxw
|
13517 |
+
4zqt
|
13518 |
+
5vc6
|
13519 |
+
4bj8
|
13520 |
+
5knx
|
13521 |
+
3pix
|
13522 |
+
3e6k
|
13523 |
+
4f7j
|
13524 |
+
3koo
|
13525 |
+
5n3y
|
13526 |
+
3jdw
|
13527 |
+
4pl3
|
13528 |
+
4nmo
|
13529 |
+
1ody
|
13530 |
+
5tpc
|
13531 |
+
6bsm
|
13532 |
+
2cm8
|
13533 |
+
5gn7
|
13534 |
+
5hu0
|
13535 |
+
1yq7
|
13536 |
+
2gga
|
13537 |
+
4wy7
|
13538 |
+
2brn
|
13539 |
+
2fmb
|
13540 |
+
5h14
|
13541 |
+
4zsp
|
13542 |
+
3nus
|
13543 |
+
5n8t
|
13544 |
+
5x5g
|
13545 |
+
5yls
|
13546 |
+
5u3b
|
13547 |
+
4x14
|
13548 |
+
4puk
|
13549 |
+
5wa6
|
13550 |
+
2y2h
|
13551 |
+
4nmt
|
13552 |
+
3uol
|
13553 |
+
4jzf
|
13554 |
+
4um3
|
13555 |
+
2wi2
|
13556 |
+
5k7h
|
13557 |
+
2ccu
|
13558 |
+
5x74
|
13559 |
+
3ddb
|
13560 |
+
1xd0
|
13561 |
+
4mm9
|
13562 |
+
1ulg
|
13563 |
+
3coz
|
13564 |
+
5epl
|
13565 |
+
4ear
|
13566 |
+
3vzg
|
13567 |
+
4qac
|
13568 |
+
4l5j
|
13569 |
+
1ai6
|
13570 |
+
3d8w
|
13571 |
+
4mi9
|
13572 |
+
2wtv
|
13573 |
+
5iee
|
13574 |
+
6ge0
|
13575 |
+
4q3r
|
13576 |
+
4qb3
|
13577 |
+
5cdh
|
13578 |
+
2vip
|
13579 |
+
3pz2
|
13580 |
+
3f34
|
13581 |
+
3rin
|
13582 |
+
5n2t
|
13583 |
+
5oqw
|
13584 |
+
3p4w
|
13585 |
+
4n5g
|
13586 |
+
2pvl
|
13587 |
+
1b0f
|
13588 |
+
5a3u
|
13589 |
+
4p6x
|
13590 |
+
3rsx
|
13591 |
+
3rcj
|
13592 |
+
5i9z
|
13593 |
+
5ai6
|
13594 |
+
3c4f
|
13595 |
+
1o4o
|
13596 |
+
1sje
|
13597 |
+
3alt
|
13598 |
+
5f41
|
13599 |
+
5yid
|
13600 |
+
3bgl
|
13601 |
+
4rdn
|
13602 |
+
4hso
|
13603 |
+
4ttv
|
13604 |
+
3ok9
|
13605 |
+
5y0g
|
13606 |
+
5twx
|
13607 |
+
1wug
|
13608 |
+
4a6c
|
13609 |
+
3gxt
|
13610 |
+
4lzs
|
13611 |
+
2zx7
|
13612 |
+
3jvr
|
13613 |
+
4as9
|
13614 |
+
3f1a
|
13615 |
+
4cd6
|
13616 |
+
4r06
|
13617 |
+
5h5s
|
13618 |
+
7gpb
|
13619 |
+
5w0i
|
13620 |
+
4wp7
|
13621 |
+
5e3g
|
13622 |
+
2ydt
|
13623 |
+
3hec
|
13624 |
+
4abb
|
13625 |
+
5ji8
|
13626 |
+
4olc
|
13627 |
+
5ieo
|
13628 |
+
5i2z
|
13629 |
+
4zy5
|
13630 |
+
4qga
|
13631 |
+
3t82
|
13632 |
+
4dff
|
13633 |
+
2wr8
|
13634 |
+
3i7b
|
13635 |
+
3v4v
|
13636 |
+
4gw8
|
13637 |
+
2hxl
|
13638 |
+
4bkt
|
13639 |
+
2wj2
|
13640 |
+
4xwk
|
13641 |
+
1xk9
|
13642 |
+
2fgh
|
13643 |
+
3tv7
|
13644 |
+
1ajp
|
13645 |
+
1tps
|
13646 |
+
3ag9
|
13647 |
+
3ls4
|
13648 |
+
5wg3
|
13649 |
+
1cwb
|
13650 |
+
3mea
|
13651 |
+
1bjr
|
13652 |
+
5auz
|
13653 |
+
2y67
|
13654 |
+
1q9m
|
13655 |
+
2i3i
|
13656 |
+
5ivj
|
13657 |
+
2vd1
|
13658 |
+
1p2g
|
13659 |
+
4l7n
|
13660 |
+
5efj
|
13661 |
+
4jzi
|
13662 |
+
5mt0
|
13663 |
+
5vlk
|
13664 |
+
3rt4
|
13665 |
+
3zmm
|
13666 |
+
2wn9
|
13667 |
+
2a25
|
13668 |
+
4hmq
|
13669 |
+
5jim
|
13670 |
+
4zyy
|
13671 |
+
4bi7
|
13672 |
+
1f3j
|
13673 |
+
2b52
|
13674 |
+
2xkd
|
13675 |
+
1yys
|
13676 |
+
3vtr
|
13677 |
+
3zrl
|
13678 |
+
4kao
|
13679 |
+
5fnc
|
13680 |
+
1ke5
|
13681 |
+
6hwz
|
13682 |
+
4d0x
|
13683 |
+
4mzs
|
13684 |
+
5mi5
|
13685 |
+
4a6l
|
13686 |
+
4eg5
|
13687 |
+
1sgu
|
13688 |
+
1w11
|
13689 |
+
3dkg
|
13690 |
+
1s19
|
13691 |
+
4wyo
|
13692 |
+
3ppp
|
13693 |
+
4rlu
|
13694 |
+
2jjk
|
13695 |
+
5ovp
|
13696 |
+
6cd9
|
13697 |
+
3qio
|
13698 |
+
4wrb
|
13699 |
+
5h9p
|
13700 |
+
5na0
|
13701 |
+
1wbt
|
13702 |
+
4ael
|
13703 |
+
5eu1
|
13704 |
+
3nw6
|
13705 |
+
1c5s
|
13706 |
+
1bl4
|
13707 |
+
4ual
|
13708 |
+
2vsl
|
13709 |
+
5vil
|
13710 |
+
4o7f
|
13711 |
+
4dhr
|
13712 |
+
1pw6
|
13713 |
+
1b5j
|
13714 |
+
3iad
|
13715 |
+
3rwg
|
13716 |
+
5wev
|
13717 |
+
2pjc
|
13718 |
+
3vi2
|
13719 |
+
4xum
|
13720 |
+
2zmm
|
13721 |
+
3fv3
|
13722 |
+
3ukr
|
13723 |
+
5myo
|
13724 |
+
3lbl
|
13725 |
+
4ppb
|
13726 |
+
1q0b
|
13727 |
+
4abi
|
13728 |
+
6bfx
|
13729 |
+
3kmy
|
13730 |
+
1q6k
|
13731 |
+
5ygd
|
13732 |
+
4z90
|
13733 |
+
4omk
|
13734 |
+
5bqh
|
13735 |
+
5lrj
|
13736 |
+
1ta6
|
13737 |
+
5jzn
|
13738 |
+
3ad8
|
13739 |
+
5izu
|
13740 |
+
5ief
|
13741 |
+
4frj
|
13742 |
+
2pre
|
13743 |
+
4ty6
|
13744 |
+
5nut
|
13745 |
+
3zps
|
13746 |
+
5e2v
|
13747 |
+
4k43
|
13748 |
+
5e7r
|
13749 |
+
6ftz
|
13750 |
+
3rjc
|
13751 |
+
4uvc
|
13752 |
+
3uix
|
13753 |
+
5up3
|
13754 |
+
4i31
|
13755 |
+
2p15
|
13756 |
+
1ag9
|
13757 |
+
1gu3
|
13758 |
+
6cw8
|
13759 |
+
5ei8
|
13760 |
+
4psh
|
13761 |
+
4i71
|
13762 |
+
6f9v
|
13763 |
+
4yoz
|
13764 |
+
6hu3
|
13765 |
+
5e2m
|
13766 |
+
5ap5
|
13767 |
+
4fob
|
13768 |
+
1uod
|
13769 |
+
3e63
|
13770 |
+
3mke
|
13771 |
+
3io7
|
13772 |
+
4whz
|
13773 |
+
4mt9
|
13774 |
+
4x21
|
13775 |
+
1ppi
|
13776 |
+
3t2p
|
13777 |
+
5q0g
|
13778 |
+
5jjs
|
13779 |
+
5icp
|
13780 |
+
4g1f
|
13781 |
+
1csh
|
13782 |
+
4mwr
|
13783 |
+
5al1
|
13784 |
+
4qxq
|
13785 |
+
3o9c
|
13786 |
+
2wxo
|
13787 |
+
4xmo
|
13788 |
+
4ii9
|
13789 |
+
5mlj
|
13790 |
+
5hm3
|
13791 |
+
4wr7
|
13792 |
+
3iqv
|
13793 |
+
4xjr
|
13794 |
+
4w9w
|
13795 |
+
5fhm
|
13796 |
+
5o2d
|
13797 |
+
5osk
|
13798 |
+
3bv9
|
13799 |
+
3i7e
|
13800 |
+
4kz4
|
13801 |
+
2oz7
|
13802 |
+
2vzr
|
13803 |
+
4d4d
|
13804 |
+
6eog
|
13805 |
+
1sfi
|
13806 |
+
5ehq
|
13807 |
+
5uy8
|
13808 |
+
4u0d
|
13809 |
+
2l11
|
13810 |
+
5v2p
|
13811 |
+
2vtm
|
13812 |
+
5ef8
|
13813 |
+
1zgv
|
13814 |
+
4b2l
|
13815 |
+
3g32
|
13816 |
+
4q4e
|
13817 |
+
4x50
|
13818 |
+
2oax
|
13819 |
+
4r8y
|
13820 |
+
4c61
|
13821 |
+
1w2g
|
13822 |
+
5er2
|
13823 |
+
6b2q
|
13824 |
+
3up7
|
13825 |
+
3r01
|
13826 |
+
5izq
|
13827 |
+
3l6f
|
13828 |
+
3p9m
|
13829 |
+
6ey8
|
13830 |
+
4b74
|
13831 |
+
6fyz
|
13832 |
+
5g1z
|
13833 |
+
3t4h
|
13834 |
+
4wkc
|
13835 |
+
2o4j
|
13836 |
+
4bdj
|
13837 |
+
5mek
|
13838 |
+
4gvd
|
13839 |
+
5qil
|
13840 |
+
5go2
|
13841 |
+
4m3f
|
13842 |
+
2e2b
|
13843 |
+
4bi2
|
13844 |
+
5l0h
|
13845 |
+
5ugb
|
13846 |
+
2ynd
|
13847 |
+
2wzz
|
13848 |
+
5wyz
|
13849 |
+
5may
|
13850 |
+
4eev
|
13851 |
+
4kiw
|
13852 |
+
2y7i
|
13853 |
+
3tcg
|
13854 |
+
3s71
|
13855 |
+
2qcd
|
13856 |
+
1vru
|
13857 |
+
1h00
|
13858 |
+
4uat
|
13859 |
+
3nyd
|
13860 |
+
3bkk
|
13861 |
+
4n9d
|
13862 |
+
1bim
|
13863 |
+
5zt1
|
13864 |
+
5ml2
|
13865 |
+
3fpd
|
13866 |
+
6h7o
|
13867 |
+
3p8z
|
13868 |
+
4ewh
|
13869 |
+
4uva
|
13870 |
+
5a3q
|
13871 |
+
4dai
|
13872 |
+
5o55
|
13873 |
+
3f69
|
13874 |
+
4puz
|
13875 |
+
6f05
|
13876 |
+
3g35
|
13877 |
+
4qij
|
13878 |
+
4dxg
|
13879 |
+
3n1c
|
13880 |
+
4dt2
|
13881 |
+
5u2e
|
13882 |
+
6c7j
|
13883 |
+
4cj4
|
13884 |
+
2w7x
|
13885 |
+
6ccq
|
13886 |
+
4qsv
|
13887 |
+
5upz
|
13888 |
+
5iu4
|
13889 |
+
4x0u
|
13890 |
+
3ffg
|
13891 |
+
1y6q
|
13892 |
+
5yba
|
13893 |
+
2f35
|
13894 |
+
4gsc
|
13895 |
+
1jt1
|
13896 |
+
4qvl
|
13897 |
+
1mwn
|
13898 |
+
1jeu
|
13899 |
+
1c3b
|
13900 |
+
3ual
|
13901 |
+
1rdn
|
13902 |
+
6dh1
|
13903 |
+
5iub
|
13904 |
+
5mav
|
13905 |
+
3t83
|
13906 |
+
3iof
|
13907 |
+
6cwf
|
13908 |
+
2fpz
|
13909 |
+
5ml4
|
13910 |
+
5f2f
|
13911 |
+
1fpc
|
13912 |
+
7kme
|
13913 |
+
1erq
|
13914 |
+
5t9u
|
13915 |
+
1lhv
|
13916 |
+
2qlf
|
13917 |
+
5jmp
|
13918 |
+
4s3f
|
13919 |
+
6hm6
|
13920 |
+
2qt9
|
13921 |
+
4p4i
|
13922 |
+
5vih
|
13923 |
+
3mnu
|
13924 |
+
6djc
|
13925 |
+
5db0
|
13926 |
+
4ca5
|
13927 |
+
5mar
|
13928 |
+
2w77
|
13929 |
+
2avq
|
13930 |
+
5eqq
|
13931 |
+
1tsi
|
13932 |
+
2vw2
|
13933 |
+
2ggd
|
13934 |
+
6f6d
|
13935 |
+
1f4g
|
13936 |
+
3ndm
|
13937 |
+
3l17
|
13938 |
+
5fni
|
13939 |
+
1c3r
|
13940 |
+
5trf
|
13941 |
+
1pau
|
13942 |
+
3vf3
|
13943 |
+
6ewk
|
13944 |
+
4re9
|
13945 |
+
4li8
|
13946 |
+
1n4k
|
13947 |
+
4l7o
|
13948 |
+
5kbh
|
13949 |
+
2gj5
|
13950 |
+
2oh4
|
13951 |
+
4wht
|
13952 |
+
1joc
|
13953 |
+
1qxl
|
13954 |
+
6elp
|
13955 |
+
4qge
|
13956 |
+
2yfe
|
13957 |
+
3g8e
|
13958 |
+
1cea
|
13959 |
+
6czu
|
13960 |
+
2fs8
|
13961 |
+
4mk5
|
13962 |
+
4i60
|
13963 |
+
5h5f
|
13964 |
+
5tcc
|
13965 |
+
4dpy
|
13966 |
+
3fh8
|
13967 |
+
4h1m
|
13968 |
+
2anm
|
13969 |
+
1uom
|
13970 |
+
3oim
|
13971 |
+
6ezi
|
13972 |
+
3da9
|
13973 |
+
3r17
|
13974 |
+
1l6s
|
13975 |
+
2uzv
|
13976 |
+
4e1e
|
13977 |
+
3d28
|
13978 |
+
4bcd
|
13979 |
+
5kez
|
13980 |
+
1bn4
|
13981 |
+
6biz
|
13982 |
+
4lwt
|
13983 |
+
3jpv
|
13984 |
+
5fsm
|
13985 |
+
4mds
|
13986 |
+
4e6c
|
13987 |
+
3o9p
|
13988 |
+
2ylo
|
13989 |
+
5fyq
|
13990 |
+
4hxq
|
13991 |
+
3mj1
|
13992 |
+
1zm7
|
13993 |
+
1s63
|
13994 |
+
4nk9
|
13995 |
+
4qmm
|
13996 |
+
3g7l
|
13997 |
+
4zyw
|
13998 |
+
2q8i
|
13999 |
+
3gfe
|
14000 |
+
5ih6
|
14001 |
+
4owo
|
14002 |
+
5o5f
|
14003 |
+
4x7q
|
14004 |
+
4wy1
|
14005 |
+
1qbq
|
14006 |
+
5du6
|
14007 |
+
1oe0
|
14008 |
+
1g2a
|
14009 |
+
4iie
|
14010 |
+
4x5p
|
14011 |
+
1fhr
|
14012 |
+
1ntv
|
14013 |
+
1o5f
|
14014 |
+
3os3
|
14015 |
+
2cbz
|
14016 |
+
4arb
|
14017 |
+
3lxs
|
14018 |
+
3lxg
|
14019 |
+
2g94
|
14020 |
+
4gv1
|
14021 |
+
5n87
|
14022 |
+
1gz9
|
14023 |
+
1b6l
|
14024 |
+
5kcx
|
14025 |
+
2xni
|
14026 |
+
3ig6
|
14027 |
+
1p4u
|
14028 |
+
3r9h
|
14029 |
+
5n2x
|
14030 |
+
6aud
|
14031 |
+
5nee
|
14032 |
+
1bnw
|
14033 |
+
6bo6
|
14034 |
+
3kaf
|
14035 |
+
2fvd
|
14036 |
+
2xaj
|
14037 |
+
4a95
|
14038 |
+
5iv2
|
14039 |
+
3n2u
|
14040 |
+
4q6e
|
14041 |
+
1i2s
|
14042 |
+
2f34
|
14043 |
+
6evo
|
14044 |
+
5ksv
|
14045 |
+
2e9n
|
14046 |
+
5cgc
|
14047 |
+
1m51
|
14048 |
+
1d4h
|
14049 |
+
5ncy
|
14050 |
+
5kls
|
14051 |
+
3s2p
|
14052 |
+
4o09
|
14053 |
+
1zaj
|
14054 |
+
1f0u
|
14055 |
+
4k3l
|
14056 |
+
4tww
|
14057 |
+
5f88
|
14058 |
+
3fcb
|
14059 |
+
4arw
|
14060 |
+
4o9w
|
14061 |
+
2ay7
|
14062 |
+
5dcz
|
14063 |
+
5dqf
|
14064 |
+
3ttj
|
14065 |
+
3lc3
|
14066 |
+
2xg3
|
14067 |
+
1uml
|
14068 |
+
3qt6
|
14069 |
+
4oty
|
14070 |
+
4wzv
|
14071 |
+
1hxb
|
14072 |
+
5l87
|
14073 |
+
4ah9
|
14074 |
+
5ma7
|
14075 |
+
3npa
|
14076 |
+
4hs8
|
14077 |
+
4qgd
|
14078 |
+
5zkc
|
14079 |
+
4d2t
|
14080 |
+
5elz
|
14081 |
+
1jk7
|
14082 |
+
5cuh
|
14083 |
+
3jqg
|
14084 |
+
5w4s
|
14085 |
+
4n7m
|
14086 |
+
3tct
|
14087 |
+
5ie1
|
14088 |
+
4n1t
|
14089 |
+
5aqh
|
14090 |
+
5oku
|
14091 |
+
5nhf
|
14092 |
+
2yge
|
14093 |
+
4gs9
|
14094 |
+
6bu3
|
14095 |
+
5vqr
|
14096 |
+
2am4
|
14097 |
+
5wr7
|
14098 |
+
4j58
|
14099 |
+
4zsr
|
14100 |
+
1yon
|
14101 |
+
2bkt
|
14102 |
+
4buq
|
14103 |
+
3u7m
|
14104 |
+
3u51
|
14105 |
+
3w55
|
14106 |
+
2gfa
|
14107 |
+
3fum
|
14108 |
+
4hyu
|
14109 |
+
4pra
|
14110 |
+
4kyk
|
14111 |
+
4gzp
|
14112 |
+
3ekn
|
14113 |
+
3v2w
|
14114 |
+
2pog
|
14115 |
+
2bb7
|
14116 |
+
3qj9
|
14117 |
+
5d3t
|
14118 |
+
2w67
|
14119 |
+
5fs5
|
14120 |
+
5qaf
|
14121 |
+
4crb
|
14122 |
+
6fe0
|
14123 |
+
3zmq
|
14124 |
+
5t1t
|
14125 |
+
2xm1
|
14126 |
+
4oaz
|
14127 |
+
6e8k
|
14128 |
+
2fys
|
14129 |
+
5egs
|
14130 |
+
4aac
|
14131 |
+
1akr
|
14132 |
+
2wi1
|
14133 |
+
2qbs
|
14134 |
+
5h2u
|
14135 |
+
1lke
|
14136 |
+
3smq
|
14137 |
+
5eds
|
14138 |
+
3wmb
|
14139 |
+
4azy
|
14140 |
+
3cz1
|
14141 |
+
1s39
|
14142 |
+
1n94
|
14143 |
+
5lc0
|
14144 |
+
5wg5
|
14145 |
+
5ttg
|
14146 |
+
1ndz
|
14147 |
+
6gmx
|
14148 |
+
4cfe
|
14149 |
+
3fsj
|
14150 |
+
1cim
|
14151 |
+
3kry
|
14152 |
+
2f2h
|
14153 |
+
2g9x
|
14154 |
+
1o47
|
14155 |
+
6aqf
|
14156 |
+
4knn
|
14157 |
+
1t29
|
14158 |
+
4k5z
|
14159 |
+
2ycf
|
14160 |
+
5ijr
|
14161 |
+
5kks
|
14162 |
+
5tg2
|
14163 |
+
4yxu
|
14164 |
+
4i7c
|
14165 |
+
3ftv
|
14166 |
+
1ke3
|
14167 |
+
4bib
|
14168 |
+
3coy
|
14169 |
+
5orw
|
14170 |
+
5bns
|
14171 |
+
4bs0
|
14172 |
+
3igp
|
14173 |
+
2uw4
|
14174 |
+
4avj
|
14175 |
+
3qcy
|
14176 |
+
1yqj
|
14177 |
+
3a73
|
14178 |
+
4uu8
|
14179 |
+
4h3f
|
14180 |
+
4rwk
|
14181 |
+
5j5r
|
14182 |
+
2rkm
|
14183 |
+
1w14
|
14184 |
+
4edu
|
14185 |
+
3e73
|
14186 |
+
5o1s
|
14187 |
+
4ngn
|
14188 |
+
1mnc
|
14189 |
+
2ypp
|
14190 |
+
3wq5
|
14191 |
+
4j74
|
14192 |
+
3rz5
|
14193 |
+
5upe
|
14194 |
+
4eh6
|
14195 |
+
1c84
|
14196 |
+
4fcf
|
14197 |
+
1sc8
|
14198 |
+
3agm
|
14199 |
+
5w10
|
14200 |
+
1gzg
|
14201 |
+
4qvv
|
14202 |
+
4qp6
|
14203 |
+
4why
|
14204 |
+
3ip9
|
14205 |
+
5he0
|
14206 |
+
4yv5
|
14207 |
+
3ril
|
14208 |
+
4uyd
|
14209 |
+
1nu3
|
14210 |
+
3ozr
|
14211 |
+
5qin
|
14212 |
+
4utv
|
14213 |
+
5x9o
|
14214 |
+
1okv
|
14215 |
+
5m4c
|
14216 |
+
4xhv
|
14217 |
+
5ll7
|
14218 |
+
3cyx
|
14219 |
+
4gm3
|
14220 |
+
2w78
|
14221 |
+
5q1d
|
14222 |
+
3bym
|
14223 |
+
5aqo
|
14224 |
+
1ga8
|
14225 |
+
1p5e
|
14226 |
+
4c4f
|
14227 |
+
2mps
|
14228 |
+
4cxw
|
14229 |
+
4w9f
|
14230 |
+
3lmk
|
14231 |
+
3sz1
|
14232 |
+
4tya
|
14233 |
+
4qjx
|
14234 |
+
2v85
|
14235 |
+
5bw4
|
14236 |
+
2ael
|
14237 |
+
4pv5
|
14238 |
+
5osy
|
14239 |
+
4m8h
|
14240 |
+
3i02
|
14241 |
+
6fs1
|
14242 |
+
3twr
|
14243 |
+
2vt3
|
14244 |
+
4rrn
|
14245 |
+
1h5u
|
14246 |
+
2qoa
|
14247 |
+
4lk6
|
14248 |
+
3qtu
|
14249 |
+
3k5d
|
14250 |
+
2qhy
|
14251 |
+
5jmw
|
14252 |
+
3bun
|
14253 |
+
1ghy
|
14254 |
+
4l70
|
14255 |
+
6cd4
|
14256 |
+
4ymb
|
14257 |
+
6bh2
|
14258 |
+
5h0h
|
14259 |
+
1ppx
|
14260 |
+
3r4p
|
14261 |
+
6gnr
|
14262 |
+
2x6k
|
14263 |
+
3f9n
|
14264 |
+
4oys
|
14265 |
+
3rf5
|
14266 |
+
3hub
|
14267 |
+
4fcq
|
14268 |
+
5o1i
|
14269 |
+
3ohh
|
14270 |
+
4mqu
|
14271 |
+
4gw5
|
14272 |
+
5m4f
|
14273 |
+
2r9w
|
14274 |
+
5yea
|
14275 |
+
1xp1
|
14276 |
+
5lm4
|
14277 |
+
2csm
|
14278 |
+
5t2g
|
14279 |
+
3n1w
|
14280 |
+
3t8s
|
14281 |
+
5nhz
|
14282 |
+
4zk5
|
14283 |
+
1e6q
|
14284 |
+
4cg9
|
14285 |
+
4bf1
|
14286 |
+
2ycr
|
14287 |
+
1c50
|
14288 |
+
3hd3
|
14289 |
+
4ehe
|
14290 |
+
5tku
|
14291 |
+
5wle
|
14292 |
+
2r64
|
14293 |
+
5l3j
|
14294 |
+
6ft8
|
14295 |
+
5ti5
|
14296 |
+
4tyt
|
14297 |
+
5lma
|
14298 |
+
3oct
|
14299 |
+
3zt2
|
14300 |
+
5ai4
|
14301 |
+
3zh8
|
14302 |
+
3fl8
|
14303 |
+
3old
|
14304 |
+
3fqs
|
14305 |
+
4xct
|
14306 |
+
4mjp
|
14307 |
+
3g2y
|
14308 |
+
6g8n
|
14309 |
+
5kkr
|
14310 |
+
1fjs
|
14311 |
+
6dxg
|
14312 |
+
4cxy
|
14313 |
+
3che
|
14314 |
+
3qfv
|
14315 |
+
1r5v
|
14316 |
+
1pr1
|
14317 |
+
3nsn
|
14318 |
+
4p1u
|
14319 |
+
3szb
|
14320 |
+
5u11
|
14321 |
+
4o0t
|
14322 |
+
3ux0
|
14323 |
+
4q4i
|
14324 |
+
2nww
|
14325 |
+
2qp8
|
14326 |
+
4rsp
|
14327 |
+
2p0x
|
14328 |
+
1fsg
|
14329 |
+
1u0g
|
14330 |
+
4djx
|
14331 |
+
6cco
|
14332 |
+
3opp
|
14333 |
+
4lg6
|
14334 |
+
2clv
|
14335 |
+
1hps
|
14336 |
+
6bhe
|
14337 |
+
6bir
|
14338 |
+
5h09
|
14339 |
+
3kwj
|
14340 |
+
2bed
|
14341 |
+
3e51
|
14342 |
+
3msk
|
14343 |
+
6axj
|
14344 |
+
3udd
|
14345 |
+
1zvx
|
14346 |
+
5u6d
|
14347 |
+
4qnb
|
14348 |
+
4eox
|
14349 |
+
2rly
|
14350 |
+
3ob2
|
14351 |
+
3osi
|
14352 |
+
5m7t
|
14353 |
+
5vqy
|
14354 |
+
5ei6
|
14355 |
+
3mbz
|
14356 |
+
4f7n
|
14357 |
+
3ipb
|
14358 |
+
1w6r
|
14359 |
+
4zx9
|
14360 |
+
6gy5
|
14361 |
+
2hh5
|
14362 |
+
3nmq
|
14363 |
+
1vjy
|
14364 |
+
4hy5
|
14365 |
+
4ts1
|
14366 |
+
2qcg
|
14367 |
+
5lwd
|
14368 |
+
1kjr
|
14369 |
+
3oyn
|
14370 |
+
3rbq
|
14371 |
+
3ujc
|
14372 |
+
3ekp
|
14373 |
+
3p7c
|
14374 |
+
4urv
|
14375 |
+
3gws
|
14376 |
+
3fw4
|
14377 |
+
1ow8
|
14378 |
+
4pov
|
14379 |
+
4k4j
|
14380 |
+
4m0f
|
14381 |
+
1ow4
|
14382 |
+
3qaq
|
14383 |
+
4ovf
|
14384 |
+
1ps3
|
14385 |
+
4gw6
|
14386 |
+
5a4c
|
14387 |
+
2ovx
|
14388 |
+
5q19
|
14389 |
+
1gwm
|
14390 |
+
2kwn
|
14391 |
+
4uce
|
14392 |
+
4y2p
|
14393 |
+
2q2c
|
14394 |
+
5lgn
|
14395 |
+
5oxg
|
14396 |
+
3i4b
|
14397 |
+
4qmo
|
14398 |
+
2wyg
|
14399 |
+
5eay
|
14400 |
+
2b4l
|
14401 |
+
2xd9
|
14402 |
+
3sus
|
14403 |
+
5zu0
|
14404 |
+
3gjt
|
14405 |
+
2b1v
|
14406 |
+
3ctq
|
14407 |
+
5tzz
|
14408 |
+
1h28
|
14409 |
+
4b13
|
14410 |
+
2q15
|
14411 |
+
2aac
|
14412 |
+
3kw9
|
14413 |
+
3qox
|
14414 |
+
4wku
|
14415 |
+
5wqk
|
14416 |
+
2fjp
|
14417 |
+
5eij
|
14418 |
+
4mga
|
14419 |
+
5ak2
|
14420 |
+
5dp4
|
14421 |
+
6f8u
|
14422 |
+
4inu
|
14423 |
+
4nrc
|
14424 |
+
5drt
|
14425 |
+
1tng
|
14426 |
+
3vhc
|
14427 |
+
1xh3
|
14428 |
+
1toi
|
14429 |
+
2lya
|
14430 |
+
3mpm
|
14431 |
+
4k55
|
14432 |
+
1qb9
|
14433 |
+
5hlw
|
14434 |
+
6ej2
|
14435 |
+
4i33
|
14436 |
+
4cwp
|
14437 |
+
2fvc
|
14438 |
+
3r02
|
14439 |
+
6ezh
|
14440 |
+
4muw
|
14441 |
+
3d91
|
14442 |
+
3img
|
14443 |
+
4op1
|
14444 |
+
4s3e
|
14445 |
+
3qxp
|
14446 |
+
4f5y
|
14447 |
+
4qmv
|
14448 |
+
5u62
|
14449 |
+
4qtc
|
14450 |
+
6tim
|
14451 |
+
4h2j
|
14452 |
+
1x7e
|
14453 |
+
1b6h
|
14454 |
+
3opr
|
14455 |
+
4gjb
|
14456 |
+
5u5h
|
14457 |
+
5v3o
|
14458 |
+
5l44
|
14459 |
+
2c6i
|
14460 |
+
4ezr
|
14461 |
+
5u4e
|
14462 |
+
1fta
|
14463 |
+
4z2j
|
14464 |
+
3n3j
|
14465 |
+
5eg4
|
14466 |
+
2yiq
|
14467 |
+
4jmx
|
14468 |
+
4q2k
|
14469 |
+
2x2r
|
14470 |
+
2fzg
|
14471 |
+
1ajx
|
14472 |
+
2yki
|
14473 |
+
3ccw
|
14474 |
+
5u0e
|
14475 |
+
5j32
|
14476 |
+
1y2e
|
14477 |
+
6gwr
|
14478 |
+
6gu7
|
14479 |
+
5dxb
|
14480 |
+
1hyo
|
14481 |
+
3lc5
|
14482 |
+
3arw
|
14483 |
+
3rz1
|
14484 |
+
5kr8
|
14485 |
+
5jv2
|
14486 |
+
4xpj
|
14487 |
+
4l2f
|
14488 |
+
3vi5
|
14489 |
+
5etj
|
14490 |
+
2a3w
|
14491 |
+
3bra
|
14492 |
+
1h79
|
14493 |
+
6ed6
|
14494 |
+
5w85
|
14495 |
+
6mub
|
14496 |
+
5od5
|
14497 |
+
5ejl
|
14498 |
+
3ubx
|
14499 |
+
2c6k
|
14500 |
+
4rn0
|
14501 |
+
3pdq
|
14502 |
+
4unp
|
14503 |
+
5mng
|
14504 |
+
4w5j
|
14505 |
+
5afn
|
14506 |
+
6h0b
|
14507 |
+
5yc4
|
14508 |
+
1ahx
|
14509 |
+
2jst
|
14510 |
+
1o3h
|
14511 |
+
3rz8
|
14512 |
+
4na9
|
14513 |
+
1f0t
|
14514 |
+
4eym
|
14515 |
+
5vew
|
14516 |
+
4k3p
|
14517 |
+
4zs9
|
14518 |
+
3b9s
|
14519 |
+
5wcl
|
14520 |
+
4mmm
|
14521 |
+
2l65
|
14522 |
+
4lph
|
14523 |
+
3frz
|
14524 |
+
3rz9
|
14525 |
+
4kba
|
14526 |
+
5a8x
|
14527 |
+
5eps
|
14528 |
+
2wor
|
14529 |
+
5f1j
|
14530 |
+
2oxd
|
14531 |
+
3ldq
|
14532 |
+
4g0k
|
14533 |
+
1u32
|
14534 |
+
5gr9
|
14535 |
+
4fl3
|
14536 |
+
3uxl
|
14537 |
+
3fud
|
14538 |
+
4x68
|
14539 |
+
3k2f
|
14540 |
+
5lsg
|
14541 |
+
1h23
|
14542 |
+
3zrm
|
14543 |
+
5v6u
|
14544 |
+
4lke
|
14545 |
+
1o4r
|
14546 |
+
5mw4
|
14547 |
+
4fcb
|
14548 |
+
4qp8
|
14549 |
+
1htf
|
14550 |
+
4q0k
|
14551 |
+
4yc0
|
14552 |
+
3ebp
|
14553 |
+
3q4b
|
14554 |
+
5dh4
|
14555 |
+
1bqo
|
14556 |
+
3sn7
|
14557 |
+
4waf
|
14558 |
+
3gst
|
14559 |
+
5ecv
|
14560 |
+
1hvj
|
14561 |
+
3m3c
|
14562 |
+
4ocv
|
14563 |
+
2ewb
|
14564 |
+
5h19
|
14565 |
+
3ryz
|
14566 |
+
3a2o
|
14567 |
+
4ea3
|
14568 |
+
4wx6
|
14569 |
+
1i32
|
14570 |
+
4lge
|
14571 |
+
3cwe
|
14572 |
+
2hmu
|
14573 |
+
1h0r
|
14574 |
+
5m9w
|
14575 |
+
3jwr
|
14576 |
+
2q70
|
14577 |
+
4iu0
|
14578 |
+
1tl3
|
14579 |
+
2gqn
|
14580 |
+
3bc3
|
14581 |
+
4gk7
|
14582 |
+
2wd3
|
14583 |
+
2x8z
|
14584 |
+
4ybt
|
14585 |
+
5dms
|
14586 |
+
1nhg
|
14587 |
+
4mw1
|
14588 |
+
3cgo
|
14589 |
+
5v4q
|
14590 |
+
4x6n
|
14591 |
+
3bh8
|
14592 |
+
3f6h
|
14593 |
+
4au7
|
14594 |
+
5i3a
|
14595 |
+
3l6x
|
14596 |
+
5d0j
|
14597 |
+
4c1u
|
14598 |
+
6fzx
|
14599 |
+
3ook
|
14600 |
+
5mt4
|
14601 |
+
4hzx
|
14602 |
+
3udp
|
14603 |
+
4g8o
|
14604 |
+
4mrz
|
14605 |
+
4tyo
|
14606 |
+
4umj
|
14607 |
+
4rfz
|
14608 |
+
1rxp
|
14609 |
+
2zyn
|
14610 |
+
5t54
|
14611 |
+
6bh3
|
14612 |
+
4cd5
|
14613 |
+
4hlk
|
14614 |
+
3t0x
|
14615 |
+
2az5
|
14616 |
+
5dy5
|
14617 |
+
1ft4
|
14618 |
+
5org
|
14619 |
+
5to8
|
14620 |
+
6eqx
|
14621 |
+
3b2q
|
14622 |
+
6ez9
|
14623 |
+
6aox
|
14624 |
+
2y5f
|
14625 |
+
4x7o
|
14626 |
+
4y4v
|
14627 |
+
5oae
|
14628 |
+
1h25
|
14629 |
+
5d2r
|
14630 |
+
2xch
|
14631 |
+
5ndd
|
14632 |
+
2cf8
|
14633 |
+
2yi7
|
14634 |
+
4nzo
|
14635 |
+
3mct
|
14636 |
+
5dia
|
14637 |
+
1iih
|
14638 |
+
3ime
|
14639 |
+
3tll
|
14640 |
+
2jle
|
14641 |
+
1h26
|
14642 |
+
3l7b
|
14643 |
+
5v88
|
14644 |
+
1o2o
|
14645 |
+
3e90
|
14646 |
+
4j46
|
14647 |
+
3dp9
|
14648 |
+
5ngb
|
14649 |
+
5jh6
|
14650 |
+
3rpy
|
14651 |
+
2vfz
|
14652 |
+
5xn3
|
14653 |
+
1e6s
|
14654 |
+
4xx4
|
14655 |
+
3ppo
|
14656 |
+
4qfo
|
14657 |
+
1o3d
|
14658 |
+
3s43
|
14659 |
+
6ar2
|
14660 |
+
3cyu
|
14661 |
+
1qf0
|
14662 |
+
1ow6
|
14663 |
+
5eml
|
14664 |
+
4amz
|
14665 |
+
5ye9
|
14666 |
+
4mti
|
14667 |
+
6f29
|
14668 |
+
5mk1
|
14669 |
+
1qsc
|
14670 |
+
1uvr
|
14671 |
+
2off
|
14672 |
+
4whq
|
14673 |
+
4d08
|
14674 |
+
6gu3
|
14675 |
+
4b6q
|
14676 |
+
4agc
|
14677 |
+
4uu5
|
14678 |
+
3blt
|
14679 |
+
2zb1
|
14680 |
+
1g37
|
14681 |
+
3krd
|
14682 |
+
3lm1
|
14683 |
+
1noj
|
14684 |
+
1t32
|
14685 |
+
3i6z
|
14686 |
+
5kbq
|
14687 |
+
1gwr
|
14688 |
+
4k6v
|
14689 |
+
2vba
|
14690 |
+
3zrc
|
14691 |
+
4nmx
|
14692 |
+
4mbc
|
14693 |
+
1ie9
|
14694 |
+
3bgz
|
14695 |
+
2k62
|
14696 |
+
1mqg
|
14697 |
+
1qy1
|
14698 |
+
1mau
|
14699 |
+
2x7u
|
14700 |
+
3iqq
|
14701 |
+
5h8e
|
14702 |
+
2aig
|
14703 |
+
5n9l
|
14704 |
+
2g5p
|
14705 |
+
4fri
|
14706 |
+
4q3u
|
14707 |
+
5flo
|
14708 |
+
4bo1
|
14709 |
+
5tyr
|
14710 |
+
5x26
|
14711 |
+
2drc
|
14712 |
+
4bbh
|
14713 |
+
3gkz
|
14714 |
+
5e6o
|
14715 |
+
4qy3
|
14716 |
+
1nq0
|
14717 |
+
5e8w
|
14718 |
+
2gu8
|
14719 |
+
1w9v
|
14720 |
+
5uci
|
14721 |
+
2veu
|
14722 |
+
5hvy
|
14723 |
+
3ewu
|
14724 |
+
1jm4
|
14725 |
+
5yas
|
14726 |
+
4ojr
|
14727 |
+
1h0w
|
14728 |
+
5eou
|
14729 |
+
3as0
|
14730 |
+
4e3g
|
14731 |
+
4euv
|
14732 |
+
2wly
|
14733 |
+
3lir
|
14734 |
+
3znr
|
14735 |
+
3q3t
|
14736 |
+
6ap8
|
14737 |
+
3g3n
|
14738 |
+
3c52
|
14739 |
+
3g2w
|
14740 |
+
4iku
|
14741 |
+
5bry
|
14742 |
+
4wvu
|
14743 |
+
3neo
|
14744 |
+
1abf
|
14745 |
+
5db2
|
14746 |
+
1sjh
|
14747 |
+
3hc8
|
14748 |
+
2liq
|
14749 |
+
5dtw
|
14750 |
+
5dhu
|
14751 |
+
1qhr
|
14752 |
+
2pl0
|
14753 |
+
4wcu
|
14754 |
+
3exo
|
14755 |
+
1jvp
|
14756 |
+
4mrd
|
14757 |
+
5jxn
|
14758 |
+
2yjc
|
14759 |
+
2o9r
|
14760 |
+
5en3
|
14761 |
+
5hpm
|
14762 |
+
4qf8
|
14763 |
+
3k05
|
14764 |
+
3h0q
|
14765 |
+
2a4l
|
14766 |
+
4xue
|
14767 |
+
3ewc
|
14768 |
+
1dtt
|
14769 |
+
4yzm
|
14770 |
+
4q4p
|
14771 |
+
3d9o
|
14772 |
+
3s8x
|
14773 |
+
4mq2
|
14774 |
+
6ek3
|
14775 |
+
5tgc
|
14776 |
+
2hds
|
14777 |
+
5fwj
|
14778 |
+
3kme
|
14779 |
+
1zog
|
14780 |
+
6ce6
|
14781 |
+
4c6v
|
14782 |
+
1xdd
|
14783 |
+
5bvf
|
14784 |
+
1dud
|
14785 |
+
3lzu
|
14786 |
+
4c1d
|
14787 |
+
2er6
|
14788 |
+
3f48
|
14789 |
+
2xuz
|
14790 |
+
5fto
|
14791 |
+
4zei
|
14792 |
+
3c39
|
14793 |
+
6fqu
|
14794 |
+
4fc0
|
14795 |
+
1bzc
|
14796 |
+
3pj8
|
14797 |
+
2auc
|
14798 |
+
4kp0
|
14799 |
+
2y7p
|
14800 |
+
4ono
|
14801 |
+
3nc9
|
14802 |
+
4bjb
|
14803 |
+
4qo4
|
14804 |
+
3mz3
|
14805 |
+
5edc
|
14806 |
+
2xzg
|
14807 |
+
6bqj
|
14808 |
+
1ga9
|
14809 |
+
4oq6
|
14810 |
+
4b80
|
14811 |
+
5ee7
|
14812 |
+
1bcu
|
14813 |
+
4y8z
|
14814 |
+
5ka1
|
14815 |
+
5lpd
|
14816 |
+
3qi4
|
14817 |
+
5vii
|
14818 |
+
5ele
|
14819 |
+
2ew6
|
14820 |
+
1s9v
|
14821 |
+
4bqw
|
14822 |
+
2x6w
|
14823 |
+
5mnc
|
14824 |
+
5eni
|
14825 |
+
2xi7
|
14826 |
+
1wqv
|
14827 |
+
2b8v
|
14828 |
+
6f92
|
14829 |
+
4jve
|
14830 |
+
3oy0
|
14831 |
+
6h41
|
14832 |
+
4zx4
|
14833 |
+
4q15
|
14834 |
+
6czv
|
14835 |
+
2wti
|
14836 |
+
5j9l
|
14837 |
+
1o5r
|
14838 |
+
5n1v
|
14839 |
+
2bq7
|
14840 |
+
4fic
|
14841 |
+
2ole
|
14842 |
+
3umw
|
14843 |
+
1a1e
|
14844 |
+
1ax0
|
14845 |
+
4ux9
|
14846 |
+
6bhi
|
14847 |
+
3pj3
|
14848 |
+
5m55
|
14849 |
+
2uw6
|
14850 |
+
2bqv
|
14851 |
+
2ea2
|
14852 |
+
5dl1
|
14853 |
+
6g7f
|
14854 |
+
5o8t
|
14855 |
+
5nze
|
14856 |
+
5fkj
|
14857 |
+
5t1l
|
14858 |
+
4wj7
|
14859 |
+
3ibi
|
14860 |
+
5h22
|
14861 |
+
4bgh
|
14862 |
+
2j9h
|
14863 |
+
2iyf
|
14864 |
+
5m28
|
14865 |
+
2v0c
|
14866 |
+
6ez6
|
14867 |
+
5b6g
|
14868 |
+
2q3z
|
14869 |
+
4des
|
14870 |
+
3pcj
|
14871 |
+
5y0z
|
14872 |
+
3u6h
|
14873 |
+
3dtc
|
14874 |
+
3cr4
|
14875 |
+
2igv
|
14876 |
+
4qaa
|
14877 |
+
1yhm
|
14878 |
+
3n35
|
14879 |
+
5ylj
|
14880 |
+
5dls
|
14881 |
+
5h1u
|
14882 |
+
4qw4
|
14883 |
+
4hv3
|
14884 |
+
4jfi
|
14885 |
+
2go4
|
14886 |
+
2m0o
|
14887 |
+
5vzy
|
14888 |
+
2h6t
|
14889 |
+
2qnn
|
14890 |
+
2aqb
|
14891 |
+
1zd5
|
14892 |
+
3pxf
|
14893 |
+
1p1n
|
14894 |
+
1bnt
|
14895 |
+
2hm1
|
14896 |
+
4z46
|
14897 |
+
5e2n
|
14898 |
+
2p8s
|
14899 |
+
1h2k
|
14900 |
+
3uh2
|
14901 |
+
1b2m
|
14902 |
+
5eiw
|
14903 |
+
4bfy
|
14904 |
+
5csx
|
14905 |
+
2z92
|
14906 |
+
2rjp
|
14907 |
+
5o7n
|
14908 |
+
3d3p
|
14909 |
+
4ban
|
14910 |
+
4l0l
|
14911 |
+
3zo2
|
14912 |
+
3zhx
|
14913 |
+
2hah
|
14914 |
+
3dx1
|
14915 |
+
4dkt
|
14916 |
+
3sz9
|
14917 |
+
3n0n
|
14918 |
+
4l4m
|
14919 |
+
6asz
|
14920 |
+
3hv4
|
14921 |
+
3imc
|
14922 |
+
3eju
|
14923 |
+
5t6z
|
14924 |
+
4jaz
|
14925 |
+
1gjb
|
14926 |
+
5fl0
|
14927 |
+
3r9n
|
14928 |
+
3sw8
|
14929 |
+
5ggp
|
14930 |
+
1btn
|
14931 |
+
5j8u
|
14932 |
+
1x8t
|
14933 |
+
3bva
|
14934 |
+
2wtc
|
14935 |
+
5lom
|
14936 |
+
2vwc
|
14937 |
+
6bw2
|
14938 |
+
6m9f
|
14939 |
+
4n1z
|
14940 |
+
3lzb
|
14941 |
+
1fwe
|
14942 |
+
2w16
|
14943 |
+
2i6b
|
14944 |
+
5ytu
|
14945 |
+
4j8r
|
14946 |
+
4je8
|
14947 |
+
3t60
|
14948 |
+
2n9x
|
14949 |
+
6f8t
|
14950 |
+
4lwu
|
14951 |
+
6ebe
|
14952 |
+
6ajj
|
14953 |
+
5wap
|
14954 |
+
5a6k
|
14955 |
+
2xp7
|
14956 |
+
3ql9
|
14957 |
+
1q7a
|
14958 |
+
5dkn
|
14959 |
+
2gnl
|
14960 |
+
3rwc
|
14961 |
+
5npr
|
14962 |
+
2e9c
|
14963 |
+
1ajv
|
14964 |
+
6e4f
|
14965 |
+
1o7o
|
14966 |
+
5alf
|
14967 |
+
2xys
|
14968 |
+
6h5w
|
14969 |
+
2jfz
|
14970 |
+
2xdx
|
14971 |
+
4bda
|
14972 |
+
3rxd
|
14973 |
+
1f57
|
14974 |
+
9icd
|
14975 |
+
3zpr
|
14976 |
+
4ciw
|
14977 |
+
2zcr
|
14978 |
+
2w9r
|
14979 |
+
3hnz
|
14980 |
+
4r1y
|
14981 |
+
3olg
|
14982 |
+
5lce
|
14983 |
+
1kwq
|
14984 |
+
5lrg
|
14985 |
+
5f0c
|
14986 |
+
3u8j
|
14987 |
+
1bl6
|
14988 |
+
3amv
|
14989 |
+
1ej4
|
14990 |
+
4ht0
|
14991 |
+
3u6w
|
14992 |
+
4q09
|
14993 |
+
5jss
|
14994 |
+
3qlc
|
14995 |
+
2b1i
|
14996 |
+
5cls
|
14997 |
+
3eyf
|
14998 |
+
6eln
|
14999 |
+
5mrh
|
15000 |
+
3nox
|
15001 |
+
2qe2
|
15002 |
+
3u6j
|
15003 |
+
1qka
|
15004 |
+
3k5u
|
15005 |
+
1ws1
|
15006 |
+
5ew0
|
15007 |
+
6ft9
|
15008 |
+
3kr4
|
15009 |
+
5iug
|
15010 |
+
1ajn
|
15011 |
+
3zn0
|
15012 |
+
2i3z
|
15013 |
+
1y3x
|
15014 |
+
2r9s
|
15015 |
+
5vpm
|
15016 |
+
4occ
|
15017 |
+
4nym
|
15018 |
+
3osw
|
15019 |
+
3hy5
|
15020 |
+
4j86
|
15021 |
+
4dfg
|
15022 |
+
5f1v
|
15023 |
+
5l4e
|
15024 |
+
2qve
|
15025 |
+
4erf
|
15026 |
+
1wss
|
15027 |
+
1ajq
|
15028 |
+
5h5r
|
15029 |
+
1ym2
|
15030 |
+
1hee
|
15031 |
+
3rq7
|
15032 |
+
1dxp
|
15033 |
+
1vgc
|
15034 |
+
3huc
|
15035 |
+
5fqb
|
15036 |
+
4mue
|
15037 |
+
1qbs
|
15038 |
+
1ujk
|
15039 |
+
6fa3
|
15040 |
+
4xo8
|
15041 |
+
4ww8
|
15042 |
+
4qxt
|
15043 |
+
3in3
|
15044 |
+
2wxp
|
15045 |
+
5j3s
|
15046 |
+
2h1h
|
15047 |
+
5d7a
|
15048 |
+
4lhm
|
15049 |
+
2rjs
|
15050 |
+
5nvf
|
15051 |
+
3l0n
|
15052 |
+
5b5f
|
15053 |
+
4oow
|
15054 |
+
3ej5
|
15055 |
+
5fum
|
15056 |
+
1li6
|
15057 |
+
5swg
|
15058 |
+
6eum
|
15059 |
+
3fas
|
15060 |
+
5klr
|
15061 |
+
2vv9
|
15062 |
+
3v5t
|
15063 |
+
2byr
|
15064 |
+
5nr7
|
15065 |
+
3suf
|
15066 |
+
2xb9
|
15067 |
+
1f4x
|
15068 |
+
5v86
|
15069 |
+
3kl6
|
15070 |
+
1qng
|
15071 |
+
2a8g
|
15072 |
+
2j62
|
15073 |
+
3zi0
|
15074 |
+
1h6e
|
15075 |
+
3ap7
|
15076 |
+
3zj6
|
15077 |
+
4hp0
|
15078 |
+
1bmk
|
15079 |
+
1nj1
|
15080 |
+
5xp7
|
15081 |
+
4iwd
|
15082 |
+
1if7
|
15083 |
+
4ia0
|
15084 |
+
3ms7
|
15085 |
+
5yjk
|
15086 |
+
5j7f
|
15087 |
+
5aba
|
15088 |
+
5ake
|
15089 |
+
1h2t
|
15090 |
+
4mzk
|
15091 |
+
4ezj
|
15092 |
+
4an3
|
15093 |
+
5jfp
|
15094 |
+
5v24
|
15095 |
+
2xmy
|
15096 |
+
1yqy
|
15097 |
+
3aox
|
15098 |
+
4yjn
|
15099 |
+
2i0h
|
15100 |
+
4lwe
|
15101 |
+
4frs
|
15102 |
+
2hwg
|
15103 |
+
3o4l
|
15104 |
+
3ddg
|
15105 |
+
4cu8
|
15106 |
+
2zfs
|
15107 |
+
5wfd
|
15108 |
+
4lnb
|
15109 |
+
4j17
|
15110 |
+
4qyy
|
15111 |
+
2r3j
|
15112 |
+
4eoi
|
15113 |
+
3pdh
|
15114 |
+
1y3p
|
15115 |
+
4g5y
|
15116 |
+
3v4t
|
15117 |
+
4okp
|
15118 |
+
5meh
|
15119 |
+
1xpc
|
15120 |
+
3avl
|
15121 |
+
6gzl
|
15122 |
+
2pqc
|
15123 |
+
4g0y
|
15124 |
+
3wab
|
15125 |
+
5iop
|
15126 |
+
2ax9
|
15127 |
+
3bex
|
15128 |
+
3cdb
|
15129 |
+
6afc
|
15130 |
+
1v0m
|
15131 |
+
3ksl
|
15132 |
+
3fvl
|
15133 |
+
6c7d
|
15134 |
+
1t2v
|
15135 |
+
5bot
|
15136 |
+
5yto
|
15137 |
+
2wed
|
15138 |
+
1jn2
|
15139 |
+
4k4e
|
15140 |
+
1a94
|
15141 |
+
3ozj
|
15142 |
+
1j81
|
15143 |
+
3e93
|
15144 |
+
1q9d
|
15145 |
+
4idt
|
15146 |
+
4k2f
|
15147 |
+
2whp
|
15148 |
+
3snc
|
15149 |
+
4otg
|
15150 |
+
2lty
|
15151 |
+
5bnr
|
15152 |
+
6c7r
|
15153 |
+
3as3
|
15154 |
+
4ge9
|
15155 |
+
4xg7
|
15156 |
+
5dw1
|
15157 |
+
3ivq
|
15158 |
+
2qrg
|
15159 |
+
2xdk
|
15160 |
+
1gno
|
15161 |
+
2gg5
|
15162 |
+
1d4y
|
15163 |
+
5dqe
|
15164 |
+
3rwi
|
15165 |
+
4x8o
|
15166 |
+
3el9
|
15167 |
+
4kup
|
15168 |
+
3eks
|
15169 |
+
2kff
|
15170 |
+
1w5y
|
15171 |
+
2flh
|
15172 |
+
2vwv
|
15173 |
+
3rvg
|
15174 |
+
4oeu
|
15175 |
+
3u4o
|
15176 |
+
2pv3
|
15177 |
+
4i0t
|
15178 |
+
3aru
|
15179 |
+
4yv0
|
15180 |
+
5ura
|
15181 |
+
5uv1
|
15182 |
+
3vjc
|
15183 |
+
4bam
|
15184 |
+
5vc5
|
15185 |
+
2ito
|
15186 |
+
1l5s
|
15187 |
+
3adv
|
15188 |
+
3oe6
|
15189 |
+
5mnb
|
15190 |
+
5gvm
|
15191 |
+
1r1j
|
15192 |
+
2qe5
|
15193 |
+
2rjr
|
15194 |
+
3wiz
|
15195 |
+
4cfm
|
15196 |
+
1gz4
|
15197 |
+
3c1n
|
15198 |
+
6ma3
|
15199 |
+
1z9h
|
15200 |
+
6g98
|
15201 |
+
1qm4
|
15202 |
+
4j24
|
15203 |
+
3pju
|
15204 |
+
5cqx
|
15205 |
+
1wvj
|
15206 |
+
2yde
|
15207 |
+
4mqp
|
15208 |
+
2np9
|
15209 |
+
4zyu
|
15210 |
+
3ua9
|
15211 |
+
3fc2
|
15212 |
+
2xp5
|
15213 |
+
1umw
|
15214 |
+
5jer
|
15215 |
+
3dcv
|
15216 |
+
4aft
|
15217 |
+
4rhu
|
15218 |
+
3ahn
|
15219 |
+
4ytf
|
15220 |
+
5os2
|
15221 |
+
5el9
|
15222 |
+
3gjw
|
15223 |
+
4oth
|
15224 |
+
1lkl
|
15225 |
+
6ela
|
15226 |
+
5vkf
|
15227 |
+
2oz6
|
15228 |
+
4q1f
|
15229 |
+
5usz
|
15230 |
+
2xfk
|
15231 |
+
3n51
|
15232 |
+
4fxq
|
15233 |
+
4oc3
|
15234 |
+
3ggu
|
15235 |
+
1hiv
|
15236 |
+
4d2s
|
15237 |
+
2fkf
|
15238 |
+
4oz3
|
15239 |
+
6fkz
|
15240 |
+
3lhg
|
15241 |
+
1jyq
|
15242 |
+
3uvw
|
15243 |
+
4f6s
|
15244 |
+
2qk8
|
15245 |
+
5jat
|
15246 |
+
1lvu
|
15247 |
+
11gs
|
15248 |
+
4cwt
|
15249 |
+
4gz3
|
15250 |
+
5vkc
|
15251 |
+
1wu1
|
15252 |
+
5m17
|
15253 |
+
1rne
|
15254 |
+
1l2z
|
15255 |
+
3s0d
|
15256 |
+
4nxq
|
15257 |
+
5iu2
|
15258 |
+
1x78
|
15259 |
+
6bc9
|
15260 |
+
6drx
|
15261 |
+
5juz
|
15262 |
+
4qvn
|
15263 |
+
5i7x
|
15264 |
+
5o7e
|
15265 |
+
4ktc
|
15266 |
+
1fl3
|
15267 |
+
1enu
|
15268 |
+
2clf
|
15269 |
+
4zs0
|
15270 |
+
4llp
|
15271 |
+
4djy
|
15272 |
+
5nrf
|
15273 |
+
4z0k
|
15274 |
+
4k8a
|
15275 |
+
6cdc
|
15276 |
+
6bin
|
15277 |
+
4e1z
|
15278 |
+
1a61
|
15279 |
+
2q64
|
15280 |
+
3s0o
|
15281 |
+
4z0u
|
15282 |
+
1ii5
|
15283 |
+
4lk7
|
15284 |
+
5ubt
|
15285 |
+
5m1z
|
15286 |
+
1t4j
|
15287 |
+
1g7v
|
15288 |
+
4q1n
|
15289 |
+
3l08
|
15290 |
+
5d7r
|
15291 |
+
2emt
|
15292 |
+
4y2b
|
15293 |
+
4j0t
|
15294 |
+
2zof
|
15295 |
+
6ecz
|
15296 |
+
4gb9
|
15297 |
+
4jfl
|
15298 |
+
2ow3
|
15299 |
+
1ibg
|
15300 |
+
3fyz
|
15301 |
+
5g5z
|
15302 |
+
7lpr
|
15303 |
+
4g8n
|
15304 |
+
4bie
|
15305 |
+
2yir
|
15306 |
+
4yps
|
15307 |
+
5jdc
|
15308 |
+
3p4v
|
15309 |
+
2fum
|
15310 |
+
5c4o
|
15311 |
+
1kcs
|
15312 |
+
4r3s
|
15313 |
+
1cj1
|
15314 |
+
6f09
|
15315 |
+
4ce3
|
15316 |
+
4ft2
|
15317 |
+
2pcu
|
15318 |
+
4mo8
|
15319 |
+
2g2r
|
15320 |
+
4lxk
|
15321 |
+
4utn
|
15322 |
+
1stc
|
15323 |
+
5nxp
|
15324 |
+
5t52
|
15325 |
+
3iod
|
15326 |
+
1h01
|
15327 |
+
4deb
|
15328 |
+
4jjs
|
15329 |
+
5ts0
|
15330 |
+
3su0
|
15331 |
+
4yhf
|
15332 |
+
1y4z
|
15333 |
+
3heg
|
15334 |
+
2g70
|
15335 |
+
3p2h
|
15336 |
+
1sqq
|
15337 |
+
1swk
|
15338 |
+
2f4b
|
15339 |
+
1igj
|
15340 |
+
3fcq
|
15341 |
+
2pja
|
15342 |
+
4ase
|
15343 |
+
2o63
|
15344 |
+
2xyf
|
15345 |
+
4j0v
|
15346 |
+
5ka7
|
15347 |
+
5kzp
|
15348 |
+
3oob
|
15349 |
+
5w6t
|
15350 |
+
1h2u
|
15351 |
+
5a00
|
15352 |
+
4zt3
|
15353 |
+
2cer
|
15354 |
+
1w96
|
15355 |
+
2pzi
|
15356 |
+
4qf7
|
15357 |
+
3c88
|
15358 |
+
4y67
|
15359 |
+
4nrl
|
15360 |
+
4du8
|
15361 |
+
4qtn
|
15362 |
+
3sue
|
15363 |
+
6fhu
|
15364 |
+
1qs4
|
15365 |
+
5u6b
|
15366 |
+
5edb
|
15367 |
+
2p2h
|
15368 |
+
5gtr
|
15369 |
+
4hbp
|
15370 |
+
3tia
|
15371 |
+
3cbp
|
15372 |
+
2cgw
|
15373 |
+
4bio
|
15374 |
+
3gwt
|
15375 |
+
5t8r
|
15376 |
+
6fo7
|
15377 |
+
1g9t
|
15378 |
+
3kr0
|
15379 |
+
1gt3
|
15380 |
+
5c83
|
15381 |
+
2r9x
|
15382 |
+
3f8c
|
15383 |
+
5nk7
|
15384 |
+
4cfu
|
15385 |
+
5e2r
|
15386 |
+
2wf1
|
15387 |
+
3uil
|
15388 |
+
5fl6
|
15389 |
+
1ms7
|
15390 |
+
4csj
|
15391 |
+
4yat
|
15392 |
+
4f1q
|
15393 |
+
4lm1
|
15394 |
+
4oc0
|
15395 |
+
3hj0
|
15396 |
+
2xwe
|
15397 |
+
3ms4
|
15398 |
+
2jh0
|
15399 |
+
3oad
|
15400 |
+
2y2j
|
15401 |
+
4bd3
|
15402 |
+
6h7n
|
15403 |
+
5exm
|
15404 |
+
1ctu
|
15405 |
+
5l3f
|
15406 |
+
2ajd
|
15407 |
+
2c94
|
15408 |
+
3g3r
|
15409 |
+
2zo3
|
15410 |
+
4dro
|
15411 |
+
1uou
|
15412 |
+
6bsl
|
15413 |
+
1uy7
|
15414 |
+
3zyb
|
15415 |
+
3t0b
|
15416 |
+
4o43
|
15417 |
+
5q0l
|
15418 |
+
3wch
|
15419 |
+
5orb
|
15420 |
+
3kgp
|
15421 |
+
3zeb
|
15422 |
+
4pyy
|
15423 |
+
4b0j
|
15424 |
+
1jq8
|
15425 |
+
3u4w
|
15426 |
+
2xyt
|
15427 |
+
5jhd
|
15428 |
+
3hmp
|
15429 |
+
4dxj
|
15430 |
+
5hg7
|
15431 |
+
3zlx
|
15432 |
+
1zkk
|
15433 |
+
1gny
|
15434 |
+
4ju6
|
15435 |
+
1il3
|
15436 |
+
4daf
|
15437 |
+
4o0x
|
15438 |
+
5ygi
|
15439 |
+
6gla
|
15440 |
+
3mtw
|
15441 |
+
3mg0
|
15442 |
+
3d9l
|
15443 |
+
2vcj
|
15444 |
+
5edq
|
15445 |
+
4bci
|
15446 |
+
4e4x
|
15447 |
+
2qdt
|
15448 |
+
3wuu
|
15449 |
+
3udv
|
15450 |
+
4dkq
|
15451 |
+
4bfp
|
15452 |
+
5i2e
|
15453 |
+
3q1x
|
15454 |
+
1qaq
|
15455 |
+
3rm8
|
15456 |
+
4ahu
|
15457 |
+
1gx4
|
15458 |
+
3wi2
|
15459 |
+
4de2
|
15460 |
+
5g2g
|
15461 |
+
2wuu
|
15462 |
+
5nud
|
15463 |
+
4hcu
|
15464 |
+
3k37
|
15465 |
+
6prc
|
15466 |
+
2e7f
|
15467 |
+
4bb9
|
15468 |
+
1amk
|
15469 |
+
4l1a
|
15470 |
+
4lqy
|
15471 |
+
4a16
|
15472 |
+
5wkf
|
15473 |
+
4qsm
|
15474 |
+
3sxu
|
15475 |
+
3uqg
|
15476 |
+
5lif
|
15477 |
+
4azf
|
15478 |
+
5ntt
|
15479 |
+
3vsw
|
15480 |
+
5fos
|
15481 |
+
1qin
|
15482 |
+
3e7b
|
15483 |
+
1ll4
|
15484 |
+
3vjm
|
15485 |
+
3ny3
|
15486 |
+
6aqs
|
15487 |
+
1k6c
|
15488 |
+
4ngr
|
15489 |
+
6fc6
|
15490 |
+
2gnj
|
15491 |
+
4zy6
|
15492 |
+
3u8d
|
15493 |
+
2aou
|
15494 |
+
4b0b
|
15495 |
+
5t2p
|
15496 |
+
5efb
|
15497 |
+
5u0d
|
15498 |
+
5vjp
|
15499 |
+
5bui
|
15500 |
+
5e13
|
15501 |
+
5f5i
|
15502 |
+
4ivk
|
15503 |
+
7hvp
|
15504 |
+
3d7k
|
15505 |
+
4vgc
|
15506 |
+
5g1p
|
15507 |
+
6b1h
|
15508 |
+
2br8
|
15509 |
+
1cqp
|
15510 |
+
4w50
|
15511 |
+
4ehv
|
15512 |
+
5kqf
|
15513 |
+
2yfa
|
15514 |
+
3ws9
|
15515 |
+
4xkb
|
15516 |
+
5mrp
|
15517 |
+
3str
|
15518 |
+
5nkd
|
15519 |
+
5mpk
|
15520 |
+
5kqy
|
15521 |
+
4lw1
|
15522 |
+
1avp
|
15523 |
+
3qdd
|
15524 |
+
5xxk
|
15525 |
+
4oks
|
15526 |
+
4hxr
|
15527 |
+
3ur0
|
15528 |
+
4pns
|
15529 |
+
4i5m
|
15530 |
+
4hgl
|
15531 |
+
2vtd
|
15532 |
+
2gph
|
15533 |
+
3rme
|
15534 |
+
5fqp
|
15535 |
+
5hfu
|
15536 |
+
2iok
|
15537 |
+
4yux
|
15538 |
+
6g1u
|
15539 |
+
2hvx
|
15540 |
+
1n0s
|
15541 |
+
4l4v
|
15542 |
+
3s1y
|
15543 |
+
1g7p
|
15544 |
+
2rr4
|
15545 |
+
2x00
|
15546 |
+
2b55
|
15547 |
+
4wmv
|
15548 |
+
4kc1
|
15549 |
+
2x39
|
15550 |
+
5joh
|
15551 |
+
2w0p
|
15552 |
+
4az6
|
15553 |
+
1o0f
|
15554 |
+
3haw
|
15555 |
+
5w44
|
15556 |
+
2xhr
|
15557 |
+
1h8s
|
15558 |
+
4ge1
|
15559 |
+
3phe
|
15560 |
+
1evh
|
15561 |
+
6b30
|
15562 |
+
1g35
|
15563 |
+
2qfo
|
15564 |
+
5gjf
|
15565 |
+
6bt6
|
15566 |
+
2gg3
|
15567 |
+
5trr
|
15568 |
+
5ly3
|
15569 |
+
5eh0
|
15570 |
+
5ioy
|
15571 |
+
1xt8
|
15572 |
+
3c3o
|
15573 |
+
5e74
|
15574 |
+
3acl
|
15575 |
+
5abh
|
15576 |
+
5fol
|
15577 |
+
5ddf
|
15578 |
+
3qxv
|
15579 |
+
3iwy
|
15580 |
+
3ttm
|
15581 |
+
5n18
|
15582 |
+
6beb
|
15583 |
+
5nxw
|
15584 |
+
5lxb
|
15585 |
+
4ra1
|
15586 |
+
4muk
|
15587 |
+
4mm4
|
15588 |
+
4hs6
|
15589 |
+
5ncq
|
15590 |
+
3zmg
|
15591 |
+
4hcv
|
15592 |
+
4i72
|
15593 |
+
4pee
|
15594 |
+
1qtn
|
15595 |
+
4awg
|
15596 |
+
4rfy
|
15597 |
+
5dyy
|
15598 |
+
3ud8
|
15599 |
+
5itf
|
15600 |
+
5cuq
|
15601 |
+
5f1c
|
15602 |
+
5hey
|
15603 |
+
2ko7
|
15604 |
+
3oil
|
15605 |
+
5tks
|
15606 |
+
3t3u
|
15607 |
+
5o3q
|
15608 |
+
4k72
|
15609 |
+
4oma
|
15610 |
+
3hv6
|
15611 |
+
6df7
|
15612 |
+
5er4
|
15613 |
+
4no6
|
15614 |
+
5ugd
|
15615 |
+
1ciz
|
15616 |
+
1rev
|
15617 |
+
6hdq
|
15618 |
+
3c43
|
15619 |
+
1a7t
|
15620 |
+
6fky
|
15621 |
+
5n1r
|
15622 |
+
3rr4
|
15623 |
+
5bqg
|
15624 |
+
3b8r
|
15625 |
+
2pfy
|
15626 |
+
5c7f
|
15627 |
+
5l6j
|
15628 |
+
1etz
|
15629 |
+
3drf
|
15630 |
+
3k7f
|
15631 |
+
4b6e
|
15632 |
+
6asu
|
15633 |
+
1fd0
|
15634 |
+
4zjc
|
15635 |
+
1y3g
|
15636 |
+
4joh
|
15637 |
+
4c38
|
15638 |
+
4h5c
|
15639 |
+
5kej
|
15640 |
+
6aji
|
15641 |
+
4mvy
|
15642 |
+
3lpi
|
15643 |
+
4pms
|
15644 |
+
6fx1
|
15645 |
+
3ioi
|
15646 |
+
2xbj
|
15647 |
+
1bnm
|
15648 |
+
4tuh
|
15649 |
+
4fgt
|
15650 |
+
5mhp
|
15651 |
+
4hwb
|
15652 |
+
6eo9
|
15653 |
+
4aje
|
15654 |
+
1v2t
|
15655 |
+
5h85
|
15656 |
+
1x8d
|
15657 |
+
3uoj
|
15658 |
+
2aog
|
15659 |
+
3o5x
|
15660 |
+
5vr8
|
15661 |
+
2o4p
|
15662 |
+
1fh8
|
15663 |
+
4jz1
|
15664 |
+
5oq4
|
15665 |
+
3zdh
|
15666 |
+
5otz
|
15667 |
+
3lnz
|
15668 |
+
1n9m
|
15669 |
+
3rak
|
15670 |
+
6ba7
|
15671 |
+
6czb
|
15672 |
+
2wyj
|
15673 |
+
4qyo
|
15674 |
+
3mxd
|
15675 |
+
2ri9
|
15676 |
+
2zq1
|
15677 |
+
3ljo
|
15678 |
+
1kvo
|
15679 |
+
6g2a
|
15680 |
+
1gj6
|
15681 |
+
5oug
|
15682 |
+
1g4o
|
15683 |
+
3mvm
|
15684 |
+
1iyl
|
15685 |
+
2cgx
|
15686 |
+
3v2x
|
15687 |
+
5iv4
|
15688 |
+
4m2u
|
15689 |
+
4q1b
|
15690 |
+
3ggc
|
15691 |
+
2c68
|
15692 |
+
3ind
|
15693 |
+
1laf
|
15694 |
+
4kxn
|
15695 |
+
2ada
|
15696 |
+
1om1
|
15697 |
+
5eh7
|
15698 |
+
4jk5
|
15699 |
+
4q93
|
15700 |
+
1b8y
|
15701 |
+
1x11
|
15702 |
+
4mr6
|
15703 |
+
4c4j
|
15704 |
+
4yik
|
15705 |
+
1osv
|
15706 |
+
4y7r
|
15707 |
+
4zow
|
15708 |
+
2hdx
|
15709 |
+
4ui6
|
15710 |
+
4r6x
|
15711 |
+
1pxi
|
15712 |
+
5ni5
|
15713 |
+
5v4b
|
15714 |
+
1h0a
|
15715 |
+
4pf5
|
15716 |
+
5ggz
|
15717 |
+
1o4m
|
15718 |
+
1urc
|
15719 |
+
5mqt
|
15720 |
+
3ads
|
15721 |
+
5gn5
|
15722 |
+
4mrg
|
15723 |
+
5ylt
|
15724 |
+
5k6a
|
15725 |
+
4nld
|
15726 |
+
2xl3
|
15727 |
+
4auy
|
15728 |
+
1zoe
|
15729 |
+
4pum
|
15730 |
+
5lxd
|
15731 |
+
5csh
|
15732 |
+
3gbq
|
15733 |
+
5xs2
|
15734 |
+
4ggl
|
15735 |
+
5a14
|
15736 |
+
4au8
|
15737 |
+
5n49
|
15738 |
+
5x8i
|
15739 |
+
6c7f
|
15740 |
+
3fvk
|
15741 |
+
4kqp
|
15742 |
+
5y97
|
15743 |
+
6gub
|
15744 |
+
5mxx
|
15745 |
+
3lox
|
15746 |
+
2oc7
|
15747 |
+
3g1m
|
15748 |
+
6hsz
|
15749 |
+
1ilq
|
15750 |
+
3twj
|
15751 |
+
5vcx
|
15752 |
+
3svv
|
15753 |
+
4na4
|
15754 |
+
3v5g
|
15755 |
+
4p7e
|
15756 |
+
2vwl
|
15757 |
+
4umu
|
15758 |
+
3v4j
|
15759 |
+
6gfz
|
15760 |
+
6duf
|
15761 |
+
5aqf
|
15762 |
+
5ezh
|
15763 |
+
5nar
|
15764 |
+
4yti
|
15765 |
+
4zyq
|
15766 |
+
4lop
|
15767 |
+
4nus
|
15768 |
+
2a3a
|
15769 |
+
2o9i
|
15770 |
+
3ia6
|
15771 |
+
5nfh
|
15772 |
+
1e00
|
15773 |
+
5u8a
|
15774 |
+
3n8n
|
15775 |
+
4axd
|
15776 |
+
3kxz
|
15777 |
+
3owd
|
15778 |
+
4fxj
|
15779 |
+
1gx0
|
15780 |
+
4u90
|
15781 |
+
1d7x
|
15782 |
+
3eq8
|
15783 |
+
3q44
|
15784 |
+
4ago
|
15785 |
+
5e2p
|
15786 |
+
1pxj
|
15787 |
+
4p6c
|
15788 |
+
1zoh
|
15789 |
+
4i7j
|
15790 |
+
4hlg
|
15791 |
+
5j6n
|
15792 |
+
3s2o
|
15793 |
+
4ec0
|
15794 |
+
3wiy
|
15795 |
+
4k77
|
15796 |
+
5yf1
|
15797 |
+
1hsl
|
15798 |
+
4tjz
|
15799 |
+
6cbh
|
15800 |
+
6g38
|
15801 |
+
4efu
|
15802 |
+
5wep
|
15803 |
+
1jwm
|
15804 |
+
3wfg
|
15805 |
+
5lvl
|
15806 |
+
5kqd
|
15807 |
+
1fq5
|
15808 |
+
5nn6
|
15809 |
+
3b5r
|
15810 |
+
5xag
|
15811 |
+
3w69
|
15812 |
+
3udr
|
15813 |
+
4c4h
|
15814 |
+
5mgi
|
15815 |
+
5ad1
|
15816 |
+
5zh3
|
15817 |
+
4i7b
|
15818 |
+
6cwi
|
15819 |
+
1tkb
|
15820 |
+
3unj
|
15821 |
+
4u54
|
15822 |
+
2x0y
|
15823 |
+
3isw
|
15824 |
+
2xbw
|
15825 |
+
6fzu
|
15826 |
+
5wgq
|
15827 |
+
4kzc
|
15828 |
+
1yhs
|
15829 |
+
5btr
|
15830 |
+
1juq
|
15831 |
+
2idk
|
15832 |
+
2v25
|
15833 |
+
4prh
|
15834 |
+
5o5a
|
15835 |
+
3r0h
|
15836 |
+
1sle
|
15837 |
+
2ieh
|
15838 |
+
5ous
|
15839 |
+
2fqy
|
15840 |
+
1p7m
|
15841 |
+
3fuf
|
15842 |
+
1w10
|
15843 |
+
1vot
|
15844 |
+
1guw
|
15845 |
+
1gbq
|
15846 |
+
5thn
|
15847 |
+
6b41
|
15848 |
+
4xoc
|
15849 |
+
5ugc
|
15850 |
+
4h71
|
15851 |
+
5i43
|
15852 |
+
4oc1
|
15853 |
+
3t0d
|
15854 |
+
4kw6
|
15855 |
+
4jrg
|
15856 |
+
4ra5
|
15857 |
+
4azp
|
15858 |
+
5sz3
|
15859 |
+
5hbj
|
15860 |
+
1npa
|
15861 |
+
4wi1
|
15862 |
+
4b7p
|
15863 |
+
3biz
|
15864 |
+
4bpj
|
15865 |
+
3lxe
|
15866 |
+
5qav
|
15867 |
+
4ge6
|
15868 |
+
4k1e
|
15869 |
+
3vje
|
15870 |
+
4mic
|
15871 |
+
4qp9
|
15872 |
+
2xg5
|
15873 |
+
1w5x
|
15874 |
+
2rin
|
15875 |
+
3omc
|
15876 |
+
5ii2
|
15877 |
+
3pax
|
15878 |
+
5elq
|
15879 |
+
3bpc
|
15880 |
+
1ec0
|
15881 |
+
4x8g
|
15882 |
+
3cft
|
15883 |
+
4qd6
|
15884 |
+
5n1x
|
15885 |
+
2v96
|
15886 |
+
4ucc
|
15887 |
+
5ocj
|
15888 |
+
4mul
|
15889 |
+
3lok
|
15890 |
+
2e5y
|
15891 |
+
3eql
|
15892 |
+
5kyj
|
15893 |
+
1n5r
|
15894 |
+
3hfz
|
15895 |
+
2pg2
|
15896 |
+
3g3m
|
15897 |
+
4fs3
|
15898 |
+
1nnk
|
15899 |
+
4n9a
|
15900 |
+
4jp9
|
15901 |
+
2j77
|
15902 |
+
6cvd
|
15903 |
+
4tkb
|
15904 |
+
3tfp
|
15905 |
+
5a5o
|
15906 |
+
5nsx
|
15907 |
+
6bbv
|
15908 |
+
5myg
|
15909 |
+
3ws8
|
15910 |
+
6ex1
|
15911 |
+
2jkr
|
15912 |
+
5kcv
|
15913 |
+
2vw5
|
15914 |
+
4ezl
|
15915 |
+
3dp0
|
15916 |
+
5hyq
|
15917 |
+
5iyy
|
15918 |
+
2oc4
|
15919 |
+
5div
|
15920 |
+
1gag
|
15921 |
+
2r38
|
15922 |
+
3chp
|
15923 |
+
3ot8
|
15924 |
+
2wqb
|
15925 |
+
6bqh
|
15926 |
+
3gxl
|
15927 |
+
2pgj
|
15928 |
+
6gfx
|
15929 |
+
2i3v
|
15930 |
+
5yqw
|
15931 |
+
5n9t
|
15932 |
+
6cc9
|
15933 |
+
3p3s
|
15934 |
+
3oe9
|
15935 |
+
2y1o
|
15936 |
+
2o4r
|
15937 |
+
1dzm
|
15938 |
+
3vp2
|
15939 |
+
3djo
|
15940 |
+
4oz2
|
15941 |
+
1p6d
|
15942 |
+
5mih
|
15943 |
+
4xt2
|
15944 |
+
3tf7
|
15945 |
+
5v19
|
15946 |
+
6g9k
|
15947 |
+
4ipf
|
15948 |
+
3bim
|
15949 |
+
4nwm
|
15950 |
+
2aeb
|
15951 |
+
3blu
|
15952 |
+
3vtc
|
15953 |
+
3nww
|
15954 |
+
3mp6
|
15955 |
+
1nu8
|
15956 |
+
3wzk
|
15957 |
+
4zec
|
15958 |
+
3gvb
|
15959 |
+
4bt4
|
15960 |
+
2f6v
|
15961 |
+
5xwr
|
15962 |
+
5m53
|
15963 |
+
4yvc
|
15964 |
+
1ai4
|
15965 |
+
1z1r
|
15966 |
+
1ryh
|
15967 |
+
1rhu
|
15968 |
+
5d1s
|
15969 |
+
3g0i
|
15970 |
+
1gpk
|
15971 |
+
4clb
|
15972 |
+
5cte
|
15973 |
+
4kmu
|
15974 |
+
6f9r
|
15975 |
+
3pjg
|
15976 |
+
1uz1
|
15977 |
+
3tww
|
15978 |
+
2lbv
|
15979 |
+
5w1w
|
15980 |
+
1s26
|
15981 |
+
3w9r
|
15982 |
+
4yes
|
15983 |
+
3sl8
|
15984 |
+
5km0
|
15985 |
+
2j79
|
15986 |
+
2h03
|
15987 |
+
1qnh
|
15988 |
+
4cpx
|
15989 |
+
5enk
|
15990 |
+
4mnv
|
15991 |
+
3r5m
|
15992 |
+
4tk4
|
15993 |
+
5wg6
|
15994 |
+
5uwf
|
15995 |
+
4cjp
|
15996 |
+
3uu1
|
15997 |
+
4bxu
|
15998 |
+
3h30
|
15999 |
+
4qwr
|
16000 |
+
2gyi
|
16001 |
+
1cnw
|
16002 |
+
4fzc
|
16003 |
+
6gdg
|
16004 |
+
4e5i
|
16005 |
+
3oq5
|
16006 |
+
3wig
|
16007 |
+
5my8
|
16008 |
+
4aj1
|
16009 |
+
3b65
|
16010 |
+
2e95
|
16011 |
+
4xcb
|
16012 |
+
3wf5
|
16013 |
+
5h15
|
16014 |
+
5htb
|
16015 |
+
3t3e
|
16016 |
+
3h5b
|
16017 |
+
1ugp
|
16018 |
+
5anq
|
16019 |
+
6g4n
|
16020 |
+
1apb
|
16021 |
+
2ai7
|
16022 |
+
4xxs
|
16023 |
+
1lrh
|
16024 |
+
1ove
|
16025 |
+
3v7t
|
16026 |
+
1xk5
|
16027 |
+
4fiv
|
16028 |
+
4mcv
|
16029 |
+
1mrw
|
16030 |
+
4b14
|
16031 |
+
5isl
|
16032 |
+
5cj6
|
16033 |
+
5un9
|
16034 |
+
3nil
|
16035 |
+
1x07
|
16036 |
+
6fni
|
16037 |
+
4u2y
|
16038 |
+
4hbv
|
16039 |
+
6h2t
|
16040 |
+
4q6d
|
16041 |
+
3b8z
|
16042 |
+
2cnf
|
16043 |
+
4isu
|
16044 |
+
5u2f
|
16045 |
+
2cng
|
16046 |
+
4q90
|
16047 |
+
4l0b
|
16048 |
+
1z6s
|
16049 |
+
6g3q
|
16050 |
+
4ylu
|
16051 |
+
3w5t
|
16052 |
+
4dei
|
16053 |
+
2zjv
|
16054 |
+
2x6y
|
16055 |
+
3ikg
|
16056 |
+
5j7p
|
16057 |
+
4mcc
|
16058 |
+
3vqs
|
16059 |
+
3u9n
|
16060 |
+
2g5t
|
16061 |
+
3owj
|
16062 |
+
5bnm
|
16063 |
+
3hkn
|
16064 |
+
3qtx
|
16065 |
+
3qzt
|
16066 |
+
5bpa
|
16067 |
+
3p17
|
16068 |
+
6fag
|
16069 |
+
5nfb
|
16070 |
+
1o43
|
16071 |
+
1nok
|
16072 |
+
3vby
|
16073 |
+
6as6
|
16074 |
+
5vjn
|
16075 |
+
3skc
|
16076 |
+
3bg8
|
16077 |
+
1tc1
|
16078 |
+
5orh
|
16079 |
+
5bq0
|
16080 |
+
5qac
|
16081 |
+
3l16
|
16082 |
+
5kw2
|
16083 |
+
3uj9
|
16084 |
+
6byk
|
16085 |
+
5kgw
|
16086 |
+
4wvt
|
16087 |
+
1bv9
|
16088 |
+
4ruz
|
16089 |
+
1fzq
|
16090 |
+
1mu8
|
16091 |
+
1srg
|
16092 |
+
4y73
|
16093 |
+
3upv
|
16094 |
+
4jj8
|
16095 |
+
5xvf
|
16096 |
+
1xka
|
16097 |
+
4ewn
|
16098 |
+
4ewr
|
16099 |
+
4a7b
|
16100 |
+
2xab
|
16101 |
+
6g9b
|
16102 |
+
4u69
|
16103 |
+
1qb6
|
16104 |
+
3c6t
|
16105 |
+
3qar
|
16106 |
+
4k5o
|
16107 |
+
2gnf
|
16108 |
+
1u3q
|
16109 |
+
3g31
|
16110 |
+
3oev
|
16111 |
+
4oc2
|
16112 |
+
1eby
|
16113 |
+
3uef
|
16114 |
+
4k0o
|
16115 |
+
5ehi
|
16116 |
+
5h63
|
16117 |
+
3wcg
|
16118 |
+
6hvi
|
16119 |
+
1hii
|
16120 |
+
4jhq
|
16121 |
+
3sgt
|
16122 |
+
4aua
|
16123 |
+
4hnc
|
16124 |
+
3bxh
|
16125 |
+
5g5v
|
16126 |
+
4j08
|
16127 |
+
4anu
|
16128 |
+
3hac
|
16129 |
+
2vcq
|
16130 |
+
2f7p
|
16131 |
+
4ycl
|
16132 |
+
3s22
|
16133 |
+
3obq
|
16134 |
+
1o9k
|
16135 |
+
4xy2
|
16136 |
+
3k9x
|
16137 |
+
1xog
|
16138 |
+
5b0x
|
16139 |
+
4m5g
|
16140 |
+
4czs
|
16141 |
+
5eyr
|
16142 |
+
4lm5
|
16143 |
+
5xup
|
16144 |
+
4rao
|
16145 |
+
3qcl
|
16146 |
+
3lkj
|
16147 |
+
2xno
|
16148 |
+
1hfs
|
16149 |
+
1gjd
|
16150 |
+
4bzs
|
16151 |
+
4j7d
|
16152 |
+
1fw0
|
16153 |
+
1jfh
|
16154 |
+
2cgr
|
16155 |
+
4pd8
|
16156 |
+
3mz6
|
16157 |
+
5obj
|
16158 |
+
3gm0
|
16159 |
+
4j3u
|
16160 |
+
1uvt
|
16161 |
+
5ml5
|
16162 |
+
4fut
|
16163 |
+
4r3c
|
16164 |
+
4kfp
|
16165 |
+
4jck
|
16166 |
+
5xhs
|
16167 |
+
5mwz
|
16168 |
+
3n86
|
16169 |
+
5qab
|
16170 |
+
5zeq
|
16171 |
+
1fo3
|
16172 |
+
4eki
|
16173 |
+
5n8w
|
16174 |
+
2exm
|
16175 |
+
4klb
|
16176 |
+
5ikb
|
16177 |
+
2qhc
|
16178 |
+
5aqr
|
16179 |
+
4qn7
|
16180 |
+
5nbw
|
16181 |
+
4k2g
|
16182 |
+
3qck
|
16183 |
+
3zo1
|
16184 |
+
4knx
|
16185 |
+
3m6r
|
16186 |
+
6dh6
|
16187 |
+
3p8n
|
16188 |
+
5f3e
|
16189 |
+
2vie
|
16190 |
+
4uyh
|
16191 |
+
5uoy
|
16192 |
+
4gr3
|
16193 |
+
6cyd
|
16194 |
+
2f14
|
16195 |
+
5v2q
|
16196 |
+
3h2m
|
16197 |
+
3ao2
|
16198 |
+
1k1n
|
16199 |
+
3gfw
|
16200 |
+
4q19
|
16201 |
+
2b1g
|
16202 |
+
4pdk
|
16203 |
+
1oxn
|
16204 |
+
2pj1
|
16205 |
+
4o3a
|
16206 |
+
2y6s
|
16207 |
+
1inh
|
16208 |
+
4u5l
|
16209 |
+
4esg
|
16210 |
+
4mg6
|
16211 |
+
4de5
|
16212 |
+
3wke
|
16213 |
+
6dgy
|
16214 |
+
4mp7
|
16215 |
+
4de1
|
16216 |
+
4z6i
|
16217 |
+
2r4b
|
16218 |
+
5q0z
|
16219 |
+
4b33
|
16220 |
+
2koh
|
16221 |
+
4qyh
|
16222 |
+
5y94
|
16223 |
+
6fo8
|
16224 |
+
3p4r
|
16225 |
+
4mny
|
16226 |
+
2vjx
|
16227 |
+
5lj0
|
16228 |
+
5yqx
|
16229 |
+
5c26
|
16230 |
+
4eb8
|
16231 |
+
3lk1
|
16232 |
+
3mg6
|
16233 |
+
4oru
|
16234 |
+
2wpb
|
16235 |
+
4k7i
|
16236 |
+
5fsy
|
16237 |
+
3ava
|
16238 |
+
2z7r
|
16239 |
+
3ex6
|
16240 |
+
4b8p
|
16241 |
+
3l13
|
16242 |
+
5fbi
|
16243 |
+
3s3k
|
16244 |
+
3chc
|
16245 |
+
2wf0
|
16246 |
+
4hgt
|
16247 |
+
6b5i
|
16248 |
+
4ayw
|
16249 |
+
3gk4
|
16250 |
+
2lcs
|
16251 |
+
5fas
|
16252 |
+
1lyx
|
16253 |
+
6bvh
|
16254 |
+
6edr
|
16255 |
+
1ghz
|
16256 |
+
1dg9
|
16257 |
+
1egh
|
16258 |
+
2x6f
|
16259 |
+
5o48
|
16260 |
+
4avg
|
16261 |
+
3znc
|
16262 |
+
1czq
|
16263 |
+
5f39
|
16264 |
+
2bpy
|
16265 |
+
2vc9
|
16266 |
+
5op5
|
16267 |
+
4ory
|
16268 |
+
3hu3
|
16269 |
+
1xuc
|
16270 |
+
3hmo
|
16271 |
+
2ybt
|
16272 |
+
1v1k
|
16273 |
+
5o22
|
16274 |
+
3qt7
|
16275 |
+
4eo8
|
16276 |
+
4bco
|
16277 |
+
2p3i
|
16278 |
+
3hii
|
16279 |
+
2xdm
|
16280 |
+
6axq
|
16281 |
+
2xhs
|
16282 |
+
5cyv
|
16283 |
+
1sre
|
16284 |
+
2y8o
|
16285 |
+
9lpr
|
16286 |
+
4l3o
|
16287 |
+
1dzk
|
16288 |
+
3lnj
|
16289 |
+
3fsm
|
16290 |
+
4ghi
|
16291 |
+
2nqi
|
16292 |
+
1i48
|
16293 |
+
5mo2
|
16294 |
+
6fr2
|
16295 |
+
1bnn
|
16296 |
+
2jbl
|
16297 |
+
1r17
|
16298 |
+
4rrf
|
16299 |
+
5jah
|
16300 |
+
6apw
|
16301 |
+
4trc
|
16302 |
+
1lgt
|
16303 |
+
2wl0
|
16304 |
+
4i0z
|
16305 |
+
3oe5
|
16306 |
+
3fjz
|
16307 |
+
2uyn
|
16308 |
+
3hxd
|
16309 |
+
6g3o
|
16310 |
+
2nqg
|
16311 |
+
3fc8
|
16312 |
+
2zvj
|
16313 |
+
3mw1
|
16314 |
+
2c5n
|
16315 |
+
3poz
|
16316 |
+
5ax9
|
16317 |
+
3mhw
|
16318 |
+
5tdw
|
16319 |
+
5n7b
|
16320 |
+
4kij
|
16321 |
+
5axq
|
16322 |
+
3pxy
|
16323 |
+
2q96
|
16324 |
+
3kjd
|
16325 |
+
5cf5
|
16326 |
+
5id0
|
16327 |
+
5e0j
|
16328 |
+
4kjv
|
16329 |
+
4e1m
|
16330 |
+
3gy4
|
16331 |
+
5m34
|
16332 |
+
1xqc
|
16333 |
+
2hzy
|
16334 |
+
5brn
|
16335 |
+
2d0k
|
16336 |
+
3s8n
|
16337 |
+
2j7f
|
16338 |
+
5zc5
|
16339 |
+
3p5o
|
16340 |
+
1xh5
|
16341 |
+
2vj7
|
16342 |
+
4zt2
|
16343 |
+
2b7a
|
16344 |
+
1thl
|
16345 |
+
1jmq
|
16346 |
+
5h7h
|
16347 |
+
5mz3
|
16348 |
+
3dxj
|
16349 |
+
5q1g
|
16350 |
+
6ays
|
16351 |
+
3w2t
|
16352 |
+
1bkm
|
16353 |
+
3pb3
|
16354 |
+
3vjl
|
16355 |
+
2a8h
|
16356 |
+
4pax
|
16357 |
+
5tt8
|
16358 |
+
2y2p
|
16359 |
+
5lyx
|
16360 |
+
1zaf
|
16361 |
+
3mb6
|
16362 |
+
2fuu
|
16363 |
+
4mw6
|
16364 |
+
2j6m
|
16365 |
+
4rll
|
16366 |
+
3qai
|
16367 |
+
4kzq
|
16368 |
+
2uym
|
16369 |
+
5v84
|
16370 |
+
3bm9
|
16371 |
+
4egk
|
16372 |
+
2bqw
|
16373 |
+
2q8y
|
16374 |
+
4pji
|
16375 |
+
6ary
|
16376 |
+
4daw
|
16377 |
+
4i06
|
16378 |
+
2wxk
|
16379 |
+
1r5n
|
data/splits/timesplit_no_lig_overlap_val
ADDED
@@ -0,0 +1,968 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
4lp9
|
2 |
+
1me7
|
3 |
+
2zv9
|
4 |
+
2qo8
|
5 |
+
1cw2
|
6 |
+
3k5c
|
7 |
+
2o65
|
8 |
+
4kqq
|
9 |
+
3rdv
|
10 |
+
1d4w
|
11 |
+
1q4l
|
12 |
+
4b5w
|
13 |
+
4bgg
|
14 |
+
4mm5
|
15 |
+
3iej
|
16 |
+
3ftu
|
17 |
+
830c
|
18 |
+
2xye
|
19 |
+
1olu
|
20 |
+
2wk2
|
21 |
+
4pxf
|
22 |
+
5o0j
|
23 |
+
1my2
|
24 |
+
5czm
|
25 |
+
4jit
|
26 |
+
5mb1
|
27 |
+
1sqp
|
28 |
+
3zlw
|
29 |
+
4xqu
|
30 |
+
3hkq
|
31 |
+
6fns
|
32 |
+
5e0l
|
33 |
+
2p8o
|
34 |
+
4gzw
|
35 |
+
3n87
|
36 |
+
1lhc
|
37 |
+
4itj
|
38 |
+
4m7c
|
39 |
+
4olh
|
40 |
+
4q1e
|
41 |
+
5l7e
|
42 |
+
3faa
|
43 |
+
5vqx
|
44 |
+
3pka
|
45 |
+
5x54
|
46 |
+
5a9u
|
47 |
+
4n9e
|
48 |
+
4est
|
49 |
+
1il9
|
50 |
+
4igr
|
51 |
+
3t2t
|
52 |
+
6dar
|
53 |
+
3gol
|
54 |
+
3vbg
|
55 |
+
2ydk
|
56 |
+
4zpf
|
57 |
+
5zo7
|
58 |
+
4xnw
|
59 |
+
1fpy
|
60 |
+
2r1y
|
61 |
+
6m8w
|
62 |
+
2jds
|
63 |
+
5icx
|
64 |
+
1hwr
|
65 |
+
6bj2
|
66 |
+
4b4m
|
67 |
+
1zsb
|
68 |
+
4do3
|
69 |
+
3t3i
|
70 |
+
1f8a
|
71 |
+
2ke1
|
72 |
+
5ezx
|
73 |
+
3p78
|
74 |
+
4rvm
|
75 |
+
3ovn
|
76 |
+
5wzv
|
77 |
+
4udb
|
78 |
+
1okz
|
79 |
+
1mpl
|
80 |
+
5npc
|
81 |
+
5ff6
|
82 |
+
1hlf
|
83 |
+
1nvq
|
84 |
+
4bhf
|
85 |
+
4y4g
|
86 |
+
5mkz
|
87 |
+
2o0u
|
88 |
+
3bcs
|
89 |
+
1wvc
|
90 |
+
4fsl
|
91 |
+
3oz1
|
92 |
+
6dgt
|
93 |
+
1me8
|
94 |
+
2puy
|
95 |
+
4odp
|
96 |
+
1hpx
|
97 |
+
4nrq
|
98 |
+
1z2b
|
99 |
+
3uik
|
100 |
+
3mfv
|
101 |
+
3vqh
|
102 |
+
4w9g
|
103 |
+
4xek
|
104 |
+
4jok
|
105 |
+
2wap
|
106 |
+
1g50
|
107 |
+
4j0p
|
108 |
+
2o9a
|
109 |
+
3m94
|
110 |
+
4i1c
|
111 |
+
5a82
|
112 |
+
4i9h
|
113 |
+
1k1i
|
114 |
+
4uro
|
115 |
+
2f7i
|
116 |
+
5fpk
|
117 |
+
2lgf
|
118 |
+
4l7f
|
119 |
+
1g3d
|
120 |
+
4ir5
|
121 |
+
3mta
|
122 |
+
3jzg
|
123 |
+
5f94
|
124 |
+
4nrt
|
125 |
+
4yax
|
126 |
+
5nhv
|
127 |
+
2xtk
|
128 |
+
4qh7
|
129 |
+
1tok
|
130 |
+
4b6p
|
131 |
+
3rg2
|
132 |
+
3q8d
|
133 |
+
3obu
|
134 |
+
4awj
|
135 |
+
3daj
|
136 |
+
2j50
|
137 |
+
5l2z
|
138 |
+
5bml
|
139 |
+
2bba
|
140 |
+
5n34
|
141 |
+
2xvn
|
142 |
+
1dpu
|
143 |
+
5fnt
|
144 |
+
1jyc
|
145 |
+
4zz1
|
146 |
+
6hm7
|
147 |
+
4rrv
|
148 |
+
4rww
|
149 |
+
5orv
|
150 |
+
3qo2
|
151 |
+
3uii
|
152 |
+
6d1x
|
153 |
+
3juq
|
154 |
+
4qk4
|
155 |
+
6mr5
|
156 |
+
5hjc
|
157 |
+
2p4s
|
158 |
+
2hnc
|
159 |
+
1k4g
|
160 |
+
4g0c
|
161 |
+
2y5g
|
162 |
+
4u3f
|
163 |
+
3tv5
|
164 |
+
1i3z
|
165 |
+
4mw7
|
166 |
+
3n2c
|
167 |
+
6cvw
|
168 |
+
3v66
|
169 |
+
3wzp
|
170 |
+
3s7m
|
171 |
+
5ujv
|
172 |
+
1p06
|
173 |
+
3ipy
|
174 |
+
4wkt
|
175 |
+
4ie0
|
176 |
+
5fot
|
177 |
+
5i59
|
178 |
+
5za9
|
179 |
+
4gii
|
180 |
+
4h2o
|
181 |
+
4yrs
|
182 |
+
5a6h
|
183 |
+
2xo8
|
184 |
+
4e3n
|
185 |
+
4m5k
|
186 |
+
3dga
|
187 |
+
6fse
|
188 |
+
6ck6
|
189 |
+
1sqc
|
190 |
+
4x1r
|
191 |
+
3dnj
|
192 |
+
3rvi
|
193 |
+
2a58
|
194 |
+
4bf6
|
195 |
+
3zlk
|
196 |
+
4mbj
|
197 |
+
4tpm
|
198 |
+
4d8c
|
199 |
+
1ejn
|
200 |
+
4yt6
|
201 |
+
2x7x
|
202 |
+
4qp1
|
203 |
+
4de3
|
204 |
+
5yg4
|
205 |
+
1x7b
|
206 |
+
5n9s
|
207 |
+
2fme
|
208 |
+
1ydt
|
209 |
+
2bdf
|
210 |
+
6baw
|
211 |
+
6fsd
|
212 |
+
2xn3
|
213 |
+
4tk0
|
214 |
+
3q4j
|
215 |
+
1u9l
|
216 |
+
1oqp
|
217 |
+
5htz
|
218 |
+
4glr
|
219 |
+
5kj0
|
220 |
+
5ukl
|
221 |
+
3fun
|
222 |
+
4wk2
|
223 |
+
4ht6
|
224 |
+
5hv1
|
225 |
+
1uze
|
226 |
+
4bcc
|
227 |
+
3ff6
|
228 |
+
5if6
|
229 |
+
1tsm
|
230 |
+
2r59
|
231 |
+
3iqh
|
232 |
+
2v7a
|
233 |
+
5d10
|
234 |
+
5nvh
|
235 |
+
3eqr
|
236 |
+
1jq9
|
237 |
+
1u1b
|
238 |
+
6cer
|
239 |
+
5uq9
|
240 |
+
1u3s
|
241 |
+
5icy
|
242 |
+
3exh
|
243 |
+
2oqs
|
244 |
+
1pzp
|
245 |
+
1d4i
|
246 |
+
4x6p
|
247 |
+
4mb9
|
248 |
+
5emk
|
249 |
+
1iky
|
250 |
+
6b7f
|
251 |
+
3chq
|
252 |
+
3h5s
|
253 |
+
5zmq
|
254 |
+
4ib5
|
255 |
+
2wej
|
256 |
+
6fjm
|
257 |
+
5ewa
|
258 |
+
2igx
|
259 |
+
2z78
|
260 |
+
5lpm
|
261 |
+
4wet
|
262 |
+
3lxl
|
263 |
+
2xba
|
264 |
+
5wbl
|
265 |
+
5zla
|
266 |
+
2x6x
|
267 |
+
4mw9
|
268 |
+
5t2d
|
269 |
+
4j3m
|
270 |
+
4aqh
|
271 |
+
3lbk
|
272 |
+
4djp
|
273 |
+
4odl
|
274 |
+
4x6j
|
275 |
+
1ero
|
276 |
+
5f3t
|
277 |
+
4k3q
|
278 |
+
5ta4
|
279 |
+
1caq
|
280 |
+
2eg7
|
281 |
+
1f73
|
282 |
+
3rxg
|
283 |
+
6ezq
|
284 |
+
1qkt
|
285 |
+
5l3e
|
286 |
+
5c28
|
287 |
+
4pp9
|
288 |
+
4bgk
|
289 |
+
3iaf
|
290 |
+
5vrp
|
291 |
+
5zz4
|
292 |
+
5ur5
|
293 |
+
3ft2
|
294 |
+
5ech
|
295 |
+
4jjq
|
296 |
+
5iz6
|
297 |
+
5dhr
|
298 |
+
4l2g
|
299 |
+
4r17
|
300 |
+
3wk6
|
301 |
+
4h1e
|
302 |
+
2aq9
|
303 |
+
5g1n
|
304 |
+
3zm9
|
305 |
+
5c4l
|
306 |
+
5mfs
|
307 |
+
1fzj
|
308 |
+
2ltw
|
309 |
+
4x7i
|
310 |
+
4c94
|
311 |
+
2cfg
|
312 |
+
2va5
|
313 |
+
3vb6
|
314 |
+
2hob
|
315 |
+
5ah2
|
316 |
+
5syn
|
317 |
+
3g6g
|
318 |
+
3rwj
|
319 |
+
5sz4
|
320 |
+
4f9v
|
321 |
+
5n2d
|
322 |
+
3n9r
|
323 |
+
5ldo
|
324 |
+
3vb7
|
325 |
+
1sqo
|
326 |
+
3drg
|
327 |
+
5j9y
|
328 |
+
6b96
|
329 |
+
4yz9
|
330 |
+
1vcj
|
331 |
+
5epr
|
332 |
+
4tx6
|
333 |
+
3dz6
|
334 |
+
3czv
|
335 |
+
5v49
|
336 |
+
1ahy
|
337 |
+
3wzq
|
338 |
+
1bq4
|
339 |
+
5u8c
|
340 |
+
6bj3
|
341 |
+
2qnb
|
342 |
+
4a9m
|
343 |
+
3d4f
|
344 |
+
5oui
|
345 |
+
5wmg
|
346 |
+
6ma4
|
347 |
+
4x5q
|
348 |
+
5cbr
|
349 |
+
6msy
|
350 |
+
5avi
|
351 |
+
1g3b
|
352 |
+
2wi4
|
353 |
+
3kjn
|
354 |
+
4dhn
|
355 |
+
4o7e
|
356 |
+
5kit
|
357 |
+
5y5t
|
358 |
+
3hfj
|
359 |
+
2qd8
|
360 |
+
5vsj
|
361 |
+
2y2i
|
362 |
+
5m0m
|
363 |
+
3tcp
|
364 |
+
4bhz
|
365 |
+
1jd6
|
366 |
+
5idn
|
367 |
+
4zzx
|
368 |
+
4kn4
|
369 |
+
2a5c
|
370 |
+
6hly
|
371 |
+
1au2
|
372 |
+
4jbo
|
373 |
+
5cgj
|
374 |
+
3ske
|
375 |
+
3lq2
|
376 |
+
4pxm
|
377 |
+
2wxg
|
378 |
+
5tb6
|
379 |
+
2vc7
|
380 |
+
3iw4
|
381 |
+
5hct
|
382 |
+
3skf
|
383 |
+
5lyy
|
384 |
+
3fmz
|
385 |
+
4p5z
|
386 |
+
5ktw
|
387 |
+
6e4w
|
388 |
+
1cx9
|
389 |
+
6em7
|
390 |
+
4mjr
|
391 |
+
4u7t
|
392 |
+
3rde
|
393 |
+
4ux4
|
394 |
+
4i6f
|
395 |
+
3l3x
|
396 |
+
4ie6
|
397 |
+
4j70
|
398 |
+
1jd0
|
399 |
+
4iaw
|
400 |
+
1szm
|
401 |
+
2afw
|
402 |
+
3ess
|
403 |
+
3sap
|
404 |
+
1olx
|
405 |
+
1bzh
|
406 |
+
5hfb
|
407 |
+
4x3h
|
408 |
+
5we9
|
409 |
+
3zsw
|
410 |
+
5ny6
|
411 |
+
1hn2
|
412 |
+
3l3z
|
413 |
+
4qp2
|
414 |
+
1d4p
|
415 |
+
4xkc
|
416 |
+
2is0
|
417 |
+
6c7e
|
418 |
+
5zku
|
419 |
+
4fai
|
420 |
+
6g9a
|
421 |
+
4xu3
|
422 |
+
5dry
|
423 |
+
4d8z
|
424 |
+
3zcz
|
425 |
+
3kbz
|
426 |
+
2y59
|
427 |
+
4nal
|
428 |
+
4rpv
|
429 |
+
4yje
|
430 |
+
3vf8
|
431 |
+
4bqx
|
432 |
+
4z9l
|
433 |
+
4ep2
|
434 |
+
4ylk
|
435 |
+
5mme
|
436 |
+
4dht
|
437 |
+
2uy4
|
438 |
+
6mu3
|
439 |
+
3kx1
|
440 |
+
5o0s
|
441 |
+
4bch
|
442 |
+
5c4k
|
443 |
+
2br1
|
444 |
+
4ddh
|
445 |
+
2f9k
|
446 |
+
2w2i
|
447 |
+
4ogn
|
448 |
+
4up5
|
449 |
+
5o4y
|
450 |
+
5hjd
|
451 |
+
2qw1
|
452 |
+
5y8z
|
453 |
+
4kqr
|
454 |
+
1o2t
|
455 |
+
6e05
|
456 |
+
3u7l
|
457 |
+
2mip
|
458 |
+
3hvg
|
459 |
+
2p59
|
460 |
+
4d3h
|
461 |
+
4pl5
|
462 |
+
3tzd
|
463 |
+
2vnp
|
464 |
+
4e3m
|
465 |
+
3vgc
|
466 |
+
5bqi
|
467 |
+
1b7h
|
468 |
+
1lhu
|
469 |
+
3rlr
|
470 |
+
3h22
|
471 |
+
2wnc
|
472 |
+
2wot
|
473 |
+
5d1t
|
474 |
+
3mo0
|
475 |
+
4wn5
|
476 |
+
3p3u
|
477 |
+
1nfs
|
478 |
+
4e90
|
479 |
+
5aqu
|
480 |
+
1bmq
|
481 |
+
3kwz
|
482 |
+
6f6n
|
483 |
+
4rj5
|
484 |
+
4omd
|
485 |
+
6min
|
486 |
+
1ujj
|
487 |
+
4ppa
|
488 |
+
4uxl
|
489 |
+
5y3n
|
490 |
+
6df2
|
491 |
+
4wvl
|
492 |
+
1xt3
|
493 |
+
5oaj
|
494 |
+
4a9r
|
495 |
+
5mli
|
496 |
+
4p4e
|
497 |
+
3juo
|
498 |
+
1z9g
|
499 |
+
2ykc
|
500 |
+
5a0e
|
501 |
+
3g0w
|
502 |
+
5t9w
|
503 |
+
1sqa
|
504 |
+
3wci
|
505 |
+
1fkw
|
506 |
+
5u4g
|
507 |
+
4mfe
|
508 |
+
4kpx
|
509 |
+
3nti
|
510 |
+
3azb
|
511 |
+
2xog
|
512 |
+
3c3r
|
513 |
+
2buc
|
514 |
+
1hyz
|
515 |
+
4dcd
|
516 |
+
6azl
|
517 |
+
3t3d
|
518 |
+
3q4l
|
519 |
+
4few
|
520 |
+
1q95
|
521 |
+
4u0b
|
522 |
+
3b7u
|
523 |
+
4bo4
|
524 |
+
4o10
|
525 |
+
5wmt
|
526 |
+
5v9t
|
527 |
+
5aok
|
528 |
+
1jtq
|
529 |
+
5uit
|
530 |
+
2vgc
|
531 |
+
2gfd
|
532 |
+
3mna
|
533 |
+
1aqc
|
534 |
+
4xtt
|
535 |
+
4z0d
|
536 |
+
4ty9
|
537 |
+
2yiv
|
538 |
+
2hrp
|
539 |
+
4zh2
|
540 |
+
2z4o
|
541 |
+
1qku
|
542 |
+
2xdw
|
543 |
+
4n7j
|
544 |
+
4yp1
|
545 |
+
3exf
|
546 |
+
4c6z
|
547 |
+
6ccu
|
548 |
+
2wxn
|
549 |
+
1bwb
|
550 |
+
2gvf
|
551 |
+
1hiy
|
552 |
+
5c4t
|
553 |
+
2za5
|
554 |
+
2xkf
|
555 |
+
4q18
|
556 |
+
1o2p
|
557 |
+
5th2
|
558 |
+
4dj7
|
559 |
+
3eyd
|
560 |
+
4j0r
|
561 |
+
2m3o
|
562 |
+
2b53
|
563 |
+
4m3b
|
564 |
+
2izl
|
565 |
+
2vtr
|
566 |
+
2x6d
|
567 |
+
2i0a
|
568 |
+
5ehg
|
569 |
+
6cw4
|
570 |
+
4c37
|
571 |
+
3cwj
|
572 |
+
1azm
|
573 |
+
2qci
|
574 |
+
5sz0
|
575 |
+
2gkl
|
576 |
+
2z4z
|
577 |
+
6awo
|
578 |
+
1v11
|
579 |
+
4l53
|
580 |
+
3p55
|
581 |
+
2ynn
|
582 |
+
2vu3
|
583 |
+
4dli
|
584 |
+
2bcd
|
585 |
+
4l0s
|
586 |
+
4uda
|
587 |
+
3m37
|
588 |
+
5j5t
|
589 |
+
2p16
|
590 |
+
4gh6
|
591 |
+
1mfg
|
592 |
+
3s3i
|
593 |
+
4j73
|
594 |
+
2v5x
|
595 |
+
2h4n
|
596 |
+
4jsz
|
597 |
+
4wk1
|
598 |
+
4igt
|
599 |
+
4k63
|
600 |
+
3qqk
|
601 |
+
16pk
|
602 |
+
5aom
|
603 |
+
1hyv
|
604 |
+
5a3w
|
605 |
+
3veh
|
606 |
+
3g4l
|
607 |
+
2ph8
|
608 |
+
5mkx
|
609 |
+
5c4u
|
610 |
+
4gto
|
611 |
+
3cj5
|
612 |
+
4prj
|
613 |
+
2vd7
|
614 |
+
5duc
|
615 |
+
3odi
|
616 |
+
6bg5
|
617 |
+
1qwu
|
618 |
+
5jn8
|
619 |
+
1v1m
|
620 |
+
1qpe
|
621 |
+
5v3r
|
622 |
+
2wc4
|
623 |
+
2vte
|
624 |
+
1a52
|
625 |
+
4dhq
|
626 |
+
2qta
|
627 |
+
6ccy
|
628 |
+
4jog
|
629 |
+
4bgy
|
630 |
+
5u9i
|
631 |
+
3az9
|
632 |
+
1gt1
|
633 |
+
2jew
|
634 |
+
3pdc
|
635 |
+
1n3i
|
636 |
+
5fyx
|
637 |
+
4f49
|
638 |
+
4nzn
|
639 |
+
6hm2
|
640 |
+
4a4l
|
641 |
+
5xij
|
642 |
+
5vk0
|
643 |
+
4xsx
|
644 |
+
2aj8
|
645 |
+
4odq
|
646 |
+
2n7b
|
647 |
+
4ygf
|
648 |
+
2a4q
|
649 |
+
2jc0
|
650 |
+
4jsa
|
651 |
+
1inq
|
652 |
+
3dc3
|
653 |
+
5tob
|
654 |
+
4urn
|
655 |
+
6bik
|
656 |
+
4ju4
|
657 |
+
5nya
|
658 |
+
5oh2
|
659 |
+
5znr
|
660 |
+
5ct2
|
661 |
+
3u4u
|
662 |
+
4x7h
|
663 |
+
3max
|
664 |
+
3rbm
|
665 |
+
3krj
|
666 |
+
1aj6
|
667 |
+
1pmv
|
668 |
+
5n0e
|
669 |
+
4nhy
|
670 |
+
4oem
|
671 |
+
6fi4
|
672 |
+
4e3j
|
673 |
+
1fq4
|
674 |
+
5myr
|
675 |
+
2hkf
|
676 |
+
1os0
|
677 |
+
3rqg
|
678 |
+
4ivc
|
679 |
+
5c7b
|
680 |
+
3lq4
|
681 |
+
1u6q
|
682 |
+
1qxz
|
683 |
+
1l5r
|
684 |
+
4xxh
|
685 |
+
3m40
|
686 |
+
5or9
|
687 |
+
4okg
|
688 |
+
4d89
|
689 |
+
2gm9
|
690 |
+
5x33
|
691 |
+
4de0
|
692 |
+
4gr8
|
693 |
+
5lz8
|
694 |
+
1p93
|
695 |
+
2brp
|
696 |
+
2gg8
|
697 |
+
6fdt
|
698 |
+
5cxh
|
699 |
+
1jvu
|
700 |
+
3wp1
|
701 |
+
1fzm
|
702 |
+
5cxa
|
703 |
+
2gbg
|
704 |
+
2g78
|
705 |
+
5aml
|
706 |
+
2y34
|
707 |
+
2qnp
|
708 |
+
1v16
|
709 |
+
1njj
|
710 |
+
2a5u
|
711 |
+
4z88
|
712 |
+
4wmx
|
713 |
+
5vo2
|
714 |
+
4fod
|
715 |
+
2pou
|
716 |
+
3jsw
|
717 |
+
2ow2
|
718 |
+
5g3m
|
719 |
+
3odl
|
720 |
+
3o9e
|
721 |
+
3eyh
|
722 |
+
4ej2
|
723 |
+
3c4e
|
724 |
+
4b6f
|
725 |
+
1pl0
|
726 |
+
3pb8
|
727 |
+
6fap
|
728 |
+
4iax
|
729 |
+
2bua
|
730 |
+
6fgg
|
731 |
+
2o4h
|
732 |
+
4uwh
|
733 |
+
5wbf
|
734 |
+
2yxj
|
735 |
+
1ff1
|
736 |
+
2giu
|
737 |
+
1qbt
|
738 |
+
2ovq
|
739 |
+
4bak
|
740 |
+
2y3p
|
741 |
+
2iwu
|
742 |
+
3hvi
|
743 |
+
2w0x
|
744 |
+
3fcl
|
745 |
+
1zpa
|
746 |
+
5czb
|
747 |
+
3t1l
|
748 |
+
2cfd
|
749 |
+
3k3g
|
750 |
+
4cfw
|
751 |
+
2e91
|
752 |
+
5op8
|
753 |
+
3hig
|
754 |
+
6h7y
|
755 |
+
3mtb
|
756 |
+
4eb9
|
757 |
+
4lkg
|
758 |
+
5ehv
|
759 |
+
5ier
|
760 |
+
4ode
|
761 |
+
1xoq
|
762 |
+
5d6p
|
763 |
+
3kwa
|
764 |
+
5np8
|
765 |
+
5v82
|
766 |
+
6ma1
|
767 |
+
3bz3
|
768 |
+
3myq
|
769 |
+
4j0s
|
770 |
+
4f4p
|
771 |
+
4lh6
|
772 |
+
1uef
|
773 |
+
4j3d
|
774 |
+
4yx4
|
775 |
+
4amx
|
776 |
+
4ptg
|
777 |
+
2c97
|
778 |
+
4ec4
|
779 |
+
4r1v
|
780 |
+
1zc9
|
781 |
+
4nuf
|
782 |
+
3g2u
|
783 |
+
6hlx
|
784 |
+
5vij
|
785 |
+
2x4o
|
786 |
+
6hlz
|
787 |
+
4lkj
|
788 |
+
3s75
|
789 |
+
2gz8
|
790 |
+
1gvk
|
791 |
+
2yhd
|
792 |
+
3hqz
|
793 |
+
3pb7
|
794 |
+
1thr
|
795 |
+
4ris
|
796 |
+
5twh
|
797 |
+
4gql
|
798 |
+
3n3l
|
799 |
+
3acx
|
800 |
+
5yvx
|
801 |
+
3gy2
|
802 |
+
1xmu
|
803 |
+
5l6p
|
804 |
+
5l8n
|
805 |
+
4msn
|
806 |
+
4rz1
|
807 |
+
3f66
|
808 |
+
3ucj
|
809 |
+
5hcl
|
810 |
+
1t1r
|
811 |
+
3kce
|
812 |
+
3u15
|
813 |
+
1wbg
|
814 |
+
5khi
|
815 |
+
3er5
|
816 |
+
4qew
|
817 |
+
5mft
|
818 |
+
6eqp
|
819 |
+
5gsw
|
820 |
+
2qd7
|
821 |
+
4cli
|
822 |
+
3f9w
|
823 |
+
3msc
|
824 |
+
1jgl
|
825 |
+
3kid
|
826 |
+
1ymx
|
827 |
+
1ui0
|
828 |
+
3d1f
|
829 |
+
1pxl
|
830 |
+
5kos
|
831 |
+
3vzd
|
832 |
+
5fcz
|
833 |
+
3ara
|
834 |
+
4li6
|
835 |
+
5ks7
|
836 |
+
4wym
|
837 |
+
5j7q
|
838 |
+
4qsh
|
839 |
+
2ce9
|
840 |
+
5vqz
|
841 |
+
3o2m
|
842 |
+
4bcm
|
843 |
+
5orx
|
844 |
+
1i41
|
845 |
+
3c5u
|
846 |
+
4kai
|
847 |
+
6gjy
|
848 |
+
4tsz
|
849 |
+
5o0e
|
850 |
+
6drt
|
851 |
+
1y57
|
852 |
+
3kqb
|
853 |
+
3jup
|
854 |
+
5ork
|
855 |
+
3ikc
|
856 |
+
3gwu
|
857 |
+
4wke
|
858 |
+
4x7l
|
859 |
+
3lp1
|
860 |
+
5ivy
|
861 |
+
3f16
|
862 |
+
4c36
|
863 |
+
1w2x
|
864 |
+
2d06
|
865 |
+
1hbj
|
866 |
+
1ols
|
867 |
+
1iup
|
868 |
+
5aix
|
869 |
+
1ydd
|
870 |
+
5w4r
|
871 |
+
3h23
|
872 |
+
3rj7
|
873 |
+
4ish
|
874 |
+
1ebw
|
875 |
+
1fcy
|
876 |
+
1d09
|
877 |
+
5hdv
|
878 |
+
4x1n
|
879 |
+
5boj
|
880 |
+
2xn7
|
881 |
+
4b6s
|
882 |
+
3f82
|
883 |
+
4clj
|
884 |
+
4zzz
|
885 |
+
5j5d
|
886 |
+
2vts
|
887 |
+
1k08
|
888 |
+
3u3f
|
889 |
+
4jk6
|
890 |
+
4csy
|
891 |
+
6hth
|
892 |
+
2mnz
|
893 |
+
2vpg
|
894 |
+
2qd6
|
895 |
+
4jkw
|
896 |
+
3ml5
|
897 |
+
1ih0
|
898 |
+
4at5
|
899 |
+
5dgu
|
900 |
+
4g31
|
901 |
+
5n0d
|
902 |
+
5aa9
|
903 |
+
4u4s
|
904 |
+
5oa6
|
905 |
+
2wzm
|
906 |
+
4b4q
|
907 |
+
6fi1
|
908 |
+
6chn
|
909 |
+
1z4u
|
910 |
+
5aa8
|
911 |
+
1lpk
|
912 |
+
3cib
|
913 |
+
5d75
|
914 |
+
5x4o
|
915 |
+
1ydb
|
916 |
+
5dhq
|
917 |
+
5t28
|
918 |
+
4zz0
|
919 |
+
3evf
|
920 |
+
5vyy
|
921 |
+
6eip
|
922 |
+
1q63
|
923 |
+
3ldw
|
924 |
+
5tq4
|
925 |
+
5uxf
|
926 |
+
2j7x
|
927 |
+
4kil
|
928 |
+
1yda
|
929 |
+
3bc4
|
930 |
+
2ew5
|
931 |
+
6ee3
|
932 |
+
4yrr
|
933 |
+
3wax
|
934 |
+
3bzf
|
935 |
+
5ody
|
936 |
+
1k06
|
937 |
+
4j84
|
938 |
+
5l6h
|
939 |
+
5eok
|
940 |
+
5nne
|
941 |
+
5m6m
|
942 |
+
2a4r
|
943 |
+
3p1d
|
944 |
+
2ayp
|
945 |
+
3iux
|
946 |
+
4b0g
|
947 |
+
1jr1
|
948 |
+
4qo9
|
949 |
+
4bh4
|
950 |
+
4xt9
|
951 |
+
2ok1
|
952 |
+
2r7g
|
953 |
+
4uib
|
954 |
+
5mmn
|
955 |
+
5akj
|
956 |
+
3hs4
|
957 |
+
5wpb
|
958 |
+
6e5x
|
959 |
+
5vnd
|
960 |
+
5evd
|
961 |
+
5wlg
|
962 |
+
5l4m
|
963 |
+
4kiu
|
964 |
+
4own
|
965 |
+
5oh9
|
966 |
+
6arv
|
967 |
+
1xr9
|
968 |
+
4hv7
|
data/splits/timesplit_test
ADDED
@@ -0,0 +1,363 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
6qqw
|
2 |
+
6d08
|
3 |
+
6jap
|
4 |
+
6np2
|
5 |
+
6uvp
|
6 |
+
6oxq
|
7 |
+
6jsn
|
8 |
+
6hzb
|
9 |
+
6qrc
|
10 |
+
6oio
|
11 |
+
6jag
|
12 |
+
6moa
|
13 |
+
6hld
|
14 |
+
6i9a
|
15 |
+
6e4c
|
16 |
+
6g24
|
17 |
+
6jb4
|
18 |
+
6s55
|
19 |
+
6seo
|
20 |
+
6dyz
|
21 |
+
5zk5
|
22 |
+
6jid
|
23 |
+
5ze6
|
24 |
+
6qlu
|
25 |
+
6a6k
|
26 |
+
6qgf
|
27 |
+
6e3z
|
28 |
+
6te6
|
29 |
+
6pka
|
30 |
+
6g2o
|
31 |
+
6jsf
|
32 |
+
5zxk
|
33 |
+
6qxd
|
34 |
+
6n97
|
35 |
+
6jt3
|
36 |
+
6qtr
|
37 |
+
6oy1
|
38 |
+
6n96
|
39 |
+
6qzh
|
40 |
+
6qqz
|
41 |
+
6qmt
|
42 |
+
6ibx
|
43 |
+
6hmt
|
44 |
+
5zk7
|
45 |
+
6k3l
|
46 |
+
6cjs
|
47 |
+
6n9l
|
48 |
+
6ibz
|
49 |
+
6ott
|
50 |
+
6gge
|
51 |
+
6hot
|
52 |
+
6e3p
|
53 |
+
6md6
|
54 |
+
6hlb
|
55 |
+
6fe5
|
56 |
+
6uwp
|
57 |
+
6npp
|
58 |
+
6g2f
|
59 |
+
6mo7
|
60 |
+
6bqd
|
61 |
+
6nsv
|
62 |
+
6i76
|
63 |
+
6n53
|
64 |
+
6g2c
|
65 |
+
6eeb
|
66 |
+
6n0m
|
67 |
+
6uvy
|
68 |
+
6ovz
|
69 |
+
6olx
|
70 |
+
6v5l
|
71 |
+
6hhg
|
72 |
+
5zcu
|
73 |
+
6dz2
|
74 |
+
6mjq
|
75 |
+
6efk
|
76 |
+
6s9w
|
77 |
+
6gdy
|
78 |
+
6kqi
|
79 |
+
6ueg
|
80 |
+
6oxt
|
81 |
+
6oy0
|
82 |
+
6qr7
|
83 |
+
6i41
|
84 |
+
6cyg
|
85 |
+
6qmr
|
86 |
+
6g27
|
87 |
+
6ggb
|
88 |
+
6g3c
|
89 |
+
6n4e
|
90 |
+
6fcj
|
91 |
+
6quv
|
92 |
+
6iql
|
93 |
+
6i74
|
94 |
+
6qr4
|
95 |
+
6rnu
|
96 |
+
6jib
|
97 |
+
6izq
|
98 |
+
6qw8
|
99 |
+
6qto
|
100 |
+
6qrd
|
101 |
+
6hza
|
102 |
+
6e5s
|
103 |
+
6dz3
|
104 |
+
6e6w
|
105 |
+
6cyh
|
106 |
+
5zlf
|
107 |
+
6om4
|
108 |
+
6gga
|
109 |
+
6pgp
|
110 |
+
6qqv
|
111 |
+
6qtq
|
112 |
+
6gj6
|
113 |
+
6os5
|
114 |
+
6s07
|
115 |
+
6i77
|
116 |
+
6hhj
|
117 |
+
6ahs
|
118 |
+
6oxx
|
119 |
+
6mjj
|
120 |
+
6hor
|
121 |
+
6jb0
|
122 |
+
6i68
|
123 |
+
6pz4
|
124 |
+
6mhb
|
125 |
+
6uim
|
126 |
+
6jsg
|
127 |
+
6i78
|
128 |
+
6oxy
|
129 |
+
6gbw
|
130 |
+
6mo0
|
131 |
+
6ggf
|
132 |
+
6qge
|
133 |
+
6cjr
|
134 |
+
6oxp
|
135 |
+
6d07
|
136 |
+
6i63
|
137 |
+
6ten
|
138 |
+
6uii
|
139 |
+
6qlr
|
140 |
+
6sen
|
141 |
+
6oxv
|
142 |
+
6g2b
|
143 |
+
5zr3
|
144 |
+
6kjf
|
145 |
+
6qr9
|
146 |
+
6g9f
|
147 |
+
6e6v
|
148 |
+
5zk9
|
149 |
+
6pnn
|
150 |
+
6nri
|
151 |
+
6uwv
|
152 |
+
6ooz
|
153 |
+
6npi
|
154 |
+
6oip
|
155 |
+
6miv
|
156 |
+
6s57
|
157 |
+
6p8x
|
158 |
+
6hoq
|
159 |
+
6qts
|
160 |
+
6ggd
|
161 |
+
6pnm
|
162 |
+
6oy2
|
163 |
+
6oi8
|
164 |
+
6mhd
|
165 |
+
6agt
|
166 |
+
6i5p
|
167 |
+
6hhr
|
168 |
+
6p8z
|
169 |
+
6c85
|
170 |
+
6g5u
|
171 |
+
6j06
|
172 |
+
6qsz
|
173 |
+
6jbb
|
174 |
+
6hhp
|
175 |
+
6np5
|
176 |
+
6nlj
|
177 |
+
6qlp
|
178 |
+
6n94
|
179 |
+
6e13
|
180 |
+
6qls
|
181 |
+
6uil
|
182 |
+
6st3
|
183 |
+
6n92
|
184 |
+
6s56
|
185 |
+
6hzd
|
186 |
+
6uhv
|
187 |
+
6k05
|
188 |
+
6q36
|
189 |
+
6ic0
|
190 |
+
6hhi
|
191 |
+
6e3m
|
192 |
+
6qtx
|
193 |
+
6jse
|
194 |
+
5zjy
|
195 |
+
6o3y
|
196 |
+
6rpg
|
197 |
+
6rr0
|
198 |
+
6gzy
|
199 |
+
6qlt
|
200 |
+
6ufo
|
201 |
+
6o0h
|
202 |
+
6o3x
|
203 |
+
5zjz
|
204 |
+
6i8t
|
205 |
+
6ooy
|
206 |
+
6oiq
|
207 |
+
6od6
|
208 |
+
6nrh
|
209 |
+
6qra
|
210 |
+
6hhh
|
211 |
+
6m7h
|
212 |
+
6ufn
|
213 |
+
6qr0
|
214 |
+
6o5u
|
215 |
+
6h14
|
216 |
+
6jwa
|
217 |
+
6ny0
|
218 |
+
6jan
|
219 |
+
6ftf
|
220 |
+
6oxw
|
221 |
+
6jon
|
222 |
+
6cf7
|
223 |
+
6rtn
|
224 |
+
6jsz
|
225 |
+
6o9c
|
226 |
+
6mo8
|
227 |
+
6qln
|
228 |
+
6qqu
|
229 |
+
6i66
|
230 |
+
6mja
|
231 |
+
6gwe
|
232 |
+
6d3z
|
233 |
+
6oxr
|
234 |
+
6r4k
|
235 |
+
6hle
|
236 |
+
6h9v
|
237 |
+
6hou
|
238 |
+
6nv9
|
239 |
+
6py0
|
240 |
+
6qlq
|
241 |
+
6nv7
|
242 |
+
6n4b
|
243 |
+
6jaq
|
244 |
+
6i8m
|
245 |
+
6dz0
|
246 |
+
6oxs
|
247 |
+
6k2n
|
248 |
+
6cjj
|
249 |
+
6ffg
|
250 |
+
6a73
|
251 |
+
6qqt
|
252 |
+
6a1c
|
253 |
+
6oxu
|
254 |
+
6qre
|
255 |
+
6qtw
|
256 |
+
6np4
|
257 |
+
6hv2
|
258 |
+
6n55
|
259 |
+
6e3o
|
260 |
+
6kjd
|
261 |
+
6sfc
|
262 |
+
6qi7
|
263 |
+
6hzc
|
264 |
+
6k04
|
265 |
+
6op0
|
266 |
+
6q38
|
267 |
+
6n8x
|
268 |
+
6np3
|
269 |
+
6uvv
|
270 |
+
6pgo
|
271 |
+
6jbe
|
272 |
+
6i75
|
273 |
+
6qqq
|
274 |
+
6i62
|
275 |
+
6j9y
|
276 |
+
6g29
|
277 |
+
6h7d
|
278 |
+
6mo9
|
279 |
+
6jao
|
280 |
+
6jmf
|
281 |
+
6hmy
|
282 |
+
6qfe
|
283 |
+
5zml
|
284 |
+
6i65
|
285 |
+
6e7m
|
286 |
+
6i61
|
287 |
+
6rz6
|
288 |
+
6qtm
|
289 |
+
6qlo
|
290 |
+
6oie
|
291 |
+
6miy
|
292 |
+
6nrf
|
293 |
+
6gj5
|
294 |
+
6jad
|
295 |
+
6mj4
|
296 |
+
6h12
|
297 |
+
6d3y
|
298 |
+
6qr2
|
299 |
+
6qxa
|
300 |
+
6o9b
|
301 |
+
6ckl
|
302 |
+
6oir
|
303 |
+
6d40
|
304 |
+
6e6j
|
305 |
+
6i7a
|
306 |
+
6g25
|
307 |
+
6oin
|
308 |
+
6jam
|
309 |
+
6oxz
|
310 |
+
6hop
|
311 |
+
6rot
|
312 |
+
6uhu
|
313 |
+
6mji
|
314 |
+
6nrj
|
315 |
+
6nt2
|
316 |
+
6op9
|
317 |
+
6pno
|
318 |
+
6e4v
|
319 |
+
6k1s
|
320 |
+
6a87
|
321 |
+
6oim
|
322 |
+
6cjp
|
323 |
+
6pyb
|
324 |
+
6h13
|
325 |
+
6qrf
|
326 |
+
6mhc
|
327 |
+
6j9w
|
328 |
+
6nrg
|
329 |
+
6fff
|
330 |
+
6n93
|
331 |
+
6jut
|
332 |
+
6g2e
|
333 |
+
6nd3
|
334 |
+
6os6
|
335 |
+
6dql
|
336 |
+
6inz
|
337 |
+
6i67
|
338 |
+
6quw
|
339 |
+
6qwi
|
340 |
+
6npm
|
341 |
+
6i64
|
342 |
+
6e3n
|
343 |
+
6qrg
|
344 |
+
6nxz
|
345 |
+
6iby
|
346 |
+
6gj7
|
347 |
+
6qr3
|
348 |
+
6qr1
|
349 |
+
6s9x
|
350 |
+
6q4q
|
351 |
+
6hbn
|
352 |
+
6nw3
|
353 |
+
6tel
|
354 |
+
6p8y
|
355 |
+
6d5w
|
356 |
+
6t6a
|
357 |
+
6o5g
|
358 |
+
6r7d
|
359 |
+
6pya
|
360 |
+
6ffe
|
361 |
+
6d3x
|
362 |
+
6gj8
|
363 |
+
6mo2
|
data/splits/timesplit_test_no_rec_overlap
ADDED
@@ -0,0 +1,144 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
6qqw
|
2 |
+
6jap
|
3 |
+
6np2
|
4 |
+
6qrc
|
5 |
+
6oio
|
6 |
+
6jag
|
7 |
+
6i9a
|
8 |
+
6jb4
|
9 |
+
6seo
|
10 |
+
6jid
|
11 |
+
5ze6
|
12 |
+
6pka
|
13 |
+
6n97
|
14 |
+
6qtr
|
15 |
+
6n96
|
16 |
+
6qzh
|
17 |
+
6qqz
|
18 |
+
6k3l
|
19 |
+
6cjs
|
20 |
+
6n9l
|
21 |
+
6ott
|
22 |
+
6npp
|
23 |
+
6nsv
|
24 |
+
6n53
|
25 |
+
6eeb
|
26 |
+
6n0m
|
27 |
+
6ovz
|
28 |
+
5zcu
|
29 |
+
6mjq
|
30 |
+
6efk
|
31 |
+
6gdy
|
32 |
+
6kqi
|
33 |
+
6ueg
|
34 |
+
6qr7
|
35 |
+
6g3c
|
36 |
+
6iql
|
37 |
+
6qr4
|
38 |
+
6jib
|
39 |
+
6qto
|
40 |
+
6qrd
|
41 |
+
6e5s
|
42 |
+
5zlf
|
43 |
+
6om4
|
44 |
+
6qqv
|
45 |
+
6qtq
|
46 |
+
6os5
|
47 |
+
6s07
|
48 |
+
6mjj
|
49 |
+
6jb0
|
50 |
+
6uim
|
51 |
+
6mo0
|
52 |
+
6cjr
|
53 |
+
6uii
|
54 |
+
6sen
|
55 |
+
6kjf
|
56 |
+
6qr9
|
57 |
+
6g9f
|
58 |
+
6npi
|
59 |
+
6oip
|
60 |
+
6miv
|
61 |
+
6qts
|
62 |
+
6oi8
|
63 |
+
6c85
|
64 |
+
6qsz
|
65 |
+
6jbb
|
66 |
+
6np5
|
67 |
+
6nlj
|
68 |
+
6n94
|
69 |
+
6e13
|
70 |
+
6uil
|
71 |
+
6n92
|
72 |
+
6uhv
|
73 |
+
6q36
|
74 |
+
6qtx
|
75 |
+
6rr0
|
76 |
+
6ufo
|
77 |
+
6oiq
|
78 |
+
6qra
|
79 |
+
6m7h
|
80 |
+
6ufn
|
81 |
+
6qr0
|
82 |
+
6o5u
|
83 |
+
6ny0
|
84 |
+
6jan
|
85 |
+
6ftf
|
86 |
+
6jon
|
87 |
+
6cf7
|
88 |
+
6o9c
|
89 |
+
6qqu
|
90 |
+
6mja
|
91 |
+
6r4k
|
92 |
+
6h9v
|
93 |
+
6py0
|
94 |
+
6jaq
|
95 |
+
6k2n
|
96 |
+
6cjj
|
97 |
+
6a73
|
98 |
+
6qqt
|
99 |
+
6qre
|
100 |
+
6qtw
|
101 |
+
6np4
|
102 |
+
6n55
|
103 |
+
6kjd
|
104 |
+
6np3
|
105 |
+
6jbe
|
106 |
+
6qqq
|
107 |
+
6j9y
|
108 |
+
6h7d
|
109 |
+
6jao
|
110 |
+
6e7m
|
111 |
+
6rz6
|
112 |
+
6qtm
|
113 |
+
6miy
|
114 |
+
6jad
|
115 |
+
6mj4
|
116 |
+
6qr2
|
117 |
+
6qxa
|
118 |
+
6o9b
|
119 |
+
6ckl
|
120 |
+
6oir
|
121 |
+
6oin
|
122 |
+
6jam
|
123 |
+
6uhu
|
124 |
+
6mji
|
125 |
+
6nt2
|
126 |
+
6op9
|
127 |
+
6e4v
|
128 |
+
6a87
|
129 |
+
6cjp
|
130 |
+
6qrf
|
131 |
+
6j9w
|
132 |
+
6n93
|
133 |
+
6nd3
|
134 |
+
6os6
|
135 |
+
6dql
|
136 |
+
6qwi
|
137 |
+
6npm
|
138 |
+
6qrg
|
139 |
+
6nxz
|
140 |
+
6qr3
|
141 |
+
6qr1
|
142 |
+
6o5g
|
143 |
+
6r7d
|
144 |
+
6mo2
|
datasets/__init__.py
ADDED
File without changes
|
datasets/conformer_matching.py
ADDED
@@ -0,0 +1,196 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import copy, time
|
2 |
+
import numpy as np
|
3 |
+
from collections import defaultdict
|
4 |
+
from rdkit import Chem, RDLogger
|
5 |
+
from rdkit.Chem import AllChem, rdMolTransforms
|
6 |
+
from rdkit import Geometry
|
7 |
+
import networkx as nx
|
8 |
+
from scipy.optimize import differential_evolution
|
9 |
+
|
10 |
+
RDLogger.DisableLog('rdApp.*')
|
11 |
+
|
12 |
+
"""
|
13 |
+
Conformer matching routines from Torsional Diffusion
|
14 |
+
"""
|
15 |
+
|
16 |
+
def GetDihedral(conf, atom_idx):
|
17 |
+
return rdMolTransforms.GetDihedralRad(conf, atom_idx[0], atom_idx[1], atom_idx[2], atom_idx[3])
|
18 |
+
|
19 |
+
|
20 |
+
def SetDihedral(conf, atom_idx, new_vale):
|
21 |
+
rdMolTransforms.SetDihedralRad(conf, atom_idx[0], atom_idx[1], atom_idx[2], atom_idx[3], new_vale)
|
22 |
+
|
23 |
+
|
24 |
+
def apply_changes(mol, values, rotable_bonds, conf_id):
|
25 |
+
opt_mol = copy.copy(mol)
|
26 |
+
[SetDihedral(opt_mol.GetConformer(conf_id), rotable_bonds[r], values[r]) for r in range(len(rotable_bonds))]
|
27 |
+
return opt_mol
|
28 |
+
|
29 |
+
|
30 |
+
def optimize_rotatable_bonds(mol, true_mol, rotable_bonds, probe_id=-1, ref_id=-1, seed=0, popsize=15, maxiter=500,
|
31 |
+
mutation=(0.5, 1), recombination=0.8):
|
32 |
+
opt = OptimizeConformer(mol, true_mol, rotable_bonds, seed=seed, probe_id=probe_id, ref_id=ref_id)
|
33 |
+
max_bound = [np.pi] * len(opt.rotable_bonds)
|
34 |
+
min_bound = [-np.pi] * len(opt.rotable_bonds)
|
35 |
+
bounds = (min_bound, max_bound)
|
36 |
+
bounds = list(zip(bounds[0], bounds[1]))
|
37 |
+
|
38 |
+
# Optimize conformations
|
39 |
+
result = differential_evolution(opt.score_conformation, bounds,
|
40 |
+
maxiter=maxiter, popsize=popsize,
|
41 |
+
mutation=mutation, recombination=recombination, disp=False, seed=seed)
|
42 |
+
opt_mol = apply_changes(opt.mol, result['x'], opt.rotable_bonds, conf_id=probe_id)
|
43 |
+
|
44 |
+
return opt_mol
|
45 |
+
|
46 |
+
|
47 |
+
class OptimizeConformer:
|
48 |
+
def __init__(self, mol, true_mol, rotable_bonds, probe_id=-1, ref_id=-1, seed=None):
|
49 |
+
super(OptimizeConformer, self).__init__()
|
50 |
+
if seed:
|
51 |
+
np.random.seed(seed)
|
52 |
+
self.rotable_bonds = rotable_bonds
|
53 |
+
self.mol = mol
|
54 |
+
self.true_mol = true_mol
|
55 |
+
self.probe_id = probe_id
|
56 |
+
self.ref_id = ref_id
|
57 |
+
|
58 |
+
def score_conformation(self, values):
|
59 |
+
for i, r in enumerate(self.rotable_bonds):
|
60 |
+
SetDihedral(self.mol.GetConformer(self.probe_id), r, values[i])
|
61 |
+
return RMSD(self.mol, self.true_mol, self.probe_id, self.ref_id)
|
62 |
+
|
63 |
+
|
64 |
+
def get_torsion_angles(mol):
|
65 |
+
torsions_list = []
|
66 |
+
G = nx.Graph()
|
67 |
+
for i, atom in enumerate(mol.GetAtoms()):
|
68 |
+
G.add_node(i)
|
69 |
+
nodes = set(G.nodes())
|
70 |
+
for bond in mol.GetBonds():
|
71 |
+
start, end = bond.GetBeginAtomIdx(), bond.GetEndAtomIdx()
|
72 |
+
G.add_edge(start, end)
|
73 |
+
for e in G.edges():
|
74 |
+
G2 = copy.deepcopy(G)
|
75 |
+
G2.remove_edge(*e)
|
76 |
+
if nx.is_connected(G2): continue
|
77 |
+
l = list(sorted(nx.connected_components(G2), key=len)[0])
|
78 |
+
if len(l) < 2: continue
|
79 |
+
n0 = list(G2.neighbors(e[0]))
|
80 |
+
n1 = list(G2.neighbors(e[1]))
|
81 |
+
torsions_list.append(
|
82 |
+
(n0[0], e[0], e[1], n1[0])
|
83 |
+
)
|
84 |
+
return torsions_list
|
85 |
+
|
86 |
+
|
87 |
+
# GeoMol
|
88 |
+
def get_torsions(mol_list):
|
89 |
+
print('USING GEOMOL GET TORSIONS FUNCTION')
|
90 |
+
atom_counter = 0
|
91 |
+
torsionList = []
|
92 |
+
for m in mol_list:
|
93 |
+
torsionSmarts = '[!$(*#*)&!D1]-&!@[!$(*#*)&!D1]'
|
94 |
+
torsionQuery = Chem.MolFromSmarts(torsionSmarts)
|
95 |
+
matches = m.GetSubstructMatches(torsionQuery)
|
96 |
+
for match in matches:
|
97 |
+
idx2 = match[0]
|
98 |
+
idx3 = match[1]
|
99 |
+
bond = m.GetBondBetweenAtoms(idx2, idx3)
|
100 |
+
jAtom = m.GetAtomWithIdx(idx2)
|
101 |
+
kAtom = m.GetAtomWithIdx(idx3)
|
102 |
+
for b1 in jAtom.GetBonds():
|
103 |
+
if (b1.GetIdx() == bond.GetIdx()):
|
104 |
+
continue
|
105 |
+
idx1 = b1.GetOtherAtomIdx(idx2)
|
106 |
+
for b2 in kAtom.GetBonds():
|
107 |
+
if ((b2.GetIdx() == bond.GetIdx())
|
108 |
+
or (b2.GetIdx() == b1.GetIdx())):
|
109 |
+
continue
|
110 |
+
idx4 = b2.GetOtherAtomIdx(idx3)
|
111 |
+
# skip 3-membered rings
|
112 |
+
if (idx4 == idx1):
|
113 |
+
continue
|
114 |
+
if m.GetAtomWithIdx(idx4).IsInRing():
|
115 |
+
torsionList.append(
|
116 |
+
(idx4 + atom_counter, idx3 + atom_counter, idx2 + atom_counter, idx1 + atom_counter))
|
117 |
+
break
|
118 |
+
else:
|
119 |
+
torsionList.append(
|
120 |
+
(idx1 + atom_counter, idx2 + atom_counter, idx3 + atom_counter, idx4 + atom_counter))
|
121 |
+
break
|
122 |
+
break
|
123 |
+
|
124 |
+
atom_counter += m.GetNumAtoms()
|
125 |
+
return torsionList
|
126 |
+
|
127 |
+
|
128 |
+
def A_transpose_matrix(alpha):
|
129 |
+
return np.array([[np.cos(alpha), np.sin(alpha)], [-np.sin(alpha), np.cos(alpha)]], dtype=np.double)
|
130 |
+
|
131 |
+
|
132 |
+
def S_vec(alpha):
|
133 |
+
return np.array([[np.cos(alpha)], [np.sin(alpha)]], dtype=np.double)
|
134 |
+
|
135 |
+
|
136 |
+
def GetDihedralFromPointCloud(Z, atom_idx):
|
137 |
+
p = Z[list(atom_idx)]
|
138 |
+
b = p[:-1] - p[1:]
|
139 |
+
b[0] *= -1
|
140 |
+
v = np.array([v - (v.dot(b[1]) / b[1].dot(b[1])) * b[1] for v in [b[0], b[2]]])
|
141 |
+
# Normalize vectors
|
142 |
+
v /= np.sqrt(np.einsum('...i,...i', v, v)).reshape(-1, 1)
|
143 |
+
b1 = b[1] / np.linalg.norm(b[1])
|
144 |
+
x = np.dot(v[0], v[1])
|
145 |
+
m = np.cross(v[0], b1)
|
146 |
+
y = np.dot(m, v[1])
|
147 |
+
return np.arctan2(y, x)
|
148 |
+
|
149 |
+
|
150 |
+
def get_dihedral_vonMises(mol, conf, atom_idx, Z):
|
151 |
+
Z = np.array(Z)
|
152 |
+
v = np.zeros((2, 1))
|
153 |
+
iAtom = mol.GetAtomWithIdx(atom_idx[1])
|
154 |
+
jAtom = mol.GetAtomWithIdx(atom_idx[2])
|
155 |
+
k_0 = atom_idx[0]
|
156 |
+
i = atom_idx[1]
|
157 |
+
j = atom_idx[2]
|
158 |
+
l_0 = atom_idx[3]
|
159 |
+
for b1 in iAtom.GetBonds():
|
160 |
+
k = b1.GetOtherAtomIdx(i)
|
161 |
+
if k == j:
|
162 |
+
continue
|
163 |
+
for b2 in jAtom.GetBonds():
|
164 |
+
l = b2.GetOtherAtomIdx(j)
|
165 |
+
if l == i:
|
166 |
+
continue
|
167 |
+
assert k != l
|
168 |
+
s_star = S_vec(GetDihedralFromPointCloud(Z, (k, i, j, l)))
|
169 |
+
a_mat = A_transpose_matrix(GetDihedral(conf, (k, i, j, k_0)) + GetDihedral(conf, (l_0, i, j, l)))
|
170 |
+
v = v + np.matmul(a_mat, s_star)
|
171 |
+
v = v / np.linalg.norm(v)
|
172 |
+
v = v.reshape(-1)
|
173 |
+
return np.arctan2(v[1], v[0])
|
174 |
+
|
175 |
+
|
176 |
+
def get_von_mises_rms(mol, mol_rdkit, rotable_bonds, conf_id):
|
177 |
+
new_dihedrals = np.zeros(len(rotable_bonds))
|
178 |
+
for idx, r in enumerate(rotable_bonds):
|
179 |
+
new_dihedrals[idx] = get_dihedral_vonMises(mol_rdkit,
|
180 |
+
mol_rdkit.GetConformer(conf_id), r,
|
181 |
+
mol.GetConformer().GetPositions())
|
182 |
+
mol_rdkit = apply_changes(mol_rdkit, new_dihedrals, rotable_bonds, conf_id)
|
183 |
+
return RMSD(mol_rdkit, mol, conf_id)
|
184 |
+
|
185 |
+
|
186 |
+
def mmff_func(mol):
|
187 |
+
mol_mmff = copy.deepcopy(mol)
|
188 |
+
AllChem.MMFFOptimizeMoleculeConfs(mol_mmff, mmffVariant='MMFF94s')
|
189 |
+
for i in range(mol.GetNumConformers()):
|
190 |
+
coords = mol_mmff.GetConformers()[i].GetPositions()
|
191 |
+
for j in range(coords.shape[0]):
|
192 |
+
mol.GetConformer(i).SetAtomPosition(j,
|
193 |
+
Geometry.Point3D(*coords[j]))
|
194 |
+
|
195 |
+
|
196 |
+
RMSD = AllChem.AlignMol
|
datasets/esm_embedding_preparation.py
ADDED
@@ -0,0 +1,88 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import os
|
2 |
+
from argparse import FileType, ArgumentParser
|
3 |
+
|
4 |
+
import numpy as np
|
5 |
+
import pandas as pd
|
6 |
+
from Bio.PDB import PDBParser
|
7 |
+
from Bio.Seq import Seq
|
8 |
+
from Bio.SeqRecord import SeqRecord
|
9 |
+
from tqdm import tqdm
|
10 |
+
from Bio import SeqIO
|
11 |
+
|
12 |
+
|
13 |
+
|
14 |
+
def esm_embedding_prep(out_file, protein_path):
|
15 |
+
biopython_parser = PDBParser()
|
16 |
+
|
17 |
+
three_to_one = {
|
18 |
+
"ALA": "A",
|
19 |
+
"ARG": "R",
|
20 |
+
"ASN": "N",
|
21 |
+
"ASP": "D",
|
22 |
+
"CYS": "C",
|
23 |
+
"GLN": "Q",
|
24 |
+
"GLU": "E",
|
25 |
+
"GLY": "G",
|
26 |
+
"HIS": "H",
|
27 |
+
"ILE": "I",
|
28 |
+
"LEU": "L",
|
29 |
+
"LYS": "K",
|
30 |
+
"MET": "M",
|
31 |
+
"MSE": "M", # MSE this is almost the same AA as MET. The sulfur is just replaced by Selen
|
32 |
+
"PHE": "F",
|
33 |
+
"PRO": "P",
|
34 |
+
"PYL": "O",
|
35 |
+
"SER": "S",
|
36 |
+
"SEC": "U",
|
37 |
+
"THR": "T",
|
38 |
+
"TRP": "W",
|
39 |
+
"TYR": "Y",
|
40 |
+
"VAL": "V",
|
41 |
+
"ASX": "B",
|
42 |
+
"GLX": "Z",
|
43 |
+
"XAA": "X",
|
44 |
+
"XLE": "J",
|
45 |
+
}
|
46 |
+
|
47 |
+
file_paths = [protein_path]
|
48 |
+
sequences = []
|
49 |
+
ids = []
|
50 |
+
for file_path in tqdm(file_paths):
|
51 |
+
structure = biopython_parser.get_structure("random_id", file_path)
|
52 |
+
structure = structure[0]
|
53 |
+
for i, chain in enumerate(structure):
|
54 |
+
seq = ""
|
55 |
+
for res_idx, residue in enumerate(chain):
|
56 |
+
if residue.get_resname() == "HOH":
|
57 |
+
continue
|
58 |
+
residue_coords = []
|
59 |
+
c_alpha, n, c = None, None, None
|
60 |
+
for atom in residue:
|
61 |
+
if atom.name == "CA":
|
62 |
+
c_alpha = list(atom.get_vector())
|
63 |
+
if atom.name == "N":
|
64 |
+
n = list(atom.get_vector())
|
65 |
+
if atom.name == "C":
|
66 |
+
c = list(atom.get_vector())
|
67 |
+
if (
|
68 |
+
c_alpha != None and n != None and c != None
|
69 |
+
): # only append residue if it is an amino acid
|
70 |
+
try:
|
71 |
+
seq += three_to_one[residue.get_resname()]
|
72 |
+
except Exception as e:
|
73 |
+
seq += "-"
|
74 |
+
print(
|
75 |
+
"encountered unknown AA: ",
|
76 |
+
residue.get_resname(),
|
77 |
+
" in the complex ",
|
78 |
+
file_path,
|
79 |
+
". Replacing it with a dash - .",
|
80 |
+
)
|
81 |
+
sequences.append(seq)
|
82 |
+
ids.append(f"{os.path.basename(file_path)}_chain_{i}")
|
83 |
+
records = []
|
84 |
+
for (index, seq) in zip(ids, sequences):
|
85 |
+
record = SeqRecord(Seq(seq), str(index))
|
86 |
+
record.description = ""
|
87 |
+
records.append(record)
|
88 |
+
SeqIO.write(records, out_file, "fasta")
|
datasets/esm_embeddings_to_pt.py
ADDED
@@ -0,0 +1,17 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
|
2 |
+
import os
|
3 |
+
from argparse import ArgumentParser
|
4 |
+
|
5 |
+
import torch
|
6 |
+
from tqdm import tqdm
|
7 |
+
|
8 |
+
|
9 |
+
parser = ArgumentParser()
|
10 |
+
parser.add_argument('--esm_embeddings_path', type=str, default='data/embeddings_output', help='')
|
11 |
+
parser.add_argument('--output_path', type=str, default='data/esm2_3billion_embeddings.pt', help='')
|
12 |
+
args = parser.parse_args()
|
13 |
+
|
14 |
+
dict = {}
|
15 |
+
for filename in tqdm(os.listdir(args.esm_embeddings_path)):
|
16 |
+
dict[filename.split('.')[0]] = torch.load(os.path.join(args.esm_embeddings_path,filename))['representations'][33]
|
17 |
+
torch.save(dict,args.output_path)
|
datasets/pdbbind.py
ADDED
@@ -0,0 +1,705 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import binascii
|
2 |
+
import glob
|
3 |
+
import hashlib
|
4 |
+
import os
|
5 |
+
import pickle
|
6 |
+
from collections import defaultdict
|
7 |
+
from multiprocessing import Pool
|
8 |
+
import random
|
9 |
+
import copy
|
10 |
+
|
11 |
+
import numpy as np
|
12 |
+
import torch
|
13 |
+
from rdkit.Chem import MolToSmiles, MolFromSmiles, AddHs
|
14 |
+
from torch_geometric.data import Dataset, HeteroData
|
15 |
+
from torch_geometric.loader import DataLoader, DataListLoader
|
16 |
+
from torch_geometric.transforms import BaseTransform
|
17 |
+
from tqdm import tqdm
|
18 |
+
|
19 |
+
from datasets.process_mols import (
|
20 |
+
read_molecule,
|
21 |
+
get_rec_graph,
|
22 |
+
generate_conformer,
|
23 |
+
get_lig_graph_with_matching,
|
24 |
+
extract_receptor_structure,
|
25 |
+
parse_receptor,
|
26 |
+
parse_pdb_from_path,
|
27 |
+
)
|
28 |
+
from utils.diffusion_utils import modify_conformer, set_time
|
29 |
+
from utils.utils import read_strings_from_txt
|
30 |
+
from utils import so3, torus
|
31 |
+
|
32 |
+
|
33 |
+
class NoiseTransform(BaseTransform):
|
34 |
+
def __init__(self, t_to_sigma, no_torsion, all_atom):
|
35 |
+
self.t_to_sigma = t_to_sigma
|
36 |
+
self.no_torsion = no_torsion
|
37 |
+
self.all_atom = all_atom
|
38 |
+
|
39 |
+
def __call__(self, data):
|
40 |
+
t = np.random.uniform()
|
41 |
+
t_tr, t_rot, t_tor = t, t, t
|
42 |
+
return self.apply_noise(data, t_tr, t_rot, t_tor)
|
43 |
+
|
44 |
+
def apply_noise(
|
45 |
+
self,
|
46 |
+
data,
|
47 |
+
t_tr,
|
48 |
+
t_rot,
|
49 |
+
t_tor,
|
50 |
+
tr_update=None,
|
51 |
+
rot_update=None,
|
52 |
+
torsion_updates=None,
|
53 |
+
):
|
54 |
+
if not torch.is_tensor(data["ligand"].pos):
|
55 |
+
data["ligand"].pos = random.choice(data["ligand"].pos)
|
56 |
+
|
57 |
+
tr_sigma, rot_sigma, tor_sigma = self.t_to_sigma(t_tr, t_rot, t_tor)
|
58 |
+
set_time(data, t_tr, t_rot, t_tor, 1, self.all_atom, device=None)
|
59 |
+
|
60 |
+
tr_update = (
|
61 |
+
torch.normal(mean=0, std=tr_sigma, size=(1, 3))
|
62 |
+
if tr_update is None
|
63 |
+
else tr_update
|
64 |
+
)
|
65 |
+
rot_update = so3.sample_vec(eps=rot_sigma) if rot_update is None else rot_update
|
66 |
+
torsion_updates = (
|
67 |
+
np.random.normal(
|
68 |
+
loc=0.0, scale=tor_sigma, size=data["ligand"].edge_mask.sum()
|
69 |
+
)
|
70 |
+
if torsion_updates is None
|
71 |
+
else torsion_updates
|
72 |
+
)
|
73 |
+
torsion_updates = None if self.no_torsion else torsion_updates
|
74 |
+
modify_conformer(
|
75 |
+
data, tr_update, torch.from_numpy(rot_update).float(), torsion_updates
|
76 |
+
)
|
77 |
+
|
78 |
+
data.tr_score = -tr_update / tr_sigma**2
|
79 |
+
data.rot_score = (
|
80 |
+
torch.from_numpy(so3.score_vec(vec=rot_update, eps=rot_sigma))
|
81 |
+
.float()
|
82 |
+
.unsqueeze(0)
|
83 |
+
)
|
84 |
+
data.tor_score = (
|
85 |
+
None
|
86 |
+
if self.no_torsion
|
87 |
+
else torch.from_numpy(torus.score(torsion_updates, tor_sigma)).float()
|
88 |
+
)
|
89 |
+
data.tor_sigma_edge = (
|
90 |
+
None
|
91 |
+
if self.no_torsion
|
92 |
+
else np.ones(data["ligand"].edge_mask.sum()) * tor_sigma
|
93 |
+
)
|
94 |
+
return data
|
95 |
+
|
96 |
+
|
97 |
+
class PDBBind(Dataset):
|
98 |
+
def __init__(
|
99 |
+
self,
|
100 |
+
root,
|
101 |
+
transform=None,
|
102 |
+
cache_path="data/cache",
|
103 |
+
split_path="data/",
|
104 |
+
limit_complexes=0,
|
105 |
+
receptor_radius=30,
|
106 |
+
num_workers=1,
|
107 |
+
c_alpha_max_neighbors=None,
|
108 |
+
popsize=15,
|
109 |
+
maxiter=15,
|
110 |
+
matching=True,
|
111 |
+
keep_original=False,
|
112 |
+
max_lig_size=None,
|
113 |
+
remove_hs=False,
|
114 |
+
num_conformers=1,
|
115 |
+
all_atoms=False,
|
116 |
+
atom_radius=5,
|
117 |
+
atom_max_neighbors=None,
|
118 |
+
esm_embeddings_path=None,
|
119 |
+
require_ligand=False,
|
120 |
+
ligands_list=None,
|
121 |
+
protein_path_list=None,
|
122 |
+
ligand_descriptions=None,
|
123 |
+
keep_local_structures=False,
|
124 |
+
):
|
125 |
+
|
126 |
+
super(PDBBind, self).__init__(root, transform)
|
127 |
+
self.pdbbind_dir = root
|
128 |
+
self.max_lig_size = max_lig_size
|
129 |
+
self.split_path = split_path
|
130 |
+
self.limit_complexes = limit_complexes
|
131 |
+
self.receptor_radius = receptor_radius
|
132 |
+
self.num_workers = num_workers
|
133 |
+
self.c_alpha_max_neighbors = c_alpha_max_neighbors
|
134 |
+
self.remove_hs = remove_hs
|
135 |
+
self.esm_embeddings_path = esm_embeddings_path
|
136 |
+
self.require_ligand = require_ligand
|
137 |
+
self.protein_path_list = protein_path_list
|
138 |
+
self.ligand_descriptions = ligand_descriptions
|
139 |
+
self.keep_local_structures = keep_local_structures
|
140 |
+
if (
|
141 |
+
matching
|
142 |
+
or protein_path_list is not None
|
143 |
+
and ligand_descriptions is not None
|
144 |
+
):
|
145 |
+
cache_path += "_torsion"
|
146 |
+
if all_atoms:
|
147 |
+
cache_path += "_allatoms"
|
148 |
+
self.full_cache_path = os.path.join(
|
149 |
+
cache_path,
|
150 |
+
f"limit{self.limit_complexes}"
|
151 |
+
f"_INDEX{os.path.splitext(os.path.basename(self.split_path))[0]}"
|
152 |
+
f"_maxLigSize{self.max_lig_size}_H{int(not self.remove_hs)}"
|
153 |
+
f"_recRad{self.receptor_radius}_recMax{self.c_alpha_max_neighbors}"
|
154 |
+
+ (
|
155 |
+
""
|
156 |
+
if not all_atoms
|
157 |
+
else f"_atomRad{atom_radius}_atomMax{atom_max_neighbors}"
|
158 |
+
)
|
159 |
+
+ ("" if not matching or num_conformers == 1 else f"_confs{num_conformers}")
|
160 |
+
+ ("" if self.esm_embeddings_path is None else f"_esmEmbeddings")
|
161 |
+
+ ("" if not keep_local_structures else f"_keptLocalStruct")
|
162 |
+
+ (
|
163 |
+
""
|
164 |
+
if protein_path_list is None or ligand_descriptions is None
|
165 |
+
else str(
|
166 |
+
binascii.crc32(
|
167 |
+
"".join(ligand_descriptions + protein_path_list).encode()
|
168 |
+
)
|
169 |
+
)
|
170 |
+
),
|
171 |
+
)
|
172 |
+
self.popsize, self.maxiter = popsize, maxiter
|
173 |
+
self.matching, self.keep_original = matching, keep_original
|
174 |
+
self.num_conformers = num_conformers
|
175 |
+
self.all_atoms = all_atoms
|
176 |
+
self.atom_radius, self.atom_max_neighbors = atom_radius, atom_max_neighbors
|
177 |
+
if not os.path.exists(
|
178 |
+
os.path.join(self.full_cache_path, "heterographs.pkl")
|
179 |
+
) or (
|
180 |
+
require_ligand
|
181 |
+
and not os.path.exists(
|
182 |
+
os.path.join(self.full_cache_path, "rdkit_ligands.pkl")
|
183 |
+
)
|
184 |
+
):
|
185 |
+
os.makedirs(self.full_cache_path, exist_ok=True)
|
186 |
+
if protein_path_list is None or ligand_descriptions is None:
|
187 |
+
self.preprocessing()
|
188 |
+
else:
|
189 |
+
self.inference_preprocessing()
|
190 |
+
|
191 |
+
print(
|
192 |
+
"loading data from memory: ",
|
193 |
+
os.path.join(self.full_cache_path, "heterographs.pkl"),
|
194 |
+
)
|
195 |
+
with open(os.path.join(self.full_cache_path, "heterographs.pkl"), "rb") as f:
|
196 |
+
self.complex_graphs = pickle.load(f)
|
197 |
+
if require_ligand:
|
198 |
+
with open(
|
199 |
+
os.path.join(self.full_cache_path, "rdkit_ligands.pkl"), "rb"
|
200 |
+
) as f:
|
201 |
+
self.rdkit_ligands = pickle.load(f)
|
202 |
+
|
203 |
+
print_statistics(self.complex_graphs)
|
204 |
+
|
205 |
+
def len(self):
|
206 |
+
return len(self.complex_graphs)
|
207 |
+
|
208 |
+
def get(self, idx):
|
209 |
+
if self.require_ligand:
|
210 |
+
complex_graph = copy.deepcopy(self.complex_graphs[idx])
|
211 |
+
complex_graph.mol = copy.deepcopy(self.rdkit_ligands[idx])
|
212 |
+
return complex_graph
|
213 |
+
else:
|
214 |
+
return copy.deepcopy(self.complex_graphs[idx])
|
215 |
+
|
216 |
+
def preprocessing(self):
|
217 |
+
print(
|
218 |
+
f"Processing complexes from [{self.split_path}] and saving it to [{self.full_cache_path}]"
|
219 |
+
)
|
220 |
+
|
221 |
+
complex_names_all = read_strings_from_txt(self.split_path)
|
222 |
+
if self.limit_complexes is not None and self.limit_complexes != 0:
|
223 |
+
complex_names_all = complex_names_all[: self.limit_complexes]
|
224 |
+
print(f"Loading {len(complex_names_all)} complexes.")
|
225 |
+
|
226 |
+
if self.esm_embeddings_path is not None:
|
227 |
+
id_to_embeddings = torch.load(self.esm_embeddings_path)
|
228 |
+
chain_embeddings_dictlist = defaultdict(list)
|
229 |
+
for key, embedding in id_to_embeddings.items():
|
230 |
+
key_name = key.split("_")[0]
|
231 |
+
if key_name in complex_names_all:
|
232 |
+
chain_embeddings_dictlist[key_name].append(embedding)
|
233 |
+
lm_embeddings_chains_all = []
|
234 |
+
for name in complex_names_all:
|
235 |
+
lm_embeddings_chains_all.append(chain_embeddings_dictlist[name])
|
236 |
+
else:
|
237 |
+
lm_embeddings_chains_all = [None] * len(complex_names_all)
|
238 |
+
|
239 |
+
if self.num_workers > 1:
|
240 |
+
# running preprocessing in parallel on multiple workers and saving the progress every 1000 complexes
|
241 |
+
for i in range(len(complex_names_all) // 1000 + 1):
|
242 |
+
if os.path.exists(
|
243 |
+
os.path.join(self.full_cache_path, f"heterographs{i}.pkl")
|
244 |
+
):
|
245 |
+
continue
|
246 |
+
complex_names = complex_names_all[1000 * i : 1000 * (i + 1)]
|
247 |
+
lm_embeddings_chains = lm_embeddings_chains_all[
|
248 |
+
1000 * i : 1000 * (i + 1)
|
249 |
+
]
|
250 |
+
complex_graphs, rdkit_ligands = [], []
|
251 |
+
if self.num_workers > 1:
|
252 |
+
p = Pool(self.num_workers, maxtasksperchild=1)
|
253 |
+
p.__enter__()
|
254 |
+
with tqdm(
|
255 |
+
total=len(complex_names),
|
256 |
+
desc=f"loading complexes {i}/{len(complex_names_all)//1000+1}",
|
257 |
+
) as pbar:
|
258 |
+
map_fn = p.imap_unordered if self.num_workers > 1 else map
|
259 |
+
for t in map_fn(
|
260 |
+
self.get_complex,
|
261 |
+
zip(
|
262 |
+
complex_names,
|
263 |
+
lm_embeddings_chains,
|
264 |
+
[None] * len(complex_names),
|
265 |
+
[None] * len(complex_names),
|
266 |
+
),
|
267 |
+
):
|
268 |
+
complex_graphs.extend(t[0])
|
269 |
+
rdkit_ligands.extend(t[1])
|
270 |
+
pbar.update()
|
271 |
+
if self.num_workers > 1:
|
272 |
+
p.__exit__(None, None, None)
|
273 |
+
|
274 |
+
with open(
|
275 |
+
os.path.join(self.full_cache_path, f"heterographs{i}.pkl"), "wb"
|
276 |
+
) as f:
|
277 |
+
pickle.dump((complex_graphs), f)
|
278 |
+
with open(
|
279 |
+
os.path.join(self.full_cache_path, f"rdkit_ligands{i}.pkl"), "wb"
|
280 |
+
) as f:
|
281 |
+
pickle.dump((rdkit_ligands), f)
|
282 |
+
|
283 |
+
complex_graphs_all = []
|
284 |
+
for i in range(len(complex_names_all) // 1000 + 1):
|
285 |
+
with open(
|
286 |
+
os.path.join(self.full_cache_path, f"heterographs{i}.pkl"), "rb"
|
287 |
+
) as f:
|
288 |
+
l = pickle.load(f)
|
289 |
+
complex_graphs_all.extend(l)
|
290 |
+
with open(
|
291 |
+
os.path.join(self.full_cache_path, f"heterographs.pkl"), "wb"
|
292 |
+
) as f:
|
293 |
+
pickle.dump((complex_graphs_all), f)
|
294 |
+
|
295 |
+
rdkit_ligands_all = []
|
296 |
+
for i in range(len(complex_names_all) // 1000 + 1):
|
297 |
+
with open(
|
298 |
+
os.path.join(self.full_cache_path, f"rdkit_ligands{i}.pkl"), "rb"
|
299 |
+
) as f:
|
300 |
+
l = pickle.load(f)
|
301 |
+
rdkit_ligands_all.extend(l)
|
302 |
+
with open(
|
303 |
+
os.path.join(self.full_cache_path, f"rdkit_ligands.pkl"), "wb"
|
304 |
+
) as f:
|
305 |
+
pickle.dump((rdkit_ligands_all), f)
|
306 |
+
else:
|
307 |
+
complex_graphs, rdkit_ligands = [], []
|
308 |
+
with tqdm(total=len(complex_names_all), desc="loading complexes") as pbar:
|
309 |
+
for t in map(
|
310 |
+
self.get_complex,
|
311 |
+
zip(
|
312 |
+
complex_names_all,
|
313 |
+
lm_embeddings_chains_all,
|
314 |
+
[None] * len(complex_names_all),
|
315 |
+
[None] * len(complex_names_all),
|
316 |
+
),
|
317 |
+
):
|
318 |
+
complex_graphs.extend(t[0])
|
319 |
+
rdkit_ligands.extend(t[1])
|
320 |
+
pbar.update()
|
321 |
+
with open(
|
322 |
+
os.path.join(self.full_cache_path, "heterographs.pkl"), "wb"
|
323 |
+
) as f:
|
324 |
+
pickle.dump((complex_graphs), f)
|
325 |
+
with open(
|
326 |
+
os.path.join(self.full_cache_path, "rdkit_ligands.pkl"), "wb"
|
327 |
+
) as f:
|
328 |
+
pickle.dump((rdkit_ligands), f)
|
329 |
+
|
330 |
+
def inference_preprocessing(self):
|
331 |
+
ligands_list = []
|
332 |
+
print("Reading molecules and generating local structures with RDKit")
|
333 |
+
for ligand_description in tqdm(self.ligand_descriptions):
|
334 |
+
mol = MolFromSmiles(ligand_description) # check if it is a smiles or a path
|
335 |
+
if mol is not None:
|
336 |
+
mol = AddHs(mol)
|
337 |
+
generate_conformer(mol)
|
338 |
+
ligands_list.append(mol)
|
339 |
+
else:
|
340 |
+
mol = read_molecule(ligand_description, remove_hs=False, sanitize=True)
|
341 |
+
if not self.keep_local_structures:
|
342 |
+
mol.RemoveAllConformers()
|
343 |
+
mol = AddHs(mol)
|
344 |
+
generate_conformer(mol)
|
345 |
+
ligands_list.append(mol)
|
346 |
+
|
347 |
+
if self.esm_embeddings_path is not None:
|
348 |
+
print("Reading language model embeddings.")
|
349 |
+
lm_embeddings_chains_all = []
|
350 |
+
if not os.path.exists(self.esm_embeddings_path):
|
351 |
+
raise Exception(
|
352 |
+
"ESM embeddings path does not exist: ", self.esm_embeddings_path
|
353 |
+
)
|
354 |
+
for protein_path in self.protein_path_list:
|
355 |
+
embeddings_paths = sorted(
|
356 |
+
glob.glob(
|
357 |
+
os.path.join(
|
358 |
+
self.esm_embeddings_path, os.path.basename(protein_path)
|
359 |
+
)
|
360 |
+
+ "*"
|
361 |
+
)
|
362 |
+
)
|
363 |
+
lm_embeddings_chains = []
|
364 |
+
for embeddings_path in embeddings_paths:
|
365 |
+
lm_embeddings_chains.append(
|
366 |
+
torch.load(embeddings_path)["representations"][33]
|
367 |
+
)
|
368 |
+
lm_embeddings_chains_all.append(lm_embeddings_chains)
|
369 |
+
else:
|
370 |
+
lm_embeddings_chains_all = [None] * len(self.protein_path_list)
|
371 |
+
|
372 |
+
print("Generating graphs for ligands and proteins")
|
373 |
+
if self.num_workers > 1:
|
374 |
+
# running preprocessing in parallel on multiple workers and saving the progress every 1000 complexes
|
375 |
+
for i in range(len(self.protein_path_list) // 1000 + 1):
|
376 |
+
if os.path.exists(
|
377 |
+
os.path.join(self.full_cache_path, f"heterographs{i}.pkl")
|
378 |
+
):
|
379 |
+
continue
|
380 |
+
protein_paths_chunk = self.protein_path_list[1000 * i : 1000 * (i + 1)]
|
381 |
+
ligand_description_chunk = self.ligand_descriptions[
|
382 |
+
1000 * i : 1000 * (i + 1)
|
383 |
+
]
|
384 |
+
ligands_chunk = ligands_list[1000 * i : 1000 * (i + 1)]
|
385 |
+
lm_embeddings_chains = lm_embeddings_chains_all[
|
386 |
+
1000 * i : 1000 * (i + 1)
|
387 |
+
]
|
388 |
+
complex_graphs, rdkit_ligands = [], []
|
389 |
+
if self.num_workers > 1:
|
390 |
+
p = Pool(self.num_workers, maxtasksperchild=1)
|
391 |
+
p.__enter__()
|
392 |
+
with tqdm(
|
393 |
+
total=len(protein_paths_chunk),
|
394 |
+
desc=f"loading complexes {i}/{len(protein_paths_chunk)//1000+1}",
|
395 |
+
) as pbar:
|
396 |
+
map_fn = p.imap_unordered if self.num_workers > 1 else map
|
397 |
+
for t in map_fn(
|
398 |
+
self.get_complex,
|
399 |
+
zip(
|
400 |
+
protein_paths_chunk,
|
401 |
+
lm_embeddings_chains,
|
402 |
+
ligands_chunk,
|
403 |
+
ligand_description_chunk,
|
404 |
+
),
|
405 |
+
):
|
406 |
+
complex_graphs.extend(t[0])
|
407 |
+
rdkit_ligands.extend(t[1])
|
408 |
+
pbar.update()
|
409 |
+
if self.num_workers > 1:
|
410 |
+
p.__exit__(None, None, None)
|
411 |
+
|
412 |
+
with open(
|
413 |
+
os.path.join(self.full_cache_path, f"heterographs{i}.pkl"), "wb"
|
414 |
+
) as f:
|
415 |
+
pickle.dump((complex_graphs), f)
|
416 |
+
with open(
|
417 |
+
os.path.join(self.full_cache_path, f"rdkit_ligands{i}.pkl"), "wb"
|
418 |
+
) as f:
|
419 |
+
pickle.dump((rdkit_ligands), f)
|
420 |
+
|
421 |
+
complex_graphs_all = []
|
422 |
+
for i in range(len(self.protein_path_list) // 1000 + 1):
|
423 |
+
with open(
|
424 |
+
os.path.join(self.full_cache_path, f"heterographs{i}.pkl"), "rb"
|
425 |
+
) as f:
|
426 |
+
l = pickle.load(f)
|
427 |
+
complex_graphs_all.extend(l)
|
428 |
+
with open(
|
429 |
+
os.path.join(self.full_cache_path, f"heterographs.pkl"), "wb"
|
430 |
+
) as f:
|
431 |
+
pickle.dump((complex_graphs_all), f)
|
432 |
+
|
433 |
+
rdkit_ligands_all = []
|
434 |
+
for i in range(len(self.protein_path_list) // 1000 + 1):
|
435 |
+
with open(
|
436 |
+
os.path.join(self.full_cache_path, f"rdkit_ligands{i}.pkl"), "rb"
|
437 |
+
) as f:
|
438 |
+
l = pickle.load(f)
|
439 |
+
rdkit_ligands_all.extend(l)
|
440 |
+
with open(
|
441 |
+
os.path.join(self.full_cache_path, f"rdkit_ligands.pkl"), "wb"
|
442 |
+
) as f:
|
443 |
+
pickle.dump((rdkit_ligands_all), f)
|
444 |
+
else:
|
445 |
+
complex_graphs, rdkit_ligands = [], []
|
446 |
+
with tqdm(
|
447 |
+
total=len(self.protein_path_list), desc="loading complexes"
|
448 |
+
) as pbar:
|
449 |
+
for t in map(
|
450 |
+
self.get_complex,
|
451 |
+
zip(
|
452 |
+
self.protein_path_list,
|
453 |
+
lm_embeddings_chains_all,
|
454 |
+
ligands_list,
|
455 |
+
self.ligand_descriptions,
|
456 |
+
),
|
457 |
+
):
|
458 |
+
complex_graphs.extend(t[0])
|
459 |
+
rdkit_ligands.extend(t[1])
|
460 |
+
pbar.update()
|
461 |
+
with open(
|
462 |
+
os.path.join(self.full_cache_path, "heterographs.pkl"), "wb"
|
463 |
+
) as f:
|
464 |
+
pickle.dump((complex_graphs), f)
|
465 |
+
with open(
|
466 |
+
os.path.join(self.full_cache_path, "rdkit_ligands.pkl"), "wb"
|
467 |
+
) as f:
|
468 |
+
pickle.dump((rdkit_ligands), f)
|
469 |
+
|
470 |
+
def get_complex(self, par):
|
471 |
+
name, lm_embedding_chains, ligand, ligand_description = par
|
472 |
+
if not os.path.exists(os.path.join(self.pdbbind_dir, name)) and ligand is None:
|
473 |
+
print("Folder not found", name)
|
474 |
+
return [], []
|
475 |
+
|
476 |
+
if ligand is not None:
|
477 |
+
rec_model = parse_pdb_from_path(name)
|
478 |
+
name = f"{name}____{ligand_description}"
|
479 |
+
ligs = [ligand]
|
480 |
+
else:
|
481 |
+
try:
|
482 |
+
rec_model = parse_receptor(name, self.pdbbind_dir)
|
483 |
+
except Exception as e:
|
484 |
+
print(f"Skipping {name} because of the error:")
|
485 |
+
print(e)
|
486 |
+
return [], []
|
487 |
+
|
488 |
+
ligs = read_mols(self.pdbbind_dir, name, remove_hs=False)
|
489 |
+
complex_graphs = []
|
490 |
+
for i, lig in enumerate(ligs):
|
491 |
+
if (
|
492 |
+
self.max_lig_size is not None
|
493 |
+
and lig.GetNumHeavyAtoms() > self.max_lig_size
|
494 |
+
):
|
495 |
+
print(
|
496 |
+
f"Ligand with {lig.GetNumHeavyAtoms()} heavy atoms is larger than max_lig_size {self.max_lig_size}. Not including {name} in preprocessed data."
|
497 |
+
)
|
498 |
+
continue
|
499 |
+
complex_graph = HeteroData()
|
500 |
+
complex_graph["name"] = name
|
501 |
+
try:
|
502 |
+
get_lig_graph_with_matching(
|
503 |
+
lig,
|
504 |
+
complex_graph,
|
505 |
+
self.popsize,
|
506 |
+
self.maxiter,
|
507 |
+
self.matching,
|
508 |
+
self.keep_original,
|
509 |
+
self.num_conformers,
|
510 |
+
remove_hs=self.remove_hs,
|
511 |
+
)
|
512 |
+
print(lm_embedding_chains)
|
513 |
+
(
|
514 |
+
rec,
|
515 |
+
rec_coords,
|
516 |
+
c_alpha_coords,
|
517 |
+
n_coords,
|
518 |
+
c_coords,
|
519 |
+
lm_embeddings,
|
520 |
+
) = extract_receptor_structure(
|
521 |
+
copy.deepcopy(rec_model),
|
522 |
+
lig,
|
523 |
+
lm_embedding_chains=lm_embedding_chains,
|
524 |
+
)
|
525 |
+
if lm_embeddings is not None and len(c_alpha_coords) != len(
|
526 |
+
lm_embeddings
|
527 |
+
):
|
528 |
+
print(
|
529 |
+
f"LM embeddings for complex {name} did not have the right length for the protein. Skipping {name}."
|
530 |
+
)
|
531 |
+
continue
|
532 |
+
|
533 |
+
get_rec_graph(
|
534 |
+
rec,
|
535 |
+
rec_coords,
|
536 |
+
c_alpha_coords,
|
537 |
+
n_coords,
|
538 |
+
c_coords,
|
539 |
+
complex_graph,
|
540 |
+
rec_radius=self.receptor_radius,
|
541 |
+
c_alpha_max_neighbors=self.c_alpha_max_neighbors,
|
542 |
+
all_atoms=self.all_atoms,
|
543 |
+
atom_radius=self.atom_radius,
|
544 |
+
atom_max_neighbors=self.atom_max_neighbors,
|
545 |
+
remove_hs=self.remove_hs,
|
546 |
+
lm_embeddings=lm_embeddings,
|
547 |
+
)
|
548 |
+
|
549 |
+
except Exception as e:
|
550 |
+
print(f"Skipping {name} because of the error:")
|
551 |
+
print(e)
|
552 |
+
raise e
|
553 |
+
continue
|
554 |
+
|
555 |
+
protein_center = torch.mean(
|
556 |
+
complex_graph["receptor"].pos, dim=0, keepdim=True
|
557 |
+
)
|
558 |
+
complex_graph["receptor"].pos -= protein_center
|
559 |
+
if self.all_atoms:
|
560 |
+
complex_graph["atom"].pos -= protein_center
|
561 |
+
|
562 |
+
if (not self.matching) or self.num_conformers == 1:
|
563 |
+
complex_graph["ligand"].pos -= protein_center
|
564 |
+
else:
|
565 |
+
for p in complex_graph["ligand"].pos:
|
566 |
+
p -= protein_center
|
567 |
+
|
568 |
+
complex_graph.original_center = protein_center
|
569 |
+
complex_graphs.append(complex_graph)
|
570 |
+
return complex_graphs, ligs
|
571 |
+
|
572 |
+
|
573 |
+
def print_statistics(complex_graphs):
|
574 |
+
statistics = ([], [], [], [])
|
575 |
+
|
576 |
+
for complex_graph in complex_graphs:
|
577 |
+
lig_pos = (
|
578 |
+
complex_graph["ligand"].pos
|
579 |
+
if torch.is_tensor(complex_graph["ligand"].pos)
|
580 |
+
else complex_graph["ligand"].pos[0]
|
581 |
+
)
|
582 |
+
radius_protein = torch.max(
|
583 |
+
torch.linalg.vector_norm(complex_graph["receptor"].pos, dim=1)
|
584 |
+
)
|
585 |
+
molecule_center = torch.mean(lig_pos, dim=0)
|
586 |
+
radius_molecule = torch.max(
|
587 |
+
torch.linalg.vector_norm(lig_pos - molecule_center.unsqueeze(0), dim=1)
|
588 |
+
)
|
589 |
+
distance_center = torch.linalg.vector_norm(molecule_center)
|
590 |
+
statistics[0].append(radius_protein)
|
591 |
+
statistics[1].append(radius_molecule)
|
592 |
+
statistics[2].append(distance_center)
|
593 |
+
if "rmsd_matching" in complex_graph:
|
594 |
+
statistics[3].append(complex_graph.rmsd_matching)
|
595 |
+
else:
|
596 |
+
statistics[3].append(0)
|
597 |
+
|
598 |
+
name = [
|
599 |
+
"radius protein",
|
600 |
+
"radius molecule",
|
601 |
+
"distance protein-mol",
|
602 |
+
"rmsd matching",
|
603 |
+
]
|
604 |
+
print("Number of complexes: ", len(complex_graphs))
|
605 |
+
for i in range(4):
|
606 |
+
array = np.asarray(statistics[i])
|
607 |
+
print(
|
608 |
+
f"{name[i]}: mean {np.mean(array)}, std {np.std(array)}, max {np.max(array)}"
|
609 |
+
)
|
610 |
+
|
611 |
+
|
612 |
+
def construct_loader(args, t_to_sigma):
|
613 |
+
transform = NoiseTransform(
|
614 |
+
t_to_sigma=t_to_sigma, no_torsion=args.no_torsion, all_atom=args.all_atoms
|
615 |
+
)
|
616 |
+
|
617 |
+
common_args = {
|
618 |
+
"transform": transform,
|
619 |
+
"root": args.data_dir,
|
620 |
+
"limit_complexes": args.limit_complexes,
|
621 |
+
"receptor_radius": args.receptor_radius,
|
622 |
+
"c_alpha_max_neighbors": args.c_alpha_max_neighbors,
|
623 |
+
"remove_hs": args.remove_hs,
|
624 |
+
"max_lig_size": args.max_lig_size,
|
625 |
+
"matching": not args.no_torsion,
|
626 |
+
"popsize": args.matching_popsize,
|
627 |
+
"maxiter": args.matching_maxiter,
|
628 |
+
"num_workers": args.num_workers,
|
629 |
+
"all_atoms": args.all_atoms,
|
630 |
+
"atom_radius": args.atom_radius,
|
631 |
+
"atom_max_neighbors": args.atom_max_neighbors,
|
632 |
+
"esm_embeddings_path": args.esm_embeddings_path,
|
633 |
+
}
|
634 |
+
|
635 |
+
train_dataset = PDBBind(
|
636 |
+
cache_path=args.cache_path,
|
637 |
+
split_path=args.split_train,
|
638 |
+
keep_original=True,
|
639 |
+
num_conformers=args.num_conformers,
|
640 |
+
**common_args,
|
641 |
+
)
|
642 |
+
val_dataset = PDBBind(
|
643 |
+
cache_path=args.cache_path,
|
644 |
+
split_path=args.split_val,
|
645 |
+
keep_original=True,
|
646 |
+
**common_args,
|
647 |
+
)
|
648 |
+
|
649 |
+
loader_class = DataListLoader if torch.cuda.is_available() else DataLoader
|
650 |
+
train_loader = loader_class(
|
651 |
+
dataset=train_dataset,
|
652 |
+
batch_size=args.batch_size,
|
653 |
+
num_workers=args.num_dataloader_workers,
|
654 |
+
shuffle=True,
|
655 |
+
pin_memory=args.pin_memory,
|
656 |
+
)
|
657 |
+
val_loader = loader_class(
|
658 |
+
dataset=val_dataset,
|
659 |
+
batch_size=args.batch_size,
|
660 |
+
num_workers=args.num_dataloader_workers,
|
661 |
+
shuffle=True,
|
662 |
+
pin_memory=args.pin_memory,
|
663 |
+
)
|
664 |
+
|
665 |
+
return train_loader, val_loader
|
666 |
+
|
667 |
+
|
668 |
+
def read_mol(pdbbind_dir, name, remove_hs=False):
|
669 |
+
lig = read_molecule(
|
670 |
+
os.path.join(pdbbind_dir, name, f"{name}_ligand.sdf"),
|
671 |
+
remove_hs=remove_hs,
|
672 |
+
sanitize=True,
|
673 |
+
)
|
674 |
+
if lig is None: # read mol2 file if sdf file cannot be sanitized
|
675 |
+
lig = read_molecule(
|
676 |
+
os.path.join(pdbbind_dir, name, f"{name}_ligand.mol2"),
|
677 |
+
remove_hs=remove_hs,
|
678 |
+
sanitize=True,
|
679 |
+
)
|
680 |
+
return lig
|
681 |
+
|
682 |
+
|
683 |
+
def read_mols(pdbbind_dir, name, remove_hs=False):
|
684 |
+
ligs = []
|
685 |
+
for file in os.listdir(os.path.join(pdbbind_dir, name)):
|
686 |
+
if file.endswith(".sdf") and "rdkit" not in file:
|
687 |
+
lig = read_molecule(
|
688 |
+
os.path.join(pdbbind_dir, name, file),
|
689 |
+
remove_hs=remove_hs,
|
690 |
+
sanitize=True,
|
691 |
+
)
|
692 |
+
if lig is None and os.path.exists(
|
693 |
+
os.path.join(pdbbind_dir, name, file[:-4] + ".mol2")
|
694 |
+
): # read mol2 file if sdf file cannot be sanitized
|
695 |
+
print(
|
696 |
+
"Using the .sdf file failed. We found a .mol2 file instead and are trying to use that."
|
697 |
+
)
|
698 |
+
lig = read_molecule(
|
699 |
+
os.path.join(pdbbind_dir, name, file[:-4] + ".mol2"),
|
700 |
+
remove_hs=remove_hs,
|
701 |
+
sanitize=True,
|
702 |
+
)
|
703 |
+
if lig is not None:
|
704 |
+
ligs.append(lig)
|
705 |
+
return ligs
|
datasets/pdbbind_lm_embedding_preparation.py
ADDED
@@ -0,0 +1,94 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import os
|
2 |
+
from argparse import FileType, ArgumentParser
|
3 |
+
|
4 |
+
import numpy as np
|
5 |
+
from Bio.PDB import PDBParser
|
6 |
+
from Bio.Seq import Seq
|
7 |
+
from Bio.SeqRecord import SeqRecord
|
8 |
+
from tqdm import tqdm
|
9 |
+
|
10 |
+
parser = ArgumentParser()
|
11 |
+
parser.add_argument('--data_dir', type=str, default='data/PDBBind_processed', help='')
|
12 |
+
parser.add_argument('--chain_cutoff', type=int, default=10, help='')
|
13 |
+
parser.add_argument('--out_file', type=str, default="data/pdbbind_sequences.fasta")
|
14 |
+
args = parser.parse_args()
|
15 |
+
|
16 |
+
cutoff = args.chain_cutoff
|
17 |
+
data_dir = args.data_dir
|
18 |
+
names = os.listdir(data_dir)
|
19 |
+
#%%
|
20 |
+
from Bio import SeqIO
|
21 |
+
biopython_parser = PDBParser()
|
22 |
+
|
23 |
+
three_to_one = {'ALA': 'A',
|
24 |
+
'ARG': 'R',
|
25 |
+
'ASN': 'N',
|
26 |
+
'ASP': 'D',
|
27 |
+
'CYS': 'C',
|
28 |
+
'GLN': 'Q',
|
29 |
+
'GLU': 'E',
|
30 |
+
'GLY': 'G',
|
31 |
+
'HIS': 'H',
|
32 |
+
'ILE': 'I',
|
33 |
+
'LEU': 'L',
|
34 |
+
'LYS': 'K',
|
35 |
+
'MET': 'M',
|
36 |
+
'MSE': 'M', # this is almost the same AA as MET. The sulfur is just replaced by Selen
|
37 |
+
'PHE': 'F',
|
38 |
+
'PRO': 'P',
|
39 |
+
'PYL': 'O',
|
40 |
+
'SER': 'S',
|
41 |
+
'SEC': 'U',
|
42 |
+
'THR': 'T',
|
43 |
+
'TRP': 'W',
|
44 |
+
'TYR': 'Y',
|
45 |
+
'VAL': 'V',
|
46 |
+
'ASX': 'B',
|
47 |
+
'GLX': 'Z',
|
48 |
+
'XAA': 'X',
|
49 |
+
'XLE': 'J'}
|
50 |
+
|
51 |
+
sequences = []
|
52 |
+
ids = []
|
53 |
+
for name in tqdm(names):
|
54 |
+
if name == '.DS_Store': continue
|
55 |
+
if os.path.exists(os.path.join(data_dir, name, f'{name}_protein_processed.pdb')):
|
56 |
+
rec_path = os.path.join(data_dir, name, f'{name}_protein_processed.pdb')
|
57 |
+
else:
|
58 |
+
rec_path = os.path.join(data_dir, name, f'{name}_protein.pdb')
|
59 |
+
if cutoff > 10:
|
60 |
+
rec_path = os.path.join(data_dir, name, f'{name}_protein_obabel_reduce.pdb')
|
61 |
+
if not os.path.exists(rec_path):
|
62 |
+
rec_path = os.path.join(data_dir, name, f'{name}_protein.pdb')
|
63 |
+
structure = biopython_parser.get_structure('random_id', rec_path)
|
64 |
+
structure = structure[0]
|
65 |
+
for i, chain in enumerate(structure):
|
66 |
+
seq = ''
|
67 |
+
for res_idx, residue in enumerate(chain):
|
68 |
+
if residue.get_resname() == 'HOH':
|
69 |
+
continue
|
70 |
+
residue_coords = []
|
71 |
+
c_alpha, n, c = None, None, None
|
72 |
+
for atom in residue:
|
73 |
+
if atom.name == 'CA':
|
74 |
+
c_alpha = list(atom.get_vector())
|
75 |
+
if atom.name == 'N':
|
76 |
+
n = list(atom.get_vector())
|
77 |
+
if atom.name == 'C':
|
78 |
+
c = list(atom.get_vector())
|
79 |
+
if c_alpha != None and n != None and c != None: # only append residue if it is an amino acid and not
|
80 |
+
try:
|
81 |
+
seq += three_to_one[residue.get_resname()]
|
82 |
+
except Exception as e:
|
83 |
+
seq += '-'
|
84 |
+
print("encountered unknown AA: ", residue.get_resname(), ' in the complex ', name, '. Replacing it with a dash - .')
|
85 |
+
sequences.append(seq)
|
86 |
+
ids.append(f'{name}_chain_{i}')
|
87 |
+
records = []
|
88 |
+
for (index, seq) in zip(ids,sequences):
|
89 |
+
record = SeqRecord(Seq(seq), str(index))
|
90 |
+
record.description = ''
|
91 |
+
records.append(record)
|
92 |
+
SeqIO.write(records, args.out_file, "fasta")
|
93 |
+
|
94 |
+
|
datasets/process_mols.py
ADDED
@@ -0,0 +1,550 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import copy
|
2 |
+
import os
|
3 |
+
import warnings
|
4 |
+
|
5 |
+
import numpy as np
|
6 |
+
import scipy.spatial as spa
|
7 |
+
import torch
|
8 |
+
from Bio.PDB import PDBParser
|
9 |
+
from Bio.PDB.PDBExceptions import PDBConstructionWarning
|
10 |
+
from rdkit import Chem
|
11 |
+
from rdkit.Chem.rdchem import BondType as BT
|
12 |
+
from rdkit.Chem import AllChem, GetPeriodicTable, RemoveHs
|
13 |
+
from rdkit.Geometry import Point3D
|
14 |
+
from scipy import spatial
|
15 |
+
from scipy.special import softmax
|
16 |
+
from torch_cluster import radius_graph
|
17 |
+
|
18 |
+
|
19 |
+
import torch.nn.functional as F
|
20 |
+
|
21 |
+
from datasets.conformer_matching import get_torsion_angles, optimize_rotatable_bonds
|
22 |
+
from utils.torsion import get_transformation_mask
|
23 |
+
|
24 |
+
|
25 |
+
biopython_parser = PDBParser()
|
26 |
+
periodic_table = GetPeriodicTable()
|
27 |
+
allowable_features = {
|
28 |
+
'possible_atomic_num_list': list(range(1, 119)) + ['misc'],
|
29 |
+
'possible_chirality_list': [
|
30 |
+
'CHI_UNSPECIFIED',
|
31 |
+
'CHI_TETRAHEDRAL_CW',
|
32 |
+
'CHI_TETRAHEDRAL_CCW',
|
33 |
+
'CHI_OTHER'
|
34 |
+
],
|
35 |
+
'possible_degree_list': [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 'misc'],
|
36 |
+
'possible_numring_list': [0, 1, 2, 3, 4, 5, 6, 'misc'],
|
37 |
+
'possible_implicit_valence_list': [0, 1, 2, 3, 4, 5, 6, 'misc'],
|
38 |
+
'possible_formal_charge_list': [-5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 'misc'],
|
39 |
+
'possible_numH_list': [0, 1, 2, 3, 4, 5, 6, 7, 8, 'misc'],
|
40 |
+
'possible_number_radical_e_list': [0, 1, 2, 3, 4, 'misc'],
|
41 |
+
'possible_hybridization_list': [
|
42 |
+
'SP', 'SP2', 'SP3', 'SP3D', 'SP3D2', 'misc'
|
43 |
+
],
|
44 |
+
'possible_is_aromatic_list': [False, True],
|
45 |
+
'possible_is_in_ring3_list': [False, True],
|
46 |
+
'possible_is_in_ring4_list': [False, True],
|
47 |
+
'possible_is_in_ring5_list': [False, True],
|
48 |
+
'possible_is_in_ring6_list': [False, True],
|
49 |
+
'possible_is_in_ring7_list': [False, True],
|
50 |
+
'possible_is_in_ring8_list': [False, True],
|
51 |
+
'possible_amino_acids': ['ALA', 'ARG', 'ASN', 'ASP', 'CYS', 'GLN', 'GLU', 'GLY', 'HIS', 'ILE', 'LEU', 'LYS', 'MET',
|
52 |
+
'PHE', 'PRO', 'SER', 'THR', 'TRP', 'TYR', 'VAL', 'HIP', 'HIE', 'TPO', 'HID', 'LEV', 'MEU',
|
53 |
+
'PTR', 'GLV', 'CYT', 'SEP', 'HIZ', 'CYM', 'GLM', 'ASQ', 'TYS', 'CYX', 'GLZ', 'misc'],
|
54 |
+
'possible_atom_type_2': ['C*', 'CA', 'CB', 'CD', 'CE', 'CG', 'CH', 'CZ', 'N*', 'ND', 'NE', 'NH', 'NZ', 'O*', 'OD',
|
55 |
+
'OE', 'OG', 'OH', 'OX', 'S*', 'SD', 'SG', 'misc'],
|
56 |
+
'possible_atom_type_3': ['C', 'CA', 'CB', 'CD', 'CD1', 'CD2', 'CE', 'CE1', 'CE2', 'CE3', 'CG', 'CG1', 'CG2', 'CH2',
|
57 |
+
'CZ', 'CZ2', 'CZ3', 'N', 'ND1', 'ND2', 'NE', 'NE1', 'NE2', 'NH1', 'NH2', 'NZ', 'O', 'OD1',
|
58 |
+
'OD2', 'OE1', 'OE2', 'OG', 'OG1', 'OH', 'OXT', 'SD', 'SG', 'misc'],
|
59 |
+
}
|
60 |
+
bonds = {BT.SINGLE: 0, BT.DOUBLE: 1, BT.TRIPLE: 2, BT.AROMATIC: 3}
|
61 |
+
|
62 |
+
lig_feature_dims = (list(map(len, [
|
63 |
+
allowable_features['possible_atomic_num_list'],
|
64 |
+
allowable_features['possible_chirality_list'],
|
65 |
+
allowable_features['possible_degree_list'],
|
66 |
+
allowable_features['possible_formal_charge_list'],
|
67 |
+
allowable_features['possible_implicit_valence_list'],
|
68 |
+
allowable_features['possible_numH_list'],
|
69 |
+
allowable_features['possible_number_radical_e_list'],
|
70 |
+
allowable_features['possible_hybridization_list'],
|
71 |
+
allowable_features['possible_is_aromatic_list'],
|
72 |
+
allowable_features['possible_numring_list'],
|
73 |
+
allowable_features['possible_is_in_ring3_list'],
|
74 |
+
allowable_features['possible_is_in_ring4_list'],
|
75 |
+
allowable_features['possible_is_in_ring5_list'],
|
76 |
+
allowable_features['possible_is_in_ring6_list'],
|
77 |
+
allowable_features['possible_is_in_ring7_list'],
|
78 |
+
allowable_features['possible_is_in_ring8_list'],
|
79 |
+
])), 0) # number of scalar features
|
80 |
+
|
81 |
+
rec_atom_feature_dims = (list(map(len, [
|
82 |
+
allowable_features['possible_amino_acids'],
|
83 |
+
allowable_features['possible_atomic_num_list'],
|
84 |
+
allowable_features['possible_atom_type_2'],
|
85 |
+
allowable_features['possible_atom_type_3'],
|
86 |
+
])), 0)
|
87 |
+
|
88 |
+
rec_residue_feature_dims = (list(map(len, [
|
89 |
+
allowable_features['possible_amino_acids']
|
90 |
+
])), 0)
|
91 |
+
|
92 |
+
|
93 |
+
def lig_atom_featurizer(mol):
|
94 |
+
ringinfo = mol.GetRingInfo()
|
95 |
+
atom_features_list = []
|
96 |
+
for idx, atom in enumerate(mol.GetAtoms()):
|
97 |
+
atom_features_list.append([
|
98 |
+
safe_index(allowable_features['possible_atomic_num_list'], atom.GetAtomicNum()),
|
99 |
+
allowable_features['possible_chirality_list'].index(str(atom.GetChiralTag())),
|
100 |
+
safe_index(allowable_features['possible_degree_list'], atom.GetTotalDegree()),
|
101 |
+
safe_index(allowable_features['possible_formal_charge_list'], atom.GetFormalCharge()),
|
102 |
+
safe_index(allowable_features['possible_implicit_valence_list'], atom.GetImplicitValence()),
|
103 |
+
safe_index(allowable_features['possible_numH_list'], atom.GetTotalNumHs()),
|
104 |
+
safe_index(allowable_features['possible_number_radical_e_list'], atom.GetNumRadicalElectrons()),
|
105 |
+
safe_index(allowable_features['possible_hybridization_list'], str(atom.GetHybridization())),
|
106 |
+
allowable_features['possible_is_aromatic_list'].index(atom.GetIsAromatic()),
|
107 |
+
safe_index(allowable_features['possible_numring_list'], ringinfo.NumAtomRings(idx)),
|
108 |
+
allowable_features['possible_is_in_ring3_list'].index(ringinfo.IsAtomInRingOfSize(idx, 3)),
|
109 |
+
allowable_features['possible_is_in_ring4_list'].index(ringinfo.IsAtomInRingOfSize(idx, 4)),
|
110 |
+
allowable_features['possible_is_in_ring5_list'].index(ringinfo.IsAtomInRingOfSize(idx, 5)),
|
111 |
+
allowable_features['possible_is_in_ring6_list'].index(ringinfo.IsAtomInRingOfSize(idx, 6)),
|
112 |
+
allowable_features['possible_is_in_ring7_list'].index(ringinfo.IsAtomInRingOfSize(idx, 7)),
|
113 |
+
allowable_features['possible_is_in_ring8_list'].index(ringinfo.IsAtomInRingOfSize(idx, 8)),
|
114 |
+
])
|
115 |
+
|
116 |
+
return torch.tensor(atom_features_list)
|
117 |
+
|
118 |
+
|
119 |
+
def rec_residue_featurizer(rec):
|
120 |
+
feature_list = []
|
121 |
+
for residue in rec.get_residues():
|
122 |
+
feature_list.append([safe_index(allowable_features['possible_amino_acids'], residue.get_resname())])
|
123 |
+
return torch.tensor(feature_list, dtype=torch.float32) # (N_res, 1)
|
124 |
+
|
125 |
+
|
126 |
+
def safe_index(l, e):
|
127 |
+
""" Return index of element e in list l. If e is not present, return the last index """
|
128 |
+
try:
|
129 |
+
return l.index(e)
|
130 |
+
except:
|
131 |
+
return len(l) - 1
|
132 |
+
|
133 |
+
|
134 |
+
|
135 |
+
def parse_receptor(pdbid, pdbbind_dir):
|
136 |
+
rec = parsePDB(pdbid, pdbbind_dir)
|
137 |
+
return rec
|
138 |
+
|
139 |
+
|
140 |
+
def parsePDB(pdbid, pdbbind_dir):
|
141 |
+
rec_path = os.path.join(pdbbind_dir, pdbid, f'{pdbid}_protein_processed.pdb')
|
142 |
+
return parse_pdb_from_path(rec_path)
|
143 |
+
|
144 |
+
def parse_pdb_from_path(path):
|
145 |
+
with warnings.catch_warnings():
|
146 |
+
warnings.filterwarnings("ignore", category=PDBConstructionWarning)
|
147 |
+
structure = biopython_parser.get_structure('random_id', path)
|
148 |
+
rec = structure[0]
|
149 |
+
return rec
|
150 |
+
|
151 |
+
|
152 |
+
def extract_receptor_structure(rec, lig, lm_embedding_chains=None):
|
153 |
+
conf = lig.GetConformer()
|
154 |
+
lig_coords = conf.GetPositions()
|
155 |
+
min_distances = []
|
156 |
+
coords = []
|
157 |
+
c_alpha_coords = []
|
158 |
+
n_coords = []
|
159 |
+
c_coords = []
|
160 |
+
valid_chain_ids = []
|
161 |
+
lengths = []
|
162 |
+
for i, chain in enumerate(rec):
|
163 |
+
chain_coords = [] # num_residues, num_atoms, 3
|
164 |
+
chain_c_alpha_coords = []
|
165 |
+
chain_n_coords = []
|
166 |
+
chain_c_coords = []
|
167 |
+
count = 0
|
168 |
+
invalid_res_ids = []
|
169 |
+
for res_idx, residue in enumerate(chain):
|
170 |
+
if residue.get_resname() == 'HOH':
|
171 |
+
invalid_res_ids.append(residue.get_id())
|
172 |
+
continue
|
173 |
+
residue_coords = []
|
174 |
+
c_alpha, n, c = None, None, None
|
175 |
+
for atom in residue:
|
176 |
+
if atom.name == 'CA':
|
177 |
+
c_alpha = list(atom.get_vector())
|
178 |
+
if atom.name == 'N':
|
179 |
+
n = list(atom.get_vector())
|
180 |
+
if atom.name == 'C':
|
181 |
+
c = list(atom.get_vector())
|
182 |
+
residue_coords.append(list(atom.get_vector()))
|
183 |
+
|
184 |
+
if c_alpha != None and n != None and c != None:
|
185 |
+
# only append residue if it is an amino acid and not some weird molecule that is part of the complex
|
186 |
+
chain_c_alpha_coords.append(c_alpha)
|
187 |
+
chain_n_coords.append(n)
|
188 |
+
chain_c_coords.append(c)
|
189 |
+
chain_coords.append(np.array(residue_coords))
|
190 |
+
count += 1
|
191 |
+
else:
|
192 |
+
invalid_res_ids.append(residue.get_id())
|
193 |
+
for res_id in invalid_res_ids:
|
194 |
+
chain.detach_child(res_id)
|
195 |
+
if len(chain_coords) > 0:
|
196 |
+
all_chain_coords = np.concatenate(chain_coords, axis=0)
|
197 |
+
distances = spatial.distance.cdist(lig_coords, all_chain_coords)
|
198 |
+
min_distance = distances.min()
|
199 |
+
else:
|
200 |
+
min_distance = np.inf
|
201 |
+
|
202 |
+
min_distances.append(min_distance)
|
203 |
+
lengths.append(count)
|
204 |
+
coords.append(chain_coords)
|
205 |
+
c_alpha_coords.append(np.array(chain_c_alpha_coords))
|
206 |
+
n_coords.append(np.array(chain_n_coords))
|
207 |
+
c_coords.append(np.array(chain_c_coords))
|
208 |
+
if not count == 0: valid_chain_ids.append(chain.get_id())
|
209 |
+
|
210 |
+
min_distances = np.array(min_distances)
|
211 |
+
if len(valid_chain_ids) == 0:
|
212 |
+
valid_chain_ids.append(np.argmin(min_distances))
|
213 |
+
valid_coords = []
|
214 |
+
valid_c_alpha_coords = []
|
215 |
+
valid_n_coords = []
|
216 |
+
valid_c_coords = []
|
217 |
+
valid_lengths = []
|
218 |
+
invalid_chain_ids = []
|
219 |
+
valid_lm_embeddings = []
|
220 |
+
for i, chain in enumerate(rec):
|
221 |
+
if chain.get_id() in valid_chain_ids:
|
222 |
+
valid_coords.append(coords[i])
|
223 |
+
valid_c_alpha_coords.append(c_alpha_coords[i])
|
224 |
+
if lm_embedding_chains is not None:
|
225 |
+
if i >= len(lm_embedding_chains):
|
226 |
+
raise ValueError('Encountered valid chain id that was not present in the LM embeddings')
|
227 |
+
valid_lm_embeddings.append(lm_embedding_chains[i])
|
228 |
+
valid_n_coords.append(n_coords[i])
|
229 |
+
valid_c_coords.append(c_coords[i])
|
230 |
+
valid_lengths.append(lengths[i])
|
231 |
+
else:
|
232 |
+
invalid_chain_ids.append(chain.get_id())
|
233 |
+
coords = [item for sublist in valid_coords for item in sublist] # list with n_residues arrays: [n_atoms, 3]
|
234 |
+
|
235 |
+
c_alpha_coords = np.concatenate(valid_c_alpha_coords, axis=0) # [n_residues, 3]
|
236 |
+
n_coords = np.concatenate(valid_n_coords, axis=0) # [n_residues, 3]
|
237 |
+
c_coords = np.concatenate(valid_c_coords, axis=0) # [n_residues, 3]
|
238 |
+
lm_embeddings = np.concatenate(valid_lm_embeddings, axis=0) if lm_embedding_chains is not None else None
|
239 |
+
for invalid_id in invalid_chain_ids:
|
240 |
+
rec.detach_child(invalid_id)
|
241 |
+
|
242 |
+
assert len(c_alpha_coords) == len(n_coords)
|
243 |
+
assert len(c_alpha_coords) == len(c_coords)
|
244 |
+
assert sum(valid_lengths) == len(c_alpha_coords)
|
245 |
+
return rec, coords, c_alpha_coords, n_coords, c_coords, lm_embeddings
|
246 |
+
|
247 |
+
|
248 |
+
def get_lig_graph(mol, complex_graph):
|
249 |
+
lig_coords = torch.from_numpy(mol.GetConformer().GetPositions()).float()
|
250 |
+
atom_feats = lig_atom_featurizer(mol)
|
251 |
+
|
252 |
+
row, col, edge_type = [], [], []
|
253 |
+
for bond in mol.GetBonds():
|
254 |
+
start, end = bond.GetBeginAtomIdx(), bond.GetEndAtomIdx()
|
255 |
+
row += [start, end]
|
256 |
+
col += [end, start]
|
257 |
+
edge_type += 2 * [bonds[bond.GetBondType()]] if bond.GetBondType() != BT.UNSPECIFIED else [0, 0]
|
258 |
+
|
259 |
+
edge_index = torch.tensor([row, col], dtype=torch.long)
|
260 |
+
edge_type = torch.tensor(edge_type, dtype=torch.long)
|
261 |
+
edge_attr = F.one_hot(edge_type, num_classes=len(bonds)).to(torch.float)
|
262 |
+
|
263 |
+
complex_graph['ligand'].x = atom_feats
|
264 |
+
complex_graph['ligand'].pos = lig_coords
|
265 |
+
complex_graph['ligand', 'lig_bond', 'ligand'].edge_index = edge_index
|
266 |
+
complex_graph['ligand', 'lig_bond', 'ligand'].edge_attr = edge_attr
|
267 |
+
return
|
268 |
+
|
269 |
+
def generate_conformer(mol):
|
270 |
+
ps = AllChem.ETKDGv2()
|
271 |
+
id = AllChem.EmbedMolecule(mol, ps)
|
272 |
+
if id == -1:
|
273 |
+
print('rdkit coords could not be generated without using random coords. using random coords now.')
|
274 |
+
ps.useRandomCoords = True
|
275 |
+
AllChem.EmbedMolecule(mol, ps)
|
276 |
+
AllChem.MMFFOptimizeMolecule(mol, confId=0)
|
277 |
+
# else:
|
278 |
+
# AllChem.MMFFOptimizeMolecule(mol_rdkit, confId=0)
|
279 |
+
|
280 |
+
def get_lig_graph_with_matching(mol_, complex_graph, popsize, maxiter, matching, keep_original, num_conformers, remove_hs):
|
281 |
+
if matching:
|
282 |
+
mol_maybe_noh = copy.deepcopy(mol_)
|
283 |
+
if remove_hs:
|
284 |
+
mol_maybe_noh = RemoveHs(mol_maybe_noh, sanitize=True)
|
285 |
+
if keep_original:
|
286 |
+
complex_graph['ligand'].orig_pos = mol_maybe_noh.GetConformer().GetPositions()
|
287 |
+
|
288 |
+
rotable_bonds = get_torsion_angles(mol_maybe_noh)
|
289 |
+
if not rotable_bonds: print("no_rotable_bonds but still using it")
|
290 |
+
|
291 |
+
for i in range(num_conformers):
|
292 |
+
mol_rdkit = copy.deepcopy(mol_)
|
293 |
+
|
294 |
+
mol_rdkit.RemoveAllConformers()
|
295 |
+
mol_rdkit = AllChem.AddHs(mol_rdkit)
|
296 |
+
generate_conformer(mol_rdkit)
|
297 |
+
if remove_hs:
|
298 |
+
mol_rdkit = RemoveHs(mol_rdkit, sanitize=True)
|
299 |
+
mol = copy.deepcopy(mol_maybe_noh)
|
300 |
+
if rotable_bonds:
|
301 |
+
optimize_rotatable_bonds(mol_rdkit, mol, rotable_bonds, popsize=popsize, maxiter=maxiter)
|
302 |
+
mol.AddConformer(mol_rdkit.GetConformer())
|
303 |
+
rms_list = []
|
304 |
+
AllChem.AlignMolConformers(mol, RMSlist=rms_list)
|
305 |
+
mol_rdkit.RemoveAllConformers()
|
306 |
+
mol_rdkit.AddConformer(mol.GetConformers()[1])
|
307 |
+
|
308 |
+
if i == 0:
|
309 |
+
complex_graph.rmsd_matching = rms_list[0]
|
310 |
+
get_lig_graph(mol_rdkit, complex_graph)
|
311 |
+
else:
|
312 |
+
if torch.is_tensor(complex_graph['ligand'].pos):
|
313 |
+
complex_graph['ligand'].pos = [complex_graph['ligand'].pos]
|
314 |
+
complex_graph['ligand'].pos.append(torch.from_numpy(mol_rdkit.GetConformer().GetPositions()).float())
|
315 |
+
|
316 |
+
else: # no matching
|
317 |
+
complex_graph.rmsd_matching = 0
|
318 |
+
if remove_hs: mol_ = RemoveHs(mol_)
|
319 |
+
get_lig_graph(mol_, complex_graph)
|
320 |
+
|
321 |
+
edge_mask, mask_rotate = get_transformation_mask(complex_graph)
|
322 |
+
complex_graph['ligand'].edge_mask = torch.tensor(edge_mask)
|
323 |
+
complex_graph['ligand'].mask_rotate = mask_rotate
|
324 |
+
|
325 |
+
return
|
326 |
+
|
327 |
+
|
328 |
+
def get_calpha_graph(rec, c_alpha_coords, n_coords, c_coords, complex_graph, cutoff=20, max_neighbor=None, lm_embeddings=None):
|
329 |
+
n_rel_pos = n_coords - c_alpha_coords
|
330 |
+
c_rel_pos = c_coords - c_alpha_coords
|
331 |
+
num_residues = len(c_alpha_coords)
|
332 |
+
if num_residues <= 1:
|
333 |
+
raise ValueError(f"rec contains only 1 residue!")
|
334 |
+
|
335 |
+
# Build the k-NN graph
|
336 |
+
distances = spa.distance.cdist(c_alpha_coords, c_alpha_coords)
|
337 |
+
src_list = []
|
338 |
+
dst_list = []
|
339 |
+
mean_norm_list = []
|
340 |
+
for i in range(num_residues):
|
341 |
+
dst = list(np.where(distances[i, :] < cutoff)[0])
|
342 |
+
dst.remove(i)
|
343 |
+
if max_neighbor != None and len(dst) > max_neighbor:
|
344 |
+
dst = list(np.argsort(distances[i, :]))[1: max_neighbor + 1]
|
345 |
+
if len(dst) == 0:
|
346 |
+
dst = list(np.argsort(distances[i, :]))[1:2] # choose second because first is i itself
|
347 |
+
print(f'The c_alpha_cutoff {cutoff} was too small for one c_alpha such that it had no neighbors. '
|
348 |
+
f'So we connected it to the closest other c_alpha')
|
349 |
+
assert i not in dst
|
350 |
+
src = [i] * len(dst)
|
351 |
+
src_list.extend(src)
|
352 |
+
dst_list.extend(dst)
|
353 |
+
valid_dist = list(distances[i, dst])
|
354 |
+
valid_dist_np = distances[i, dst]
|
355 |
+
sigma = np.array([1., 2., 5., 10., 30.]).reshape((-1, 1))
|
356 |
+
weights = softmax(- valid_dist_np.reshape((1, -1)) ** 2 / sigma, axis=1) # (sigma_num, neigh_num)
|
357 |
+
assert weights[0].sum() > 1 - 1e-2 and weights[0].sum() < 1.01
|
358 |
+
diff_vecs = c_alpha_coords[src, :] - c_alpha_coords[dst, :] # (neigh_num, 3)
|
359 |
+
mean_vec = weights.dot(diff_vecs) # (sigma_num, 3)
|
360 |
+
denominator = weights.dot(np.linalg.norm(diff_vecs, axis=1)) # (sigma_num,)
|
361 |
+
mean_vec_ratio_norm = np.linalg.norm(mean_vec, axis=1) / denominator # (sigma_num,)
|
362 |
+
mean_norm_list.append(mean_vec_ratio_norm)
|
363 |
+
assert len(src_list) == len(dst_list)
|
364 |
+
|
365 |
+
node_feat = rec_residue_featurizer(rec)
|
366 |
+
mu_r_norm = torch.from_numpy(np.array(mean_norm_list).astype(np.float32))
|
367 |
+
side_chain_vecs = torch.from_numpy(
|
368 |
+
np.concatenate([np.expand_dims(n_rel_pos, axis=1), np.expand_dims(c_rel_pos, axis=1)], axis=1))
|
369 |
+
|
370 |
+
complex_graph['receptor'].x = torch.cat([node_feat, torch.tensor(lm_embeddings)], axis=1) if lm_embeddings is not None else node_feat
|
371 |
+
complex_graph['receptor'].pos = torch.from_numpy(c_alpha_coords).float()
|
372 |
+
complex_graph['receptor'].mu_r_norm = mu_r_norm
|
373 |
+
complex_graph['receptor'].side_chain_vecs = side_chain_vecs.float()
|
374 |
+
complex_graph['receptor', 'rec_contact', 'receptor'].edge_index = torch.from_numpy(np.asarray([src_list, dst_list]))
|
375 |
+
|
376 |
+
return
|
377 |
+
|
378 |
+
|
379 |
+
def rec_atom_featurizer(rec):
|
380 |
+
atom_feats = []
|
381 |
+
for i, atom in enumerate(rec.get_atoms()):
|
382 |
+
atom_name, element = atom.name, atom.element
|
383 |
+
if element == 'CD':
|
384 |
+
element = 'C'
|
385 |
+
assert not element == ''
|
386 |
+
try:
|
387 |
+
atomic_num = periodic_table.GetAtomicNumber(element)
|
388 |
+
except:
|
389 |
+
atomic_num = -1
|
390 |
+
atom_feat = [safe_index(allowable_features['possible_amino_acids'], atom.get_parent().get_resname()),
|
391 |
+
safe_index(allowable_features['possible_atomic_num_list'], atomic_num),
|
392 |
+
safe_index(allowable_features['possible_atom_type_2'], (atom_name + '*')[:2]),
|
393 |
+
safe_index(allowable_features['possible_atom_type_3'], atom_name)]
|
394 |
+
atom_feats.append(atom_feat)
|
395 |
+
|
396 |
+
return atom_feats
|
397 |
+
|
398 |
+
|
399 |
+
def get_rec_graph(rec, rec_coords, c_alpha_coords, n_coords, c_coords, complex_graph, rec_radius, c_alpha_max_neighbors=None, all_atoms=False,
|
400 |
+
atom_radius=5, atom_max_neighbors=None, remove_hs=False, lm_embeddings=None):
|
401 |
+
if all_atoms:
|
402 |
+
return get_fullrec_graph(rec, rec_coords, c_alpha_coords, n_coords, c_coords, complex_graph,
|
403 |
+
c_alpha_cutoff=rec_radius, c_alpha_max_neighbors=c_alpha_max_neighbors,
|
404 |
+
atom_cutoff=atom_radius, atom_max_neighbors=atom_max_neighbors, remove_hs=remove_hs,lm_embeddings=lm_embeddings)
|
405 |
+
else:
|
406 |
+
return get_calpha_graph(rec, c_alpha_coords, n_coords, c_coords, complex_graph, rec_radius, c_alpha_max_neighbors,lm_embeddings=lm_embeddings)
|
407 |
+
|
408 |
+
|
409 |
+
def get_fullrec_graph(rec, rec_coords, c_alpha_coords, n_coords, c_coords, complex_graph, c_alpha_cutoff=20,
|
410 |
+
c_alpha_max_neighbors=None, atom_cutoff=5, atom_max_neighbors=None, remove_hs=False, lm_embeddings=None):
|
411 |
+
# builds the receptor graph with both residues and atoms
|
412 |
+
|
413 |
+
n_rel_pos = n_coords - c_alpha_coords
|
414 |
+
c_rel_pos = c_coords - c_alpha_coords
|
415 |
+
num_residues = len(c_alpha_coords)
|
416 |
+
if num_residues <= 1:
|
417 |
+
raise ValueError(f"rec contains only 1 residue!")
|
418 |
+
|
419 |
+
# Build the k-NN graph of residues
|
420 |
+
distances = spa.distance.cdist(c_alpha_coords, c_alpha_coords)
|
421 |
+
src_list = []
|
422 |
+
dst_list = []
|
423 |
+
mean_norm_list = []
|
424 |
+
for i in range(num_residues):
|
425 |
+
dst = list(np.where(distances[i, :] < c_alpha_cutoff)[0])
|
426 |
+
dst.remove(i)
|
427 |
+
if c_alpha_max_neighbors != None and len(dst) > c_alpha_max_neighbors:
|
428 |
+
dst = list(np.argsort(distances[i, :]))[1: c_alpha_max_neighbors + 1]
|
429 |
+
if len(dst) == 0:
|
430 |
+
dst = list(np.argsort(distances[i, :]))[1:2] # choose second because first is i itself
|
431 |
+
print(f'The c_alpha_cutoff {c_alpha_cutoff} was too small for one c_alpha such that it had no neighbors. '
|
432 |
+
f'So we connected it to the closest other c_alpha')
|
433 |
+
assert i not in dst
|
434 |
+
src = [i] * len(dst)
|
435 |
+
src_list.extend(src)
|
436 |
+
dst_list.extend(dst)
|
437 |
+
valid_dist = list(distances[i, dst])
|
438 |
+
valid_dist_np = distances[i, dst]
|
439 |
+
sigma = np.array([1., 2., 5., 10., 30.]).reshape((-1, 1))
|
440 |
+
weights = softmax(- valid_dist_np.reshape((1, -1)) ** 2 / sigma, axis=1) # (sigma_num, neigh_num)
|
441 |
+
assert 1 - 1e-2 < weights[0].sum() < 1.01
|
442 |
+
diff_vecs = c_alpha_coords[src, :] - c_alpha_coords[dst, :] # (neigh_num, 3)
|
443 |
+
mean_vec = weights.dot(diff_vecs) # (sigma_num, 3)
|
444 |
+
denominator = weights.dot(np.linalg.norm(diff_vecs, axis=1)) # (sigma_num,)
|
445 |
+
mean_vec_ratio_norm = np.linalg.norm(mean_vec, axis=1) / denominator # (sigma_num,)
|
446 |
+
mean_norm_list.append(mean_vec_ratio_norm)
|
447 |
+
assert len(src_list) == len(dst_list)
|
448 |
+
|
449 |
+
node_feat = rec_residue_featurizer(rec)
|
450 |
+
mu_r_norm = torch.from_numpy(np.array(mean_norm_list).astype(np.float32))
|
451 |
+
side_chain_vecs = torch.from_numpy(
|
452 |
+
np.concatenate([np.expand_dims(n_rel_pos, axis=1), np.expand_dims(c_rel_pos, axis=1)], axis=1))
|
453 |
+
|
454 |
+
complex_graph['receptor'].x = torch.cat([node_feat, torch.tensor(lm_embeddings)], axis=1) if lm_embeddings is not None else node_feat
|
455 |
+
complex_graph['receptor'].pos = torch.from_numpy(c_alpha_coords).float()
|
456 |
+
complex_graph['receptor'].mu_r_norm = mu_r_norm
|
457 |
+
complex_graph['receptor'].side_chain_vecs = side_chain_vecs.float()
|
458 |
+
complex_graph['receptor', 'rec_contact', 'receptor'].edge_index = torch.from_numpy(np.asarray([src_list, dst_list]))
|
459 |
+
|
460 |
+
src_c_alpha_idx = np.concatenate([np.asarray([i]*len(l)) for i, l in enumerate(rec_coords)])
|
461 |
+
atom_feat = torch.from_numpy(np.asarray(rec_atom_featurizer(rec)))
|
462 |
+
atom_coords = torch.from_numpy(np.concatenate(rec_coords, axis=0)).float()
|
463 |
+
|
464 |
+
if remove_hs:
|
465 |
+
not_hs = (atom_feat[:, 1] != 0)
|
466 |
+
src_c_alpha_idx = src_c_alpha_idx[not_hs]
|
467 |
+
atom_feat = atom_feat[not_hs]
|
468 |
+
atom_coords = atom_coords[not_hs]
|
469 |
+
|
470 |
+
atoms_edge_index = radius_graph(atom_coords, atom_cutoff, max_num_neighbors=atom_max_neighbors if atom_max_neighbors else 1000)
|
471 |
+
atom_res_edge_index = torch.from_numpy(np.asarray([np.arange(len(atom_feat)), src_c_alpha_idx])).long()
|
472 |
+
|
473 |
+
complex_graph['atom'].x = atom_feat
|
474 |
+
complex_graph['atom'].pos = atom_coords
|
475 |
+
complex_graph['atom', 'atom_contact', 'atom'].edge_index = atoms_edge_index
|
476 |
+
complex_graph['atom', 'atom_rec_contact', 'receptor'].edge_index = atom_res_edge_index
|
477 |
+
|
478 |
+
return
|
479 |
+
|
480 |
+
def write_mol_with_coords(mol, new_coords, path):
|
481 |
+
w = Chem.SDWriter(path)
|
482 |
+
conf = mol.GetConformer()
|
483 |
+
for i in range(mol.GetNumAtoms()):
|
484 |
+
x,y,z = new_coords.astype(np.double)[i]
|
485 |
+
conf.SetAtomPosition(i,Point3D(x,y,z))
|
486 |
+
w.write(mol)
|
487 |
+
w.close()
|
488 |
+
|
489 |
+
def read_molecule(molecule_file, sanitize=False, calc_charges=False, remove_hs=False):
|
490 |
+
if molecule_file.endswith('.mol2'):
|
491 |
+
mol = Chem.MolFromMol2File(molecule_file, sanitize=False, removeHs=False)
|
492 |
+
elif molecule_file.endswith('.sdf'):
|
493 |
+
print(molecule_file)
|
494 |
+
supplier = Chem.SDMolSupplier(molecule_file, sanitize=False, removeHs=False)
|
495 |
+
mol = supplier[0]
|
496 |
+
print(mol)
|
497 |
+
elif molecule_file.endswith('.pdbqt'):
|
498 |
+
with open(molecule_file) as file:
|
499 |
+
pdbqt_data = file.readlines()
|
500 |
+
pdb_block = ''
|
501 |
+
for line in pdbqt_data:
|
502 |
+
pdb_block += '{}\n'.format(line[:66])
|
503 |
+
mol = Chem.MolFromPDBBlock(pdb_block, sanitize=False, removeHs=False)
|
504 |
+
elif molecule_file.endswith('.pdb'):
|
505 |
+
mol = Chem.MolFromPDBFile(molecule_file, sanitize=False, removeHs=False)
|
506 |
+
else:
|
507 |
+
return ValueError('Expect the format of the molecule_file to be '
|
508 |
+
'one of .mol2, .sdf, .pdbqt and .pdb, got {}'.format(molecule_file))
|
509 |
+
|
510 |
+
print(sanitize, calc_charges, remove_hs)
|
511 |
+
|
512 |
+
try:
|
513 |
+
if sanitize or calc_charges:
|
514 |
+
Chem.SanitizeMol(mol)
|
515 |
+
|
516 |
+
if calc_charges:
|
517 |
+
# Compute Gasteiger charges on the molecule.
|
518 |
+
try:
|
519 |
+
AllChem.ComputeGasteigerCharges(mol)
|
520 |
+
except:
|
521 |
+
warnings.warn('Unable to compute charges for the molecule.')
|
522 |
+
|
523 |
+
if remove_hs:
|
524 |
+
mol = Chem.RemoveHs(mol, sanitize=sanitize)
|
525 |
+
except Exception as e:
|
526 |
+
print(e)
|
527 |
+
return None
|
528 |
+
|
529 |
+
return mol
|
530 |
+
|
531 |
+
|
532 |
+
def read_sdf_or_mol2(sdf_fileName, mol2_fileName):
|
533 |
+
|
534 |
+
mol = Chem.MolFromMolFile(sdf_fileName, sanitize=False)
|
535 |
+
problem = False
|
536 |
+
try:
|
537 |
+
Chem.SanitizeMol(mol)
|
538 |
+
mol = Chem.RemoveHs(mol)
|
539 |
+
except Exception as e:
|
540 |
+
problem = True
|
541 |
+
if problem:
|
542 |
+
mol = Chem.MolFromMol2File(mol2_fileName, sanitize=False)
|
543 |
+
try:
|
544 |
+
Chem.SanitizeMol(mol)
|
545 |
+
mol = Chem.RemoveHs(mol)
|
546 |
+
problem = False
|
547 |
+
except Exception as e:
|
548 |
+
problem = True
|
549 |
+
|
550 |
+
return mol, problem
|
environment.yml
ADDED
@@ -0,0 +1,102 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
name: diffdock
|
2 |
+
channels:
|
3 |
+
- pytorch
|
4 |
+
- defaults
|
5 |
+
dependencies:
|
6 |
+
- blas=1.0
|
7 |
+
- brotlipy=0.7.0
|
8 |
+
- bzip2=1.0.8
|
9 |
+
- ca-certificates=2022.07.19
|
10 |
+
- certifi=2022.9.14
|
11 |
+
- cffi=1.15.1
|
12 |
+
- charset-normalizer=2.0.4
|
13 |
+
- cryptography=37.0.1
|
14 |
+
- ffmpeg=4.3
|
15 |
+
- freetype=2.11.0
|
16 |
+
- gettext=0.21.0
|
17 |
+
- giflib=5.2.1
|
18 |
+
- gmp=6.2.1
|
19 |
+
- gnutls=3.6.15
|
20 |
+
- icu=58.2
|
21 |
+
- idna=3.3
|
22 |
+
- intel-openmp=2021.4.0
|
23 |
+
- jpeg=9e
|
24 |
+
- lame=3.100
|
25 |
+
- lcms2=2.12
|
26 |
+
- lerc=3.0
|
27 |
+
- libcxx=14.0.6
|
28 |
+
- libdeflate=1.8
|
29 |
+
- libffi=3.3
|
30 |
+
- libiconv=1.16
|
31 |
+
- libidn2=2.3.2
|
32 |
+
- libpng=1.6.37
|
33 |
+
- libtasn1=4.16.0
|
34 |
+
- libtiff=4.4.0
|
35 |
+
- libunistring=0.9.10
|
36 |
+
- libwebp=1.2.2
|
37 |
+
- libwebp-base=1.2.2
|
38 |
+
- libxml2=2.9.14
|
39 |
+
- llvm-openmp=14.0.6
|
40 |
+
- lz4-c=1.9.3
|
41 |
+
- mkl=2021.4.0
|
42 |
+
- mkl-service=2.4.0
|
43 |
+
- mkl_fft=1.3.1
|
44 |
+
- mkl_random=1.2.2
|
45 |
+
- ncurses=6.3
|
46 |
+
- nettle=3.7.3
|
47 |
+
- numpy=1.23.1
|
48 |
+
- numpy-base=1.23.1
|
49 |
+
- openh264=2.1.1
|
50 |
+
- openssl=1.1.1q
|
51 |
+
- pillow=9.2.0
|
52 |
+
- pip=22.2.2
|
53 |
+
- pycparser=2.21
|
54 |
+
- pyopenssl=22.0.0
|
55 |
+
- pysocks=1.7.1
|
56 |
+
- python=3.9.13
|
57 |
+
- pytorch=1.12.1
|
58 |
+
- readline=8.1.2
|
59 |
+
- requests=2.28.1
|
60 |
+
- setuptools=63.4.1
|
61 |
+
- six=1.16.0
|
62 |
+
- sqlite=3.39.3
|
63 |
+
- tk=8.6.12
|
64 |
+
- torchaudio=0.12.1
|
65 |
+
- torchvision=0.13.1
|
66 |
+
- typing_extensions=4.3.0
|
67 |
+
- tzdata=2022c
|
68 |
+
- urllib3=1.26.11
|
69 |
+
- wheel=0.37.1
|
70 |
+
- xz=5.2.6
|
71 |
+
- zlib=1.2.12
|
72 |
+
- zstd=1.5.2
|
73 |
+
- pip:
|
74 |
+
- biopandas==0.4.1
|
75 |
+
- biopython==1.79
|
76 |
+
- e3nn==0.5.0
|
77 |
+
- jinja2==3.1.2
|
78 |
+
- joblib==1.2.0
|
79 |
+
- markupsafe==2.1.1
|
80 |
+
- mpmath==1.2.1
|
81 |
+
- networkx==2.8.7
|
82 |
+
- opt-einsum==3.3.0
|
83 |
+
- opt-einsum-fx==0.1.4
|
84 |
+
- packaging==21.3
|
85 |
+
- pandas==1.5.0
|
86 |
+
- pyaml==21.10.1
|
87 |
+
- pyparsing==3.0.9
|
88 |
+
- python-dateutil==2.8.2
|
89 |
+
- pytz==2022.4
|
90 |
+
- pyyaml==6.0
|
91 |
+
- rdkit-pypi==2022.3.5
|
92 |
+
- scikit-learn==1.1.2
|
93 |
+
- scipy==1.9.1
|
94 |
+
- spyrmsd==0.5.2
|
95 |
+
- sympy==1.11.1
|
96 |
+
- threadpoolctl==3.1.0
|
97 |
+
- torch-cluster==1.6.0
|
98 |
+
- torch-geometric==2.1.0.post1
|
99 |
+
- torch-scatter==2.0.9
|
100 |
+
- torch-sparse==0.6.15
|
101 |
+
- torch-spline-conv==1.2.1
|
102 |
+
- tqdm==4.64.1
|
esm/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
MIT License
|
2 |
+
|
3 |
+
Copyright (c) Facebook, Inc. and its affiliates.
|
4 |
+
|
5 |
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6 |
+
of this software and associated documentation files (the "Software"), to deal
|
7 |
+
in the Software without restriction, including without limitation the rights
|
8 |
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9 |
+
copies of the Software, and to permit persons to whom the Software is
|
10 |
+
furnished to do so, subject to the following conditions:
|
11 |
+
|
12 |
+
The above copyright notice and this permission notice shall be included in all
|
13 |
+
copies or substantial portions of the Software.
|
14 |
+
|
15 |
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16 |
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17 |
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18 |
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19 |
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20 |
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21 |
+
SOFTWARE.
|
esm/esm/__init__.py
ADDED
@@ -0,0 +1,12 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Copyright (c) Facebook, Inc. and its affiliates.
|
2 |
+
#
|
3 |
+
# This source code is licensed under the MIT license found in the
|
4 |
+
# LICENSE file in the root directory of this source tree.
|
5 |
+
|
6 |
+
from .version import version as __version__ # noqa
|
7 |
+
|
8 |
+
from .data import Alphabet, BatchConverter, FastaBatchedDataset # noqa
|
9 |
+
from .model.esm1 import ProteinBertModel # noqa
|
10 |
+
from .model.esm2 import ESM2 # noqa
|
11 |
+
from .model.msa_transformer import MSATransformer #noqa
|
12 |
+
from . import pretrained # noqa
|
esm/esm/axial_attention.py
ADDED
@@ -0,0 +1,239 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Copyright (c) Facebook, Inc. and its affiliates.
|
2 |
+
#
|
3 |
+
# This source code is licensed under the MIT license found in the
|
4 |
+
# LICENSE file in the root directory of this source tree.
|
5 |
+
|
6 |
+
import math
|
7 |
+
import torch
|
8 |
+
import torch.nn as nn
|
9 |
+
|
10 |
+
|
11 |
+
class RowSelfAttention(nn.Module):
|
12 |
+
"""Compute self-attention over rows of a 2D input."""
|
13 |
+
|
14 |
+
def __init__(
|
15 |
+
self,
|
16 |
+
embed_dim,
|
17 |
+
num_heads,
|
18 |
+
dropout=0.0,
|
19 |
+
max_tokens_per_msa: int = 2 ** 16,
|
20 |
+
):
|
21 |
+
super().__init__()
|
22 |
+
self.num_heads = num_heads
|
23 |
+
self.dropout = dropout
|
24 |
+
self.head_dim = embed_dim // num_heads
|
25 |
+
self.scaling = self.head_dim ** -0.5
|
26 |
+
self.max_tokens_per_msa = max_tokens_per_msa
|
27 |
+
self.attn_shape = "hnij"
|
28 |
+
|
29 |
+
self.k_proj = nn.Linear(embed_dim, embed_dim)
|
30 |
+
self.v_proj = nn.Linear(embed_dim, embed_dim)
|
31 |
+
self.q_proj = nn.Linear(embed_dim, embed_dim)
|
32 |
+
|
33 |
+
self.out_proj = nn.Linear(embed_dim, embed_dim)
|
34 |
+
self.dropout_module = nn.Dropout(dropout)
|
35 |
+
|
36 |
+
def align_scaling(self, q):
|
37 |
+
num_rows = q.size(0)
|
38 |
+
return self.scaling / math.sqrt(num_rows)
|
39 |
+
|
40 |
+
def _batched_forward(
|
41 |
+
self,
|
42 |
+
x,
|
43 |
+
self_attn_mask=None,
|
44 |
+
self_attn_padding_mask=None,
|
45 |
+
):
|
46 |
+
num_rows, num_cols, batch_size, embed_dim = x.size()
|
47 |
+
max_rows = max(1, self.max_tokens_per_msa // num_cols)
|
48 |
+
attns = 0
|
49 |
+
scaling = self.align_scaling(x)
|
50 |
+
for start in range(0, num_rows, max_rows):
|
51 |
+
attn_weights = self.compute_attention_weights(
|
52 |
+
x[start : start + max_rows],
|
53 |
+
scaling,
|
54 |
+
self_attn_mask=self_attn_mask,
|
55 |
+
self_attn_padding_mask=self_attn_padding_mask[:, start : start + max_rows]
|
56 |
+
if self_attn_padding_mask is not None
|
57 |
+
else None,
|
58 |
+
)
|
59 |
+
attns += attn_weights
|
60 |
+
attn_probs = attns.softmax(-1)
|
61 |
+
attn_probs = self.dropout_module(attn_probs)
|
62 |
+
|
63 |
+
outputs = []
|
64 |
+
for start in range(0, num_rows, max_rows):
|
65 |
+
output = self.compute_attention_update(x[start : start + max_rows], attn_probs)
|
66 |
+
outputs.append(output)
|
67 |
+
|
68 |
+
output = torch.cat(outputs, 0)
|
69 |
+
return output, attn_probs
|
70 |
+
|
71 |
+
def compute_attention_weights(
|
72 |
+
self,
|
73 |
+
x,
|
74 |
+
scaling: float,
|
75 |
+
self_attn_mask=None,
|
76 |
+
self_attn_padding_mask=None,
|
77 |
+
):
|
78 |
+
num_rows, num_cols, batch_size, embed_dim = x.size()
|
79 |
+
q = self.q_proj(x).view(num_rows, num_cols, batch_size, self.num_heads, self.head_dim)
|
80 |
+
k = self.k_proj(x).view(num_rows, num_cols, batch_size, self.num_heads, self.head_dim)
|
81 |
+
q *= scaling
|
82 |
+
if self_attn_padding_mask is not None:
|
83 |
+
# Zero out any padded aligned positions - this is important since
|
84 |
+
# we take a sum across the alignment axis.
|
85 |
+
q *= 1 - self_attn_padding_mask.permute(1, 2, 0).unsqueeze(3).unsqueeze(4).to(q)
|
86 |
+
|
87 |
+
attn_weights = torch.einsum(f"rinhd,rjnhd->{self.attn_shape}", q, k)
|
88 |
+
|
89 |
+
if self_attn_mask is not None:
|
90 |
+
raise NotImplementedError
|
91 |
+
# Mask Size: [B x R x C], Weights Size: [H x B x C x C]
|
92 |
+
|
93 |
+
if self_attn_padding_mask is not None:
|
94 |
+
attn_weights = attn_weights.masked_fill(
|
95 |
+
self_attn_padding_mask[:, 0].unsqueeze(0).unsqueeze(2),
|
96 |
+
-10000,
|
97 |
+
)
|
98 |
+
|
99 |
+
return attn_weights
|
100 |
+
|
101 |
+
def compute_attention_update(
|
102 |
+
self,
|
103 |
+
x,
|
104 |
+
attn_probs,
|
105 |
+
):
|
106 |
+
num_rows, num_cols, batch_size, embed_dim = x.size()
|
107 |
+
v = self.v_proj(x).view(num_rows, num_cols, batch_size, self.num_heads, self.head_dim)
|
108 |
+
context = torch.einsum(f"{self.attn_shape},rjnhd->rinhd", attn_probs, v)
|
109 |
+
context = context.contiguous().view(num_rows, num_cols, batch_size, embed_dim)
|
110 |
+
output = self.out_proj(context)
|
111 |
+
return output
|
112 |
+
|
113 |
+
def forward(
|
114 |
+
self,
|
115 |
+
x,
|
116 |
+
self_attn_mask=None,
|
117 |
+
self_attn_padding_mask=None,
|
118 |
+
):
|
119 |
+
num_rows, num_cols, batch_size, embed_dim = x.size()
|
120 |
+
if (num_rows * num_cols > self.max_tokens_per_msa) and not torch.is_grad_enabled():
|
121 |
+
return self._batched_forward(x, self_attn_mask, self_attn_padding_mask)
|
122 |
+
else:
|
123 |
+
scaling = self.align_scaling(x)
|
124 |
+
attn_weights = self.compute_attention_weights(
|
125 |
+
x, scaling, self_attn_mask, self_attn_padding_mask
|
126 |
+
)
|
127 |
+
attn_probs = attn_weights.softmax(-1)
|
128 |
+
attn_probs = self.dropout_module(attn_probs)
|
129 |
+
output = self.compute_attention_update(x, attn_probs)
|
130 |
+
return output, attn_probs
|
131 |
+
|
132 |
+
|
133 |
+
class ColumnSelfAttention(nn.Module):
|
134 |
+
"""Compute self-attention over columns of a 2D input."""
|
135 |
+
|
136 |
+
def __init__(
|
137 |
+
self,
|
138 |
+
embed_dim,
|
139 |
+
num_heads,
|
140 |
+
dropout=0.0,
|
141 |
+
max_tokens_per_msa: int = 2 ** 16,
|
142 |
+
):
|
143 |
+
super().__init__()
|
144 |
+
|
145 |
+
self.num_heads = num_heads
|
146 |
+
self.dropout = dropout
|
147 |
+
self.head_dim = embed_dim // num_heads
|
148 |
+
self.scaling = self.head_dim ** -0.5
|
149 |
+
self.max_tokens_per_msa = max_tokens_per_msa
|
150 |
+
|
151 |
+
self.k_proj = nn.Linear(embed_dim, embed_dim)
|
152 |
+
self.v_proj = nn.Linear(embed_dim, embed_dim)
|
153 |
+
self.q_proj = nn.Linear(embed_dim, embed_dim)
|
154 |
+
|
155 |
+
self.out_proj = nn.Linear(embed_dim, embed_dim)
|
156 |
+
self.dropout_module = nn.Dropout(dropout)
|
157 |
+
|
158 |
+
def _batched_forward(
|
159 |
+
self,
|
160 |
+
x,
|
161 |
+
self_attn_mask=None,
|
162 |
+
self_attn_padding_mask=None,
|
163 |
+
):
|
164 |
+
num_rows, num_cols, batch_size, embed_dim = x.size()
|
165 |
+
max_cols = max(1, self.max_tokens_per_msa // num_rows)
|
166 |
+
outputs = []
|
167 |
+
attns = []
|
168 |
+
for start in range(0, num_cols, max_cols):
|
169 |
+
output, attn = self(
|
170 |
+
x[:, start : start + max_cols],
|
171 |
+
self_attn_mask=self_attn_mask,
|
172 |
+
self_attn_padding_mask=self_attn_padding_mask[:, :, start : start + max_cols]
|
173 |
+
if self_attn_padding_mask is not None
|
174 |
+
else None,
|
175 |
+
)
|
176 |
+
outputs.append(output)
|
177 |
+
attns.append(attn)
|
178 |
+
output = torch.cat(outputs, 1)
|
179 |
+
attns = torch.cat(attns, 1)
|
180 |
+
return output, attns
|
181 |
+
|
182 |
+
def compute_attention_update(
|
183 |
+
self,
|
184 |
+
x,
|
185 |
+
self_attn_mask=None,
|
186 |
+
self_attn_padding_mask=None,
|
187 |
+
):
|
188 |
+
num_rows, num_cols, batch_size, embed_dim = x.size()
|
189 |
+
if num_rows == 1:
|
190 |
+
# if there is only 1 position, this is equivalent and doesn't break with padding
|
191 |
+
attn_probs = torch.ones(
|
192 |
+
self.num_heads,
|
193 |
+
num_cols,
|
194 |
+
batch_size,
|
195 |
+
num_rows,
|
196 |
+
num_rows,
|
197 |
+
device=x.device,
|
198 |
+
dtype=x.dtype,
|
199 |
+
)
|
200 |
+
output = self.out_proj(self.v_proj(x))
|
201 |
+
else:
|
202 |
+
q = self.q_proj(x).view(num_rows, num_cols, batch_size, self.num_heads, self.head_dim)
|
203 |
+
k = self.k_proj(x).view(num_rows, num_cols, batch_size, self.num_heads, self.head_dim)
|
204 |
+
v = self.v_proj(x).view(num_rows, num_cols, batch_size, self.num_heads, self.head_dim)
|
205 |
+
q *= self.scaling
|
206 |
+
|
207 |
+
attn_weights = torch.einsum("icnhd,jcnhd->hcnij", q, k)
|
208 |
+
|
209 |
+
if self_attn_mask is not None:
|
210 |
+
raise NotImplementedError
|
211 |
+
if self_attn_padding_mask is not None:
|
212 |
+
attn_weights = attn_weights.masked_fill(
|
213 |
+
self_attn_padding_mask.permute(2, 0, 1).unsqueeze(0).unsqueeze(3),
|
214 |
+
-10000,
|
215 |
+
)
|
216 |
+
|
217 |
+
attn_probs = attn_weights.softmax(-1)
|
218 |
+
attn_probs = self.dropout_module(attn_probs)
|
219 |
+
context = torch.einsum("hcnij,jcnhd->icnhd", attn_probs, v)
|
220 |
+
context = context.contiguous().view(num_rows, num_cols, batch_size, embed_dim)
|
221 |
+
output = self.out_proj(context)
|
222 |
+
return output, attn_probs
|
223 |
+
|
224 |
+
def forward(
|
225 |
+
self,
|
226 |
+
x,
|
227 |
+
self_attn_mask=None,
|
228 |
+
self_attn_padding_mask=None,
|
229 |
+
):
|
230 |
+
num_rows, num_cols, batch_size, embed_dim = x.size()
|
231 |
+
# if False and num_rows * num_cols > 2 ** 14 and not torch.is_grad_enabled():
|
232 |
+
if (num_rows * num_cols) > self.max_tokens_per_msa and not torch.is_grad_enabled():
|
233 |
+
return self._batched_forward(
|
234 |
+
x,
|
235 |
+
self_attn_mask,
|
236 |
+
self_attn_padding_mask,
|
237 |
+
)
|
238 |
+
else:
|
239 |
+
return self.compute_attention_update(x, self_attn_mask, self_attn_padding_mask)
|
esm/esm/constants.py
ADDED
@@ -0,0 +1,10 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Copyright (c) Facebook, Inc. and its affiliates.
|
2 |
+
#
|
3 |
+
# This source code is licensed under the MIT license found in the
|
4 |
+
# LICENSE file in the root directory of this source tree.
|
5 |
+
|
6 |
+
# fmt: off
|
7 |
+
proteinseq_toks = {
|
8 |
+
'toks': ['L', 'A', 'G', 'V', 'S', 'E', 'R', 'T', 'I', 'D', 'P', 'K', 'Q', 'N', 'F', 'Y', 'M', 'H', 'W', 'C', 'X', 'B', 'U', 'Z', 'O', '.', '-']
|
9 |
+
}
|
10 |
+
# fmt: on
|
esm/esm/data.py
ADDED
@@ -0,0 +1,493 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Copyright (c) Facebook, Inc. and its affiliates.
|
2 |
+
#
|
3 |
+
# This source code is licensed under the MIT license found in the
|
4 |
+
# LICENSE file in the root directory of this source tree.
|
5 |
+
|
6 |
+
import itertools
|
7 |
+
import os
|
8 |
+
from typing import Sequence, Tuple, List, Union
|
9 |
+
import pickle
|
10 |
+
import re
|
11 |
+
import shutil
|
12 |
+
import torch
|
13 |
+
from pathlib import Path
|
14 |
+
from esm.constants import proteinseq_toks
|
15 |
+
|
16 |
+
RawMSA = Sequence[Tuple[str, str]]
|
17 |
+
|
18 |
+
|
19 |
+
class FastaBatchedDataset(object):
|
20 |
+
def __init__(self, sequence_labels, sequence_strs):
|
21 |
+
self.sequence_labels = list(sequence_labels)
|
22 |
+
self.sequence_strs = list(sequence_strs)
|
23 |
+
|
24 |
+
@classmethod
|
25 |
+
def from_file(cls, fasta_file):
|
26 |
+
sequence_labels, sequence_strs = [], []
|
27 |
+
cur_seq_label = None
|
28 |
+
buf = []
|
29 |
+
|
30 |
+
def _flush_current_seq():
|
31 |
+
nonlocal cur_seq_label, buf
|
32 |
+
if cur_seq_label is None:
|
33 |
+
return
|
34 |
+
sequence_labels.append(cur_seq_label)
|
35 |
+
sequence_strs.append("".join(buf))
|
36 |
+
cur_seq_label = None
|
37 |
+
buf = []
|
38 |
+
|
39 |
+
with open(fasta_file, "r") as infile:
|
40 |
+
for line_idx, line in enumerate(infile):
|
41 |
+
if line.startswith(">"): # label line
|
42 |
+
_flush_current_seq()
|
43 |
+
line = line[1:].strip()
|
44 |
+
if len(line) > 0:
|
45 |
+
cur_seq_label = line
|
46 |
+
else:
|
47 |
+
cur_seq_label = f"seqnum{line_idx:09d}"
|
48 |
+
else: # sequence line
|
49 |
+
buf.append(line.strip())
|
50 |
+
|
51 |
+
_flush_current_seq()
|
52 |
+
|
53 |
+
assert len(set(sequence_labels)) == len(
|
54 |
+
sequence_labels
|
55 |
+
), "Found duplicate sequence labels"
|
56 |
+
|
57 |
+
return cls(sequence_labels, sequence_strs)
|
58 |
+
|
59 |
+
def __len__(self):
|
60 |
+
return len(self.sequence_labels)
|
61 |
+
|
62 |
+
def __getitem__(self, idx):
|
63 |
+
return self.sequence_labels[idx], self.sequence_strs[idx]
|
64 |
+
|
65 |
+
def get_batch_indices(self, toks_per_batch, extra_toks_per_seq=0):
|
66 |
+
sizes = [(len(s), i) for i, s in enumerate(self.sequence_strs)]
|
67 |
+
sizes.sort()
|
68 |
+
batches = []
|
69 |
+
buf = []
|
70 |
+
max_len = 0
|
71 |
+
|
72 |
+
def _flush_current_buf():
|
73 |
+
nonlocal max_len, buf
|
74 |
+
if len(buf) == 0:
|
75 |
+
return
|
76 |
+
batches.append(buf)
|
77 |
+
buf = []
|
78 |
+
max_len = 0
|
79 |
+
|
80 |
+
for sz, i in sizes:
|
81 |
+
sz += extra_toks_per_seq
|
82 |
+
if max(sz, max_len) * (len(buf) + 1) > toks_per_batch:
|
83 |
+
_flush_current_buf()
|
84 |
+
max_len = max(max_len, sz)
|
85 |
+
buf.append(i)
|
86 |
+
|
87 |
+
_flush_current_buf()
|
88 |
+
return batches
|
89 |
+
|
90 |
+
|
91 |
+
class Alphabet(object):
|
92 |
+
def __init__(
|
93 |
+
self,
|
94 |
+
standard_toks: Sequence[str],
|
95 |
+
prepend_toks: Sequence[str] = ("<null_0>", "<pad>", "<eos>", "<unk>"),
|
96 |
+
append_toks: Sequence[str] = ("<cls>", "<mask>", "<sep>"),
|
97 |
+
prepend_bos: bool = True,
|
98 |
+
append_eos: bool = False,
|
99 |
+
use_msa: bool = False,
|
100 |
+
):
|
101 |
+
self.standard_toks = list(standard_toks)
|
102 |
+
self.prepend_toks = list(prepend_toks)
|
103 |
+
self.append_toks = list(append_toks)
|
104 |
+
self.prepend_bos = prepend_bos
|
105 |
+
self.append_eos = append_eos
|
106 |
+
self.use_msa = use_msa
|
107 |
+
|
108 |
+
self.all_toks = list(self.prepend_toks)
|
109 |
+
self.all_toks.extend(self.standard_toks)
|
110 |
+
for i in range((8 - (len(self.all_toks) % 8)) % 8):
|
111 |
+
self.all_toks.append(f"<null_{i + 1}>")
|
112 |
+
self.all_toks.extend(self.append_toks)
|
113 |
+
|
114 |
+
self.tok_to_idx = {tok: i for i, tok in enumerate(self.all_toks)}
|
115 |
+
|
116 |
+
self.unk_idx = self.tok_to_idx["<unk>"]
|
117 |
+
self.padding_idx = self.get_idx("<pad>")
|
118 |
+
self.cls_idx = self.get_idx("<cls>")
|
119 |
+
self.mask_idx = self.get_idx("<mask>")
|
120 |
+
self.eos_idx = self.get_idx("<eos>")
|
121 |
+
self.all_special_tokens = ['<eos>', '<unk>', '<pad>', '<cls>', '<mask>']
|
122 |
+
self.unique_no_split_tokens = self.all_toks
|
123 |
+
|
124 |
+
def __len__(self):
|
125 |
+
return len(self.all_toks)
|
126 |
+
|
127 |
+
def get_idx(self, tok):
|
128 |
+
return self.tok_to_idx.get(tok, self.unk_idx)
|
129 |
+
|
130 |
+
def get_tok(self, ind):
|
131 |
+
return self.all_toks[ind]
|
132 |
+
|
133 |
+
def to_dict(self):
|
134 |
+
return self.tok_to_idx.copy()
|
135 |
+
|
136 |
+
def get_batch_converter(self, truncation_seq_length: int = None):
|
137 |
+
if self.use_msa:
|
138 |
+
return MSABatchConverter(self, truncation_seq_length)
|
139 |
+
else:
|
140 |
+
return BatchConverter(self, truncation_seq_length)
|
141 |
+
|
142 |
+
@classmethod
|
143 |
+
def from_architecture(cls, name: str) -> "Alphabet":
|
144 |
+
if name in ("ESM-1", "protein_bert_base"):
|
145 |
+
standard_toks = proteinseq_toks["toks"]
|
146 |
+
prepend_toks: Tuple[str, ...] = ("<null_0>", "<pad>", "<eos>", "<unk>")
|
147 |
+
append_toks: Tuple[str, ...] = ("<cls>", "<mask>", "<sep>")
|
148 |
+
prepend_bos = True
|
149 |
+
append_eos = False
|
150 |
+
use_msa = False
|
151 |
+
elif name in ("ESM-1b", "roberta_large"):
|
152 |
+
standard_toks = proteinseq_toks["toks"]
|
153 |
+
prepend_toks = ("<cls>", "<pad>", "<eos>", "<unk>")
|
154 |
+
append_toks = ("<mask>",)
|
155 |
+
prepend_bos = True
|
156 |
+
append_eos = True
|
157 |
+
use_msa = False
|
158 |
+
elif name in ("MSA Transformer", "msa_transformer"):
|
159 |
+
standard_toks = proteinseq_toks["toks"]
|
160 |
+
prepend_toks = ("<cls>", "<pad>", "<eos>", "<unk>")
|
161 |
+
append_toks = ("<mask>",)
|
162 |
+
prepend_bos = True
|
163 |
+
append_eos = False
|
164 |
+
use_msa = True
|
165 |
+
elif "invariant_gvp" in name.lower():
|
166 |
+
standard_toks = proteinseq_toks["toks"]
|
167 |
+
prepend_toks = ("<null_0>", "<pad>", "<eos>", "<unk>")
|
168 |
+
append_toks = ("<mask>", "<cath>", "<af2>")
|
169 |
+
prepend_bos = True
|
170 |
+
append_eos = False
|
171 |
+
use_msa = False
|
172 |
+
else:
|
173 |
+
raise ValueError("Unknown architecture selected")
|
174 |
+
return cls(standard_toks, prepend_toks, append_toks, prepend_bos, append_eos, use_msa)
|
175 |
+
|
176 |
+
def _tokenize(self, text) -> str:
|
177 |
+
return text.split()
|
178 |
+
|
179 |
+
def tokenize(self, text, **kwargs) -> List[str]:
|
180 |
+
"""
|
181 |
+
Inspired by https://github.com/huggingface/transformers/blob/master/src/transformers/tokenization_utils.py
|
182 |
+
Converts a string in a sequence of tokens, using the tokenizer.
|
183 |
+
|
184 |
+
Args:
|
185 |
+
text (:obj:`str`):
|
186 |
+
The sequence to be encoded.
|
187 |
+
|
188 |
+
Returns:
|
189 |
+
:obj:`List[str]`: The list of tokens.
|
190 |
+
"""
|
191 |
+
|
192 |
+
def split_on_token(tok, text):
|
193 |
+
result = []
|
194 |
+
split_text = text.split(tok)
|
195 |
+
for i, sub_text in enumerate(split_text):
|
196 |
+
# AddedToken can control whitespace stripping around them.
|
197 |
+
# We use them for GPT2 and Roberta to have different behavior depending on the special token
|
198 |
+
# Cf. https://github.com/huggingface/transformers/pull/2778
|
199 |
+
# and https://github.com/huggingface/transformers/issues/3788
|
200 |
+
# We strip left and right by default
|
201 |
+
if i < len(split_text) - 1:
|
202 |
+
sub_text = sub_text.rstrip()
|
203 |
+
if i > 0:
|
204 |
+
sub_text = sub_text.lstrip()
|
205 |
+
|
206 |
+
if i == 0 and not sub_text:
|
207 |
+
result.append(tok)
|
208 |
+
elif i == len(split_text) - 1:
|
209 |
+
if sub_text:
|
210 |
+
result.append(sub_text)
|
211 |
+
else:
|
212 |
+
pass
|
213 |
+
else:
|
214 |
+
if sub_text:
|
215 |
+
result.append(sub_text)
|
216 |
+
result.append(tok)
|
217 |
+
return result
|
218 |
+
|
219 |
+
def split_on_tokens(tok_list, text):
|
220 |
+
if not text.strip():
|
221 |
+
return []
|
222 |
+
|
223 |
+
tokenized_text = []
|
224 |
+
text_list = [text]
|
225 |
+
for tok in tok_list:
|
226 |
+
tokenized_text = []
|
227 |
+
for sub_text in text_list:
|
228 |
+
if sub_text not in self.unique_no_split_tokens:
|
229 |
+
tokenized_text.extend(split_on_token(tok, sub_text))
|
230 |
+
else:
|
231 |
+
tokenized_text.append(sub_text)
|
232 |
+
text_list = tokenized_text
|
233 |
+
|
234 |
+
return list(
|
235 |
+
itertools.chain.from_iterable(
|
236 |
+
(
|
237 |
+
self._tokenize(token)
|
238 |
+
if token not in self.unique_no_split_tokens
|
239 |
+
else [token]
|
240 |
+
for token in tokenized_text
|
241 |
+
)
|
242 |
+
)
|
243 |
+
)
|
244 |
+
|
245 |
+
no_split_token = self.unique_no_split_tokens
|
246 |
+
tokenized_text = split_on_tokens(no_split_token, text)
|
247 |
+
return tokenized_text
|
248 |
+
|
249 |
+
def encode(self, text):
|
250 |
+
return [self.tok_to_idx[tok] for tok in self.tokenize(text)]
|
251 |
+
|
252 |
+
|
253 |
+
class BatchConverter(object):
|
254 |
+
"""Callable to convert an unprocessed (labels + strings) batch to a
|
255 |
+
processed (labels + tensor) batch.
|
256 |
+
"""
|
257 |
+
|
258 |
+
def __init__(self, alphabet, truncation_seq_length: int = None):
|
259 |
+
self.alphabet = alphabet
|
260 |
+
self.truncation_seq_length = truncation_seq_length
|
261 |
+
|
262 |
+
def __call__(self, raw_batch: Sequence[Tuple[str, str]]):
|
263 |
+
# RoBERTa uses an eos token, while ESM-1 does not.
|
264 |
+
batch_size = len(raw_batch)
|
265 |
+
batch_labels, seq_str_list = zip(*raw_batch)
|
266 |
+
seq_encoded_list = [self.alphabet.encode(seq_str) for seq_str in seq_str_list]
|
267 |
+
if self.truncation_seq_length:
|
268 |
+
seq_encoded_list = [seq_str[:self.truncation_seq_length] for seq_str in seq_encoded_list]
|
269 |
+
max_len = max(len(seq_encoded) for seq_encoded in seq_encoded_list)
|
270 |
+
tokens = torch.empty(
|
271 |
+
(
|
272 |
+
batch_size,
|
273 |
+
max_len + int(self.alphabet.prepend_bos) + int(self.alphabet.append_eos),
|
274 |
+
),
|
275 |
+
dtype=torch.int64,
|
276 |
+
)
|
277 |
+
tokens.fill_(self.alphabet.padding_idx)
|
278 |
+
labels = []
|
279 |
+
strs = []
|
280 |
+
|
281 |
+
for i, (label, seq_str, seq_encoded) in enumerate(
|
282 |
+
zip(batch_labels, seq_str_list, seq_encoded_list)
|
283 |
+
):
|
284 |
+
labels.append(label)
|
285 |
+
strs.append(seq_str)
|
286 |
+
if self.alphabet.prepend_bos:
|
287 |
+
tokens[i, 0] = self.alphabet.cls_idx
|
288 |
+
seq = torch.tensor(seq_encoded, dtype=torch.int64)
|
289 |
+
tokens[
|
290 |
+
i,
|
291 |
+
int(self.alphabet.prepend_bos) : len(seq_encoded)
|
292 |
+
+ int(self.alphabet.prepend_bos),
|
293 |
+
] = seq
|
294 |
+
if self.alphabet.append_eos:
|
295 |
+
tokens[i, len(seq_encoded) + int(self.alphabet.prepend_bos)] = self.alphabet.eos_idx
|
296 |
+
|
297 |
+
return labels, strs, tokens
|
298 |
+
|
299 |
+
|
300 |
+
class MSABatchConverter(BatchConverter):
|
301 |
+
def __call__(self, inputs: Union[Sequence[RawMSA], RawMSA]):
|
302 |
+
if isinstance(inputs[0][0], str):
|
303 |
+
# Input is a single MSA
|
304 |
+
raw_batch: Sequence[RawMSA] = [inputs] # type: ignore
|
305 |
+
else:
|
306 |
+
raw_batch = inputs # type: ignore
|
307 |
+
|
308 |
+
batch_size = len(raw_batch)
|
309 |
+
max_alignments = max(len(msa) for msa in raw_batch)
|
310 |
+
max_seqlen = max(len(msa[0][1]) for msa in raw_batch)
|
311 |
+
|
312 |
+
tokens = torch.empty(
|
313 |
+
(
|
314 |
+
batch_size,
|
315 |
+
max_alignments,
|
316 |
+
max_seqlen + int(self.alphabet.prepend_bos) + int(self.alphabet.append_eos),
|
317 |
+
),
|
318 |
+
dtype=torch.int64,
|
319 |
+
)
|
320 |
+
tokens.fill_(self.alphabet.padding_idx)
|
321 |
+
labels = []
|
322 |
+
strs = []
|
323 |
+
|
324 |
+
for i, msa in enumerate(raw_batch):
|
325 |
+
msa_seqlens = set(len(seq) for _, seq in msa)
|
326 |
+
if not len(msa_seqlens) == 1:
|
327 |
+
raise RuntimeError(
|
328 |
+
"Received unaligned sequences for input to MSA, all sequence "
|
329 |
+
"lengths must be equal."
|
330 |
+
)
|
331 |
+
msa_labels, msa_strs, msa_tokens = super().__call__(msa)
|
332 |
+
labels.append(msa_labels)
|
333 |
+
strs.append(msa_strs)
|
334 |
+
tokens[i, : msa_tokens.size(0), : msa_tokens.size(1)] = msa_tokens
|
335 |
+
|
336 |
+
return labels, strs, tokens
|
337 |
+
|
338 |
+
|
339 |
+
def read_fasta(
|
340 |
+
path,
|
341 |
+
keep_gaps=True,
|
342 |
+
keep_insertions=True,
|
343 |
+
to_upper=False,
|
344 |
+
):
|
345 |
+
with open(path, "r") as f:
|
346 |
+
for result in read_alignment_lines(
|
347 |
+
f, keep_gaps=keep_gaps, keep_insertions=keep_insertions, to_upper=to_upper
|
348 |
+
):
|
349 |
+
yield result
|
350 |
+
|
351 |
+
|
352 |
+
def read_alignment_lines(
|
353 |
+
lines,
|
354 |
+
keep_gaps=True,
|
355 |
+
keep_insertions=True,
|
356 |
+
to_upper=False,
|
357 |
+
):
|
358 |
+
seq = desc = None
|
359 |
+
|
360 |
+
def parse(s):
|
361 |
+
if not keep_gaps:
|
362 |
+
s = re.sub("-", "", s)
|
363 |
+
if not keep_insertions:
|
364 |
+
s = re.sub("[a-z]", "", s)
|
365 |
+
return s.upper() if to_upper else s
|
366 |
+
|
367 |
+
for line in lines:
|
368 |
+
# Line may be empty if seq % file_line_width == 0
|
369 |
+
if len(line) > 0 and line[0] == ">":
|
370 |
+
if seq is not None:
|
371 |
+
yield desc, parse(seq)
|
372 |
+
desc = line.strip()
|
373 |
+
seq = ""
|
374 |
+
else:
|
375 |
+
assert isinstance(seq, str)
|
376 |
+
seq += line.strip()
|
377 |
+
assert isinstance(seq, str) and isinstance(desc, str)
|
378 |
+
yield desc, parse(seq)
|
379 |
+
|
380 |
+
|
381 |
+
class ESMStructuralSplitDataset(torch.utils.data.Dataset):
|
382 |
+
"""
|
383 |
+
Structural Split Dataset as described in section A.10 of the supplement of our paper.
|
384 |
+
https://doi.org/10.1101/622803
|
385 |
+
|
386 |
+
We use the full version of SCOPe 2.07, clustered at 90% sequence identity,
|
387 |
+
generated on January 23, 2020.
|
388 |
+
|
389 |
+
For each SCOPe domain:
|
390 |
+
- We extract the sequence from the corresponding PDB file
|
391 |
+
- We extract the 3D coordinates of the Carbon beta atoms, aligning them
|
392 |
+
to the sequence. We put NaN where Cb atoms are missing.
|
393 |
+
- From the 3D coordinates, we calculate a pairwise distance map, based
|
394 |
+
on L2 distance
|
395 |
+
- We use DSSP to generate secondary structure labels for the corresponding
|
396 |
+
PDB file. This is also aligned to the sequence. We put - where SSP
|
397 |
+
labels are missing.
|
398 |
+
|
399 |
+
For each SCOPe classification level of family/superfamily/fold (in order of difficulty),
|
400 |
+
we have split the data into 5 partitions for cross validation. These are provided
|
401 |
+
in a downloaded splits folder, in the format:
|
402 |
+
splits/{split_level}/{cv_partition}/{train|valid}.txt
|
403 |
+
where train is the partition and valid is the concatentation of the remaining 4.
|
404 |
+
|
405 |
+
For each SCOPe domain, we provide a pkl dump that contains:
|
406 |
+
- seq : The domain sequence, stored as an L-length string
|
407 |
+
- ssp : The secondary structure labels, stored as an L-length string
|
408 |
+
- dist : The distance map, stored as an LxL numpy array
|
409 |
+
- coords : The 3D coordinates, stored as an Lx3 numpy array
|
410 |
+
|
411 |
+
"""
|
412 |
+
|
413 |
+
base_folder = "structural-data"
|
414 |
+
file_list = [
|
415 |
+
# url tar filename filename MD5 Hash
|
416 |
+
(
|
417 |
+
"https://dl.fbaipublicfiles.com/fair-esm/structural-data/splits.tar.gz",
|
418 |
+
"splits.tar.gz",
|
419 |
+
"splits",
|
420 |
+
"456fe1c7f22c9d3d8dfe9735da52411d",
|
421 |
+
),
|
422 |
+
(
|
423 |
+
"https://dl.fbaipublicfiles.com/fair-esm/structural-data/pkl.tar.gz",
|
424 |
+
"pkl.tar.gz",
|
425 |
+
"pkl",
|
426 |
+
"644ea91e56066c750cd50101d390f5db",
|
427 |
+
),
|
428 |
+
]
|
429 |
+
|
430 |
+
def __init__(
|
431 |
+
self,
|
432 |
+
split_level,
|
433 |
+
cv_partition,
|
434 |
+
split,
|
435 |
+
root_path=os.path.expanduser("~/.cache/torch/data/esm"),
|
436 |
+
download=False,
|
437 |
+
):
|
438 |
+
super().__init__()
|
439 |
+
assert split in [
|
440 |
+
"train",
|
441 |
+
"valid",
|
442 |
+
], "train_valid must be 'train' or 'valid'"
|
443 |
+
self.root_path = root_path
|
444 |
+
self.base_path = os.path.join(self.root_path, self.base_folder)
|
445 |
+
|
446 |
+
# check if root path has what you need or else download it
|
447 |
+
if download:
|
448 |
+
self.download()
|
449 |
+
|
450 |
+
self.split_file = os.path.join(
|
451 |
+
self.base_path, "splits", split_level, cv_partition, f"{split}.txt"
|
452 |
+
)
|
453 |
+
self.pkl_dir = os.path.join(self.base_path, "pkl")
|
454 |
+
self.names = []
|
455 |
+
with open(self.split_file) as f:
|
456 |
+
self.names = f.read().splitlines()
|
457 |
+
|
458 |
+
def __len__(self):
|
459 |
+
return len(self.names)
|
460 |
+
|
461 |
+
def _check_exists(self) -> bool:
|
462 |
+
for (_, _, filename, _) in self.file_list:
|
463 |
+
fpath = os.path.join(self.base_path, filename)
|
464 |
+
if not os.path.exists(fpath) or not os.path.isdir(fpath):
|
465 |
+
return False
|
466 |
+
return True
|
467 |
+
|
468 |
+
def download(self):
|
469 |
+
|
470 |
+
if self._check_exists():
|
471 |
+
print("Files already downloaded and verified")
|
472 |
+
return
|
473 |
+
|
474 |
+
from torchvision.datasets.utils import download_url
|
475 |
+
|
476 |
+
for url, tar_filename, filename, md5_hash in self.file_list:
|
477 |
+
download_path = os.path.join(self.base_path, tar_filename)
|
478 |
+
download_url(url=url, root=self.base_path, filename=tar_filename, md5=md5_hash)
|
479 |
+
shutil.unpack_archive(download_path, self.base_path)
|
480 |
+
|
481 |
+
def __getitem__(self, idx):
|
482 |
+
"""
|
483 |
+
Returns a dict with the following entires
|
484 |
+
- seq : Str (domain sequence)
|
485 |
+
- ssp : Str (SSP labels)
|
486 |
+
- dist : np.array (distance map)
|
487 |
+
- coords : np.array (3D coordinates)
|
488 |
+
"""
|
489 |
+
name = self.names[idx]
|
490 |
+
pkl_fname = os.path.join(self.pkl_dir, name[1:3], f"{name}.pkl")
|
491 |
+
with open(pkl_fname, "rb") as f:
|
492 |
+
obj = pickle.load(f)
|
493 |
+
return obj
|
esm/esm/inverse_folding/__init__.py
ADDED
@@ -0,0 +1,8 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Copyright (c) Facebook, Inc. and its affiliates.
|
2 |
+
#
|
3 |
+
# This source code is licensed under the MIT license found in the
|
4 |
+
# LICENSE file in the root directory of this source tree.
|
5 |
+
|
6 |
+
from . import gvp_transformer
|
7 |
+
from . import util
|
8 |
+
from . import multichain_util
|
esm/esm/inverse_folding/features.py
ADDED
@@ -0,0 +1,352 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Copyright (c) Facebook, Inc. and its affiliates.
|
2 |
+
#
|
3 |
+
# This source code is licensed under the MIT license found in the
|
4 |
+
# LICENSE file in the root directory of this source tree.
|
5 |
+
#
|
6 |
+
# Portions of this file were adapted from the open source code for the following
|
7 |
+
# two papers:
|
8 |
+
#
|
9 |
+
# Ingraham, J., Garg, V., Barzilay, R., & Jaakkola, T. (2019). Generative
|
10 |
+
# models for graph-based protein design. Advances in Neural Information
|
11 |
+
# Processing Systems, 32.
|
12 |
+
#
|
13 |
+
# Jing, B., Eismann, S., Suriana, P., Townshend, R. J. L., & Dror, R. (2020).
|
14 |
+
# Learning from Protein Structure with Geometric Vector Perceptrons. In
|
15 |
+
# International Conference on Learning Representations.
|
16 |
+
#
|
17 |
+
# MIT License
|
18 |
+
#
|
19 |
+
# Copyright (c) 2020 Bowen Jing, Stephan Eismann, Patricia Suriana, Raphael Townshend, Ron Dror
|
20 |
+
#
|
21 |
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
22 |
+
# of this software and associated documentation files (the "Software"), to deal
|
23 |
+
# in the Software without restriction, including without limitation the rights
|
24 |
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
25 |
+
# copies of the Software, and to permit persons to whom the Software is
|
26 |
+
# furnished to do so, subject to the following conditions:
|
27 |
+
#
|
28 |
+
# The above copyright notice and this permission notice shall be included in all
|
29 |
+
# copies or substantial portions of the Software.
|
30 |
+
#
|
31 |
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
32 |
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
33 |
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
34 |
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
35 |
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
36 |
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
37 |
+
# SOFTWARE.
|
38 |
+
#
|
39 |
+
# ================================================================
|
40 |
+
# The below license applies to the portions of the code (parts of
|
41 |
+
# src/datasets.py and src/models.py) adapted from Ingraham, et al.
|
42 |
+
# ================================================================
|
43 |
+
#
|
44 |
+
# MIT License
|
45 |
+
#
|
46 |
+
# Copyright (c) 2019 John Ingraham, Vikas Garg, Regina Barzilay, Tommi Jaakkola
|
47 |
+
#
|
48 |
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
49 |
+
# of this software and associated documentation files (the "Software"), to deal
|
50 |
+
# in the Software without restriction, including without limitation the rights
|
51 |
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
52 |
+
# copies of the Software, and to permit persons to whom the Software is
|
53 |
+
# furnished to do so, subject to the following conditions:
|
54 |
+
#
|
55 |
+
# The above copyright notice and this permission notice shall be included in all
|
56 |
+
# copies or substantial portions of the Software.
|
57 |
+
#
|
58 |
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
59 |
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
60 |
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
61 |
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
62 |
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
63 |
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
64 |
+
# SOFTWARE.
|
65 |
+
|
66 |
+
import math
|
67 |
+
import numpy as np
|
68 |
+
import torch
|
69 |
+
import torch.nn as nn
|
70 |
+
import torch.nn.functional as F
|
71 |
+
|
72 |
+
from .gvp_utils import flatten_graph
|
73 |
+
from .gvp_modules import GVP, LayerNorm
|
74 |
+
from .util import normalize, norm, nan_to_num, rbf
|
75 |
+
|
76 |
+
|
77 |
+
class GVPInputFeaturizer(nn.Module):
|
78 |
+
|
79 |
+
@staticmethod
|
80 |
+
def get_node_features(coords, coord_mask, with_coord_mask=True):
|
81 |
+
# scalar features
|
82 |
+
node_scalar_features = GVPInputFeaturizer._dihedrals(coords)
|
83 |
+
if with_coord_mask:
|
84 |
+
node_scalar_features = torch.cat([
|
85 |
+
node_scalar_features,
|
86 |
+
coord_mask.float().unsqueeze(-1)
|
87 |
+
], dim=-1)
|
88 |
+
# vector features
|
89 |
+
X_ca = coords[:, :, 1]
|
90 |
+
orientations = GVPInputFeaturizer._orientations(X_ca)
|
91 |
+
sidechains = GVPInputFeaturizer._sidechains(coords)
|
92 |
+
node_vector_features = torch.cat([orientations, sidechains.unsqueeze(-2)], dim=-2)
|
93 |
+
return node_scalar_features, node_vector_features
|
94 |
+
|
95 |
+
@staticmethod
|
96 |
+
def _orientations(X):
|
97 |
+
forward = normalize(X[:, 1:] - X[:, :-1])
|
98 |
+
backward = normalize(X[:, :-1] - X[:, 1:])
|
99 |
+
forward = F.pad(forward, [0, 0, 0, 1])
|
100 |
+
backward = F.pad(backward, [0, 0, 1, 0])
|
101 |
+
return torch.cat([forward.unsqueeze(-2), backward.unsqueeze(-2)], -2)
|
102 |
+
|
103 |
+
@staticmethod
|
104 |
+
def _sidechains(X):
|
105 |
+
n, origin, c = X[:, :, 0], X[:, :, 1], X[:, :, 2]
|
106 |
+
c, n = normalize(c - origin), normalize(n - origin)
|
107 |
+
bisector = normalize(c + n)
|
108 |
+
perp = normalize(torch.cross(c, n, dim=-1))
|
109 |
+
vec = -bisector * math.sqrt(1 / 3) - perp * math.sqrt(2 / 3)
|
110 |
+
return vec
|
111 |
+
|
112 |
+
@staticmethod
|
113 |
+
def _dihedrals(X, eps=1e-7):
|
114 |
+
X = torch.flatten(X[:, :, :3], 1, 2)
|
115 |
+
bsz = X.shape[0]
|
116 |
+
dX = X[:, 1:] - X[:, :-1]
|
117 |
+
U = normalize(dX, dim=-1)
|
118 |
+
u_2 = U[:, :-2]
|
119 |
+
u_1 = U[:, 1:-1]
|
120 |
+
u_0 = U[:, 2:]
|
121 |
+
|
122 |
+
# Backbone normals
|
123 |
+
n_2 = normalize(torch.cross(u_2, u_1, dim=-1), dim=-1)
|
124 |
+
n_1 = normalize(torch.cross(u_1, u_0, dim=-1), dim=-1)
|
125 |
+
|
126 |
+
# Angle between normals
|
127 |
+
cosD = torch.sum(n_2 * n_1, -1)
|
128 |
+
cosD = torch.clamp(cosD, -1 + eps, 1 - eps)
|
129 |
+
D = torch.sign(torch.sum(u_2 * n_1, -1)) * torch.acos(cosD)
|
130 |
+
|
131 |
+
# This scheme will remove phi[0], psi[-1], omega[-1]
|
132 |
+
D = F.pad(D, [1, 2])
|
133 |
+
D = torch.reshape(D, [bsz, -1, 3])
|
134 |
+
# Lift angle representations to the circle
|
135 |
+
D_features = torch.cat([torch.cos(D), torch.sin(D)], -1)
|
136 |
+
return D_features
|
137 |
+
|
138 |
+
@staticmethod
|
139 |
+
def _positional_embeddings(edge_index,
|
140 |
+
num_embeddings=None,
|
141 |
+
num_positional_embeddings=16,
|
142 |
+
period_range=[2, 1000]):
|
143 |
+
# From https://github.com/jingraham/neurips19-graph-protein-design
|
144 |
+
num_embeddings = num_embeddings or num_positional_embeddings
|
145 |
+
d = edge_index[0] - edge_index[1]
|
146 |
+
|
147 |
+
frequency = torch.exp(
|
148 |
+
torch.arange(0, num_embeddings, 2, dtype=torch.float32,
|
149 |
+
device=edge_index.device)
|
150 |
+
* -(np.log(10000.0) / num_embeddings)
|
151 |
+
)
|
152 |
+
angles = d.unsqueeze(-1) * frequency
|
153 |
+
E = torch.cat((torch.cos(angles), torch.sin(angles)), -1)
|
154 |
+
return E
|
155 |
+
|
156 |
+
@staticmethod
|
157 |
+
def _dist(X, coord_mask, padding_mask, top_k_neighbors, eps=1e-8):
|
158 |
+
""" Pairwise euclidean distances """
|
159 |
+
bsz, maxlen = X.size(0), X.size(1)
|
160 |
+
coord_mask_2D = torch.unsqueeze(coord_mask,1) * torch.unsqueeze(coord_mask,2)
|
161 |
+
residue_mask = ~padding_mask
|
162 |
+
residue_mask_2D = torch.unsqueeze(residue_mask,1) * torch.unsqueeze(residue_mask,2)
|
163 |
+
dX = torch.unsqueeze(X,1) - torch.unsqueeze(X,2)
|
164 |
+
D = coord_mask_2D * norm(dX, dim=-1)
|
165 |
+
|
166 |
+
# sorting preference: first those with coords, then among the residues that
|
167 |
+
# exist but are masked use distance in sequence as tie breaker, and then the
|
168 |
+
# residues that came from padding are last
|
169 |
+
seqpos = torch.arange(maxlen, device=X.device)
|
170 |
+
Dseq = torch.abs(seqpos.unsqueeze(1) - seqpos.unsqueeze(0)).repeat(bsz, 1, 1)
|
171 |
+
D_adjust = nan_to_num(D) + (~coord_mask_2D) * (1e8 + Dseq*1e6) + (
|
172 |
+
~residue_mask_2D) * (1e10)
|
173 |
+
|
174 |
+
if top_k_neighbors == -1:
|
175 |
+
D_neighbors = D_adjust
|
176 |
+
E_idx = seqpos.repeat(
|
177 |
+
*D_neighbors.shape[:-1], 1)
|
178 |
+
else:
|
179 |
+
# Identify k nearest neighbors (including self)
|
180 |
+
k = min(top_k_neighbors, X.size(1))
|
181 |
+
D_neighbors, E_idx = torch.topk(D_adjust, k, dim=-1, largest=False)
|
182 |
+
|
183 |
+
coord_mask_neighbors = (D_neighbors < 5e7)
|
184 |
+
residue_mask_neighbors = (D_neighbors < 5e9)
|
185 |
+
return D_neighbors, E_idx, coord_mask_neighbors, residue_mask_neighbors
|
186 |
+
|
187 |
+
|
188 |
+
class Normalize(nn.Module):
|
189 |
+
def __init__(self, features, epsilon=1e-6):
|
190 |
+
super(Normalize, self).__init__()
|
191 |
+
self.gain = nn.Parameter(torch.ones(features))
|
192 |
+
self.bias = nn.Parameter(torch.zeros(features))
|
193 |
+
self.epsilon = epsilon
|
194 |
+
|
195 |
+
def forward(self, x, dim=-1):
|
196 |
+
mu = x.mean(dim, keepdim=True)
|
197 |
+
sigma = torch.sqrt(x.var(dim, keepdim=True) + self.epsilon)
|
198 |
+
gain = self.gain
|
199 |
+
bias = self.bias
|
200 |
+
# Reshape
|
201 |
+
if dim != -1:
|
202 |
+
shape = [1] * len(mu.size())
|
203 |
+
shape[dim] = self.gain.size()[0]
|
204 |
+
gain = gain.view(shape)
|
205 |
+
bias = bias.view(shape)
|
206 |
+
return gain * (x - mu) / (sigma + self.epsilon) + bias
|
207 |
+
|
208 |
+
|
209 |
+
class DihedralFeatures(nn.Module):
|
210 |
+
def __init__(self, node_embed_dim):
|
211 |
+
""" Embed dihedral angle features. """
|
212 |
+
super(DihedralFeatures, self).__init__()
|
213 |
+
# 3 dihedral angles; sin and cos of each angle
|
214 |
+
node_in = 6
|
215 |
+
# Normalization and embedding
|
216 |
+
self.node_embedding = nn.Linear(node_in, node_embed_dim, bias=True)
|
217 |
+
self.norm_nodes = Normalize(node_embed_dim)
|
218 |
+
|
219 |
+
def forward(self, X):
|
220 |
+
""" Featurize coordinates as an attributed graph """
|
221 |
+
V = self._dihedrals(X)
|
222 |
+
V = self.node_embedding(V)
|
223 |
+
V = self.norm_nodes(V)
|
224 |
+
return V
|
225 |
+
|
226 |
+
@staticmethod
|
227 |
+
def _dihedrals(X, eps=1e-7, return_angles=False):
|
228 |
+
# First 3 coordinates are N, CA, C
|
229 |
+
X = X[:,:,:3,:].reshape(X.shape[0], 3*X.shape[1], 3)
|
230 |
+
|
231 |
+
# Shifted slices of unit vectors
|
232 |
+
dX = X[:,1:,:] - X[:,:-1,:]
|
233 |
+
U = F.normalize(dX, dim=-1)
|
234 |
+
u_2 = U[:,:-2,:]
|
235 |
+
u_1 = U[:,1:-1,:]
|
236 |
+
u_0 = U[:,2:,:]
|
237 |
+
# Backbone normals
|
238 |
+
n_2 = F.normalize(torch.cross(u_2, u_1, dim=-1), dim=-1)
|
239 |
+
n_1 = F.normalize(torch.cross(u_1, u_0, dim=-1), dim=-1)
|
240 |
+
|
241 |
+
# Angle between normals
|
242 |
+
cosD = (n_2 * n_1).sum(-1)
|
243 |
+
cosD = torch.clamp(cosD, -1+eps, 1-eps)
|
244 |
+
D = torch.sign((u_2 * n_1).sum(-1)) * torch.acos(cosD)
|
245 |
+
|
246 |
+
# This scheme will remove phi[0], psi[-1], omega[-1]
|
247 |
+
D = F.pad(D, (1,2), 'constant', 0)
|
248 |
+
D = D.view((D.size(0), int(D.size(1)/3), 3))
|
249 |
+
phi, psi, omega = torch.unbind(D,-1)
|
250 |
+
|
251 |
+
if return_angles:
|
252 |
+
return phi, psi, omega
|
253 |
+
|
254 |
+
# Lift angle representations to the circle
|
255 |
+
D_features = torch.cat((torch.cos(D), torch.sin(D)), 2)
|
256 |
+
return D_features
|
257 |
+
|
258 |
+
|
259 |
+
class GVPGraphEmbedding(GVPInputFeaturizer):
|
260 |
+
|
261 |
+
def __init__(self, args):
|
262 |
+
super().__init__()
|
263 |
+
self.top_k_neighbors = args.top_k_neighbors
|
264 |
+
self.num_positional_embeddings = 16
|
265 |
+
self.remove_edges_without_coords = True
|
266 |
+
node_input_dim = (7, 3)
|
267 |
+
edge_input_dim = (34, 1)
|
268 |
+
node_hidden_dim = (args.node_hidden_dim_scalar,
|
269 |
+
args.node_hidden_dim_vector)
|
270 |
+
edge_hidden_dim = (args.edge_hidden_dim_scalar,
|
271 |
+
args.edge_hidden_dim_vector)
|
272 |
+
self.embed_node = nn.Sequential(
|
273 |
+
GVP(node_input_dim, node_hidden_dim, activations=(None, None)),
|
274 |
+
LayerNorm(node_hidden_dim, eps=1e-4)
|
275 |
+
)
|
276 |
+
self.embed_edge = nn.Sequential(
|
277 |
+
GVP(edge_input_dim, edge_hidden_dim, activations=(None, None)),
|
278 |
+
LayerNorm(edge_hidden_dim, eps=1e-4)
|
279 |
+
)
|
280 |
+
self.embed_confidence = nn.Linear(16, args.node_hidden_dim_scalar)
|
281 |
+
|
282 |
+
def forward(self, coords, coord_mask, padding_mask, confidence):
|
283 |
+
with torch.no_grad():
|
284 |
+
node_features = self.get_node_features(coords, coord_mask)
|
285 |
+
edge_features, edge_index = self.get_edge_features(
|
286 |
+
coords, coord_mask, padding_mask)
|
287 |
+
node_embeddings_scalar, node_embeddings_vector = self.embed_node(node_features)
|
288 |
+
edge_embeddings = self.embed_edge(edge_features)
|
289 |
+
|
290 |
+
rbf_rep = rbf(confidence, 0., 1.)
|
291 |
+
node_embeddings = (
|
292 |
+
node_embeddings_scalar + self.embed_confidence(rbf_rep),
|
293 |
+
node_embeddings_vector
|
294 |
+
)
|
295 |
+
|
296 |
+
node_embeddings, edge_embeddings, edge_index = flatten_graph(
|
297 |
+
node_embeddings, edge_embeddings, edge_index)
|
298 |
+
return node_embeddings, edge_embeddings, edge_index
|
299 |
+
|
300 |
+
def get_edge_features(self, coords, coord_mask, padding_mask):
|
301 |
+
X_ca = coords[:, :, 1]
|
302 |
+
# Get distances to the top k neighbors
|
303 |
+
E_dist, E_idx, E_coord_mask, E_residue_mask = GVPInputFeaturizer._dist(
|
304 |
+
X_ca, coord_mask, padding_mask, self.top_k_neighbors)
|
305 |
+
# Flatten the graph to be batch size 1 for torch_geometric package
|
306 |
+
dest = E_idx
|
307 |
+
B, L, k = E_idx.shape[:3]
|
308 |
+
src = torch.arange(L, device=E_idx.device).view([1, L, 1]).expand(B, L, k)
|
309 |
+
# After flattening, [2, B, E]
|
310 |
+
edge_index = torch.stack([src, dest], dim=0).flatten(2, 3)
|
311 |
+
# After flattening, [B, E]
|
312 |
+
E_dist = E_dist.flatten(1, 2)
|
313 |
+
E_coord_mask = E_coord_mask.flatten(1, 2).unsqueeze(-1)
|
314 |
+
E_residue_mask = E_residue_mask.flatten(1, 2)
|
315 |
+
# Calculate relative positional embeddings and distance RBF
|
316 |
+
pos_embeddings = GVPInputFeaturizer._positional_embeddings(
|
317 |
+
edge_index,
|
318 |
+
num_positional_embeddings=self.num_positional_embeddings,
|
319 |
+
)
|
320 |
+
D_rbf = rbf(E_dist, 0., 20.)
|
321 |
+
# Calculate relative orientation
|
322 |
+
X_src = X_ca.unsqueeze(2).expand(-1, -1, k, -1).flatten(1, 2)
|
323 |
+
X_dest = torch.gather(
|
324 |
+
X_ca,
|
325 |
+
1,
|
326 |
+
edge_index[1, :, :].unsqueeze(-1).expand([B, L*k, 3])
|
327 |
+
)
|
328 |
+
coord_mask_src = coord_mask.unsqueeze(2).expand(-1, -1, k).flatten(1, 2)
|
329 |
+
coord_mask_dest = torch.gather(
|
330 |
+
coord_mask,
|
331 |
+
1,
|
332 |
+
edge_index[1, :, :].expand([B, L*k])
|
333 |
+
)
|
334 |
+
E_vectors = X_src - X_dest
|
335 |
+
# For the ones without coordinates, substitute in the average vector
|
336 |
+
E_vector_mean = torch.sum(E_vectors * E_coord_mask, dim=1,
|
337 |
+
keepdims=True) / torch.sum(E_coord_mask, dim=1, keepdims=True)
|
338 |
+
E_vectors = E_vectors * E_coord_mask + E_vector_mean * ~(E_coord_mask)
|
339 |
+
# Normalize and remove nans
|
340 |
+
edge_s = torch.cat([D_rbf, pos_embeddings], dim=-1)
|
341 |
+
edge_v = normalize(E_vectors).unsqueeze(-2)
|
342 |
+
edge_s, edge_v = map(nan_to_num, (edge_s, edge_v))
|
343 |
+
# Also add indications of whether the coordinates are present
|
344 |
+
edge_s = torch.cat([
|
345 |
+
edge_s,
|
346 |
+
(~coord_mask_src).float().unsqueeze(-1),
|
347 |
+
(~coord_mask_dest).float().unsqueeze(-1),
|
348 |
+
], dim=-1)
|
349 |
+
edge_index[:, ~E_residue_mask] = -1
|
350 |
+
if self.remove_edges_without_coords:
|
351 |
+
edge_index[:, ~E_coord_mask.squeeze(-1)] = -1
|
352 |
+
return (edge_s, edge_v), edge_index.transpose(0, 1)
|
esm/esm/inverse_folding/gvp_encoder.py
ADDED
@@ -0,0 +1,56 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Copyright (c) Facebook, Inc. and its affiliates.
|
2 |
+
#
|
3 |
+
# This source code is licensed under the MIT license found in the
|
4 |
+
# LICENSE file in the root directory of this source tree.
|
5 |
+
|
6 |
+
from argparse import Namespace
|
7 |
+
|
8 |
+
import torch
|
9 |
+
import torch.nn as nn
|
10 |
+
import torch.nn.functional as F
|
11 |
+
|
12 |
+
from .features import GVPGraphEmbedding
|
13 |
+
from .gvp_modules import GVPConvLayer, LayerNorm
|
14 |
+
from .gvp_utils import unflatten_graph
|
15 |
+
|
16 |
+
|
17 |
+
|
18 |
+
class GVPEncoder(nn.Module):
|
19 |
+
|
20 |
+
def __init__(self, args):
|
21 |
+
super().__init__()
|
22 |
+
self.args = args
|
23 |
+
self.embed_graph = GVPGraphEmbedding(args)
|
24 |
+
|
25 |
+
node_hidden_dim = (args.node_hidden_dim_scalar,
|
26 |
+
args.node_hidden_dim_vector)
|
27 |
+
edge_hidden_dim = (args.edge_hidden_dim_scalar,
|
28 |
+
args.edge_hidden_dim_vector)
|
29 |
+
|
30 |
+
conv_activations = (F.relu, torch.sigmoid)
|
31 |
+
self.encoder_layers = nn.ModuleList(
|
32 |
+
GVPConvLayer(
|
33 |
+
node_hidden_dim,
|
34 |
+
edge_hidden_dim,
|
35 |
+
drop_rate=args.dropout,
|
36 |
+
vector_gate=True,
|
37 |
+
attention_heads=0,
|
38 |
+
n_message=3,
|
39 |
+
conv_activations=conv_activations,
|
40 |
+
n_edge_gvps=0,
|
41 |
+
eps=1e-4,
|
42 |
+
layernorm=True,
|
43 |
+
)
|
44 |
+
for i in range(args.num_encoder_layers)
|
45 |
+
)
|
46 |
+
|
47 |
+
def forward(self, coords, coord_mask, padding_mask, confidence):
|
48 |
+
node_embeddings, edge_embeddings, edge_index = self.embed_graph(
|
49 |
+
coords, coord_mask, padding_mask, confidence)
|
50 |
+
|
51 |
+
for i, layer in enumerate(self.encoder_layers):
|
52 |
+
node_embeddings, edge_embeddings = layer(node_embeddings,
|
53 |
+
edge_index, edge_embeddings)
|
54 |
+
|
55 |
+
node_embeddings = unflatten_graph(node_embeddings, coords.shape[0])
|
56 |
+
return node_embeddings
|
esm/esm/inverse_folding/gvp_modules.py
ADDED
@@ -0,0 +1,473 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Contents of this file are from the open source code for
|
2 |
+
#
|
3 |
+
# Jing, B., Eismann, S., Suriana, P., Townshend, R. J. L., & Dror, R. (2020).
|
4 |
+
# Learning from Protein Structure with Geometric Vector Perceptrons. In
|
5 |
+
# International Conference on Learning Representations.
|
6 |
+
#
|
7 |
+
# MIT License
|
8 |
+
#
|
9 |
+
# Copyright (c) 2020 Bowen Jing, Stephan Eismann, Patricia Suriana, Raphael Townshend, Ron Dror
|
10 |
+
#
|
11 |
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
12 |
+
# of this software and associated documentation files (the "Software"), to deal
|
13 |
+
# in the Software without restriction, including without limitation the rights
|
14 |
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
15 |
+
# copies of the Software, and to permit persons to whom the Software is
|
16 |
+
# furnished to do so, subject to the following conditions:
|
17 |
+
#
|
18 |
+
# The above copyright notice and this permission notice shall be included in all
|
19 |
+
# copies or substantial portions of the Software.
|
20 |
+
#
|
21 |
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
22 |
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
23 |
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
24 |
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
25 |
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
26 |
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
27 |
+
# SOFTWARE.
|
28 |
+
|
29 |
+
import typing as T
|
30 |
+
import torch
|
31 |
+
from torch import nn
|
32 |
+
import torch.nn.functional as F
|
33 |
+
from torch_geometric.nn import MessagePassing
|
34 |
+
from torch_scatter import scatter_add, scatter
|
35 |
+
|
36 |
+
def tuple_size(tp):
|
37 |
+
return tuple([0 if a is None else a.size() for a in tp])
|
38 |
+
|
39 |
+
def tuple_sum(tp1, tp2):
|
40 |
+
s1, v1 = tp1
|
41 |
+
s2, v2 = tp2
|
42 |
+
if v2 is None and v2 is None:
|
43 |
+
return (s1 + s2, None)
|
44 |
+
return (s1 + s2, v1 + v2)
|
45 |
+
|
46 |
+
def tuple_cat(*args, dim=-1):
|
47 |
+
'''
|
48 |
+
Concatenates any number of tuples (s, V) elementwise.
|
49 |
+
|
50 |
+
:param dim: dimension along which to concatenate when viewed
|
51 |
+
as the `dim` index for the scalar-channel tensors.
|
52 |
+
This means that `dim=-1` will be applied as
|
53 |
+
`dim=-2` for the vector-channel tensors.
|
54 |
+
'''
|
55 |
+
dim %= len(args[0][0].shape)
|
56 |
+
s_args, v_args = list(zip(*args))
|
57 |
+
return torch.cat(s_args, dim=dim), torch.cat(v_args, dim=dim)
|
58 |
+
|
59 |
+
def tuple_index(x, idx):
|
60 |
+
'''
|
61 |
+
Indexes into a tuple (s, V) along the first dimension.
|
62 |
+
|
63 |
+
:param idx: any object which can be used to index into a `torch.Tensor`
|
64 |
+
'''
|
65 |
+
return x[0][idx], x[1][idx]
|
66 |
+
|
67 |
+
def randn(n, dims, device="cpu"):
|
68 |
+
'''
|
69 |
+
Returns random tuples (s, V) drawn elementwise from a normal distribution.
|
70 |
+
|
71 |
+
:param n: number of data points
|
72 |
+
:param dims: tuple of dimensions (n_scalar, n_vector)
|
73 |
+
|
74 |
+
:return: (s, V) with s.shape = (n, n_scalar) and
|
75 |
+
V.shape = (n, n_vector, 3)
|
76 |
+
'''
|
77 |
+
return torch.randn(n, dims[0], device=device), \
|
78 |
+
torch.randn(n, dims[1], 3, device=device)
|
79 |
+
|
80 |
+
def _norm_no_nan(x, axis=-1, keepdims=False, eps=1e-8, sqrt=True):
|
81 |
+
'''
|
82 |
+
L2 norm of tensor clamped above a minimum value `eps`.
|
83 |
+
|
84 |
+
:param sqrt: if `False`, returns the square of the L2 norm
|
85 |
+
'''
|
86 |
+
# clamp is slow
|
87 |
+
# out = torch.clamp(torch.sum(torch.square(x), axis, keepdims), min=eps)
|
88 |
+
out = torch.sum(torch.square(x), axis, keepdims) + eps
|
89 |
+
return torch.sqrt(out) if sqrt else out
|
90 |
+
|
91 |
+
def _split(x, nv):
|
92 |
+
'''
|
93 |
+
Splits a merged representation of (s, V) back into a tuple.
|
94 |
+
Should be used only with `_merge(s, V)` and only if the tuple
|
95 |
+
representation cannot be used.
|
96 |
+
|
97 |
+
:param x: the `torch.Tensor` returned from `_merge`
|
98 |
+
:param nv: the number of vector channels in the input to `_merge`
|
99 |
+
'''
|
100 |
+
v = torch.reshape(x[..., -3*nv:], x.shape[:-1] + (nv, 3))
|
101 |
+
s = x[..., :-3*nv]
|
102 |
+
return s, v
|
103 |
+
|
104 |
+
def _merge(s, v):
|
105 |
+
'''
|
106 |
+
Merges a tuple (s, V) into a single `torch.Tensor`, where the
|
107 |
+
vector channels are flattened and appended to the scalar channels.
|
108 |
+
Should be used only if the tuple representation cannot be used.
|
109 |
+
Use `_split(x, nv)` to reverse.
|
110 |
+
'''
|
111 |
+
v = torch.reshape(v, v.shape[:-2] + (3*v.shape[-2],))
|
112 |
+
return torch.cat([s, v], -1)
|
113 |
+
|
114 |
+
class GVP(nn.Module):
|
115 |
+
'''
|
116 |
+
Geometric Vector Perceptron. See manuscript and README.md
|
117 |
+
for more details.
|
118 |
+
|
119 |
+
:param in_dims: tuple (n_scalar, n_vector)
|
120 |
+
:param out_dims: tuple (n_scalar, n_vector)
|
121 |
+
:param h_dim: intermediate number of vector channels, optional
|
122 |
+
:param activations: tuple of functions (scalar_act, vector_act)
|
123 |
+
:param tuple_io: whether to keep accepting tuple inputs and outputs when vi
|
124 |
+
or vo = 0
|
125 |
+
'''
|
126 |
+
def __init__(self, in_dims, out_dims, h_dim=None, vector_gate=False,
|
127 |
+
activations=(F.relu, torch.sigmoid), tuple_io=True,
|
128 |
+
eps=1e-8):
|
129 |
+
super(GVP, self).__init__()
|
130 |
+
self.si, self.vi = in_dims
|
131 |
+
self.so, self.vo = out_dims
|
132 |
+
self.tuple_io = tuple_io
|
133 |
+
if self.vi:
|
134 |
+
self.h_dim = h_dim or max(self.vi, self.vo)
|
135 |
+
self.wh = nn.Linear(self.vi, self.h_dim, bias=False)
|
136 |
+
self.ws = nn.Linear(self.h_dim + self.si, self.so)
|
137 |
+
if self.vo:
|
138 |
+
self.wv = nn.Linear(self.h_dim, self.vo, bias=False)
|
139 |
+
if vector_gate:
|
140 |
+
self.wg = nn.Linear(self.so, self.vo)
|
141 |
+
else:
|
142 |
+
self.ws = nn.Linear(self.si, self.so)
|
143 |
+
|
144 |
+
self.vector_gate = vector_gate
|
145 |
+
self.scalar_act, self.vector_act = activations
|
146 |
+
self.eps = eps
|
147 |
+
|
148 |
+
def forward(self, x):
|
149 |
+
'''
|
150 |
+
:param x: tuple (s, V) of `torch.Tensor`,
|
151 |
+
or (if vectors_in is 0), a single `torch.Tensor`
|
152 |
+
:return: tuple (s, V) of `torch.Tensor`,
|
153 |
+
or (if vectors_out is 0), a single `torch.Tensor`
|
154 |
+
'''
|
155 |
+
if self.vi:
|
156 |
+
s, v = x
|
157 |
+
v = torch.transpose(v, -1, -2)
|
158 |
+
vh = self.wh(v)
|
159 |
+
vn = _norm_no_nan(vh, axis=-2, eps=self.eps)
|
160 |
+
s = self.ws(torch.cat([s, vn], -1))
|
161 |
+
if self.scalar_act:
|
162 |
+
s = self.scalar_act(s)
|
163 |
+
if self.vo:
|
164 |
+
v = self.wv(vh)
|
165 |
+
v = torch.transpose(v, -1, -2)
|
166 |
+
if self.vector_gate:
|
167 |
+
g = self.wg(s).unsqueeze(-1)
|
168 |
+
else:
|
169 |
+
g = _norm_no_nan(v, axis=-1, keepdims=True, eps=self.eps)
|
170 |
+
if self.vector_act:
|
171 |
+
g = self.vector_act(g)
|
172 |
+
v = v * g
|
173 |
+
else:
|
174 |
+
if self.tuple_io:
|
175 |
+
assert x[1] is None
|
176 |
+
x = x[0]
|
177 |
+
s = self.ws(x)
|
178 |
+
if self.scalar_act:
|
179 |
+
s = self.scalar_act(s)
|
180 |
+
if self.vo:
|
181 |
+
v = torch.zeros(list(s.shape)[:-1] + [self.vo, 3],
|
182 |
+
device=s.device)
|
183 |
+
|
184 |
+
if self.vo:
|
185 |
+
return (s, v)
|
186 |
+
elif self.tuple_io:
|
187 |
+
return (s, None)
|
188 |
+
else:
|
189 |
+
return s
|
190 |
+
|
191 |
+
|
192 |
+
class _VDropout(nn.Module):
|
193 |
+
'''
|
194 |
+
Vector channel dropout where the elements of each
|
195 |
+
vector channel are dropped together.
|
196 |
+
'''
|
197 |
+
def __init__(self, drop_rate):
|
198 |
+
super(_VDropout, self).__init__()
|
199 |
+
self.drop_rate = drop_rate
|
200 |
+
|
201 |
+
def forward(self, x):
|
202 |
+
'''
|
203 |
+
:param x: `torch.Tensor` corresponding to vector channels
|
204 |
+
'''
|
205 |
+
if x is None:
|
206 |
+
return None
|
207 |
+
device = x.device
|
208 |
+
if not self.training:
|
209 |
+
return x
|
210 |
+
mask = torch.bernoulli(
|
211 |
+
(1 - self.drop_rate) * torch.ones(x.shape[:-1], device=device)
|
212 |
+
).unsqueeze(-1)
|
213 |
+
x = mask * x / (1 - self.drop_rate)
|
214 |
+
return x
|
215 |
+
|
216 |
+
class Dropout(nn.Module):
|
217 |
+
'''
|
218 |
+
Combined dropout for tuples (s, V).
|
219 |
+
Takes tuples (s, V) as input and as output.
|
220 |
+
'''
|
221 |
+
def __init__(self, drop_rate):
|
222 |
+
super(Dropout, self).__init__()
|
223 |
+
self.sdropout = nn.Dropout(drop_rate)
|
224 |
+
self.vdropout = _VDropout(drop_rate)
|
225 |
+
|
226 |
+
def forward(self, x):
|
227 |
+
'''
|
228 |
+
:param x: tuple (s, V) of `torch.Tensor`,
|
229 |
+
or single `torch.Tensor`
|
230 |
+
(will be assumed to be scalar channels)
|
231 |
+
'''
|
232 |
+
if type(x) is torch.Tensor:
|
233 |
+
return self.sdropout(x)
|
234 |
+
s, v = x
|
235 |
+
return self.sdropout(s), self.vdropout(v)
|
236 |
+
|
237 |
+
class LayerNorm(nn.Module):
|
238 |
+
'''
|
239 |
+
Combined LayerNorm for tuples (s, V).
|
240 |
+
Takes tuples (s, V) as input and as output.
|
241 |
+
'''
|
242 |
+
def __init__(self, dims, tuple_io=True, eps=1e-8):
|
243 |
+
super(LayerNorm, self).__init__()
|
244 |
+
self.tuple_io = tuple_io
|
245 |
+
self.s, self.v = dims
|
246 |
+
self.scalar_norm = nn.LayerNorm(self.s)
|
247 |
+
self.eps = eps
|
248 |
+
|
249 |
+
def forward(self, x):
|
250 |
+
'''
|
251 |
+
:param x: tuple (s, V) of `torch.Tensor`,
|
252 |
+
or single `torch.Tensor`
|
253 |
+
(will be assumed to be scalar channels)
|
254 |
+
'''
|
255 |
+
if not self.v:
|
256 |
+
if self.tuple_io:
|
257 |
+
return self.scalar_norm(x[0]), None
|
258 |
+
return self.scalar_norm(x)
|
259 |
+
s, v = x
|
260 |
+
vn = _norm_no_nan(v, axis=-1, keepdims=True, sqrt=False, eps=self.eps)
|
261 |
+
nonzero_mask = (vn > 2 * self.eps)
|
262 |
+
vn = torch.sum(vn * nonzero_mask, dim=-2, keepdim=True
|
263 |
+
) / (self.eps + torch.sum(nonzero_mask, dim=-2, keepdim=True))
|
264 |
+
vn = torch.sqrt(vn + self.eps)
|
265 |
+
v = nonzero_mask * (v / vn)
|
266 |
+
return self.scalar_norm(s), v
|
267 |
+
|
268 |
+
class GVPConv(MessagePassing):
|
269 |
+
'''
|
270 |
+
Graph convolution / message passing with Geometric Vector Perceptrons.
|
271 |
+
Takes in a graph with node and edge embeddings,
|
272 |
+
and returns new node embeddings.
|
273 |
+
|
274 |
+
This does NOT do residual updates and pointwise feedforward layers
|
275 |
+
---see `GVPConvLayer`.
|
276 |
+
|
277 |
+
:param in_dims: input node embedding dimensions (n_scalar, n_vector)
|
278 |
+
:param out_dims: output node embedding dimensions (n_scalar, n_vector)
|
279 |
+
:param edge_dims: input edge embedding dimensions (n_scalar, n_vector)
|
280 |
+
:param n_layers: number of GVPs in the message function
|
281 |
+
:param module_list: preconstructed message function, overrides n_layers
|
282 |
+
:param aggr: should be "add" if some incoming edges are masked, as in
|
283 |
+
a masked autoregressive decoder architecture
|
284 |
+
'''
|
285 |
+
def __init__(self, in_dims, out_dims, edge_dims, n_layers=3,
|
286 |
+
vector_gate=False, module_list=None, aggr="mean", eps=1e-8,
|
287 |
+
activations=(F.relu, torch.sigmoid)):
|
288 |
+
super(GVPConv, self).__init__(aggr=aggr)
|
289 |
+
self.eps = eps
|
290 |
+
self.si, self.vi = in_dims
|
291 |
+
self.so, self.vo = out_dims
|
292 |
+
self.se, self.ve = edge_dims
|
293 |
+
|
294 |
+
module_list = module_list or []
|
295 |
+
if not module_list:
|
296 |
+
if n_layers == 1:
|
297 |
+
module_list.append(
|
298 |
+
GVP((2*self.si + self.se, 2*self.vi + self.ve),
|
299 |
+
(self.so, self.vo), activations=(None, None)))
|
300 |
+
else:
|
301 |
+
module_list.append(
|
302 |
+
GVP((2*self.si + self.se, 2*self.vi + self.ve), out_dims,
|
303 |
+
vector_gate=vector_gate, activations=activations)
|
304 |
+
)
|
305 |
+
for i in range(n_layers - 2):
|
306 |
+
module_list.append(GVP(out_dims, out_dims,
|
307 |
+
vector_gate=vector_gate))
|
308 |
+
module_list.append(GVP(out_dims, out_dims,
|
309 |
+
activations=(None, None)))
|
310 |
+
self.message_func = nn.Sequential(*module_list)
|
311 |
+
|
312 |
+
def forward(self, x, edge_index, edge_attr):
|
313 |
+
'''
|
314 |
+
:param x: tuple (s, V) of `torch.Tensor`
|
315 |
+
:param edge_index: array of shape [2, n_edges]
|
316 |
+
:param edge_attr: tuple (s, V) of `torch.Tensor`
|
317 |
+
'''
|
318 |
+
x_s, x_v = x
|
319 |
+
message = self.propagate(edge_index,
|
320 |
+
s=x_s, v=x_v.reshape(x_v.shape[0], 3*x_v.shape[1]),
|
321 |
+
edge_attr=edge_attr)
|
322 |
+
return _split(message, self.vo)
|
323 |
+
|
324 |
+
def message(self, s_i, v_i, s_j, v_j, edge_attr):
|
325 |
+
v_j = v_j.view(v_j.shape[0], v_j.shape[1]//3, 3)
|
326 |
+
v_i = v_i.view(v_i.shape[0], v_i.shape[1]//3, 3)
|
327 |
+
message = tuple_cat((s_j, v_j), edge_attr, (s_i, v_i))
|
328 |
+
message = self.message_func(message)
|
329 |
+
return _merge(*message)
|
330 |
+
|
331 |
+
|
332 |
+
class GVPConvLayer(nn.Module):
|
333 |
+
'''
|
334 |
+
Full graph convolution / message passing layer with
|
335 |
+
Geometric Vector Perceptrons. Residually updates node embeddings with
|
336 |
+
aggregated incoming messages, applies a pointwise feedforward
|
337 |
+
network to node embeddings, and returns updated node embeddings.
|
338 |
+
|
339 |
+
To only compute the aggregated messages, see `GVPConv`.
|
340 |
+
|
341 |
+
:param node_dims: node embedding dimensions (n_scalar, n_vector)
|
342 |
+
:param edge_dims: input edge embedding dimensions (n_scalar, n_vector)
|
343 |
+
:param n_message: number of GVPs to use in message function
|
344 |
+
:param n_feedforward: number of GVPs to use in feedforward function
|
345 |
+
:param drop_rate: drop probability in all dropout layers
|
346 |
+
:param autoregressive: if `True`, this `GVPConvLayer` will be used
|
347 |
+
with a different set of input node embeddings for messages
|
348 |
+
where src >= dst
|
349 |
+
'''
|
350 |
+
def __init__(self, node_dims, edge_dims, vector_gate=False,
|
351 |
+
n_message=3, n_feedforward=2, drop_rate=.1,
|
352 |
+
autoregressive=False, attention_heads=0,
|
353 |
+
conv_activations=(F.relu, torch.sigmoid),
|
354 |
+
n_edge_gvps=0, layernorm=True, eps=1e-8):
|
355 |
+
|
356 |
+
super(GVPConvLayer, self).__init__()
|
357 |
+
if attention_heads == 0:
|
358 |
+
self.conv = GVPConv(
|
359 |
+
node_dims, node_dims, edge_dims, n_layers=n_message,
|
360 |
+
vector_gate=vector_gate,
|
361 |
+
aggr="add" if autoregressive else "mean",
|
362 |
+
activations=conv_activations,
|
363 |
+
eps=eps,
|
364 |
+
)
|
365 |
+
else:
|
366 |
+
raise NotImplementedError
|
367 |
+
if layernorm:
|
368 |
+
self.norm = nn.ModuleList([LayerNorm(node_dims, eps=eps) for _ in range(2)])
|
369 |
+
else:
|
370 |
+
self.norm = nn.ModuleList([nn.Identity() for _ in range(2)])
|
371 |
+
self.dropout = nn.ModuleList([Dropout(drop_rate) for _ in range(2)])
|
372 |
+
|
373 |
+
ff_func = []
|
374 |
+
if n_feedforward == 1:
|
375 |
+
ff_func.append(GVP(node_dims, node_dims, activations=(None, None)))
|
376 |
+
else:
|
377 |
+
hid_dims = 4*node_dims[0], 2*node_dims[1]
|
378 |
+
ff_func.append(GVP(node_dims, hid_dims, vector_gate=vector_gate))
|
379 |
+
for i in range(n_feedforward-2):
|
380 |
+
ff_func.append(GVP(hid_dims, hid_dims, vector_gate=vector_gate))
|
381 |
+
ff_func.append(GVP(hid_dims, node_dims, activations=(None, None)))
|
382 |
+
self.ff_func = nn.Sequential(*ff_func)
|
383 |
+
|
384 |
+
self.edge_message_func = None
|
385 |
+
if n_edge_gvps > 0:
|
386 |
+
si, vi = node_dims
|
387 |
+
se, ve = edge_dims
|
388 |
+
module_list = [
|
389 |
+
GVP((2*si + se, 2*vi + ve), edge_dims, vector_gate=vector_gate)
|
390 |
+
]
|
391 |
+
for i in range(n_edge_gvps - 2):
|
392 |
+
module_list.append(GVP(edge_dims, edge_dims,
|
393 |
+
vector_gate=vector_gate))
|
394 |
+
if n_edge_gvps > 1:
|
395 |
+
module_list.append(GVP(edge_dims, edge_dims,
|
396 |
+
activations=(None, None)))
|
397 |
+
self.edge_message_func = nn.Sequential(*module_list)
|
398 |
+
if layernorm:
|
399 |
+
self.edge_norm = LayerNorm(edge_dims, eps=eps)
|
400 |
+
else:
|
401 |
+
self.edge_norm = nn.Identity()
|
402 |
+
self.edge_dropout = Dropout(drop_rate)
|
403 |
+
|
404 |
+
def forward(self, x, edge_index, edge_attr,
|
405 |
+
autoregressive_x=None, node_mask=None):
|
406 |
+
'''
|
407 |
+
:param x: tuple (s, V) of `torch.Tensor`
|
408 |
+
:param edge_index: array of shape [2, n_edges]
|
409 |
+
:param edge_attr: tuple (s, V) of `torch.Tensor`
|
410 |
+
:param autoregressive_x: tuple (s, V) of `torch.Tensor`.
|
411 |
+
If not `None`, will be used as srcqq node embeddings
|
412 |
+
for forming messages where src >= dst. The corrent node
|
413 |
+
embeddings `x` will still be the base of the update and the
|
414 |
+
pointwise feedforward.
|
415 |
+
:param node_mask: array of type `bool` to index into the first
|
416 |
+
dim of node embeddings (s, V). If not `None`, only
|
417 |
+
these nodes will be updated.
|
418 |
+
'''
|
419 |
+
if self.edge_message_func:
|
420 |
+
src, dst = edge_index
|
421 |
+
if autoregressive_x is None:
|
422 |
+
x_src = x[0][src], x[1][src]
|
423 |
+
else:
|
424 |
+
mask = (src < dst).unsqueeze(-1)
|
425 |
+
x_src = (
|
426 |
+
torch.where(mask, x[0][src], autoregressive_x[0][src]),
|
427 |
+
torch.where(mask.unsqueeze(-1), x[1][src],
|
428 |
+
autoregressive_x[1][src])
|
429 |
+
)
|
430 |
+
x_dst = x[0][dst], x[1][dst]
|
431 |
+
x_edge = (
|
432 |
+
torch.cat([x_src[0], edge_attr[0], x_dst[0]], dim=-1),
|
433 |
+
torch.cat([x_src[1], edge_attr[1], x_dst[1]], dim=-2)
|
434 |
+
)
|
435 |
+
edge_attr_dh = self.edge_message_func(x_edge)
|
436 |
+
edge_attr = self.edge_norm(tuple_sum(edge_attr,
|
437 |
+
self.edge_dropout(edge_attr_dh)))
|
438 |
+
|
439 |
+
if autoregressive_x is not None:
|
440 |
+
src, dst = edge_index
|
441 |
+
mask = src < dst
|
442 |
+
edge_index_forward = edge_index[:, mask]
|
443 |
+
edge_index_backward = edge_index[:, ~mask]
|
444 |
+
edge_attr_forward = tuple_index(edge_attr, mask)
|
445 |
+
edge_attr_backward = tuple_index(edge_attr, ~mask)
|
446 |
+
|
447 |
+
dh = tuple_sum(
|
448 |
+
self.conv(x, edge_index_forward, edge_attr_forward),
|
449 |
+
self.conv(autoregressive_x, edge_index_backward, edge_attr_backward)
|
450 |
+
)
|
451 |
+
|
452 |
+
count = scatter_add(torch.ones_like(dst), dst,
|
453 |
+
dim_size=dh[0].size(0)).clamp(min=1).unsqueeze(-1)
|
454 |
+
|
455 |
+
dh = dh[0] / count, dh[1] / count.unsqueeze(-1)
|
456 |
+
|
457 |
+
else:
|
458 |
+
dh = self.conv(x, edge_index, edge_attr)
|
459 |
+
|
460 |
+
if node_mask is not None:
|
461 |
+
x_ = x
|
462 |
+
x, dh = tuple_index(x, node_mask), tuple_index(dh, node_mask)
|
463 |
+
|
464 |
+
x = self.norm[0](tuple_sum(x, self.dropout[0](dh)))
|
465 |
+
|
466 |
+
dh = self.ff_func(x)
|
467 |
+
x = self.norm[1](tuple_sum(x, self.dropout[1](dh)))
|
468 |
+
|
469 |
+
if node_mask is not None:
|
470 |
+
x_[0][node_mask], x_[1][node_mask] = x[0], x[1]
|
471 |
+
x = x_
|
472 |
+
|
473 |
+
return x, edge_attr
|
esm/esm/inverse_folding/gvp_transformer.py
ADDED
@@ -0,0 +1,137 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Copyright (c) Facebook, Inc. and its affiliates.
|
2 |
+
#
|
3 |
+
# This source code is licensed under the MIT license found in the
|
4 |
+
# LICENSE file in the root directory of this source tree.
|
5 |
+
|
6 |
+
import argparse
|
7 |
+
from typing import Any, Dict, List, Optional, Tuple, NamedTuple
|
8 |
+
import torch
|
9 |
+
from torch import nn
|
10 |
+
from torch import Tensor
|
11 |
+
import torch.nn.functional as F
|
12 |
+
from scipy.spatial import transform
|
13 |
+
|
14 |
+
from esm.data import Alphabet
|
15 |
+
|
16 |
+
from .features import DihedralFeatures
|
17 |
+
from .gvp_encoder import GVPEncoder
|
18 |
+
from .gvp_utils import unflatten_graph
|
19 |
+
from .gvp_transformer_encoder import GVPTransformerEncoder
|
20 |
+
from .transformer_decoder import TransformerDecoder
|
21 |
+
from .util import rotate, CoordBatchConverter
|
22 |
+
|
23 |
+
|
24 |
+
class GVPTransformerModel(nn.Module):
|
25 |
+
"""
|
26 |
+
GVP-Transformer inverse folding model.
|
27 |
+
|
28 |
+
Architecture: Geometric GVP-GNN as initial layers, followed by
|
29 |
+
sequence-to-sequence Transformer encoder and decoder.
|
30 |
+
"""
|
31 |
+
|
32 |
+
def __init__(self, args, alphabet):
|
33 |
+
super().__init__()
|
34 |
+
encoder_embed_tokens = self.build_embedding(
|
35 |
+
args, alphabet, args.encoder_embed_dim,
|
36 |
+
)
|
37 |
+
decoder_embed_tokens = self.build_embedding(
|
38 |
+
args, alphabet, args.decoder_embed_dim,
|
39 |
+
)
|
40 |
+
encoder = self.build_encoder(args, alphabet, encoder_embed_tokens)
|
41 |
+
decoder = self.build_decoder(args, alphabet, decoder_embed_tokens)
|
42 |
+
self.args = args
|
43 |
+
self.encoder = encoder
|
44 |
+
self.decoder = decoder
|
45 |
+
|
46 |
+
@classmethod
|
47 |
+
def build_encoder(cls, args, src_dict, embed_tokens):
|
48 |
+
encoder = GVPTransformerEncoder(args, src_dict, embed_tokens)
|
49 |
+
return encoder
|
50 |
+
|
51 |
+
@classmethod
|
52 |
+
def build_decoder(cls, args, tgt_dict, embed_tokens):
|
53 |
+
decoder = TransformerDecoder(
|
54 |
+
args,
|
55 |
+
tgt_dict,
|
56 |
+
embed_tokens,
|
57 |
+
)
|
58 |
+
return decoder
|
59 |
+
|
60 |
+
@classmethod
|
61 |
+
def build_embedding(cls, args, dictionary, embed_dim):
|
62 |
+
num_embeddings = len(dictionary)
|
63 |
+
padding_idx = dictionary.padding_idx
|
64 |
+
emb = nn.Embedding(num_embeddings, embed_dim, padding_idx)
|
65 |
+
nn.init.normal_(emb.weight, mean=0, std=embed_dim ** -0.5)
|
66 |
+
nn.init.constant_(emb.weight[padding_idx], 0)
|
67 |
+
return emb
|
68 |
+
|
69 |
+
def forward(
|
70 |
+
self,
|
71 |
+
coords,
|
72 |
+
padding_mask,
|
73 |
+
confidence,
|
74 |
+
prev_output_tokens,
|
75 |
+
return_all_hiddens: bool = False,
|
76 |
+
features_only: bool = False,
|
77 |
+
):
|
78 |
+
encoder_out = self.encoder(coords, padding_mask, confidence,
|
79 |
+
return_all_hiddens=return_all_hiddens)
|
80 |
+
logits, extra = self.decoder(
|
81 |
+
prev_output_tokens,
|
82 |
+
encoder_out=encoder_out,
|
83 |
+
features_only=features_only,
|
84 |
+
return_all_hiddens=return_all_hiddens,
|
85 |
+
)
|
86 |
+
return logits, extra
|
87 |
+
|
88 |
+
def sample(self, coords, partial_seq=None, temperature=1.0, confidence=None):
|
89 |
+
"""
|
90 |
+
Samples sequences based on multinomial sampling (no beam search).
|
91 |
+
|
92 |
+
Args:
|
93 |
+
coords: L x 3 x 3 list representing one backbone
|
94 |
+
partial_seq: Optional, partial sequence with mask tokens if part of
|
95 |
+
the sequence is known
|
96 |
+
temperature: sampling temperature, use low temperature for higher
|
97 |
+
sequence recovery and high temperature for higher diversity
|
98 |
+
confidence: optional length L list of confidence scores for coordinates
|
99 |
+
"""
|
100 |
+
L = len(coords)
|
101 |
+
# Convert to batch format
|
102 |
+
batch_converter = CoordBatchConverter(self.decoder.dictionary)
|
103 |
+
batch_coords, confidence, _, _, padding_mask = (
|
104 |
+
batch_converter([(coords, confidence, None)])
|
105 |
+
)
|
106 |
+
|
107 |
+
# Start with prepend token
|
108 |
+
mask_idx = self.decoder.dictionary.get_idx('<mask>')
|
109 |
+
sampled_tokens = torch.full((1, 1+L), mask_idx, dtype=int)
|
110 |
+
sampled_tokens[0, 0] = self.decoder.dictionary.get_idx('<cath>')
|
111 |
+
if partial_seq is not None:
|
112 |
+
for i, c in enumerate(partial_seq):
|
113 |
+
sampled_tokens[0, i+1] = self.decoder.dictionary.get_idx(c)
|
114 |
+
|
115 |
+
# Save incremental states for faster sampling
|
116 |
+
incremental_state = dict()
|
117 |
+
|
118 |
+
# Run encoder only once
|
119 |
+
encoder_out = self.encoder(batch_coords, padding_mask, confidence)
|
120 |
+
|
121 |
+
# Decode one token at a time
|
122 |
+
for i in range(1, L+1):
|
123 |
+
if sampled_tokens[0, i] != mask_idx:
|
124 |
+
continue
|
125 |
+
logits, _ = self.decoder(
|
126 |
+
sampled_tokens[:, :i],
|
127 |
+
encoder_out,
|
128 |
+
incremental_state=incremental_state,
|
129 |
+
)
|
130 |
+
logits = logits[0].transpose(0, 1)
|
131 |
+
logits /= temperature
|
132 |
+
probs = F.softmax(logits, dim=-1)
|
133 |
+
sampled_tokens[:, i] = torch.multinomial(probs, 1).squeeze(-1)
|
134 |
+
sampled_seq = sampled_tokens[0, 1:]
|
135 |
+
|
136 |
+
# Convert back to string via lookup
|
137 |
+
return ''.join([self.decoder.dictionary.get_tok(a) for a in sampled_seq])
|
esm/esm/inverse_folding/gvp_transformer_encoder.py
ADDED
@@ -0,0 +1,184 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Copyright (c) Facebook, Inc. and its affiliates.
|
2 |
+
#
|
3 |
+
# Contents of this file were adapted from the open source fairseq repository.
|
4 |
+
#
|
5 |
+
# This source code is licensed under the MIT license found in the
|
6 |
+
# LICENSE file in the root directory of this source tree.
|
7 |
+
|
8 |
+
import argparse
|
9 |
+
import math
|
10 |
+
from typing import Dict, List, Optional
|
11 |
+
|
12 |
+
import torch
|
13 |
+
import torch.nn as nn
|
14 |
+
from torch import Tensor
|
15 |
+
|
16 |
+
from esm.modules import SinusoidalPositionalEmbedding
|
17 |
+
from .features import GVPInputFeaturizer, DihedralFeatures
|
18 |
+
from .gvp_encoder import GVPEncoder
|
19 |
+
from .transformer_layer import TransformerEncoderLayer
|
20 |
+
from .util import nan_to_num, get_rotation_frames, rotate, rbf
|
21 |
+
|
22 |
+
|
23 |
+
class GVPTransformerEncoder(nn.Module):
|
24 |
+
"""
|
25 |
+
Transformer encoder consisting of *args.encoder.layers* layers. Each layer
|
26 |
+
is a :class:`TransformerEncoderLayer`.
|
27 |
+
|
28 |
+
Args:
|
29 |
+
args (argparse.Namespace): parsed command-line arguments
|
30 |
+
dictionary (~fairseq.data.Dictionary): encoding dictionary
|
31 |
+
embed_tokens (torch.nn.Embedding): input embedding
|
32 |
+
"""
|
33 |
+
|
34 |
+
def __init__(self, args, dictionary, embed_tokens):
|
35 |
+
super().__init__()
|
36 |
+
self.args = args
|
37 |
+
self.dictionary = dictionary
|
38 |
+
|
39 |
+
self.dropout_module = nn.Dropout(args.dropout)
|
40 |
+
|
41 |
+
embed_dim = embed_tokens.embedding_dim
|
42 |
+
self.padding_idx = embed_tokens.padding_idx
|
43 |
+
|
44 |
+
self.embed_tokens = embed_tokens
|
45 |
+
self.embed_scale = math.sqrt(embed_dim)
|
46 |
+
self.embed_positions = SinusoidalPositionalEmbedding(
|
47 |
+
embed_dim,
|
48 |
+
self.padding_idx,
|
49 |
+
)
|
50 |
+
self.embed_gvp_input_features = nn.Linear(15, embed_dim)
|
51 |
+
self.embed_confidence = nn.Linear(16, embed_dim)
|
52 |
+
self.embed_dihedrals = DihedralFeatures(embed_dim)
|
53 |
+
|
54 |
+
gvp_args = argparse.Namespace()
|
55 |
+
for k, v in vars(args).items():
|
56 |
+
if k.startswith("gvp_"):
|
57 |
+
setattr(gvp_args, k[4:], v)
|
58 |
+
self.gvp_encoder = GVPEncoder(gvp_args)
|
59 |
+
gvp_out_dim = gvp_args.node_hidden_dim_scalar + (3 *
|
60 |
+
gvp_args.node_hidden_dim_vector)
|
61 |
+
self.embed_gvp_output = nn.Linear(gvp_out_dim, embed_dim)
|
62 |
+
|
63 |
+
self.layers = nn.ModuleList([])
|
64 |
+
self.layers.extend(
|
65 |
+
[self.build_encoder_layer(args) for i in range(args.encoder_layers)]
|
66 |
+
)
|
67 |
+
self.num_layers = len(self.layers)
|
68 |
+
self.layer_norm = nn.LayerNorm(embed_dim)
|
69 |
+
|
70 |
+
def build_encoder_layer(self, args):
|
71 |
+
return TransformerEncoderLayer(args)
|
72 |
+
|
73 |
+
def forward_embedding(self, coords, padding_mask, confidence):
|
74 |
+
"""
|
75 |
+
Args:
|
76 |
+
coords: N, CA, C backbone coordinates in shape length x 3 (atoms) x 3
|
77 |
+
padding_mask: boolean Tensor (true for padding) of shape length
|
78 |
+
confidence: confidence scores between 0 and 1 of shape length
|
79 |
+
"""
|
80 |
+
components = dict()
|
81 |
+
coord_mask = torch.all(torch.all(torch.isfinite(coords), dim=-1), dim=-1)
|
82 |
+
coords = nan_to_num(coords)
|
83 |
+
mask_tokens = (
|
84 |
+
padding_mask * self.dictionary.padding_idx +
|
85 |
+
~padding_mask * self.dictionary.get_idx("<mask>")
|
86 |
+
)
|
87 |
+
components["tokens"] = self.embed_tokens(mask_tokens) * self.embed_scale
|
88 |
+
components["diherals"] = self.embed_dihedrals(coords)
|
89 |
+
|
90 |
+
# GVP encoder
|
91 |
+
gvp_out_scalars, gvp_out_vectors = self.gvp_encoder(coords,
|
92 |
+
coord_mask, padding_mask, confidence)
|
93 |
+
R = get_rotation_frames(coords)
|
94 |
+
# Rotate to local rotation frame for rotation-invariance
|
95 |
+
gvp_out_features = torch.cat([
|
96 |
+
gvp_out_scalars,
|
97 |
+
rotate(gvp_out_vectors, R.transpose(-2, -1)).flatten(-2, -1),
|
98 |
+
], dim=-1)
|
99 |
+
components["gvp_out"] = self.embed_gvp_output(gvp_out_features)
|
100 |
+
|
101 |
+
components["confidence"] = self.embed_confidence(
|
102 |
+
rbf(confidence, 0., 1.))
|
103 |
+
|
104 |
+
# In addition to GVP encoder outputs, also directly embed GVP input node
|
105 |
+
# features to the Transformer
|
106 |
+
scalar_features, vector_features = GVPInputFeaturizer.get_node_features(
|
107 |
+
coords, coord_mask, with_coord_mask=False)
|
108 |
+
features = torch.cat([
|
109 |
+
scalar_features,
|
110 |
+
rotate(vector_features, R.transpose(-2, -1)).flatten(-2, -1),
|
111 |
+
], dim=-1)
|
112 |
+
components["gvp_input_features"] = self.embed_gvp_input_features(features)
|
113 |
+
|
114 |
+
embed = sum(components.values())
|
115 |
+
# for k, v in components.items():
|
116 |
+
# print(k, torch.mean(v, dim=(0,1)), torch.std(v, dim=(0,1)))
|
117 |
+
|
118 |
+
x = embed
|
119 |
+
x = x + self.embed_positions(mask_tokens)
|
120 |
+
x = self.dropout_module(x)
|
121 |
+
return x, components
|
122 |
+
|
123 |
+
def forward(
|
124 |
+
self,
|
125 |
+
coords,
|
126 |
+
encoder_padding_mask,
|
127 |
+
confidence,
|
128 |
+
return_all_hiddens: bool = False,
|
129 |
+
):
|
130 |
+
"""
|
131 |
+
Args:
|
132 |
+
coords (Tensor): backbone coordinates
|
133 |
+
shape batch_size x num_residues x num_atoms (3 for N, CA, C) x 3
|
134 |
+
encoder_padding_mask (ByteTensor): the positions of
|
135 |
+
padding elements of shape `(batch_size x num_residues)`
|
136 |
+
confidence (Tensor): the confidence score of shape (batch_size x
|
137 |
+
num_residues). The value is between 0. and 1. for each residue
|
138 |
+
coordinate, or -1. if no coordinate is given
|
139 |
+
return_all_hiddens (bool, optional): also return all of the
|
140 |
+
intermediate hidden states (default: False).
|
141 |
+
|
142 |
+
Returns:
|
143 |
+
dict:
|
144 |
+
- **encoder_out** (Tensor): the last encoder layer's output of
|
145 |
+
shape `(num_residues, batch_size, embed_dim)`
|
146 |
+
- **encoder_padding_mask** (ByteTensor): the positions of
|
147 |
+
padding elements of shape `(batch_size, num_residues)`
|
148 |
+
- **encoder_embedding** (Tensor): the (scaled) embedding lookup
|
149 |
+
of shape `(batch_size, num_residues, embed_dim)`
|
150 |
+
- **encoder_states** (List[Tensor]): all intermediate
|
151 |
+
hidden states of shape `(num_residues, batch_size, embed_dim)`.
|
152 |
+
Only populated if *return_all_hiddens* is True.
|
153 |
+
"""
|
154 |
+
x, encoder_embedding = self.forward_embedding(coords,
|
155 |
+
encoder_padding_mask, confidence)
|
156 |
+
# account for padding while computing the representation
|
157 |
+
x = x * (1 - encoder_padding_mask.unsqueeze(-1).type_as(x))
|
158 |
+
|
159 |
+
# B x T x C -> T x B x C
|
160 |
+
x = x.transpose(0, 1)
|
161 |
+
|
162 |
+
encoder_states = []
|
163 |
+
|
164 |
+
if return_all_hiddens:
|
165 |
+
encoder_states.append(x)
|
166 |
+
|
167 |
+
# encoder layers
|
168 |
+
for layer in self.layers:
|
169 |
+
x = layer(
|
170 |
+
x, encoder_padding_mask=encoder_padding_mask
|
171 |
+
)
|
172 |
+
if return_all_hiddens:
|
173 |
+
assert encoder_states is not None
|
174 |
+
encoder_states.append(x)
|
175 |
+
|
176 |
+
if self.layer_norm is not None:
|
177 |
+
x = self.layer_norm(x)
|
178 |
+
|
179 |
+
return {
|
180 |
+
"encoder_out": [x], # T x B x C
|
181 |
+
"encoder_padding_mask": [encoder_padding_mask], # B x T
|
182 |
+
"encoder_embedding": [encoder_embedding], # dictionary
|
183 |
+
"encoder_states": encoder_states, # List[T x B x C]
|
184 |
+
}
|
esm/esm/inverse_folding/gvp_utils.py
ADDED
@@ -0,0 +1,68 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Copyright (c) Facebook, Inc. and its affiliates.
|
2 |
+
#
|
3 |
+
# This source code is licensed under the MIT license found in the
|
4 |
+
# LICENSE file in the root directory of this source tree.
|
5 |
+
|
6 |
+
import torch
|
7 |
+
|
8 |
+
|
9 |
+
def flatten_graph(node_embeddings, edge_embeddings, edge_index):
|
10 |
+
"""
|
11 |
+
Flattens the graph into a batch size one (with disconnected subgraphs for
|
12 |
+
each example) to be compatible with pytorch-geometric package.
|
13 |
+
Args:
|
14 |
+
node_embeddings: node embeddings in tuple form (scalar, vector)
|
15 |
+
- scalar: shape batch size x nodes x node_embed_dim
|
16 |
+
- vector: shape batch size x nodes x node_embed_dim x 3
|
17 |
+
edge_embeddings: edge embeddings of in tuple form (scalar, vector)
|
18 |
+
- scalar: shape batch size x edges x edge_embed_dim
|
19 |
+
- vector: shape batch size x edges x edge_embed_dim x 3
|
20 |
+
edge_index: shape batch_size x 2 (source node and target node) x edges
|
21 |
+
Returns:
|
22 |
+
node_embeddings: node embeddings in tuple form (scalar, vector)
|
23 |
+
- scalar: shape batch total_nodes x node_embed_dim
|
24 |
+
- vector: shape batch total_nodes x node_embed_dim x 3
|
25 |
+
edge_embeddings: edge embeddings of in tuple form (scalar, vector)
|
26 |
+
- scalar: shape batch total_edges x edge_embed_dim
|
27 |
+
- vector: shape batch total_edges x edge_embed_dim x 3
|
28 |
+
edge_index: shape 2 x total_edges
|
29 |
+
"""
|
30 |
+
x_s, x_v = node_embeddings
|
31 |
+
e_s, e_v = edge_embeddings
|
32 |
+
batch_size, N = x_s.shape[0], x_s.shape[1]
|
33 |
+
node_embeddings = (torch.flatten(x_s, 0, 1), torch.flatten(x_v, 0, 1))
|
34 |
+
edge_embeddings = (torch.flatten(e_s, 0, 1), torch.flatten(e_v, 0, 1))
|
35 |
+
|
36 |
+
edge_mask = torch.any(edge_index != -1, dim=1)
|
37 |
+
# Re-number the nodes by adding batch_idx * N to each batch
|
38 |
+
edge_index = edge_index + (torch.arange(batch_size, device=edge_index.device) *
|
39 |
+
N).unsqueeze(-1).unsqueeze(-1)
|
40 |
+
edge_index = edge_index.permute(1, 0, 2).flatten(1, 2)
|
41 |
+
edge_mask = edge_mask.flatten()
|
42 |
+
edge_index = edge_index[:, edge_mask]
|
43 |
+
edge_embeddings = (
|
44 |
+
edge_embeddings[0][edge_mask, :],
|
45 |
+
edge_embeddings[1][edge_mask, :]
|
46 |
+
)
|
47 |
+
return node_embeddings, edge_embeddings, edge_index
|
48 |
+
|
49 |
+
|
50 |
+
def unflatten_graph(node_embeddings, batch_size):
|
51 |
+
"""
|
52 |
+
Unflattens node embeddings.
|
53 |
+
Args:
|
54 |
+
node_embeddings: node embeddings in tuple form (scalar, vector)
|
55 |
+
- scalar: shape batch total_nodes x node_embed_dim
|
56 |
+
- vector: shape batch total_nodes x node_embed_dim x 3
|
57 |
+
batch_size: int
|
58 |
+
Returns:
|
59 |
+
node_embeddings: node embeddings in tuple form (scalar, vector)
|
60 |
+
- scalar: shape batch size x nodes x node_embed_dim
|
61 |
+
- vector: shape batch size x nodes x node_embed_dim x 3
|
62 |
+
"""
|
63 |
+
x_s, x_v = node_embeddings
|
64 |
+
x_s = x_s.reshape(batch_size, -1, x_s.shape[1])
|
65 |
+
x_v = x_v.reshape(batch_size, -1, x_v.shape[1], x_v.shape[2])
|
66 |
+
return (x_s, x_v)
|
67 |
+
|
68 |
+
|
esm/esm/inverse_folding/multichain_util.py
ADDED
@@ -0,0 +1,151 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Copyright (c) Facebook, Inc. and its affiliates.
|
2 |
+
#
|
3 |
+
# This source code is licensed under the MIT license found in the
|
4 |
+
# LICENSE file in the root directory of this source tree.
|
5 |
+
|
6 |
+
import biotite.structure
|
7 |
+
import numpy as np
|
8 |
+
import torch
|
9 |
+
from typing import Sequence, Tuple, List
|
10 |
+
|
11 |
+
from esm.inverse_folding.util import (
|
12 |
+
load_structure,
|
13 |
+
extract_coords_from_structure,
|
14 |
+
load_coords,
|
15 |
+
get_sequence_loss,
|
16 |
+
get_encoder_output,
|
17 |
+
)
|
18 |
+
|
19 |
+
|
20 |
+
def extract_coords_from_complex(structure: biotite.structure.AtomArray):
|
21 |
+
"""
|
22 |
+
Args:
|
23 |
+
structure: biotite AtomArray
|
24 |
+
Returns:
|
25 |
+
Tuple (coords_list, seq_list)
|
26 |
+
- coords: Dictionary mapping chain ids to L x 3 x 3 array for N, CA, C
|
27 |
+
coordinates representing the backbone of each chain
|
28 |
+
- seqs: Dictionary mapping chain ids to native sequences of each chain
|
29 |
+
"""
|
30 |
+
coords = {}
|
31 |
+
seqs = {}
|
32 |
+
all_chains = biotite.structure.get_chains(structure)
|
33 |
+
for chain_id in all_chains:
|
34 |
+
chain = structure[structure.chain_id == chain_id]
|
35 |
+
coords[chain_id], seqs[chain_id] = extract_coords_from_structure(chain)
|
36 |
+
return coords, seqs
|
37 |
+
|
38 |
+
|
39 |
+
def load_complex_coords(fpath, chains):
|
40 |
+
"""
|
41 |
+
Args:
|
42 |
+
fpath: filepath to either pdb or cif file
|
43 |
+
chains: the chain ids (the order matters for autoregressive model)
|
44 |
+
Returns:
|
45 |
+
Tuple (coords_list, seq_list)
|
46 |
+
- coords: Dictionary mapping chain ids to L x 3 x 3 array for N, CA, C
|
47 |
+
coordinates representing the backbone of each chain
|
48 |
+
- seqs: Dictionary mapping chain ids to native sequences of each chain
|
49 |
+
"""
|
50 |
+
structure = load_structure(fpath, chains)
|
51 |
+
return extract_coords_from_complex(structure)
|
52 |
+
|
53 |
+
|
54 |
+
def _concatenate_coords(coords, target_chain_id, padding_length=10):
|
55 |
+
"""
|
56 |
+
Args:
|
57 |
+
coords: Dictionary mapping chain ids to L x 3 x 3 array for N, CA, C
|
58 |
+
coordinates representing the backbone of each chain
|
59 |
+
target_chain_id: The chain id to sample sequences for
|
60 |
+
padding_length: Length of padding between concatenated chains
|
61 |
+
Returns:
|
62 |
+
Tuple (coords, seq)
|
63 |
+
- coords is an L x 3 x 3 array for N, CA, C coordinates, a
|
64 |
+
concatenation of the chains with padding in between
|
65 |
+
- seq is the extracted sequence, with padding tokens inserted
|
66 |
+
between the concatenated chains
|
67 |
+
"""
|
68 |
+
pad_coords = np.full((padding_length, 3, 3), np.nan, dtype=np.float32)
|
69 |
+
# For best performance, put the target chain first in concatenation.
|
70 |
+
coords_list = [coords[target_chain_id]]
|
71 |
+
for chain_id in coords:
|
72 |
+
if chain_id == target_chain_id:
|
73 |
+
continue
|
74 |
+
coords_list.append(pad_coords)
|
75 |
+
coords_list.append(coords[chain_id])
|
76 |
+
coords_concatenated = np.concatenate(coords_list, axis=0)
|
77 |
+
return coords_concatenated
|
78 |
+
|
79 |
+
|
80 |
+
def sample_sequence_in_complex(model, coords, target_chain_id, temperature=1.,
|
81 |
+
padding_length=10):
|
82 |
+
"""
|
83 |
+
Samples sequence for one chain in a complex.
|
84 |
+
Args:
|
85 |
+
model: An instance of the GVPTransformer model
|
86 |
+
coords: Dictionary mapping chain ids to L x 3 x 3 array for N, CA, C
|
87 |
+
coordinates representing the backbone of each chain
|
88 |
+
target_chain_id: The chain id to sample sequences for
|
89 |
+
padding_length: padding length in between chains
|
90 |
+
Returns:
|
91 |
+
Sampled sequence for the target chain
|
92 |
+
"""
|
93 |
+
target_chain_len = coords[target_chain_id].shape[0]
|
94 |
+
all_coords = _concatenate_coords(coords, target_chain_id)
|
95 |
+
|
96 |
+
# Supply padding tokens for other chains to avoid unused sampling for speed
|
97 |
+
padding_pattern = ['<pad>'] * all_coords.shape[0]
|
98 |
+
for i in range(target_chain_len):
|
99 |
+
padding_pattern[i] = '<mask>'
|
100 |
+
sampled = model.sample(all_coords, partial_seq=padding_pattern,
|
101 |
+
temperature=temperature)
|
102 |
+
sampled = sampled[:target_chain_len]
|
103 |
+
return sampled
|
104 |
+
|
105 |
+
|
106 |
+
def score_sequence_in_complex(model, alphabet, coords, target_chain_id,
|
107 |
+
target_seq, padding_length=10):
|
108 |
+
"""
|
109 |
+
Scores sequence for one chain in a complex.
|
110 |
+
Args:
|
111 |
+
model: An instance of the GVPTransformer model
|
112 |
+
alphabet: Alphabet for the model
|
113 |
+
coords: Dictionary mapping chain ids to L x 3 x 3 array for N, CA, C
|
114 |
+
coordinates representing the backbone of each chain
|
115 |
+
target_chain_id: The chain id to sample sequences for
|
116 |
+
target_seq: Target sequence for the target chain for scoring.
|
117 |
+
padding_length: padding length in between chains
|
118 |
+
Returns:
|
119 |
+
Tuple (ll_fullseq, ll_withcoord)
|
120 |
+
- ll_fullseq: Average log-likelihood over the full target chain
|
121 |
+
- ll_withcoord: Average log-likelihood in target chain excluding those
|
122 |
+
residues without coordinates
|
123 |
+
"""
|
124 |
+
all_coords = _concatenate_coords(coords, target_chain_id)
|
125 |
+
|
126 |
+
loss, target_padding_mask = get_sequence_loss(model, alphabet, all_coords,
|
127 |
+
target_seq)
|
128 |
+
ll_fullseq = -np.sum(loss * ~target_padding_mask) / np.sum(
|
129 |
+
~target_padding_mask)
|
130 |
+
|
131 |
+
# Also calculate average when excluding masked portions
|
132 |
+
coord_mask = np.all(np.isfinite(coords[target_chain_id]), axis=(-1, -2))
|
133 |
+
ll_withcoord = -np.sum(loss * coord_mask) / np.sum(coord_mask)
|
134 |
+
return ll_fullseq, ll_withcoord
|
135 |
+
|
136 |
+
|
137 |
+
def get_encoder_output_for_complex(model, alphabet, coords, target_chain_id):
|
138 |
+
"""
|
139 |
+
Args:
|
140 |
+
model: An instance of the GVPTransformer model
|
141 |
+
alphabet: Alphabet for the model
|
142 |
+
coords: Dictionary mapping chain ids to L x 3 x 3 array for N, CA, C
|
143 |
+
coordinates representing the backbone of each chain
|
144 |
+
target_chain_id: The chain id to sample sequences for
|
145 |
+
Returns:
|
146 |
+
Dictionary mapping chain id to encoder output for each chain
|
147 |
+
"""
|
148 |
+
all_coords = _concatenate_coords(coords, target_chain_id)
|
149 |
+
all_rep = get_encoder_output(model, alphabet, all_coords)
|
150 |
+
target_chain_len = coords[target_chain_id].shape[0]
|
151 |
+
return all_rep[:target_chain_len]
|
esm/esm/inverse_folding/transformer_decoder.py
ADDED
@@ -0,0 +1,228 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Copyright (c) Facebook, Inc. and its affiliates.
|
2 |
+
#
|
3 |
+
# Contents of this file were adapted from the open source fairseq repository.
|
4 |
+
#
|
5 |
+
# This source code is licensed under the MIT license found in the
|
6 |
+
# LICENSE file in the root directory of this source tree.
|
7 |
+
|
8 |
+
import math
|
9 |
+
from typing import Any, Dict, List, Optional
|
10 |
+
|
11 |
+
import torch
|
12 |
+
import torch.nn as nn
|
13 |
+
from torch import Tensor
|
14 |
+
|
15 |
+
from esm.modules import SinusoidalPositionalEmbedding
|
16 |
+
from .transformer_layer import TransformerDecoderLayer
|
17 |
+
|
18 |
+
|
19 |
+
def fill_with_neg_inf(t):
|
20 |
+
"""FP16-compatible function that fills a tensor with -inf."""
|
21 |
+
return t.float().fill_(float("-inf")).type_as(t)
|
22 |
+
|
23 |
+
|
24 |
+
class TransformerDecoder(nn.Module):
|
25 |
+
"""
|
26 |
+
Transformer decoder consisting of *args.decoder.layers* layers. Each layer
|
27 |
+
is a :class:`TransformerDecoderLayer`.
|
28 |
+
|
29 |
+
Args:
|
30 |
+
args (argparse.Namespace): parsed command-line arguments
|
31 |
+
dictionary (~fairseq.data.Dictionary): decoding dictionary
|
32 |
+
embed_tokens (torch.nn.Embedding): output embedding
|
33 |
+
no_encoder_attn (bool, optional): whether to attend to encoder outputs
|
34 |
+
(default: False).
|
35 |
+
"""
|
36 |
+
|
37 |
+
def __init__(
|
38 |
+
self,
|
39 |
+
args,
|
40 |
+
dictionary,
|
41 |
+
embed_tokens,
|
42 |
+
):
|
43 |
+
super().__init__()
|
44 |
+
self.args = args
|
45 |
+
self.dictionary = dictionary
|
46 |
+
self._future_mask = torch.empty(0)
|
47 |
+
|
48 |
+
self.dropout_module = nn.Dropout(args.dropout)
|
49 |
+
|
50 |
+
input_embed_dim = embed_tokens.embedding_dim
|
51 |
+
embed_dim = args.decoder_embed_dim
|
52 |
+
self.embed_dim = embed_dim
|
53 |
+
|
54 |
+
self.padding_idx = embed_tokens.padding_idx
|
55 |
+
|
56 |
+
self.embed_tokens = embed_tokens
|
57 |
+
self.embed_scale = math.sqrt(embed_dim)
|
58 |
+
|
59 |
+
self.project_in_dim = (
|
60 |
+
nn.Linear(input_embed_dim, embed_dim, bias=False)
|
61 |
+
if embed_dim != input_embed_dim
|
62 |
+
else None
|
63 |
+
)
|
64 |
+
self.embed_positions = SinusoidalPositionalEmbedding(
|
65 |
+
embed_dim,
|
66 |
+
self.padding_idx,
|
67 |
+
)
|
68 |
+
|
69 |
+
self.layers = nn.ModuleList([])
|
70 |
+
self.layers.extend(
|
71 |
+
[
|
72 |
+
self.build_decoder_layer(args)
|
73 |
+
for _ in range(args.decoder_layers)
|
74 |
+
]
|
75 |
+
)
|
76 |
+
self.num_layers = len(self.layers)
|
77 |
+
self.layer_norm = nn.LayerNorm(embed_dim)
|
78 |
+
|
79 |
+
self.build_output_projection(args, dictionary)
|
80 |
+
|
81 |
+
def build_output_projection(self, args, dictionary):
|
82 |
+
self.output_projection = nn.Linear(
|
83 |
+
args.decoder_embed_dim, len(dictionary), bias=False
|
84 |
+
)
|
85 |
+
nn.init.normal_(
|
86 |
+
self.output_projection.weight, mean=0, std=args.decoder_embed_dim ** -0.5
|
87 |
+
)
|
88 |
+
|
89 |
+
def build_decoder_layer(self, args):
|
90 |
+
return TransformerDecoderLayer(args)
|
91 |
+
|
92 |
+
def forward(
|
93 |
+
self,
|
94 |
+
prev_output_tokens,
|
95 |
+
encoder_out: Optional[Dict[str, List[Tensor]]] = None,
|
96 |
+
incremental_state: Optional[Dict[str, Dict[str, Optional[Tensor]]]] = None,
|
97 |
+
features_only: bool = False,
|
98 |
+
return_all_hiddens: bool = False,
|
99 |
+
):
|
100 |
+
"""
|
101 |
+
Args:
|
102 |
+
prev_output_tokens (LongTensor): previous decoder outputs of shape
|
103 |
+
`(batch, tgt_len)`, for teacher forcing
|
104 |
+
encoder_out (optional): output from the encoder, used for
|
105 |
+
encoder-side attention, should be of size T x B x C
|
106 |
+
incremental_state (dict): dictionary used for storing state during
|
107 |
+
:ref:`Incremental decoding`
|
108 |
+
features_only (bool, optional): only return features without
|
109 |
+
applying output layer (default: False).
|
110 |
+
|
111 |
+
Returns:
|
112 |
+
tuple:
|
113 |
+
- the decoder's output of shape `(batch, tgt_len, vocab)`
|
114 |
+
- a dictionary with any model-specific outputs
|
115 |
+
"""
|
116 |
+
|
117 |
+
x, extra = self.extract_features(
|
118 |
+
prev_output_tokens,
|
119 |
+
encoder_out=encoder_out,
|
120 |
+
incremental_state=incremental_state,
|
121 |
+
)
|
122 |
+
|
123 |
+
if not features_only:
|
124 |
+
x = self.output_layer(x)
|
125 |
+
x = x.transpose(1, 2) # B x T x C -> B x C x T
|
126 |
+
return x, extra
|
127 |
+
|
128 |
+
def extract_features(
|
129 |
+
self,
|
130 |
+
prev_output_tokens,
|
131 |
+
encoder_out: Optional[Dict[str, List[Tensor]]],
|
132 |
+
incremental_state: Optional[Dict[str, Dict[str, Optional[Tensor]]]] = None,
|
133 |
+
):
|
134 |
+
"""
|
135 |
+
Similar to *forward* but only return features.
|
136 |
+
|
137 |
+
Includes several features from "Jointly Learning to Align and
|
138 |
+
Translate with Transformer Models" (Garg et al., EMNLP 2019).
|
139 |
+
|
140 |
+
Returns:
|
141 |
+
tuple:
|
142 |
+
- the decoder's features of shape `(batch, tgt_len, embed_dim)`
|
143 |
+
- a dictionary with any model-specific outputs
|
144 |
+
"""
|
145 |
+
bs, slen = prev_output_tokens.size()
|
146 |
+
|
147 |
+
enc: Optional[Tensor] = None
|
148 |
+
padding_mask: Optional[Tensor] = None
|
149 |
+
if encoder_out is not None and len(encoder_out["encoder_out"]) > 0:
|
150 |
+
enc = encoder_out["encoder_out"][0]
|
151 |
+
assert (
|
152 |
+
enc.size()[1] == bs
|
153 |
+
), f"Expected enc.shape == (t, {bs}, c) got {enc.shape}"
|
154 |
+
if encoder_out is not None and len(encoder_out["encoder_padding_mask"]) > 0:
|
155 |
+
padding_mask = encoder_out["encoder_padding_mask"][0]
|
156 |
+
|
157 |
+
# embed positions
|
158 |
+
positions = self.embed_positions(
|
159 |
+
prev_output_tokens
|
160 |
+
)
|
161 |
+
|
162 |
+
if incremental_state is not None:
|
163 |
+
prev_output_tokens = prev_output_tokens[:, -1:]
|
164 |
+
positions = positions[:, -1:]
|
165 |
+
|
166 |
+
# embed tokens and positions
|
167 |
+
x = self.embed_scale * self.embed_tokens(prev_output_tokens)
|
168 |
+
|
169 |
+
if self.project_in_dim is not None:
|
170 |
+
x = self.project_in_dim(x)
|
171 |
+
|
172 |
+
x += positions
|
173 |
+
|
174 |
+
x = self.dropout_module(x)
|
175 |
+
|
176 |
+
# B x T x C -> T x B x C
|
177 |
+
x = x.transpose(0, 1)
|
178 |
+
|
179 |
+
self_attn_padding_mask: Optional[Tensor] = None
|
180 |
+
if prev_output_tokens.eq(self.padding_idx).any():
|
181 |
+
self_attn_padding_mask = prev_output_tokens.eq(self.padding_idx)
|
182 |
+
|
183 |
+
# decoder layers
|
184 |
+
attn: Optional[Tensor] = None
|
185 |
+
inner_states: List[Optional[Tensor]] = [x]
|
186 |
+
for idx, layer in enumerate(self.layers):
|
187 |
+
if incremental_state is None:
|
188 |
+
self_attn_mask = self.buffered_future_mask(x)
|
189 |
+
else:
|
190 |
+
self_attn_mask = None
|
191 |
+
|
192 |
+
x, layer_attn, _ = layer(
|
193 |
+
x,
|
194 |
+
enc,
|
195 |
+
padding_mask,
|
196 |
+
incremental_state,
|
197 |
+
self_attn_mask=self_attn_mask,
|
198 |
+
self_attn_padding_mask=self_attn_padding_mask,
|
199 |
+
need_attn=False,
|
200 |
+
need_head_weights=False,
|
201 |
+
)
|
202 |
+
inner_states.append(x)
|
203 |
+
|
204 |
+
if self.layer_norm is not None:
|
205 |
+
x = self.layer_norm(x)
|
206 |
+
|
207 |
+
# T x B x C -> B x C x T
|
208 |
+
x = x.transpose(0, 1)
|
209 |
+
|
210 |
+
return x, {"inner_states": inner_states}
|
211 |
+
|
212 |
+
def output_layer(self, features):
|
213 |
+
"""Project features to the vocabulary size."""
|
214 |
+
return self.output_projection(features)
|
215 |
+
|
216 |
+
def buffered_future_mask(self, tensor):
|
217 |
+
dim = tensor.size(0)
|
218 |
+
# self._future_mask.device != tensor.device is not working in TorchScript. This is a workaround.
|
219 |
+
if (
|
220 |
+
self._future_mask.size(0) == 0
|
221 |
+
or (not self._future_mask.device == tensor.device)
|
222 |
+
or self._future_mask.size(0) < dim
|
223 |
+
):
|
224 |
+
self._future_mask = torch.triu(
|
225 |
+
fill_with_neg_inf(torch.zeros([dim, dim])), 1
|
226 |
+
)
|
227 |
+
self._future_mask = self._future_mask.to(tensor)
|
228 |
+
return self._future_mask[:dim, :dim]
|
esm/esm/inverse_folding/transformer_layer.py
ADDED
@@ -0,0 +1,304 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Copyright (c) Facebook, Inc. and its affiliates.
|
2 |
+
#
|
3 |
+
# Contents of this file were adapted from the open source fairseq repository.
|
4 |
+
#
|
5 |
+
# This source code is licensed under the MIT license found in the
|
6 |
+
# LICENSE file in the root directory of this source tree.
|
7 |
+
|
8 |
+
from typing import Dict, List, Optional
|
9 |
+
|
10 |
+
import torch
|
11 |
+
import torch.nn as nn
|
12 |
+
import torch.nn.functional as F
|
13 |
+
from esm.multihead_attention import MultiheadAttention
|
14 |
+
from torch import Tensor
|
15 |
+
|
16 |
+
|
17 |
+
class TransformerEncoderLayer(nn.Module):
|
18 |
+
"""Encoder layer block.
|
19 |
+
`layernorm -> dropout -> add residual`
|
20 |
+
|
21 |
+
Args:
|
22 |
+
args (argparse.Namespace): parsed command-line arguments
|
23 |
+
"""
|
24 |
+
|
25 |
+
def __init__(self, args):
|
26 |
+
super().__init__()
|
27 |
+
self.args = args
|
28 |
+
self.embed_dim = args.encoder_embed_dim
|
29 |
+
self.self_attn = self.build_self_attention(self.embed_dim, args)
|
30 |
+
self.self_attn_layer_norm = torch.nn.LayerNorm(self.embed_dim)
|
31 |
+
self.dropout_module = nn.Dropout(args.dropout)
|
32 |
+
self.activation_fn = F.relu
|
33 |
+
self.fc1 = self.build_fc1(
|
34 |
+
self.embed_dim,
|
35 |
+
args.encoder_ffn_embed_dim,
|
36 |
+
)
|
37 |
+
self.fc2 = self.build_fc2(
|
38 |
+
args.encoder_ffn_embed_dim,
|
39 |
+
self.embed_dim,
|
40 |
+
)
|
41 |
+
|
42 |
+
self.final_layer_norm = nn.LayerNorm(self.embed_dim)
|
43 |
+
|
44 |
+
def build_fc1(self, input_dim, output_dim):
|
45 |
+
return nn.Linear(input_dim, output_dim)
|
46 |
+
|
47 |
+
def build_fc2(self, input_dim, output_dim):
|
48 |
+
return nn.Linear(input_dim, output_dim)
|
49 |
+
|
50 |
+
def build_self_attention(self, embed_dim, args):
|
51 |
+
return MultiheadAttention(
|
52 |
+
embed_dim,
|
53 |
+
args.encoder_attention_heads,
|
54 |
+
dropout=args.attention_dropout,
|
55 |
+
self_attention=True,
|
56 |
+
)
|
57 |
+
|
58 |
+
def residual_connection(self, x, residual):
|
59 |
+
return residual + x
|
60 |
+
|
61 |
+
def forward(
|
62 |
+
self,
|
63 |
+
x,
|
64 |
+
encoder_padding_mask: Optional[Tensor],
|
65 |
+
attn_mask: Optional[Tensor] = None,
|
66 |
+
):
|
67 |
+
"""
|
68 |
+
Args:
|
69 |
+
x (Tensor): input to the layer of shape `(seq_len, batch, embed_dim)`
|
70 |
+
encoder_padding_mask (ByteTensor): binary ByteTensor of shape
|
71 |
+
`(batch, seq_len)` where padding elements are indicated by ``1``.
|
72 |
+
attn_mask (ByteTensor): binary tensor of shape `(tgt_len, src_len)`,
|
73 |
+
where `tgt_len` is the length of output and `src_len` is the
|
74 |
+
length of input, though here both are equal to `seq_len`.
|
75 |
+
`attn_mask[tgt_i, src_j] = 1` means that when calculating the
|
76 |
+
embedding for `tgt_i`, we exclude (mask out) `src_j`. This is
|
77 |
+
useful for strided self-attention.
|
78 |
+
|
79 |
+
Returns:
|
80 |
+
encoded output of shape `(seq_len, batch, embed_dim)`
|
81 |
+
"""
|
82 |
+
# anything in original attn_mask = 1, becomes -1e8
|
83 |
+
# anything in original attn_mask = 0, becomes 0
|
84 |
+
# Note that we cannot use -inf here, because at some edge cases,
|
85 |
+
# the attention weight (before softmax) for some padded element in query
|
86 |
+
# will become -inf, which results in NaN in model parameters
|
87 |
+
if attn_mask is not None:
|
88 |
+
attn_mask = attn_mask.masked_fill(
|
89 |
+
attn_mask.to(torch.bool), -1e8 if x.dtype == torch.float32 else -1e4
|
90 |
+
)
|
91 |
+
|
92 |
+
residual = x
|
93 |
+
x = self.self_attn_layer_norm(x)
|
94 |
+
x, _ = self.self_attn(
|
95 |
+
query=x,
|
96 |
+
key=x,
|
97 |
+
value=x,
|
98 |
+
key_padding_mask=encoder_padding_mask,
|
99 |
+
need_weights=False,
|
100 |
+
attn_mask=attn_mask,
|
101 |
+
)
|
102 |
+
x = self.dropout_module(x)
|
103 |
+
x = self.residual_connection(x, residual)
|
104 |
+
|
105 |
+
residual = x
|
106 |
+
x = self.final_layer_norm(x)
|
107 |
+
x = self.activation_fn(self.fc1(x))
|
108 |
+
x = self.fc2(x)
|
109 |
+
x = self.dropout_module(x)
|
110 |
+
x = self.residual_connection(x, residual)
|
111 |
+
return x
|
112 |
+
|
113 |
+
|
114 |
+
class TransformerDecoderLayer(nn.Module):
|
115 |
+
"""Decoder layer block.
|
116 |
+
`layernorm -> dropout -> add residual`
|
117 |
+
|
118 |
+
Args:
|
119 |
+
args (argparse.Namespace): parsed command-line arguments
|
120 |
+
no_encoder_attn (bool, optional): whether to attend to encoder outputs
|
121 |
+
(default: False).
|
122 |
+
"""
|
123 |
+
|
124 |
+
def __init__(
|
125 |
+
self, args, no_encoder_attn=False, add_bias_kv=False, add_zero_attn=False
|
126 |
+
):
|
127 |
+
super().__init__()
|
128 |
+
self.embed_dim = args.decoder_embed_dim
|
129 |
+
self.dropout_module = nn.Dropout(args.dropout)
|
130 |
+
|
131 |
+
self.self_attn = self.build_self_attention(
|
132 |
+
self.embed_dim,
|
133 |
+
args,
|
134 |
+
add_bias_kv=add_bias_kv,
|
135 |
+
add_zero_attn=add_zero_attn,
|
136 |
+
)
|
137 |
+
self.nh = self.self_attn.num_heads
|
138 |
+
self.head_dim = self.self_attn.head_dim
|
139 |
+
|
140 |
+
self.activation_fn = F.relu
|
141 |
+
|
142 |
+
self.self_attn_layer_norm = nn.LayerNorm(self.embed_dim)
|
143 |
+
|
144 |
+
if no_encoder_attn:
|
145 |
+
self.encoder_attn = None
|
146 |
+
self.encoder_attn_layer_norm = None
|
147 |
+
else:
|
148 |
+
self.encoder_attn = self.build_encoder_attention(self.embed_dim, args)
|
149 |
+
self.encoder_attn_layer_norm = nn.LayerNorm(self.embed_dim)
|
150 |
+
|
151 |
+
self.ffn_layernorm = (
|
152 |
+
LayerNorm(args.decoder_ffn_embed_dim)
|
153 |
+
if getattr(args, "scale_fc", False)
|
154 |
+
else None
|
155 |
+
)
|
156 |
+
self.w_resid = (
|
157 |
+
nn.Parameter(
|
158 |
+
torch.ones(
|
159 |
+
self.embed_dim,
|
160 |
+
),
|
161 |
+
requires_grad=True,
|
162 |
+
)
|
163 |
+
if getattr(args, "scale_resids", False)
|
164 |
+
else None
|
165 |
+
)
|
166 |
+
|
167 |
+
self.fc1 = self.build_fc1(
|
168 |
+
self.embed_dim,
|
169 |
+
args.decoder_ffn_embed_dim,
|
170 |
+
)
|
171 |
+
self.fc2 = self.build_fc2(
|
172 |
+
args.decoder_ffn_embed_dim,
|
173 |
+
self.embed_dim,
|
174 |
+
)
|
175 |
+
|
176 |
+
self.final_layer_norm = nn.LayerNorm(self.embed_dim)
|
177 |
+
self.need_attn = True
|
178 |
+
|
179 |
+
def build_fc1(self, input_dim, output_dim):
|
180 |
+
return nn.Linear(input_dim, output_dim)
|
181 |
+
|
182 |
+
def build_fc2(self, input_dim, output_dim):
|
183 |
+
return nn.Linear(input_dim, output_dim)
|
184 |
+
|
185 |
+
def build_self_attention(
|
186 |
+
self, embed_dim, args, add_bias_kv=False, add_zero_attn=False
|
187 |
+
):
|
188 |
+
return MultiheadAttention(
|
189 |
+
embed_dim,
|
190 |
+
args.decoder_attention_heads,
|
191 |
+
dropout=args.attention_dropout,
|
192 |
+
add_bias_kv=add_bias_kv,
|
193 |
+
add_zero_attn=add_zero_attn,
|
194 |
+
self_attention=True,
|
195 |
+
)
|
196 |
+
|
197 |
+
def build_encoder_attention(self, embed_dim, args):
|
198 |
+
return MultiheadAttention(
|
199 |
+
embed_dim,
|
200 |
+
args.decoder_attention_heads,
|
201 |
+
kdim=args.encoder_embed_dim,
|
202 |
+
vdim=args.encoder_embed_dim,
|
203 |
+
dropout=args.attention_dropout,
|
204 |
+
encoder_decoder_attention=True,
|
205 |
+
)
|
206 |
+
|
207 |
+
def residual_connection(self, x, residual):
|
208 |
+
return residual + x
|
209 |
+
|
210 |
+
def forward(
|
211 |
+
self,
|
212 |
+
x,
|
213 |
+
encoder_out: Optional[torch.Tensor] = None,
|
214 |
+
encoder_padding_mask: Optional[torch.Tensor] = None,
|
215 |
+
incremental_state: Optional[Dict[str, Dict[str, Optional[Tensor]]]] = None,
|
216 |
+
prev_self_attn_state: Optional[List[torch.Tensor]] = None,
|
217 |
+
prev_attn_state: Optional[List[torch.Tensor]] = None,
|
218 |
+
self_attn_mask: Optional[torch.Tensor] = None,
|
219 |
+
self_attn_padding_mask: Optional[torch.Tensor] = None,
|
220 |
+
need_attn: bool = False,
|
221 |
+
need_head_weights: bool = False,
|
222 |
+
):
|
223 |
+
"""
|
224 |
+
Args:
|
225 |
+
x (Tensor): input to the layer of shape `(seq_len, batch, embed_dim)`
|
226 |
+
encoder_padding_mask (ByteTensor, optional): binary
|
227 |
+
ByteTensor of shape `(batch, src_len)` where padding
|
228 |
+
elements are indicated by ``1``.
|
229 |
+
need_attn (bool, optional): return attention weights
|
230 |
+
need_head_weights (bool, optional): return attention weights
|
231 |
+
for each head (default: return average over heads).
|
232 |
+
|
233 |
+
Returns:
|
234 |
+
encoded output of shape `(seq_len, batch, embed_dim)`
|
235 |
+
"""
|
236 |
+
if need_head_weights:
|
237 |
+
need_attn = True
|
238 |
+
|
239 |
+
residual = x
|
240 |
+
x = self.self_attn_layer_norm(x)
|
241 |
+
if prev_self_attn_state is not None:
|
242 |
+
prev_key, prev_value = prev_self_attn_state[:2]
|
243 |
+
saved_state: Dict[str, Optional[Tensor]] = {
|
244 |
+
"prev_key": prev_key,
|
245 |
+
"prev_value": prev_value,
|
246 |
+
}
|
247 |
+
if len(prev_self_attn_state) >= 3:
|
248 |
+
saved_state["prev_key_padding_mask"] = prev_self_attn_state[2]
|
249 |
+
assert incremental_state is not None
|
250 |
+
self.self_attn._set_input_buffer(incremental_state, saved_state)
|
251 |
+
_self_attn_input_buffer = self.self_attn._get_input_buffer(incremental_state)
|
252 |
+
y = x
|
253 |
+
|
254 |
+
x, attn = self.self_attn(
|
255 |
+
query=x,
|
256 |
+
key=y,
|
257 |
+
value=y,
|
258 |
+
key_padding_mask=self_attn_padding_mask,
|
259 |
+
incremental_state=incremental_state,
|
260 |
+
need_weights=False,
|
261 |
+
attn_mask=self_attn_mask,
|
262 |
+
)
|
263 |
+
x = self.dropout_module(x)
|
264 |
+
x = self.residual_connection(x, residual)
|
265 |
+
|
266 |
+
if self.encoder_attn is not None and encoder_out is not None:
|
267 |
+
residual = x
|
268 |
+
x = self.encoder_attn_layer_norm(x)
|
269 |
+
if prev_attn_state is not None:
|
270 |
+
prev_key, prev_value = prev_attn_state[:2]
|
271 |
+
saved_state: Dict[str, Optional[Tensor]] = {
|
272 |
+
"prev_key": prev_key,
|
273 |
+
"prev_value": prev_value,
|
274 |
+
}
|
275 |
+
if len(prev_attn_state) >= 3:
|
276 |
+
saved_state["prev_key_padding_mask"] = prev_attn_state[2]
|
277 |
+
assert incremental_state is not None
|
278 |
+
self.encoder_attn._set_input_buffer(incremental_state, saved_state)
|
279 |
+
|
280 |
+
x, attn = self.encoder_attn(
|
281 |
+
query=x,
|
282 |
+
key=encoder_out,
|
283 |
+
value=encoder_out,
|
284 |
+
key_padding_mask=encoder_padding_mask,
|
285 |
+
incremental_state=incremental_state,
|
286 |
+
static_kv=True,
|
287 |
+
need_weights=need_attn or (not self.training and self.need_attn),
|
288 |
+
need_head_weights=need_head_weights,
|
289 |
+
)
|
290 |
+
x = self.dropout_module(x)
|
291 |
+
x = self.residual_connection(x, residual)
|
292 |
+
|
293 |
+
residual = x
|
294 |
+
x = self.final_layer_norm(x)
|
295 |
+
|
296 |
+
x = self.activation_fn(self.fc1(x))
|
297 |
+
if self.ffn_layernorm is not None:
|
298 |
+
x = self.ffn_layernorm(x)
|
299 |
+
x = self.fc2(x)
|
300 |
+
x = self.dropout_module(x)
|
301 |
+
if self.w_resid is not None:
|
302 |
+
residual = torch.mul(self.w_resid, residual)
|
303 |
+
x = self.residual_connection(x, residual)
|
304 |
+
return x, attn, None
|
esm/esm/inverse_folding/util.py
ADDED
@@ -0,0 +1,320 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Copyright (c) Facebook, Inc. and its affiliates.
|
2 |
+
#
|
3 |
+
# This source code is licensed under the MIT license found in the
|
4 |
+
# LICENSE file in the root directory of this source tree.
|
5 |
+
|
6 |
+
import json
|
7 |
+
import math
|
8 |
+
|
9 |
+
import biotite.structure
|
10 |
+
from biotite.structure.io import pdbx, pdb
|
11 |
+
from biotite.structure.residues import get_residues
|
12 |
+
from biotite.structure import filter_backbone
|
13 |
+
from biotite.structure import get_chains
|
14 |
+
from biotite.sequence import ProteinSequence
|
15 |
+
import numpy as np
|
16 |
+
from scipy.spatial import transform
|
17 |
+
from scipy.stats import special_ortho_group
|
18 |
+
import torch
|
19 |
+
import torch.nn as nn
|
20 |
+
import torch.nn.functional as F
|
21 |
+
import torch.utils.data as data
|
22 |
+
from typing import Sequence, Tuple, List
|
23 |
+
|
24 |
+
from esm.data import BatchConverter
|
25 |
+
|
26 |
+
|
27 |
+
def load_structure(fpath, chain=None):
|
28 |
+
"""
|
29 |
+
Args:
|
30 |
+
fpath: filepath to either pdb or cif file
|
31 |
+
chain: the chain id or list of chain ids to load
|
32 |
+
Returns:
|
33 |
+
biotite.structure.AtomArray
|
34 |
+
"""
|
35 |
+
if fpath.endswith('cif'):
|
36 |
+
with open(fpath) as fin:
|
37 |
+
pdbxf = pdbx.PDBxFile.read(fin)
|
38 |
+
structure = pdbx.get_structure(pdbxf, model=1)
|
39 |
+
elif fpath.endswith('pdb'):
|
40 |
+
with open(fpath) as fin:
|
41 |
+
pdbf = pdb.PDBFile.read(fin)
|
42 |
+
structure = pdb.get_structure(pdbf, model=1)
|
43 |
+
bbmask = filter_backbone(structure)
|
44 |
+
structure = structure[bbmask]
|
45 |
+
all_chains = get_chains(structure)
|
46 |
+
if len(all_chains) == 0:
|
47 |
+
raise ValueError('No chains found in the input file.')
|
48 |
+
if chain is None:
|
49 |
+
chain_ids = all_chains
|
50 |
+
elif isinstance(chain, list):
|
51 |
+
chain_ids = chain
|
52 |
+
else:
|
53 |
+
chain_ids = [chain]
|
54 |
+
for chain in chain_ids:
|
55 |
+
if chain not in all_chains:
|
56 |
+
raise ValueError(f'Chain {chain} not found in input file')
|
57 |
+
chain_filter = [a.chain_id in chain_ids for a in structure]
|
58 |
+
structure = structure[chain_filter]
|
59 |
+
return structure
|
60 |
+
|
61 |
+
|
62 |
+
def extract_coords_from_structure(structure: biotite.structure.AtomArray):
|
63 |
+
"""
|
64 |
+
Args:
|
65 |
+
structure: An instance of biotite AtomArray
|
66 |
+
Returns:
|
67 |
+
Tuple (coords, seq)
|
68 |
+
- coords is an L x 3 x 3 array for N, CA, C coordinates
|
69 |
+
- seq is the extracted sequence
|
70 |
+
"""
|
71 |
+
coords = get_atom_coords_residuewise(["N", "CA", "C"], structure)
|
72 |
+
residue_identities = get_residues(structure)[1]
|
73 |
+
seq = ''.join([ProteinSequence.convert_letter_3to1(r) for r in residue_identities])
|
74 |
+
return coords, seq
|
75 |
+
|
76 |
+
|
77 |
+
def load_coords(fpath, chain):
|
78 |
+
"""
|
79 |
+
Args:
|
80 |
+
fpath: filepath to either pdb or cif file
|
81 |
+
chain: the chain id
|
82 |
+
Returns:
|
83 |
+
Tuple (coords, seq)
|
84 |
+
- coords is an L x 3 x 3 array for N, CA, C coordinates
|
85 |
+
- seq is the extracted sequence
|
86 |
+
"""
|
87 |
+
structure = load_structure(fpath, chain)
|
88 |
+
return extract_coords_from_structure(structure)
|
89 |
+
|
90 |
+
|
91 |
+
def get_atom_coords_residuewise(atoms: List[str], struct: biotite.structure.AtomArray):
|
92 |
+
"""
|
93 |
+
Example for atoms argument: ["N", "CA", "C"]
|
94 |
+
"""
|
95 |
+
def filterfn(s, axis=None):
|
96 |
+
filters = np.stack([s.atom_name == name for name in atoms], axis=1)
|
97 |
+
sum = filters.sum(0)
|
98 |
+
if not np.all(sum <= np.ones(filters.shape[1])):
|
99 |
+
raise RuntimeError("structure has multiple atoms with same name")
|
100 |
+
index = filters.argmax(0)
|
101 |
+
coords = s[index].coord
|
102 |
+
coords[sum == 0] = float("nan")
|
103 |
+
return coords
|
104 |
+
|
105 |
+
return biotite.structure.apply_residue_wise(struct, struct, filterfn)
|
106 |
+
|
107 |
+
|
108 |
+
def get_sequence_loss(model, alphabet, coords, seq):
|
109 |
+
batch_converter = CoordBatchConverter(alphabet)
|
110 |
+
batch = [(coords, None, seq)]
|
111 |
+
coords, confidence, strs, tokens, padding_mask = batch_converter(batch)
|
112 |
+
|
113 |
+
prev_output_tokens = tokens[:, :-1]
|
114 |
+
target = tokens[:, 1:]
|
115 |
+
target_padding_mask = (target == alphabet.padding_idx)
|
116 |
+
logits, _ = model.forward(coords, padding_mask, confidence, prev_output_tokens)
|
117 |
+
loss = F.cross_entropy(logits, target, reduction='none')
|
118 |
+
loss = loss[0].detach().numpy()
|
119 |
+
target_padding_mask = target_padding_mask[0].numpy()
|
120 |
+
return loss, target_padding_mask
|
121 |
+
|
122 |
+
|
123 |
+
def score_sequence(model, alphabet, coords, seq):
|
124 |
+
loss, target_padding_mask = get_sequence_loss(model, alphabet, coords, seq)
|
125 |
+
ll_fullseq = -np.sum(loss * ~target_padding_mask) / np.sum(~target_padding_mask)
|
126 |
+
# Also calculate average when excluding masked portions
|
127 |
+
coord_mask = np.all(np.isfinite(coords), axis=(-1, -2))
|
128 |
+
ll_withcoord = -np.sum(loss * coord_mask) / np.sum(coord_mask)
|
129 |
+
return ll_fullseq, ll_withcoord
|
130 |
+
|
131 |
+
|
132 |
+
def get_encoder_output(model, alphabet, coords):
|
133 |
+
batch_converter = CoordBatchConverter(alphabet)
|
134 |
+
# the batch_converter is essential for forming the correct input format
|
135 |
+
batch = [(coords, None, None)]
|
136 |
+
coords, confidence, _, _, padding_mask = batch_converter(batch)
|
137 |
+
encoder_out = model.encoder.forward(coords, padding_mask, confidence,
|
138 |
+
return_all_hiddens=False)
|
139 |
+
# remove beginning and end (bos and eos tokens)
|
140 |
+
return encoder_out['encoder_out'][0][1:-1, 0]
|
141 |
+
|
142 |
+
|
143 |
+
def rotate(v, R):
|
144 |
+
"""
|
145 |
+
Rotates a vector by a rotation matrix.
|
146 |
+
|
147 |
+
Args:
|
148 |
+
v: 3D vector, tensor of shape (length x batch_size x channels x 3)
|
149 |
+
R: rotation matrix, tensor of shape (length x batch_size x 3 x 3)
|
150 |
+
|
151 |
+
Returns:
|
152 |
+
Rotated version of v by rotation matrix R.
|
153 |
+
"""
|
154 |
+
R = R.unsqueeze(-3)
|
155 |
+
v = v.unsqueeze(-1)
|
156 |
+
return torch.sum(v * R, dim=-2)
|
157 |
+
|
158 |
+
|
159 |
+
def get_rotation_frames(coords):
|
160 |
+
"""
|
161 |
+
Returns a local rotation frame defined by N, CA, C positions.
|
162 |
+
|
163 |
+
Args:
|
164 |
+
coords: coordinates, tensor of shape (batch_size x length x 3 x 3)
|
165 |
+
where the third dimension is in order of N, CA, C
|
166 |
+
|
167 |
+
Returns:
|
168 |
+
Local relative rotation frames in shape (batch_size x length x 3 x 3)
|
169 |
+
"""
|
170 |
+
v1 = coords[:, :, 2] - coords[:, :, 1]
|
171 |
+
v2 = coords[:, :, 0] - coords[:, :, 1]
|
172 |
+
e1 = normalize(v1, dim=-1)
|
173 |
+
u2 = v2 - e1 * torch.sum(e1 * v2, dim=-1, keepdim=True)
|
174 |
+
e2 = normalize(u2, dim=-1)
|
175 |
+
e3 = torch.cross(e1, e2, dim=-1)
|
176 |
+
R = torch.stack([e1, e2, e3], dim=-2)
|
177 |
+
return R
|
178 |
+
|
179 |
+
|
180 |
+
def nan_to_num(ts, val=0.0):
|
181 |
+
"""
|
182 |
+
Replaces nans in tensor with a fixed value.
|
183 |
+
"""
|
184 |
+
val = torch.tensor(val, dtype=ts.dtype, device=ts.device)
|
185 |
+
return torch.where(~torch.isfinite(ts), val, ts)
|
186 |
+
|
187 |
+
|
188 |
+
def rbf(values, v_min, v_max, n_bins=16):
|
189 |
+
"""
|
190 |
+
Returns RBF encodings in a new dimension at the end.
|
191 |
+
"""
|
192 |
+
rbf_centers = torch.linspace(v_min, v_max, n_bins, device=values.device)
|
193 |
+
rbf_centers = rbf_centers.view([1] * len(values.shape) + [-1])
|
194 |
+
rbf_std = (v_max - v_min) / n_bins
|
195 |
+
v_expand = torch.unsqueeze(values, -1)
|
196 |
+
z = (values.unsqueeze(-1) - rbf_centers) / rbf_std
|
197 |
+
return torch.exp(-z ** 2)
|
198 |
+
|
199 |
+
|
200 |
+
def norm(tensor, dim, eps=1e-8, keepdim=False):
|
201 |
+
"""
|
202 |
+
Returns L2 norm along a dimension.
|
203 |
+
"""
|
204 |
+
return torch.sqrt(
|
205 |
+
torch.sum(torch.square(tensor), dim=dim, keepdim=keepdim) + eps)
|
206 |
+
|
207 |
+
|
208 |
+
def normalize(tensor, dim=-1):
|
209 |
+
"""
|
210 |
+
Normalizes a tensor along a dimension after removing nans.
|
211 |
+
"""
|
212 |
+
return nan_to_num(
|
213 |
+
torch.div(tensor, norm(tensor, dim=dim, keepdim=True))
|
214 |
+
)
|
215 |
+
|
216 |
+
|
217 |
+
class CoordBatchConverter(BatchConverter):
|
218 |
+
def __call__(self, raw_batch: Sequence[Tuple[Sequence, str]], device=None):
|
219 |
+
"""
|
220 |
+
Args:
|
221 |
+
raw_batch: List of tuples (coords, confidence, seq)
|
222 |
+
In each tuple,
|
223 |
+
coords: list of floats, shape L x 3 x 3
|
224 |
+
confidence: list of floats, shape L; or scalar float; or None
|
225 |
+
seq: string of length L
|
226 |
+
Returns:
|
227 |
+
coords: Tensor of shape batch_size x L x 3 x 3
|
228 |
+
confidence: Tensor of shape batch_size x L
|
229 |
+
strs: list of strings
|
230 |
+
tokens: LongTensor of shape batch_size x L
|
231 |
+
padding_mask: ByteTensor of shape batch_size x L
|
232 |
+
"""
|
233 |
+
self.alphabet.cls_idx = self.alphabet.get_idx("<cath>")
|
234 |
+
batch = []
|
235 |
+
for coords, confidence, seq in raw_batch:
|
236 |
+
if confidence is None:
|
237 |
+
confidence = 1.
|
238 |
+
if isinstance(confidence, float) or isinstance(confidence, int):
|
239 |
+
confidence = [float(confidence)] * len(coords)
|
240 |
+
if seq is None:
|
241 |
+
seq = 'X' * len(coords)
|
242 |
+
batch.append(((coords, confidence), seq))
|
243 |
+
|
244 |
+
coords_and_confidence, strs, tokens = super().__call__(batch)
|
245 |
+
|
246 |
+
# pad beginning and end of each protein due to legacy reasons
|
247 |
+
coords = [
|
248 |
+
F.pad(torch.tensor(cd), (0, 0, 0, 0, 1, 1), value=np.inf)
|
249 |
+
for cd, _ in coords_and_confidence
|
250 |
+
]
|
251 |
+
confidence = [
|
252 |
+
F.pad(torch.tensor(cf), (1, 1), value=-1.)
|
253 |
+
for _, cf in coords_and_confidence
|
254 |
+
]
|
255 |
+
coords = self.collate_dense_tensors(coords, pad_v=np.nan)
|
256 |
+
confidence = self.collate_dense_tensors(confidence, pad_v=-1.)
|
257 |
+
if device is not None:
|
258 |
+
coords = coords.to(device)
|
259 |
+
confidence = confidence.to(device)
|
260 |
+
tokens = tokens.to(device)
|
261 |
+
padding_mask = torch.isnan(coords[:,:,0,0])
|
262 |
+
coord_mask = torch.isfinite(coords.sum(-2).sum(-1))
|
263 |
+
confidence = confidence * coord_mask + (-1.) * padding_mask
|
264 |
+
return coords, confidence, strs, tokens, padding_mask
|
265 |
+
|
266 |
+
def from_lists(self, coords_list, confidence_list=None, seq_list=None, device=None):
|
267 |
+
"""
|
268 |
+
Args:
|
269 |
+
coords_list: list of length batch_size, each item is a list of
|
270 |
+
floats in shape L x 3 x 3 to describe a backbone
|
271 |
+
confidence_list: one of
|
272 |
+
- None, default to highest confidence
|
273 |
+
- list of length batch_size, each item is a scalar
|
274 |
+
- list of length batch_size, each item is a list of floats of
|
275 |
+
length L to describe the confidence scores for the backbone
|
276 |
+
with values between 0. and 1.
|
277 |
+
seq_list: either None or a list of strings
|
278 |
+
Returns:
|
279 |
+
coords: Tensor of shape batch_size x L x 3 x 3
|
280 |
+
confidence: Tensor of shape batch_size x L
|
281 |
+
strs: list of strings
|
282 |
+
tokens: LongTensor of shape batch_size x L
|
283 |
+
padding_mask: ByteTensor of shape batch_size x L
|
284 |
+
"""
|
285 |
+
batch_size = len(coords_list)
|
286 |
+
if confidence_list is None:
|
287 |
+
confidence_list = [None] * batch_size
|
288 |
+
if seq_list is None:
|
289 |
+
seq_list = [None] * batch_size
|
290 |
+
raw_batch = zip(coords_list, confidence_list, seq_list)
|
291 |
+
return self.__call__(raw_batch, device)
|
292 |
+
|
293 |
+
@staticmethod
|
294 |
+
def collate_dense_tensors(samples, pad_v):
|
295 |
+
"""
|
296 |
+
Takes a list of tensors with the following dimensions:
|
297 |
+
[(d_11, ..., d_1K),
|
298 |
+
(d_21, ..., d_2K),
|
299 |
+
...,
|
300 |
+
(d_N1, ..., d_NK)]
|
301 |
+
and stack + pads them into a single tensor of:
|
302 |
+
(N, max_i=1,N { d_i1 }, ..., max_i=1,N {diK})
|
303 |
+
"""
|
304 |
+
if len(samples) == 0:
|
305 |
+
return torch.Tensor()
|
306 |
+
if len(set(x.dim() for x in samples)) != 1:
|
307 |
+
raise RuntimeError(
|
308 |
+
f"Samples has varying dimensions: {[x.dim() for x in samples]}"
|
309 |
+
)
|
310 |
+
(device,) = tuple(set(x.device for x in samples)) # assumes all on same device
|
311 |
+
max_shape = [max(lst) for lst in zip(*[x.shape for x in samples])]
|
312 |
+
result = torch.empty(
|
313 |
+
len(samples), *max_shape, dtype=samples[0].dtype, device=device
|
314 |
+
)
|
315 |
+
result.fill_(pad_v)
|
316 |
+
for i in range(len(samples)):
|
317 |
+
result_i = result[i]
|
318 |
+
t = samples[i]
|
319 |
+
result_i[tuple(slice(0, k) for k in t.shape)] = t
|
320 |
+
return result
|
esm/esm/model/esm1.py
ADDED
@@ -0,0 +1,200 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Copyright (c) Facebook, Inc. and its affiliates.
|
2 |
+
#
|
3 |
+
# This source code is licensed under the MIT license found in the
|
4 |
+
# LICENSE file in the root directory of this source tree.
|
5 |
+
|
6 |
+
import math
|
7 |
+
|
8 |
+
import torch
|
9 |
+
import torch.nn as nn
|
10 |
+
import torch.nn.functional as F
|
11 |
+
|
12 |
+
from ..modules import (
|
13 |
+
TransformerLayer,
|
14 |
+
LearnedPositionalEmbedding,
|
15 |
+
SinusoidalPositionalEmbedding,
|
16 |
+
RobertaLMHead,
|
17 |
+
ESM1bLayerNorm,
|
18 |
+
ContactPredictionHead,
|
19 |
+
)
|
20 |
+
|
21 |
+
|
22 |
+
class ProteinBertModel(nn.Module):
|
23 |
+
@classmethod
|
24 |
+
def add_args(cls, parser):
|
25 |
+
parser.add_argument(
|
26 |
+
"--num_layers", default=36, type=int, metavar="N", help="number of layers"
|
27 |
+
)
|
28 |
+
parser.add_argument(
|
29 |
+
"--embed_dim", default=1280, type=int, metavar="N", help="embedding dimension"
|
30 |
+
)
|
31 |
+
parser.add_argument(
|
32 |
+
"--logit_bias", action="store_true", help="whether to apply bias to logits"
|
33 |
+
)
|
34 |
+
parser.add_argument(
|
35 |
+
"--ffn_embed_dim",
|
36 |
+
default=5120,
|
37 |
+
type=int,
|
38 |
+
metavar="N",
|
39 |
+
help="embedding dimension for FFN",
|
40 |
+
)
|
41 |
+
parser.add_argument(
|
42 |
+
"--attention_heads",
|
43 |
+
default=20,
|
44 |
+
type=int,
|
45 |
+
metavar="N",
|
46 |
+
help="number of attention heads",
|
47 |
+
)
|
48 |
+
|
49 |
+
def __init__(self, args, alphabet):
|
50 |
+
super().__init__()
|
51 |
+
self.args = args
|
52 |
+
self.alphabet_size = len(alphabet)
|
53 |
+
self.padding_idx = alphabet.padding_idx
|
54 |
+
self.mask_idx = alphabet.mask_idx
|
55 |
+
self.cls_idx = alphabet.cls_idx
|
56 |
+
self.eos_idx = alphabet.eos_idx
|
57 |
+
self.prepend_bos = alphabet.prepend_bos
|
58 |
+
self.append_eos = alphabet.append_eos
|
59 |
+
self.emb_layer_norm_before = getattr(self.args, "emb_layer_norm_before", False)
|
60 |
+
if self.args.arch == "roberta_large":
|
61 |
+
self.model_version = "ESM-1b"
|
62 |
+
self._init_submodules_esm1b()
|
63 |
+
else:
|
64 |
+
self.model_version = "ESM-1"
|
65 |
+
self._init_submodules_esm1()
|
66 |
+
|
67 |
+
def _init_submodules_common(self):
|
68 |
+
self.embed_tokens = nn.Embedding(
|
69 |
+
self.alphabet_size, self.args.embed_dim, padding_idx=self.padding_idx
|
70 |
+
)
|
71 |
+
self.layers = nn.ModuleList(
|
72 |
+
[
|
73 |
+
TransformerLayer(
|
74 |
+
self.args.embed_dim,
|
75 |
+
self.args.ffn_embed_dim,
|
76 |
+
self.args.attention_heads,
|
77 |
+
add_bias_kv=(self.model_version != "ESM-1b"),
|
78 |
+
use_esm1b_layer_norm=(self.model_version == "ESM-1b"),
|
79 |
+
)
|
80 |
+
for _ in range(self.args.layers)
|
81 |
+
]
|
82 |
+
)
|
83 |
+
|
84 |
+
self.contact_head = ContactPredictionHead(
|
85 |
+
self.args.layers * self.args.attention_heads,
|
86 |
+
self.prepend_bos,
|
87 |
+
self.append_eos,
|
88 |
+
eos_idx=self.eos_idx,
|
89 |
+
)
|
90 |
+
|
91 |
+
def _init_submodules_esm1b(self):
|
92 |
+
self._init_submodules_common()
|
93 |
+
self.embed_scale = 1
|
94 |
+
self.embed_positions = LearnedPositionalEmbedding(
|
95 |
+
self.args.max_positions, self.args.embed_dim, self.padding_idx
|
96 |
+
)
|
97 |
+
self.emb_layer_norm_before = (
|
98 |
+
ESM1bLayerNorm(self.args.embed_dim) if self.emb_layer_norm_before else None
|
99 |
+
)
|
100 |
+
self.emb_layer_norm_after = ESM1bLayerNorm(self.args.embed_dim)
|
101 |
+
self.lm_head = RobertaLMHead(
|
102 |
+
embed_dim=self.args.embed_dim,
|
103 |
+
output_dim=self.alphabet_size,
|
104 |
+
weight=self.embed_tokens.weight,
|
105 |
+
)
|
106 |
+
|
107 |
+
def _init_submodules_esm1(self):
|
108 |
+
self._init_submodules_common()
|
109 |
+
self.embed_scale = math.sqrt(self.args.embed_dim)
|
110 |
+
self.embed_positions = SinusoidalPositionalEmbedding(self.args.embed_dim, self.padding_idx)
|
111 |
+
self.embed_out = nn.Parameter(torch.zeros((self.alphabet_size, self.args.embed_dim)))
|
112 |
+
self.embed_out_bias = None
|
113 |
+
if self.args.final_bias:
|
114 |
+
self.embed_out_bias = nn.Parameter(torch.zeros(self.alphabet_size))
|
115 |
+
|
116 |
+
def forward(self, tokens, repr_layers=[], need_head_weights=False, return_contacts=False):
|
117 |
+
if return_contacts:
|
118 |
+
need_head_weights = True
|
119 |
+
|
120 |
+
assert tokens.ndim == 2
|
121 |
+
padding_mask = tokens.eq(self.padding_idx) # B, T
|
122 |
+
|
123 |
+
x = self.embed_scale * self.embed_tokens(tokens)
|
124 |
+
|
125 |
+
if getattr(self.args, "token_dropout", False):
|
126 |
+
x.masked_fill_((tokens == self.mask_idx).unsqueeze(-1), 0.0)
|
127 |
+
# x: B x T x C
|
128 |
+
mask_ratio_train = 0.15 * 0.8
|
129 |
+
src_lengths = (~padding_mask).sum(-1)
|
130 |
+
mask_ratio_observed = (tokens == self.mask_idx).sum(-1).float() / src_lengths
|
131 |
+
x = x * (1 - mask_ratio_train) / (1 - mask_ratio_observed)[:, None, None]
|
132 |
+
|
133 |
+
x = x + self.embed_positions(tokens)
|
134 |
+
|
135 |
+
if self.model_version == "ESM-1b":
|
136 |
+
if self.emb_layer_norm_before:
|
137 |
+
x = self.emb_layer_norm_before(x)
|
138 |
+
if padding_mask is not None:
|
139 |
+
x = x * (1 - padding_mask.unsqueeze(-1).type_as(x))
|
140 |
+
|
141 |
+
repr_layers = set(repr_layers)
|
142 |
+
hidden_representations = {}
|
143 |
+
if 0 in repr_layers:
|
144 |
+
hidden_representations[0] = x
|
145 |
+
|
146 |
+
if need_head_weights:
|
147 |
+
attn_weights = []
|
148 |
+
|
149 |
+
# (B, T, E) => (T, B, E)
|
150 |
+
x = x.transpose(0, 1)
|
151 |
+
|
152 |
+
if not padding_mask.any():
|
153 |
+
padding_mask = None
|
154 |
+
|
155 |
+
for layer_idx, layer in enumerate(self.layers):
|
156 |
+
x, attn = layer(
|
157 |
+
x, self_attn_padding_mask=padding_mask, need_head_weights=need_head_weights
|
158 |
+
)
|
159 |
+
if (layer_idx + 1) in repr_layers:
|
160 |
+
hidden_representations[layer_idx + 1] = x.transpose(0, 1)
|
161 |
+
if need_head_weights:
|
162 |
+
# (H, B, T, T) => (B, H, T, T)
|
163 |
+
attn_weights.append(attn.transpose(1, 0))
|
164 |
+
|
165 |
+
if self.model_version == "ESM-1b":
|
166 |
+
x = self.emb_layer_norm_after(x)
|
167 |
+
x = x.transpose(0, 1) # (T, B, E) => (B, T, E)
|
168 |
+
|
169 |
+
# last hidden representation should have layer norm applied
|
170 |
+
if (layer_idx + 1) in repr_layers:
|
171 |
+
hidden_representations[layer_idx + 1] = x
|
172 |
+
x = self.lm_head(x)
|
173 |
+
else:
|
174 |
+
x = F.linear(x, self.embed_out, bias=self.embed_out_bias)
|
175 |
+
x = x.transpose(0, 1) # (T, B, E) => (B, T, E)
|
176 |
+
|
177 |
+
result = {"logits": x, "representations": hidden_representations}
|
178 |
+
if need_head_weights:
|
179 |
+
# attentions: B x L x H x T x T
|
180 |
+
attentions = torch.stack(attn_weights, 1)
|
181 |
+
if self.model_version == "ESM-1":
|
182 |
+
# ESM-1 models have an additional null-token for attention, which we remove
|
183 |
+
attentions = attentions[..., :-1]
|
184 |
+
if padding_mask is not None:
|
185 |
+
attention_mask = 1 - padding_mask.type_as(attentions)
|
186 |
+
attention_mask = attention_mask.unsqueeze(1) * attention_mask.unsqueeze(2)
|
187 |
+
attentions = attentions * attention_mask[:, None, None, :, :]
|
188 |
+
result["attentions"] = attentions
|
189 |
+
if return_contacts:
|
190 |
+
contacts = self.contact_head(tokens, attentions)
|
191 |
+
result["contacts"] = contacts
|
192 |
+
|
193 |
+
return result
|
194 |
+
|
195 |
+
def predict_contacts(self, tokens):
|
196 |
+
return self(tokens, return_contacts=True)["contacts"]
|
197 |
+
|
198 |
+
@property
|
199 |
+
def num_layers(self):
|
200 |
+
return self.args.layers
|
esm/esm/model/esm2.py
ADDED
@@ -0,0 +1,147 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Copyright (c) Facebook, Inc. and its affiliates.
|
2 |
+
#
|
3 |
+
# This source code is licensed under the MIT license found in the
|
4 |
+
# LICENSE file in the root directory of this source tree.
|
5 |
+
|
6 |
+
from typing import Union
|
7 |
+
import torch
|
8 |
+
import torch.nn as nn
|
9 |
+
|
10 |
+
import esm
|
11 |
+
from esm.modules import ContactPredictionHead, ESM1bLayerNorm, RobertaLMHead, TransformerLayer
|
12 |
+
|
13 |
+
|
14 |
+
class ESM2(nn.Module):
|
15 |
+
def __init__(
|
16 |
+
self,
|
17 |
+
num_layers: int = 33,
|
18 |
+
embed_dim: int = 1280,
|
19 |
+
attention_heads: int = 20,
|
20 |
+
alphabet: Union[esm.data.Alphabet, str] = "ESM-1b",
|
21 |
+
token_dropout: bool = True,
|
22 |
+
):
|
23 |
+
super().__init__()
|
24 |
+
self.num_layers = num_layers
|
25 |
+
self.embed_dim = embed_dim
|
26 |
+
self.attention_heads = attention_heads
|
27 |
+
if not isinstance(alphabet, esm.data.Alphabet):
|
28 |
+
alphabet = esm.data.Alphabet.from_architecture(alphabet)
|
29 |
+
self.alphabet = alphabet
|
30 |
+
self.alphabet_size = len(alphabet)
|
31 |
+
self.padding_idx = alphabet.padding_idx
|
32 |
+
self.mask_idx = alphabet.mask_idx
|
33 |
+
self.cls_idx = alphabet.cls_idx
|
34 |
+
self.eos_idx = alphabet.eos_idx
|
35 |
+
self.prepend_bos = alphabet.prepend_bos
|
36 |
+
self.append_eos = alphabet.append_eos
|
37 |
+
self.token_dropout = token_dropout
|
38 |
+
|
39 |
+
self._init_submodules()
|
40 |
+
|
41 |
+
def _init_submodules(self):
|
42 |
+
self.embed_scale = 1
|
43 |
+
self.embed_tokens = nn.Embedding(
|
44 |
+
self.alphabet_size,
|
45 |
+
self.embed_dim,
|
46 |
+
padding_idx=self.padding_idx,
|
47 |
+
)
|
48 |
+
|
49 |
+
self.layers = nn.ModuleList(
|
50 |
+
[
|
51 |
+
TransformerLayer(
|
52 |
+
self.embed_dim,
|
53 |
+
4 * self.embed_dim,
|
54 |
+
self.attention_heads,
|
55 |
+
add_bias_kv=False,
|
56 |
+
use_esm1b_layer_norm=True,
|
57 |
+
use_rotary_embeddings=True,
|
58 |
+
)
|
59 |
+
for _ in range(self.num_layers)
|
60 |
+
]
|
61 |
+
)
|
62 |
+
|
63 |
+
self.contact_head = ContactPredictionHead(
|
64 |
+
self.num_layers * self.attention_heads,
|
65 |
+
self.prepend_bos,
|
66 |
+
self.append_eos,
|
67 |
+
eos_idx=self.eos_idx,
|
68 |
+
)
|
69 |
+
self.emb_layer_norm_after = ESM1bLayerNorm(self.embed_dim)
|
70 |
+
|
71 |
+
self.lm_head = RobertaLMHead(
|
72 |
+
embed_dim=self.embed_dim,
|
73 |
+
output_dim=self.alphabet_size,
|
74 |
+
weight=self.embed_tokens.weight,
|
75 |
+
)
|
76 |
+
|
77 |
+
def forward(self, tokens, repr_layers=[], need_head_weights=False, return_contacts=False):
|
78 |
+
if return_contacts:
|
79 |
+
need_head_weights = True
|
80 |
+
|
81 |
+
assert tokens.ndim == 2
|
82 |
+
padding_mask = tokens.eq(self.padding_idx) # B, T
|
83 |
+
|
84 |
+
x = self.embed_scale * self.embed_tokens(tokens)
|
85 |
+
|
86 |
+
if self.token_dropout:
|
87 |
+
x.masked_fill_((tokens == self.mask_idx).unsqueeze(-1), 0.0)
|
88 |
+
# x: B x T x C
|
89 |
+
mask_ratio_train = 0.15 * 0.8
|
90 |
+
src_lengths = (~padding_mask).sum(-1)
|
91 |
+
mask_ratio_observed = (tokens == self.mask_idx).sum(-1).to(x.dtype) / src_lengths
|
92 |
+
x = x * (1 - mask_ratio_train) / (1 - mask_ratio_observed)[:, None, None]
|
93 |
+
|
94 |
+
if padding_mask is not None:
|
95 |
+
x = x * (1 - padding_mask.unsqueeze(-1).type_as(x))
|
96 |
+
|
97 |
+
repr_layers = set(repr_layers)
|
98 |
+
hidden_representations = {}
|
99 |
+
if 0 in repr_layers:
|
100 |
+
hidden_representations[0] = x
|
101 |
+
|
102 |
+
if need_head_weights:
|
103 |
+
attn_weights = []
|
104 |
+
|
105 |
+
# (B, T, E) => (T, B, E)
|
106 |
+
x = x.transpose(0, 1)
|
107 |
+
|
108 |
+
if not padding_mask.any():
|
109 |
+
padding_mask = None
|
110 |
+
|
111 |
+
for layer_idx, layer in enumerate(self.layers):
|
112 |
+
x, attn = layer(
|
113 |
+
x,
|
114 |
+
self_attn_padding_mask=padding_mask,
|
115 |
+
need_head_weights=need_head_weights,
|
116 |
+
)
|
117 |
+
if (layer_idx + 1) in repr_layers:
|
118 |
+
hidden_representations[layer_idx + 1] = x.transpose(0, 1)
|
119 |
+
if need_head_weights:
|
120 |
+
# (H, B, T, T) => (B, H, T, T)
|
121 |
+
attn_weights.append(attn.transpose(1, 0))
|
122 |
+
|
123 |
+
x = self.emb_layer_norm_after(x)
|
124 |
+
x = x.transpose(0, 1) # (T, B, E) => (B, T, E)
|
125 |
+
|
126 |
+
# last hidden representation should have layer norm applied
|
127 |
+
if (layer_idx + 1) in repr_layers:
|
128 |
+
hidden_representations[layer_idx + 1] = x
|
129 |
+
x = self.lm_head(x)
|
130 |
+
|
131 |
+
result = {"logits": x, "representations": hidden_representations}
|
132 |
+
if need_head_weights:
|
133 |
+
# attentions: B x L x H x T x T
|
134 |
+
attentions = torch.stack(attn_weights, 1)
|
135 |
+
if padding_mask is not None:
|
136 |
+
attention_mask = 1 - padding_mask.type_as(attentions)
|
137 |
+
attention_mask = attention_mask.unsqueeze(1) * attention_mask.unsqueeze(2)
|
138 |
+
attentions = attentions * attention_mask[:, None, None, :, :]
|
139 |
+
result["attentions"] = attentions
|
140 |
+
if return_contacts:
|
141 |
+
contacts = self.contact_head(tokens, attentions)
|
142 |
+
result["contacts"] = contacts
|
143 |
+
|
144 |
+
return result
|
145 |
+
|
146 |
+
def predict_contacts(self, tokens):
|
147 |
+
return self(tokens, return_contacts=True)["contacts"]
|
esm/esm/model/msa_transformer.py
ADDED
@@ -0,0 +1,238 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Copyright (c) Facebook, Inc. and its affiliates.
|
2 |
+
#
|
3 |
+
# This source code is licensed under the MIT license found in the
|
4 |
+
# LICENSE file in the root directory of this source tree.
|
5 |
+
|
6 |
+
import torch
|
7 |
+
import torch.nn as nn
|
8 |
+
|
9 |
+
from ..modules import (
|
10 |
+
AxialTransformerLayer,
|
11 |
+
LearnedPositionalEmbedding,
|
12 |
+
RobertaLMHead,
|
13 |
+
ESM1bLayerNorm,
|
14 |
+
ContactPredictionHead,
|
15 |
+
)
|
16 |
+
|
17 |
+
from ..axial_attention import RowSelfAttention, ColumnSelfAttention
|
18 |
+
|
19 |
+
|
20 |
+
|
21 |
+
class MSATransformer(nn.Module):
|
22 |
+
@classmethod
|
23 |
+
def add_args(cls, parser):
|
24 |
+
# fmt: off
|
25 |
+
parser.add_argument(
|
26 |
+
"--num_layers",
|
27 |
+
default=12,
|
28 |
+
type=int,
|
29 |
+
metavar="N",
|
30 |
+
help="number of layers"
|
31 |
+
)
|
32 |
+
parser.add_argument(
|
33 |
+
"--embed_dim",
|
34 |
+
default=768,
|
35 |
+
type=int,
|
36 |
+
metavar="N",
|
37 |
+
help="embedding dimension"
|
38 |
+
)
|
39 |
+
parser.add_argument(
|
40 |
+
"--logit_bias",
|
41 |
+
action="store_true",
|
42 |
+
help="whether to apply bias to logits"
|
43 |
+
)
|
44 |
+
parser.add_argument(
|
45 |
+
"--ffn_embed_dim",
|
46 |
+
default=3072,
|
47 |
+
type=int,
|
48 |
+
metavar="N",
|
49 |
+
help="embedding dimension for FFN",
|
50 |
+
)
|
51 |
+
parser.add_argument(
|
52 |
+
"--attention_heads",
|
53 |
+
default=12,
|
54 |
+
type=int,
|
55 |
+
metavar="N",
|
56 |
+
help="number of attention heads",
|
57 |
+
)
|
58 |
+
parser.add_argument(
|
59 |
+
"--dropout",
|
60 |
+
default=0.1,
|
61 |
+
type=float,
|
62 |
+
help="Dropout to apply."
|
63 |
+
)
|
64 |
+
parser.add_argument(
|
65 |
+
"--attention_dropout",
|
66 |
+
default=0.1,
|
67 |
+
type=float,
|
68 |
+
help="Dropout to apply."
|
69 |
+
)
|
70 |
+
parser.add_argument(
|
71 |
+
"--activation_dropout",
|
72 |
+
default=0.1,
|
73 |
+
type=float,
|
74 |
+
help="Dropout to apply."
|
75 |
+
)
|
76 |
+
parser.add_argument(
|
77 |
+
"--max_tokens_per_msa",
|
78 |
+
default=2 ** 14,
|
79 |
+
type=int,
|
80 |
+
help=(
|
81 |
+
"Used during inference to batch attention computations in a single "
|
82 |
+
"forward pass. This allows increased input sizes with less memory."
|
83 |
+
),
|
84 |
+
)
|
85 |
+
# fmt: on
|
86 |
+
|
87 |
+
def __init__(self, args, alphabet):
|
88 |
+
super().__init__()
|
89 |
+
self.args = args
|
90 |
+
self.alphabet_size = len(alphabet)
|
91 |
+
self.padding_idx = alphabet.padding_idx
|
92 |
+
self.mask_idx = alphabet.mask_idx
|
93 |
+
self.cls_idx = alphabet.cls_idx
|
94 |
+
self.eos_idx = alphabet.eos_idx
|
95 |
+
self.prepend_bos = alphabet.prepend_bos
|
96 |
+
self.append_eos = alphabet.append_eos
|
97 |
+
|
98 |
+
self.embed_tokens = nn.Embedding(
|
99 |
+
self.alphabet_size, self.args.embed_dim, padding_idx=self.padding_idx
|
100 |
+
)
|
101 |
+
|
102 |
+
if getattr(self.args, "embed_positions_msa", False):
|
103 |
+
emb_dim = getattr(self.args, "embed_positions_msa_dim", self.args.embed_dim)
|
104 |
+
self.msa_position_embedding = nn.Parameter(
|
105 |
+
0.01 * torch.randn(1, 1024, 1, emb_dim),
|
106 |
+
requires_grad=True,
|
107 |
+
)
|
108 |
+
else:
|
109 |
+
self.register_parameter("msa_position_embedding", None)
|
110 |
+
|
111 |
+
self.dropout_module = nn.Dropout(self.args.dropout)
|
112 |
+
self.layers = nn.ModuleList(
|
113 |
+
[
|
114 |
+
AxialTransformerLayer(
|
115 |
+
self.args.embed_dim,
|
116 |
+
self.args.ffn_embed_dim,
|
117 |
+
self.args.attention_heads,
|
118 |
+
self.args.dropout,
|
119 |
+
self.args.attention_dropout,
|
120 |
+
self.args.activation_dropout,
|
121 |
+
getattr(self.args, "max_tokens_per_msa", self.args.max_tokens),
|
122 |
+
)
|
123 |
+
for _ in range(self.args.layers)
|
124 |
+
]
|
125 |
+
)
|
126 |
+
|
127 |
+
self.contact_head = ContactPredictionHead(
|
128 |
+
self.args.layers * self.args.attention_heads,
|
129 |
+
self.prepend_bos,
|
130 |
+
self.append_eos,
|
131 |
+
eos_idx=self.eos_idx,
|
132 |
+
)
|
133 |
+
self.embed_positions = LearnedPositionalEmbedding(
|
134 |
+
self.args.max_positions,
|
135 |
+
self.args.embed_dim,
|
136 |
+
self.padding_idx,
|
137 |
+
)
|
138 |
+
self.emb_layer_norm_before = ESM1bLayerNorm(self.args.embed_dim)
|
139 |
+
self.emb_layer_norm_after = ESM1bLayerNorm(self.args.embed_dim)
|
140 |
+
self.lm_head = RobertaLMHead(
|
141 |
+
embed_dim=self.args.embed_dim,
|
142 |
+
output_dim=self.alphabet_size,
|
143 |
+
weight=self.embed_tokens.weight,
|
144 |
+
)
|
145 |
+
|
146 |
+
def forward(self, tokens, repr_layers=[], need_head_weights=False, return_contacts=False):
|
147 |
+
if return_contacts:
|
148 |
+
need_head_weights = True
|
149 |
+
|
150 |
+
assert tokens.ndim == 3
|
151 |
+
batch_size, num_alignments, seqlen = tokens.size()
|
152 |
+
padding_mask = tokens.eq(self.padding_idx) # B, R, C
|
153 |
+
if not padding_mask.any():
|
154 |
+
padding_mask = None
|
155 |
+
|
156 |
+
x = self.embed_tokens(tokens)
|
157 |
+
x += self.embed_positions(tokens.view(batch_size * num_alignments, seqlen)).view(x.size())
|
158 |
+
if self.msa_position_embedding is not None:
|
159 |
+
if x.size(1) > 1024:
|
160 |
+
raise RuntimeError(
|
161 |
+
"Using model with MSA position embedding trained on maximum MSA "
|
162 |
+
f"depth of 1024, but received {x.size(1)} alignments."
|
163 |
+
)
|
164 |
+
x += self.msa_position_embedding[:, :num_alignments]
|
165 |
+
|
166 |
+
x = self.emb_layer_norm_before(x)
|
167 |
+
|
168 |
+
x = self.dropout_module(x)
|
169 |
+
|
170 |
+
if padding_mask is not None:
|
171 |
+
x = x * (1 - padding_mask.unsqueeze(-1).type_as(x))
|
172 |
+
|
173 |
+
repr_layers = set(repr_layers)
|
174 |
+
hidden_representations = {}
|
175 |
+
if 0 in repr_layers:
|
176 |
+
hidden_representations[0] = x
|
177 |
+
|
178 |
+
if need_head_weights:
|
179 |
+
row_attn_weights = []
|
180 |
+
col_attn_weights = []
|
181 |
+
|
182 |
+
# B x R x C x D -> R x C x B x D
|
183 |
+
x = x.permute(1, 2, 0, 3)
|
184 |
+
|
185 |
+
for layer_idx, layer in enumerate(self.layers):
|
186 |
+
x = layer(
|
187 |
+
x,
|
188 |
+
self_attn_padding_mask=padding_mask,
|
189 |
+
need_head_weights=need_head_weights,
|
190 |
+
)
|
191 |
+
if need_head_weights:
|
192 |
+
x, col_attn, row_attn = x
|
193 |
+
# H x C x B x R x R -> B x H x C x R x R
|
194 |
+
col_attn_weights.append(col_attn.permute(2, 0, 1, 3, 4))
|
195 |
+
# H x B x C x C -> B x H x C x C
|
196 |
+
row_attn_weights.append(row_attn.permute(1, 0, 2, 3))
|
197 |
+
if (layer_idx + 1) in repr_layers:
|
198 |
+
hidden_representations[layer_idx + 1] = x.permute(2, 0, 1, 3)
|
199 |
+
|
200 |
+
x = self.emb_layer_norm_after(x)
|
201 |
+
x = x.permute(2, 0, 1, 3) # R x C x B x D -> B x R x C x D
|
202 |
+
|
203 |
+
# last hidden representation should have layer norm applied
|
204 |
+
if (layer_idx + 1) in repr_layers:
|
205 |
+
hidden_representations[layer_idx + 1] = x
|
206 |
+
x = self.lm_head(x)
|
207 |
+
|
208 |
+
result = {"logits": x, "representations": hidden_representations}
|
209 |
+
if need_head_weights:
|
210 |
+
# col_attentions: B x L x H x C x R x R
|
211 |
+
col_attentions = torch.stack(col_attn_weights, 1)
|
212 |
+
# row_attentions: B x L x H x C x C
|
213 |
+
row_attentions = torch.stack(row_attn_weights, 1)
|
214 |
+
result["col_attentions"] = col_attentions
|
215 |
+
result["row_attentions"] = row_attentions
|
216 |
+
if return_contacts:
|
217 |
+
contacts = self.contact_head(tokens, row_attentions)
|
218 |
+
result["contacts"] = contacts
|
219 |
+
|
220 |
+
return result
|
221 |
+
|
222 |
+
def predict_contacts(self, tokens):
|
223 |
+
return self(tokens, return_contacts=True)["contacts"]
|
224 |
+
|
225 |
+
@property
|
226 |
+
def num_layers(self):
|
227 |
+
return self.args.layers
|
228 |
+
|
229 |
+
def max_tokens_per_msa_(self, value: int) -> None:
|
230 |
+
"""The MSA Transformer automatically batches attention computations when
|
231 |
+
gradients are disabled to allow you to pass in larger MSAs at test time than
|
232 |
+
you can fit in GPU memory. By default this occurs when more than 2^14 tokens
|
233 |
+
are passed in the input MSA. You can set this value to infinity to disable
|
234 |
+
this behavior.
|
235 |
+
"""
|
236 |
+
for module in self.modules():
|
237 |
+
if isinstance(module, (RowSelfAttention, ColumnSelfAttention)):
|
238 |
+
module.max_tokens_per_msa = value
|
esm/esm/modules.py
ADDED
@@ -0,0 +1,418 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Copyright (c) Facebook, Inc. and its affiliates.
|
2 |
+
#
|
3 |
+
# This source code is licensed under the MIT license found in the
|
4 |
+
# LICENSE file in the root directory of this source tree.
|
5 |
+
|
6 |
+
import math
|
7 |
+
from typing import Optional
|
8 |
+
|
9 |
+
import torch
|
10 |
+
import torch.nn as nn
|
11 |
+
import torch.nn.functional as F
|
12 |
+
|
13 |
+
from .multihead_attention import MultiheadAttention # noqa
|
14 |
+
from .axial_attention import ColumnSelfAttention, RowSelfAttention
|
15 |
+
|
16 |
+
|
17 |
+
def gelu(x):
|
18 |
+
"""Implementation of the gelu activation function.
|
19 |
+
|
20 |
+
For information: OpenAI GPT's gelu is slightly different
|
21 |
+
(and gives slightly different results):
|
22 |
+
0.5 * x * (1 + torch.tanh(math.sqrt(2 / math.pi) * (x + 0.044715 * torch.pow(x, 3))))
|
23 |
+
"""
|
24 |
+
return x * 0.5 * (1.0 + torch.erf(x / math.sqrt(2.0)))
|
25 |
+
|
26 |
+
|
27 |
+
def symmetrize(x):
|
28 |
+
"Make layer symmetric in final two dimensions, used for contact prediction."
|
29 |
+
return x + x.transpose(-1, -2)
|
30 |
+
|
31 |
+
|
32 |
+
def apc(x):
|
33 |
+
"Perform average product correct, used for contact prediction."
|
34 |
+
a1 = x.sum(-1, keepdims=True)
|
35 |
+
a2 = x.sum(-2, keepdims=True)
|
36 |
+
a12 = x.sum((-1, -2), keepdims=True)
|
37 |
+
|
38 |
+
avg = a1 * a2
|
39 |
+
avg.div_(a12) # in-place to reduce memory
|
40 |
+
normalized = x - avg
|
41 |
+
return normalized
|
42 |
+
|
43 |
+
|
44 |
+
class ESM1LayerNorm(nn.Module):
|
45 |
+
def __init__(self, hidden_size, eps=1e-12, affine=True):
|
46 |
+
"""Construct a layernorm layer in the TF style (eps inside the sqrt)."""
|
47 |
+
super().__init__()
|
48 |
+
self.hidden_size = (hidden_size,) if isinstance(hidden_size, int) else tuple(hidden_size)
|
49 |
+
self.eps = eps
|
50 |
+
self.affine = bool(affine)
|
51 |
+
if self.affine:
|
52 |
+
self.weight = nn.Parameter(torch.ones(hidden_size))
|
53 |
+
self.bias = nn.Parameter(torch.zeros(hidden_size))
|
54 |
+
else:
|
55 |
+
self.weight, self.bias = None, None
|
56 |
+
|
57 |
+
def forward(self, x):
|
58 |
+
dims = tuple(-(i + 1) for i in range(len(self.hidden_size)))
|
59 |
+
means = x.mean(dims, keepdim=True)
|
60 |
+
x_zeromean = x - means
|
61 |
+
variances = x_zeromean.pow(2).mean(dims, keepdim=True)
|
62 |
+
x = x_zeromean / torch.sqrt(variances + self.eps)
|
63 |
+
if self.affine:
|
64 |
+
x = (self.weight * x) + self.bias
|
65 |
+
return x
|
66 |
+
|
67 |
+
|
68 |
+
try:
|
69 |
+
from apex.normalization import FusedLayerNorm as _FusedLayerNorm
|
70 |
+
|
71 |
+
class ESM1bLayerNorm(_FusedLayerNorm):
|
72 |
+
@torch.jit.unused
|
73 |
+
def forward(self, x):
|
74 |
+
if not x.is_cuda:
|
75 |
+
return super().forward(x)
|
76 |
+
else:
|
77 |
+
with torch.cuda.device(x.device):
|
78 |
+
return super().forward(x)
|
79 |
+
|
80 |
+
except ImportError:
|
81 |
+
from torch.nn import LayerNorm as ESM1bLayerNorm
|
82 |
+
|
83 |
+
|
84 |
+
class TransformerLayer(nn.Module):
|
85 |
+
"""Transformer layer block."""
|
86 |
+
|
87 |
+
def __init__(
|
88 |
+
self,
|
89 |
+
embed_dim,
|
90 |
+
ffn_embed_dim,
|
91 |
+
attention_heads,
|
92 |
+
add_bias_kv=True,
|
93 |
+
use_esm1b_layer_norm=False,
|
94 |
+
use_rotary_embeddings: bool = False,
|
95 |
+
):
|
96 |
+
super().__init__()
|
97 |
+
self.embed_dim = embed_dim
|
98 |
+
self.ffn_embed_dim = ffn_embed_dim
|
99 |
+
self.attention_heads = attention_heads
|
100 |
+
self.use_rotary_embeddings = use_rotary_embeddings
|
101 |
+
self._init_submodules(add_bias_kv, use_esm1b_layer_norm)
|
102 |
+
|
103 |
+
def _init_submodules(self, add_bias_kv, use_esm1b_layer_norm):
|
104 |
+
BertLayerNorm = ESM1bLayerNorm if use_esm1b_layer_norm else ESM1LayerNorm
|
105 |
+
|
106 |
+
self.self_attn = MultiheadAttention(
|
107 |
+
self.embed_dim,
|
108 |
+
self.attention_heads,
|
109 |
+
add_bias_kv=add_bias_kv,
|
110 |
+
add_zero_attn=False,
|
111 |
+
use_rotary_embeddings=self.use_rotary_embeddings,
|
112 |
+
)
|
113 |
+
self.self_attn_layer_norm = BertLayerNorm(self.embed_dim)
|
114 |
+
|
115 |
+
self.fc1 = nn.Linear(self.embed_dim, self.ffn_embed_dim)
|
116 |
+
self.fc2 = nn.Linear(self.ffn_embed_dim, self.embed_dim)
|
117 |
+
|
118 |
+
self.final_layer_norm = BertLayerNorm(self.embed_dim)
|
119 |
+
|
120 |
+
def forward(
|
121 |
+
self, x, self_attn_mask=None, self_attn_padding_mask=None, need_head_weights=False
|
122 |
+
):
|
123 |
+
residual = x
|
124 |
+
x = self.self_attn_layer_norm(x)
|
125 |
+
x, attn = self.self_attn(
|
126 |
+
query=x,
|
127 |
+
key=x,
|
128 |
+
value=x,
|
129 |
+
key_padding_mask=self_attn_padding_mask,
|
130 |
+
need_weights=True,
|
131 |
+
need_head_weights=need_head_weights,
|
132 |
+
attn_mask=self_attn_mask,
|
133 |
+
)
|
134 |
+
x = residual + x
|
135 |
+
|
136 |
+
residual = x
|
137 |
+
x = self.final_layer_norm(x)
|
138 |
+
x = gelu(self.fc1(x))
|
139 |
+
x = self.fc2(x)
|
140 |
+
x = residual + x
|
141 |
+
|
142 |
+
return x, attn
|
143 |
+
|
144 |
+
|
145 |
+
class AxialTransformerLayer(nn.Module):
|
146 |
+
"""Implements an Axial MSA Transformer block."""
|
147 |
+
|
148 |
+
def __init__(
|
149 |
+
self,
|
150 |
+
embedding_dim: int = 768,
|
151 |
+
ffn_embedding_dim: int = 3072,
|
152 |
+
num_attention_heads: int = 8,
|
153 |
+
dropout: float = 0.1,
|
154 |
+
attention_dropout: float = 0.1,
|
155 |
+
activation_dropout: float = 0.1,
|
156 |
+
max_tokens_per_msa: int = 2**14,
|
157 |
+
) -> None:
|
158 |
+
super().__init__()
|
159 |
+
|
160 |
+
# Initialize parameters
|
161 |
+
self.embedding_dim = embedding_dim
|
162 |
+
self.dropout_prob = dropout
|
163 |
+
|
164 |
+
row_self_attention = RowSelfAttention(
|
165 |
+
embedding_dim,
|
166 |
+
num_attention_heads,
|
167 |
+
dropout=dropout,
|
168 |
+
max_tokens_per_msa=max_tokens_per_msa,
|
169 |
+
)
|
170 |
+
|
171 |
+
column_self_attention = ColumnSelfAttention(
|
172 |
+
embedding_dim,
|
173 |
+
num_attention_heads,
|
174 |
+
dropout=dropout,
|
175 |
+
max_tokens_per_msa=max_tokens_per_msa,
|
176 |
+
)
|
177 |
+
|
178 |
+
feed_forward_layer = FeedForwardNetwork(
|
179 |
+
embedding_dim,
|
180 |
+
ffn_embedding_dim,
|
181 |
+
activation_dropout=activation_dropout,
|
182 |
+
max_tokens_per_msa=max_tokens_per_msa,
|
183 |
+
)
|
184 |
+
|
185 |
+
self.row_self_attention = self.build_residual(row_self_attention)
|
186 |
+
self.column_self_attention = self.build_residual(column_self_attention)
|
187 |
+
self.feed_forward_layer = self.build_residual(feed_forward_layer)
|
188 |
+
|
189 |
+
def build_residual(self, layer: nn.Module):
|
190 |
+
return NormalizedResidualBlock(
|
191 |
+
layer,
|
192 |
+
self.embedding_dim,
|
193 |
+
self.dropout_prob,
|
194 |
+
)
|
195 |
+
|
196 |
+
def forward(
|
197 |
+
self,
|
198 |
+
x: torch.Tensor,
|
199 |
+
self_attn_mask: Optional[torch.Tensor] = None,
|
200 |
+
self_attn_padding_mask: Optional[torch.Tensor] = None,
|
201 |
+
need_head_weights: bool = False,
|
202 |
+
):
|
203 |
+
"""
|
204 |
+
LayerNorm is applied either before or after the self-attention/ffn
|
205 |
+
modules similar to the original Transformer implementation.
|
206 |
+
"""
|
207 |
+
x, row_attn = self.row_self_attention(
|
208 |
+
x,
|
209 |
+
self_attn_mask=self_attn_mask,
|
210 |
+
self_attn_padding_mask=self_attn_padding_mask,
|
211 |
+
)
|
212 |
+
x, column_attn = self.column_self_attention(
|
213 |
+
x,
|
214 |
+
self_attn_mask=self_attn_mask,
|
215 |
+
self_attn_padding_mask=self_attn_padding_mask,
|
216 |
+
)
|
217 |
+
x = self.feed_forward_layer(x)
|
218 |
+
if need_head_weights:
|
219 |
+
return x, column_attn, row_attn
|
220 |
+
else:
|
221 |
+
return x
|
222 |
+
|
223 |
+
|
224 |
+
class LearnedPositionalEmbedding(nn.Embedding):
|
225 |
+
"""
|
226 |
+
This module learns positional embeddings up to a fixed maximum size.
|
227 |
+
Padding ids are ignored by either offsetting based on padding_idx
|
228 |
+
or by setting padding_idx to None and ensuring that the appropriate
|
229 |
+
position ids are passed to the forward function.
|
230 |
+
"""
|
231 |
+
|
232 |
+
def __init__(self, num_embeddings: int, embedding_dim: int, padding_idx: int):
|
233 |
+
if padding_idx is not None:
|
234 |
+
num_embeddings_ = num_embeddings + padding_idx + 1
|
235 |
+
else:
|
236 |
+
num_embeddings_ = num_embeddings
|
237 |
+
super().__init__(num_embeddings_, embedding_dim, padding_idx)
|
238 |
+
self.max_positions = num_embeddings
|
239 |
+
|
240 |
+
def forward(self, input: torch.Tensor):
|
241 |
+
"""Input is expected to be of size [bsz x seqlen]."""
|
242 |
+
if input.size(1) > self.max_positions:
|
243 |
+
raise ValueError(
|
244 |
+
f"Sequence length {input.size(1)} above maximum "
|
245 |
+
f" sequence length of {self.max_positions}"
|
246 |
+
)
|
247 |
+
mask = input.ne(self.padding_idx).int()
|
248 |
+
positions = (torch.cumsum(mask, dim=1).type_as(mask) * mask).long() + self.padding_idx
|
249 |
+
return F.embedding(
|
250 |
+
positions,
|
251 |
+
self.weight,
|
252 |
+
self.padding_idx,
|
253 |
+
self.max_norm,
|
254 |
+
self.norm_type,
|
255 |
+
self.scale_grad_by_freq,
|
256 |
+
self.sparse,
|
257 |
+
)
|
258 |
+
|
259 |
+
|
260 |
+
class SinusoidalPositionalEmbedding(nn.Module):
|
261 |
+
def __init__(self, embed_dim, padding_idx, learned=False):
|
262 |
+
super().__init__()
|
263 |
+
self.embed_dim = embed_dim
|
264 |
+
self.padding_idx = padding_idx
|
265 |
+
self.register_buffer("_float_tensor", torch.FloatTensor(1))
|
266 |
+
self.weights = None
|
267 |
+
|
268 |
+
def forward(self, x):
|
269 |
+
bsz, seq_len = x.shape
|
270 |
+
max_pos = self.padding_idx + 1 + seq_len
|
271 |
+
if self.weights is None or max_pos > self.weights.size(0):
|
272 |
+
self.weights = self.get_embedding(max_pos)
|
273 |
+
self.weights = self.weights.type_as(self._float_tensor)
|
274 |
+
|
275 |
+
positions = self.make_positions(x)
|
276 |
+
return self.weights.index_select(0, positions.view(-1)).view(bsz, seq_len, -1).detach()
|
277 |
+
|
278 |
+
def make_positions(self, x):
|
279 |
+
mask = x.ne(self.padding_idx)
|
280 |
+
range_buf = torch.arange(x.size(1), device=x.device).expand_as(x) + self.padding_idx + 1
|
281 |
+
positions = range_buf.expand_as(x)
|
282 |
+
return positions * mask.long() + self.padding_idx * (1 - mask.long())
|
283 |
+
|
284 |
+
def get_embedding(self, num_embeddings):
|
285 |
+
half_dim = self.embed_dim // 2
|
286 |
+
emb = math.log(10000) / (half_dim - 1)
|
287 |
+
emb = torch.exp(torch.arange(half_dim, dtype=torch.float) * -emb)
|
288 |
+
emb = torch.arange(num_embeddings, dtype=torch.float).unsqueeze(1) * emb.unsqueeze(0)
|
289 |
+
emb = torch.cat([torch.sin(emb), torch.cos(emb)], dim=1).view(num_embeddings, -1)
|
290 |
+
if self.embed_dim % 2 == 1:
|
291 |
+
# zero pad
|
292 |
+
emb = torch.cat([emb, torch.zeros(num_embeddings, 1)], dim=1)
|
293 |
+
if self.padding_idx is not None:
|
294 |
+
emb[self.padding_idx, :] = 0
|
295 |
+
return emb
|
296 |
+
|
297 |
+
|
298 |
+
class RobertaLMHead(nn.Module):
|
299 |
+
"""Head for masked language modeling."""
|
300 |
+
|
301 |
+
def __init__(self, embed_dim, output_dim, weight):
|
302 |
+
super().__init__()
|
303 |
+
self.dense = nn.Linear(embed_dim, embed_dim)
|
304 |
+
self.layer_norm = ESM1bLayerNorm(embed_dim)
|
305 |
+
self.weight = weight
|
306 |
+
self.bias = nn.Parameter(torch.zeros(output_dim))
|
307 |
+
|
308 |
+
def forward(self, features):
|
309 |
+
x = self.dense(features)
|
310 |
+
x = gelu(x)
|
311 |
+
x = self.layer_norm(x)
|
312 |
+
# project back to size of vocabulary with bias
|
313 |
+
x = F.linear(x, self.weight) + self.bias
|
314 |
+
return x
|
315 |
+
|
316 |
+
|
317 |
+
class ContactPredictionHead(nn.Module):
|
318 |
+
"""Performs symmetrization, apc, and computes a logistic regression on the output features"""
|
319 |
+
|
320 |
+
def __init__(
|
321 |
+
self,
|
322 |
+
in_features: int,
|
323 |
+
prepend_bos: bool,
|
324 |
+
append_eos: bool,
|
325 |
+
bias=True,
|
326 |
+
eos_idx: Optional[int] = None,
|
327 |
+
):
|
328 |
+
super().__init__()
|
329 |
+
self.in_features = in_features
|
330 |
+
self.prepend_bos = prepend_bos
|
331 |
+
self.append_eos = append_eos
|
332 |
+
if append_eos and eos_idx is None:
|
333 |
+
raise ValueError("Using an alphabet with eos token, but no eos token was passed in.")
|
334 |
+
self.eos_idx = eos_idx
|
335 |
+
self.regression = nn.Linear(in_features, 1, bias)
|
336 |
+
self.activation = nn.Sigmoid()
|
337 |
+
|
338 |
+
def forward(self, tokens, attentions):
|
339 |
+
# remove eos token attentions
|
340 |
+
if self.append_eos:
|
341 |
+
eos_mask = tokens.ne(self.eos_idx).to(attentions)
|
342 |
+
eos_mask = eos_mask.unsqueeze(1) * eos_mask.unsqueeze(2)
|
343 |
+
attentions = attentions * eos_mask[:, None, None, :, :]
|
344 |
+
attentions = attentions[..., :-1, :-1]
|
345 |
+
# remove cls token attentions
|
346 |
+
if self.prepend_bos:
|
347 |
+
attentions = attentions[..., 1:, 1:]
|
348 |
+
batch_size, layers, heads, seqlen, _ = attentions.size()
|
349 |
+
attentions = attentions.view(batch_size, layers * heads, seqlen, seqlen)
|
350 |
+
|
351 |
+
# features: B x C x T x T
|
352 |
+
attentions = attentions.to(
|
353 |
+
self.regression.weight.device
|
354 |
+
) # attentions always float32, may need to convert to float16
|
355 |
+
attentions = apc(symmetrize(attentions))
|
356 |
+
attentions = attentions.permute(0, 2, 3, 1)
|
357 |
+
return self.activation(self.regression(attentions).squeeze(3))
|
358 |
+
|
359 |
+
|
360 |
+
class NormalizedResidualBlock(nn.Module):
|
361 |
+
def __init__(
|
362 |
+
self,
|
363 |
+
layer: nn.Module,
|
364 |
+
embedding_dim: int,
|
365 |
+
dropout: float = 0.1,
|
366 |
+
):
|
367 |
+
super().__init__()
|
368 |
+
self.embedding_dim = embedding_dim
|
369 |
+
|
370 |
+
self.layer = layer
|
371 |
+
self.dropout_module = nn.Dropout(
|
372 |
+
dropout,
|
373 |
+
)
|
374 |
+
self.layer_norm = ESM1bLayerNorm(self.embedding_dim)
|
375 |
+
|
376 |
+
def forward(self, x, *args, **kwargs):
|
377 |
+
residual = x
|
378 |
+
x = self.layer_norm(x)
|
379 |
+
outputs = self.layer(x, *args, **kwargs)
|
380 |
+
if isinstance(outputs, tuple):
|
381 |
+
x, *out = outputs
|
382 |
+
else:
|
383 |
+
x = outputs
|
384 |
+
out = None
|
385 |
+
|
386 |
+
x = self.dropout_module(x)
|
387 |
+
x = residual + x
|
388 |
+
|
389 |
+
if out is not None:
|
390 |
+
return (x,) + tuple(out)
|
391 |
+
else:
|
392 |
+
return x
|
393 |
+
|
394 |
+
|
395 |
+
class FeedForwardNetwork(nn.Module):
|
396 |
+
def __init__(
|
397 |
+
self,
|
398 |
+
embedding_dim: int,
|
399 |
+
ffn_embedding_dim: int,
|
400 |
+
activation_dropout: float = 0.1,
|
401 |
+
max_tokens_per_msa: int = 2**14,
|
402 |
+
):
|
403 |
+
super().__init__()
|
404 |
+
self.embedding_dim = embedding_dim
|
405 |
+
self.ffn_embedding_dim = ffn_embedding_dim
|
406 |
+
self.max_tokens_per_msa = max_tokens_per_msa
|
407 |
+
self.activation_fn = nn.GELU()
|
408 |
+
self.activation_dropout_module = nn.Dropout(
|
409 |
+
activation_dropout,
|
410 |
+
)
|
411 |
+
self.fc1 = nn.Linear(embedding_dim, ffn_embedding_dim)
|
412 |
+
self.fc2 = nn.Linear(ffn_embedding_dim, embedding_dim)
|
413 |
+
|
414 |
+
def forward(self, x):
|
415 |
+
x = self.activation_fn(self.fc1(x))
|
416 |
+
x = self.activation_dropout_module(x)
|
417 |
+
x = self.fc2(x)
|
418 |
+
return x
|
esm/esm/multihead_attention.py
ADDED
@@ -0,0 +1,508 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Copyright (c) Facebook, Inc. and its affiliates.
|
2 |
+
#
|
3 |
+
# This source code is licensed under the MIT license found in the
|
4 |
+
# LICENSE file in the root directory of this source tree.
|
5 |
+
|
6 |
+
import math
|
7 |
+
from typing import Dict, Optional, Tuple
|
8 |
+
|
9 |
+
import torch
|
10 |
+
import torch.nn.functional as F
|
11 |
+
from torch import Tensor, nn
|
12 |
+
from torch.nn import Parameter
|
13 |
+
from esm.rotary_embedding import RotaryEmbedding
|
14 |
+
|
15 |
+
import uuid
|
16 |
+
|
17 |
+
|
18 |
+
def utils_softmax(x, dim: int, onnx_trace: bool = False):
|
19 |
+
if onnx_trace:
|
20 |
+
return F.softmax(x.float(), dim=dim)
|
21 |
+
else:
|
22 |
+
return F.softmax(x, dim=dim, dtype=torch.float32)
|
23 |
+
|
24 |
+
|
25 |
+
class FairseqIncrementalState(object):
|
26 |
+
def __init__(self, *args, **kwargs):
|
27 |
+
super().__init__(*args, **kwargs)
|
28 |
+
self.init_incremental_state()
|
29 |
+
|
30 |
+
def init_incremental_state(self):
|
31 |
+
self._incremental_state_id = str(uuid.uuid4())
|
32 |
+
|
33 |
+
def _get_full_incremental_state_key(self, key: str) -> str:
|
34 |
+
return "{}.{}".format(self._incremental_state_id, key)
|
35 |
+
|
36 |
+
def get_incremental_state(
|
37 |
+
self,
|
38 |
+
incremental_state: Optional[Dict[str, Dict[str, Optional[Tensor]]]],
|
39 |
+
key: str,
|
40 |
+
) -> Optional[Dict[str, Optional[Tensor]]]:
|
41 |
+
"""Helper for getting incremental state for an nn.Module."""
|
42 |
+
full_key = self._get_full_incremental_state_key(key)
|
43 |
+
if incremental_state is None or full_key not in incremental_state:
|
44 |
+
return None
|
45 |
+
return incremental_state[full_key]
|
46 |
+
|
47 |
+
def set_incremental_state(
|
48 |
+
self,
|
49 |
+
incremental_state: Optional[Dict[str, Dict[str, Optional[Tensor]]]],
|
50 |
+
key: str,
|
51 |
+
value: Dict[str, Optional[Tensor]],
|
52 |
+
) -> Optional[Dict[str, Dict[str, Optional[Tensor]]]]:
|
53 |
+
"""Helper for setting incremental state for an nn.Module."""
|
54 |
+
if incremental_state is not None:
|
55 |
+
full_key = self._get_full_incremental_state_key(key)
|
56 |
+
incremental_state[full_key] = value
|
57 |
+
return incremental_state
|
58 |
+
|
59 |
+
|
60 |
+
def with_incremental_state(cls):
|
61 |
+
cls.__bases__ = (FairseqIncrementalState,) + tuple(
|
62 |
+
b for b in cls.__bases__ if b != FairseqIncrementalState
|
63 |
+
)
|
64 |
+
return cls
|
65 |
+
|
66 |
+
|
67 |
+
@with_incremental_state
|
68 |
+
class MultiheadAttention(nn.Module):
|
69 |
+
"""Multi-headed attention.
|
70 |
+
|
71 |
+
See "Attention Is All You Need" for more details.
|
72 |
+
"""
|
73 |
+
|
74 |
+
def __init__(
|
75 |
+
self,
|
76 |
+
embed_dim,
|
77 |
+
num_heads,
|
78 |
+
kdim=None,
|
79 |
+
vdim=None,
|
80 |
+
dropout=0.0,
|
81 |
+
bias=True,
|
82 |
+
add_bias_kv: bool = False,
|
83 |
+
add_zero_attn: bool = False,
|
84 |
+
self_attention: bool = False,
|
85 |
+
encoder_decoder_attention: bool = False,
|
86 |
+
use_rotary_embeddings: bool = False,
|
87 |
+
):
|
88 |
+
super().__init__()
|
89 |
+
self.embed_dim = embed_dim
|
90 |
+
self.kdim = kdim if kdim is not None else embed_dim
|
91 |
+
self.vdim = vdim if vdim is not None else embed_dim
|
92 |
+
self.qkv_same_dim = self.kdim == embed_dim and self.vdim == embed_dim
|
93 |
+
|
94 |
+
self.num_heads = num_heads
|
95 |
+
self.dropout = dropout
|
96 |
+
self.head_dim = embed_dim // num_heads
|
97 |
+
assert (
|
98 |
+
self.head_dim * num_heads == self.embed_dim
|
99 |
+
), "embed_dim must be divisible by num_heads"
|
100 |
+
self.scaling = self.head_dim**-0.5
|
101 |
+
|
102 |
+
self.self_attention = self_attention
|
103 |
+
self.encoder_decoder_attention = encoder_decoder_attention
|
104 |
+
|
105 |
+
assert not self.self_attention or self.qkv_same_dim, (
|
106 |
+
"Self-attention requires query, key and " "value to be of the same size"
|
107 |
+
)
|
108 |
+
|
109 |
+
self.k_proj = nn.Linear(self.kdim, embed_dim, bias=bias)
|
110 |
+
self.v_proj = nn.Linear(self.vdim, embed_dim, bias=bias)
|
111 |
+
self.q_proj = nn.Linear(embed_dim, embed_dim, bias=bias)
|
112 |
+
|
113 |
+
self.out_proj = nn.Linear(embed_dim, embed_dim, bias=bias)
|
114 |
+
|
115 |
+
if add_bias_kv:
|
116 |
+
self.bias_k = Parameter(torch.Tensor(1, 1, embed_dim))
|
117 |
+
self.bias_v = Parameter(torch.Tensor(1, 1, embed_dim))
|
118 |
+
else:
|
119 |
+
self.bias_k = self.bias_v = None
|
120 |
+
|
121 |
+
self.add_zero_attn = add_zero_attn
|
122 |
+
|
123 |
+
self.reset_parameters()
|
124 |
+
|
125 |
+
self.onnx_trace = False
|
126 |
+
self.rot_emb = None
|
127 |
+
if use_rotary_embeddings:
|
128 |
+
self.rot_emb = RotaryEmbedding(dim=self.head_dim)
|
129 |
+
|
130 |
+
self.enable_torch_version = False
|
131 |
+
if hasattr(F, "multi_head_attention_forward"):
|
132 |
+
self.enable_torch_version = True
|
133 |
+
else:
|
134 |
+
self.enable_torch_version = False
|
135 |
+
|
136 |
+
def prepare_for_onnx_export_(self):
|
137 |
+
self.onnx_trace = True
|
138 |
+
|
139 |
+
def reset_parameters(self):
|
140 |
+
if self.qkv_same_dim:
|
141 |
+
# Empirically observed the convergence to be much better with
|
142 |
+
# the scaled initialization
|
143 |
+
nn.init.xavier_uniform_(self.k_proj.weight, gain=1 / math.sqrt(2))
|
144 |
+
nn.init.xavier_uniform_(self.v_proj.weight, gain=1 / math.sqrt(2))
|
145 |
+
nn.init.xavier_uniform_(self.q_proj.weight, gain=1 / math.sqrt(2))
|
146 |
+
else:
|
147 |
+
nn.init.xavier_uniform_(self.k_proj.weight)
|
148 |
+
nn.init.xavier_uniform_(self.v_proj.weight)
|
149 |
+
nn.init.xavier_uniform_(self.q_proj.weight)
|
150 |
+
|
151 |
+
nn.init.xavier_uniform_(self.out_proj.weight)
|
152 |
+
if self.out_proj.bias is not None:
|
153 |
+
nn.init.constant_(self.out_proj.bias, 0.0)
|
154 |
+
if self.bias_k is not None:
|
155 |
+
nn.init.xavier_normal_(self.bias_k)
|
156 |
+
if self.bias_v is not None:
|
157 |
+
nn.init.xavier_normal_(self.bias_v)
|
158 |
+
|
159 |
+
def forward(
|
160 |
+
self,
|
161 |
+
query,
|
162 |
+
key: Optional[Tensor],
|
163 |
+
value: Optional[Tensor],
|
164 |
+
key_padding_mask: Optional[Tensor] = None,
|
165 |
+
incremental_state: Optional[Dict[str, Dict[str, Optional[Tensor]]]] = None,
|
166 |
+
need_weights: bool = True,
|
167 |
+
static_kv: bool = False,
|
168 |
+
attn_mask: Optional[Tensor] = None,
|
169 |
+
before_softmax: bool = False,
|
170 |
+
need_head_weights: bool = False,
|
171 |
+
) -> Tuple[Tensor, Optional[Tensor]]:
|
172 |
+
"""Input shape: Time x Batch x Channel
|
173 |
+
|
174 |
+
Args:
|
175 |
+
key_padding_mask (ByteTensor, optional): mask to exclude
|
176 |
+
keys that are pads, of shape `(batch, src_len)`, where
|
177 |
+
padding elements are indicated by 1s.
|
178 |
+
need_weights (bool, optional): return the attention weights,
|
179 |
+
averaged over heads (default: False).
|
180 |
+
attn_mask (ByteTensor, optional): typically used to
|
181 |
+
implement causal attention, where the mask prevents the
|
182 |
+
attention from looking forward in time (default: None).
|
183 |
+
before_softmax (bool, optional): return the raw attention
|
184 |
+
weights and values before the attention softmax.
|
185 |
+
need_head_weights (bool, optional): return the attention
|
186 |
+
weights for each head. Implies *need_weights*. Default:
|
187 |
+
return the average attention weights over all heads.
|
188 |
+
"""
|
189 |
+
if need_head_weights:
|
190 |
+
need_weights = True
|
191 |
+
|
192 |
+
tgt_len, bsz, embed_dim = query.size()
|
193 |
+
assert embed_dim == self.embed_dim
|
194 |
+
assert list(query.size()) == [tgt_len, bsz, embed_dim]
|
195 |
+
|
196 |
+
if (
|
197 |
+
not self.rot_emb
|
198 |
+
and self.enable_torch_version
|
199 |
+
and not self.onnx_trace
|
200 |
+
and incremental_state is None
|
201 |
+
and not static_kv
|
202 |
+
# A workaround for quantization to work. Otherwise JIT compilation
|
203 |
+
# treats bias in linear module as method.
|
204 |
+
and not torch.jit.is_scripting()
|
205 |
+
and not need_head_weights
|
206 |
+
):
|
207 |
+
assert key is not None and value is not None
|
208 |
+
return F.multi_head_attention_forward(
|
209 |
+
query,
|
210 |
+
key,
|
211 |
+
value,
|
212 |
+
self.embed_dim,
|
213 |
+
self.num_heads,
|
214 |
+
torch.empty([0]),
|
215 |
+
torch.cat((self.q_proj.bias, self.k_proj.bias, self.v_proj.bias)),
|
216 |
+
self.bias_k,
|
217 |
+
self.bias_v,
|
218 |
+
self.add_zero_attn,
|
219 |
+
self.dropout,
|
220 |
+
self.out_proj.weight,
|
221 |
+
self.out_proj.bias,
|
222 |
+
self.training,
|
223 |
+
key_padding_mask,
|
224 |
+
need_weights,
|
225 |
+
attn_mask,
|
226 |
+
use_separate_proj_weight=True,
|
227 |
+
q_proj_weight=self.q_proj.weight,
|
228 |
+
k_proj_weight=self.k_proj.weight,
|
229 |
+
v_proj_weight=self.v_proj.weight,
|
230 |
+
)
|
231 |
+
if incremental_state is not None:
|
232 |
+
saved_state = self._get_input_buffer(incremental_state)
|
233 |
+
if saved_state is not None and "prev_key" in saved_state:
|
234 |
+
# previous time steps are cached - no need to recompute
|
235 |
+
# key and value if they are static
|
236 |
+
if static_kv:
|
237 |
+
assert self.encoder_decoder_attention and not self.self_attention
|
238 |
+
key = value = None
|
239 |
+
else:
|
240 |
+
saved_state = None
|
241 |
+
|
242 |
+
if self.self_attention:
|
243 |
+
q = self.q_proj(query)
|
244 |
+
k = self.k_proj(query)
|
245 |
+
v = self.v_proj(query)
|
246 |
+
elif self.encoder_decoder_attention:
|
247 |
+
# encoder-decoder attention
|
248 |
+
q = self.q_proj(query)
|
249 |
+
if key is None:
|
250 |
+
assert value is None
|
251 |
+
k = v = None
|
252 |
+
else:
|
253 |
+
k = self.k_proj(key)
|
254 |
+
v = self.v_proj(key)
|
255 |
+
|
256 |
+
else:
|
257 |
+
assert key is not None and value is not None
|
258 |
+
q = self.q_proj(query)
|
259 |
+
k = self.k_proj(key)
|
260 |
+
v = self.v_proj(value)
|
261 |
+
q *= self.scaling
|
262 |
+
|
263 |
+
if self.bias_k is not None:
|
264 |
+
assert self.bias_v is not None
|
265 |
+
k = torch.cat([k, self.bias_k.repeat(1, bsz, 1)])
|
266 |
+
v = torch.cat([v, self.bias_v.repeat(1, bsz, 1)])
|
267 |
+
if attn_mask is not None:
|
268 |
+
attn_mask = torch.cat(
|
269 |
+
[attn_mask, attn_mask.new_zeros(attn_mask.size(0), 1)], dim=1
|
270 |
+
)
|
271 |
+
if key_padding_mask is not None:
|
272 |
+
key_padding_mask = torch.cat(
|
273 |
+
[
|
274 |
+
key_padding_mask,
|
275 |
+
key_padding_mask.new_zeros(key_padding_mask.size(0), 1),
|
276 |
+
],
|
277 |
+
dim=1,
|
278 |
+
)
|
279 |
+
|
280 |
+
q = q.contiguous().view(tgt_len, bsz * self.num_heads, self.head_dim).transpose(0, 1)
|
281 |
+
if k is not None:
|
282 |
+
k = k.contiguous().view(-1, bsz * self.num_heads, self.head_dim).transpose(0, 1)
|
283 |
+
if v is not None:
|
284 |
+
v = v.contiguous().view(-1, bsz * self.num_heads, self.head_dim).transpose(0, 1)
|
285 |
+
|
286 |
+
if saved_state is not None:
|
287 |
+
# saved states are stored with shape (bsz, num_heads, seq_len, head_dim)
|
288 |
+
if "prev_key" in saved_state:
|
289 |
+
_prev_key = saved_state["prev_key"]
|
290 |
+
assert _prev_key is not None
|
291 |
+
prev_key = _prev_key.view(bsz * self.num_heads, -1, self.head_dim)
|
292 |
+
if static_kv:
|
293 |
+
k = prev_key
|
294 |
+
else:
|
295 |
+
assert k is not None
|
296 |
+
k = torch.cat([prev_key, k], dim=1)
|
297 |
+
if "prev_value" in saved_state:
|
298 |
+
_prev_value = saved_state["prev_value"]
|
299 |
+
assert _prev_value is not None
|
300 |
+
prev_value = _prev_value.view(bsz * self.num_heads, -1, self.head_dim)
|
301 |
+
if static_kv:
|
302 |
+
v = prev_value
|
303 |
+
else:
|
304 |
+
assert v is not None
|
305 |
+
v = torch.cat([prev_value, v], dim=1)
|
306 |
+
prev_key_padding_mask: Optional[Tensor] = None
|
307 |
+
if "prev_key_padding_mask" in saved_state:
|
308 |
+
prev_key_padding_mask = saved_state["prev_key_padding_mask"]
|
309 |
+
assert k is not None and v is not None
|
310 |
+
key_padding_mask = MultiheadAttention._append_prev_key_padding_mask(
|
311 |
+
key_padding_mask=key_padding_mask,
|
312 |
+
prev_key_padding_mask=prev_key_padding_mask,
|
313 |
+
batch_size=bsz,
|
314 |
+
src_len=k.size(1),
|
315 |
+
static_kv=static_kv,
|
316 |
+
)
|
317 |
+
|
318 |
+
saved_state["prev_key"] = k.view(bsz, self.num_heads, -1, self.head_dim)
|
319 |
+
saved_state["prev_value"] = v.view(bsz, self.num_heads, -1, self.head_dim)
|
320 |
+
saved_state["prev_key_padding_mask"] = key_padding_mask
|
321 |
+
# In this branch incremental_state is never None
|
322 |
+
assert incremental_state is not None
|
323 |
+
incremental_state = self._set_input_buffer(incremental_state, saved_state)
|
324 |
+
assert k is not None
|
325 |
+
src_len = k.size(1)
|
326 |
+
|
327 |
+
# This is part of a workaround to get around fork/join parallelism
|
328 |
+
# not supporting Optional types.
|
329 |
+
if key_padding_mask is not None and key_padding_mask.dim() == 0:
|
330 |
+
key_padding_mask = None
|
331 |
+
|
332 |
+
if key_padding_mask is not None:
|
333 |
+
assert key_padding_mask.size(0) == bsz
|
334 |
+
assert key_padding_mask.size(1) == src_len
|
335 |
+
|
336 |
+
if self.add_zero_attn:
|
337 |
+
assert v is not None
|
338 |
+
src_len += 1
|
339 |
+
k = torch.cat([k, k.new_zeros((k.size(0), 1) + k.size()[2:])], dim=1)
|
340 |
+
v = torch.cat([v, v.new_zeros((v.size(0), 1) + v.size()[2:])], dim=1)
|
341 |
+
if attn_mask is not None:
|
342 |
+
attn_mask = torch.cat(
|
343 |
+
[attn_mask, attn_mask.new_zeros(attn_mask.size(0), 1)], dim=1
|
344 |
+
)
|
345 |
+
if key_padding_mask is not None:
|
346 |
+
key_padding_mask = torch.cat(
|
347 |
+
[
|
348 |
+
key_padding_mask,
|
349 |
+
torch.zeros(key_padding_mask.size(0), 1).type_as(key_padding_mask),
|
350 |
+
],
|
351 |
+
dim=1,
|
352 |
+
)
|
353 |
+
|
354 |
+
if self.rot_emb:
|
355 |
+
q, k = self.rot_emb(q, k)
|
356 |
+
|
357 |
+
attn_weights = torch.bmm(q, k.transpose(1, 2))
|
358 |
+
attn_weights = MultiheadAttention.apply_sparse_mask(attn_weights, tgt_len, src_len, bsz)
|
359 |
+
|
360 |
+
assert list(attn_weights.size()) == [bsz * self.num_heads, tgt_len, src_len]
|
361 |
+
|
362 |
+
if attn_mask is not None:
|
363 |
+
attn_mask = attn_mask.unsqueeze(0)
|
364 |
+
if self.onnx_trace:
|
365 |
+
attn_mask = attn_mask.repeat(attn_weights.size(0), 1, 1)
|
366 |
+
attn_weights += attn_mask
|
367 |
+
|
368 |
+
if key_padding_mask is not None:
|
369 |
+
# don't attend to padding symbols
|
370 |
+
attn_weights = attn_weights.view(bsz, self.num_heads, tgt_len, src_len)
|
371 |
+
attn_weights = attn_weights.masked_fill(
|
372 |
+
key_padding_mask.unsqueeze(1).unsqueeze(2).to(torch.bool), float("-inf")
|
373 |
+
)
|
374 |
+
attn_weights = attn_weights.view(bsz * self.num_heads, tgt_len, src_len)
|
375 |
+
|
376 |
+
if before_softmax:
|
377 |
+
return attn_weights, v
|
378 |
+
|
379 |
+
attn_weights_float = utils_softmax(attn_weights, dim=-1, onnx_trace=self.onnx_trace)
|
380 |
+
attn_weights = attn_weights_float.type_as(attn_weights)
|
381 |
+
attn_probs = F.dropout(
|
382 |
+
attn_weights_float.type_as(attn_weights),
|
383 |
+
p=self.dropout,
|
384 |
+
training=self.training,
|
385 |
+
)
|
386 |
+
assert v is not None
|
387 |
+
attn = torch.bmm(attn_probs, v)
|
388 |
+
assert list(attn.size()) == [bsz * self.num_heads, tgt_len, self.head_dim]
|
389 |
+
if self.onnx_trace and attn.size(1) == 1:
|
390 |
+
# when ONNX tracing a single decoder step (sequence length == 1)
|
391 |
+
# the transpose is a no-op copy before view, thus unnecessary
|
392 |
+
attn = attn.contiguous().view(tgt_len, bsz, embed_dim)
|
393 |
+
else:
|
394 |
+
attn = attn.transpose(0, 1).contiguous().view(tgt_len, bsz, embed_dim)
|
395 |
+
attn = self.out_proj(attn)
|
396 |
+
attn_weights: Optional[Tensor] = None
|
397 |
+
if need_weights:
|
398 |
+
attn_weights = attn_weights_float.view(
|
399 |
+
bsz, self.num_heads, tgt_len, src_len
|
400 |
+
).type_as(attn).transpose(1, 0)
|
401 |
+
if not need_head_weights:
|
402 |
+
# average attention weights over heads
|
403 |
+
attn_weights = attn_weights.mean(dim=0)
|
404 |
+
|
405 |
+
return attn, attn_weights
|
406 |
+
|
407 |
+
@staticmethod
|
408 |
+
def _append_prev_key_padding_mask(
|
409 |
+
key_padding_mask: Optional[Tensor],
|
410 |
+
prev_key_padding_mask: Optional[Tensor],
|
411 |
+
batch_size: int,
|
412 |
+
src_len: int,
|
413 |
+
static_kv: bool,
|
414 |
+
) -> Optional[Tensor]:
|
415 |
+
# saved key padding masks have shape (bsz, seq_len)
|
416 |
+
if prev_key_padding_mask is not None and static_kv:
|
417 |
+
new_key_padding_mask = prev_key_padding_mask
|
418 |
+
elif prev_key_padding_mask is not None and key_padding_mask is not None:
|
419 |
+
new_key_padding_mask = torch.cat(
|
420 |
+
[prev_key_padding_mask.float(), key_padding_mask.float()], dim=1
|
421 |
+
)
|
422 |
+
# During incremental decoding, as the padding token enters and
|
423 |
+
# leaves the frame, there will be a time when prev or current
|
424 |
+
# is None
|
425 |
+
elif prev_key_padding_mask is not None:
|
426 |
+
filler = torch.zeros(
|
427 |
+
(batch_size, src_len - prev_key_padding_mask.size(1)),
|
428 |
+
device=prev_key_padding_mask.device,
|
429 |
+
)
|
430 |
+
new_key_padding_mask = torch.cat(
|
431 |
+
[prev_key_padding_mask.float(), filler.float()], dim=1
|
432 |
+
)
|
433 |
+
elif key_padding_mask is not None:
|
434 |
+
filler = torch.zeros(
|
435 |
+
(batch_size, src_len - key_padding_mask.size(1)),
|
436 |
+
device=key_padding_mask.device,
|
437 |
+
)
|
438 |
+
new_key_padding_mask = torch.cat([filler.float(), key_padding_mask.float()], dim=1)
|
439 |
+
else:
|
440 |
+
new_key_padding_mask = prev_key_padding_mask
|
441 |
+
return new_key_padding_mask
|
442 |
+
|
443 |
+
@torch.jit.export
|
444 |
+
def reorder_incremental_state(
|
445 |
+
self, incremental_state: Dict[str, Dict[str, Optional[Tensor]]], new_order: Tensor
|
446 |
+
):
|
447 |
+
"""Reorder buffered internal state (for incremental generation)."""
|
448 |
+
input_buffer = self._get_input_buffer(incremental_state)
|
449 |
+
if input_buffer is not None:
|
450 |
+
for k in input_buffer.keys():
|
451 |
+
input_buffer_k = input_buffer[k]
|
452 |
+
if input_buffer_k is not None:
|
453 |
+
if self.encoder_decoder_attention and input_buffer_k.size(0) == new_order.size(
|
454 |
+
0
|
455 |
+
):
|
456 |
+
break
|
457 |
+
input_buffer[k] = input_buffer_k.index_select(0, new_order)
|
458 |
+
incremental_state = self._set_input_buffer(incremental_state, input_buffer)
|
459 |
+
return incremental_state
|
460 |
+
|
461 |
+
def _get_input_buffer(
|
462 |
+
self, incremental_state: Optional[Dict[str, Dict[str, Optional[Tensor]]]]
|
463 |
+
) -> Dict[str, Optional[Tensor]]:
|
464 |
+
result = self.get_incremental_state(incremental_state, "attn_state")
|
465 |
+
if result is not None:
|
466 |
+
return result
|
467 |
+
else:
|
468 |
+
empty_result: Dict[str, Optional[Tensor]] = {}
|
469 |
+
return empty_result
|
470 |
+
|
471 |
+
def _set_input_buffer(
|
472 |
+
self,
|
473 |
+
incremental_state: Dict[str, Dict[str, Optional[Tensor]]],
|
474 |
+
buffer: Dict[str, Optional[Tensor]],
|
475 |
+
):
|
476 |
+
return self.set_incremental_state(incremental_state, "attn_state", buffer)
|
477 |
+
|
478 |
+
def apply_sparse_mask(attn_weights, tgt_len: int, src_len: int, bsz: int):
|
479 |
+
return attn_weights
|
480 |
+
|
481 |
+
def upgrade_state_dict_named(self, state_dict, name):
|
482 |
+
prefix = name + "." if name != "" else ""
|
483 |
+
items_to_add = {}
|
484 |
+
keys_to_remove = []
|
485 |
+
for k in state_dict.keys():
|
486 |
+
if k.endswith(prefix + "in_proj_weight"):
|
487 |
+
# in_proj_weight used to be q + k + v with same dimensions
|
488 |
+
dim = int(state_dict[k].shape[0] / 3)
|
489 |
+
items_to_add[prefix + "q_proj.weight"] = state_dict[k][:dim]
|
490 |
+
items_to_add[prefix + "k_proj.weight"] = state_dict[k][dim : 2 * dim]
|
491 |
+
items_to_add[prefix + "v_proj.weight"] = state_dict[k][2 * dim :]
|
492 |
+
|
493 |
+
keys_to_remove.append(k)
|
494 |
+
|
495 |
+
k_bias = prefix + "in_proj_bias"
|
496 |
+
if k_bias in state_dict.keys():
|
497 |
+
dim = int(state_dict[k].shape[0] / 3)
|
498 |
+
items_to_add[prefix + "q_proj.bias"] = state_dict[k_bias][:dim]
|
499 |
+
items_to_add[prefix + "k_proj.bias"] = state_dict[k_bias][dim : 2 * dim]
|
500 |
+
items_to_add[prefix + "v_proj.bias"] = state_dict[k_bias][2 * dim :]
|
501 |
+
|
502 |
+
keys_to_remove.append(prefix + "in_proj_bias")
|
503 |
+
|
504 |
+
for k in keys_to_remove:
|
505 |
+
del state_dict[k]
|
506 |
+
|
507 |
+
for key, value in items_to_add.items():
|
508 |
+
state_dict[key] = value
|
esm/esm/pretrained.py
ADDED
@@ -0,0 +1,397 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Copyright (c) Facebook, Inc. and its affiliates.
|
2 |
+
#
|
3 |
+
# This source code is licensed under the MIT license found in the
|
4 |
+
# LICENSE file in the root directory of this source tree.
|
5 |
+
|
6 |
+
import re
|
7 |
+
import urllib
|
8 |
+
import warnings
|
9 |
+
from argparse import Namespace
|
10 |
+
from pathlib import Path
|
11 |
+
|
12 |
+
import torch
|
13 |
+
|
14 |
+
import esm
|
15 |
+
from esm.model.esm2 import ESM2
|
16 |
+
|
17 |
+
|
18 |
+
def _has_regression_weights(model_name):
|
19 |
+
"""Return whether we expect / require regression weights;
|
20 |
+
Right now that is all models except ESM-1v and ESM-IF"""
|
21 |
+
return not ("esm1v" in model_name or "esm_if" in model_name)
|
22 |
+
|
23 |
+
|
24 |
+
def load_model_and_alphabet(model_name):
|
25 |
+
if model_name.endswith(".pt"): # treat as filepath
|
26 |
+
return load_model_and_alphabet_local(model_name)
|
27 |
+
else:
|
28 |
+
return load_model_and_alphabet_hub(model_name)
|
29 |
+
|
30 |
+
|
31 |
+
def load_hub_workaround(url):
|
32 |
+
try:
|
33 |
+
data = torch.hub.load_state_dict_from_url(url, progress=False, map_location="cpu")
|
34 |
+
except RuntimeError:
|
35 |
+
# Pytorch version issue - see https://github.com/pytorch/pytorch/issues/43106
|
36 |
+
fn = Path(url).name
|
37 |
+
data = torch.load(
|
38 |
+
f"{torch.hub.get_dir()}/checkpoints/{fn}",
|
39 |
+
map_location="cpu",
|
40 |
+
)
|
41 |
+
except urllib.error.HTTPError as e:
|
42 |
+
raise Exception(f"Could not load {url}, check if you specified a correct model name?")
|
43 |
+
return data
|
44 |
+
|
45 |
+
|
46 |
+
def load_regression_hub(model_name):
|
47 |
+
url = f"https://dl.fbaipublicfiles.com/fair-esm/regression/{model_name}-contact-regression.pt"
|
48 |
+
regression_data = load_hub_workaround(url)
|
49 |
+
return regression_data
|
50 |
+
|
51 |
+
|
52 |
+
def _download_model_and_regression_data(model_name):
|
53 |
+
url = f"https://dl.fbaipublicfiles.com/fair-esm/models/{model_name}.pt"
|
54 |
+
model_data = load_hub_workaround(url)
|
55 |
+
if _has_regression_weights(model_name):
|
56 |
+
regression_data = load_regression_hub(model_name)
|
57 |
+
else:
|
58 |
+
regression_data = None
|
59 |
+
return model_data, regression_data
|
60 |
+
|
61 |
+
|
62 |
+
def load_model_and_alphabet_hub(model_name):
|
63 |
+
model_data, regression_data = _download_model_and_regression_data(model_name)
|
64 |
+
return load_model_and_alphabet_core(model_name, model_data, regression_data)
|
65 |
+
|
66 |
+
|
67 |
+
def load_model_and_alphabet_local(model_location):
|
68 |
+
"""Load from local path. The regression weights need to be co-located"""
|
69 |
+
model_location = Path(model_location)
|
70 |
+
model_data = torch.load(str(model_location), map_location="cpu")
|
71 |
+
model_name = model_location.stem
|
72 |
+
if _has_regression_weights(model_name):
|
73 |
+
regression_location = str(model_location.with_suffix("")) + "-contact-regression.pt"
|
74 |
+
regression_data = torch.load(regression_location, map_location="cpu")
|
75 |
+
else:
|
76 |
+
regression_data = None
|
77 |
+
return load_model_and_alphabet_core(model_name, model_data, regression_data)
|
78 |
+
|
79 |
+
|
80 |
+
def has_emb_layer_norm_before(model_state):
|
81 |
+
"""Determine whether layer norm needs to be applied before the encoder"""
|
82 |
+
return any(k.startswith("emb_layer_norm_before") for k, param in model_state.items())
|
83 |
+
|
84 |
+
|
85 |
+
def _load_model_and_alphabet_core_v1(model_data):
|
86 |
+
import esm # since esm.inverse_folding is imported below, you actually have to re-import esm here
|
87 |
+
|
88 |
+
alphabet = esm.Alphabet.from_architecture(model_data["args"].arch)
|
89 |
+
|
90 |
+
if model_data["args"].arch == "roberta_large":
|
91 |
+
# upgrade state dict
|
92 |
+
pra = lambda s: "".join(s.split("encoder_")[1:] if "encoder" in s else s)
|
93 |
+
prs1 = lambda s: "".join(s.split("encoder.")[1:] if "encoder" in s else s)
|
94 |
+
prs2 = lambda s: "".join(
|
95 |
+
s.split("sentence_encoder.")[1:] if "sentence_encoder" in s else s
|
96 |
+
)
|
97 |
+
model_args = {pra(arg[0]): arg[1] for arg in vars(model_data["args"]).items()}
|
98 |
+
model_state = {prs1(prs2(arg[0])): arg[1] for arg in model_data["model"].items()}
|
99 |
+
model_state["embed_tokens.weight"][alphabet.mask_idx].zero_() # For token drop
|
100 |
+
model_args["emb_layer_norm_before"] = has_emb_layer_norm_before(model_state)
|
101 |
+
model_type = esm.ProteinBertModel
|
102 |
+
|
103 |
+
elif model_data["args"].arch == "protein_bert_base":
|
104 |
+
|
105 |
+
# upgrade state dict
|
106 |
+
pra = lambda s: "".join(s.split("decoder_")[1:] if "decoder" in s else s)
|
107 |
+
prs = lambda s: "".join(s.split("decoder.")[1:] if "decoder" in s else s)
|
108 |
+
model_args = {pra(arg[0]): arg[1] for arg in vars(model_data["args"]).items()}
|
109 |
+
model_state = {prs(arg[0]): arg[1] for arg in model_data["model"].items()}
|
110 |
+
model_type = esm.ProteinBertModel
|
111 |
+
elif model_data["args"].arch == "msa_transformer":
|
112 |
+
|
113 |
+
# upgrade state dict
|
114 |
+
pra = lambda s: "".join(s.split("encoder_")[1:] if "encoder" in s else s)
|
115 |
+
prs1 = lambda s: "".join(s.split("encoder.")[1:] if "encoder" in s else s)
|
116 |
+
prs2 = lambda s: "".join(
|
117 |
+
s.split("sentence_encoder.")[1:] if "sentence_encoder" in s else s
|
118 |
+
)
|
119 |
+
prs3 = lambda s: s.replace("row", "column") if "row" in s else s.replace("column", "row")
|
120 |
+
model_args = {pra(arg[0]): arg[1] for arg in vars(model_data["args"]).items()}
|
121 |
+
model_state = {prs1(prs2(prs3(arg[0]))): arg[1] for arg in model_data["model"].items()}
|
122 |
+
if model_args.get("embed_positions_msa", False):
|
123 |
+
emb_dim = model_state["msa_position_embedding"].size(-1)
|
124 |
+
model_args["embed_positions_msa_dim"] = emb_dim # initial release, bug: emb_dim==1
|
125 |
+
|
126 |
+
model_type = esm.MSATransformer
|
127 |
+
|
128 |
+
elif "invariant_gvp" in model_data["args"].arch:
|
129 |
+
import esm.inverse_folding
|
130 |
+
|
131 |
+
model_type = esm.inverse_folding.gvp_transformer.GVPTransformerModel
|
132 |
+
model_args = vars(model_data["args"]) # convert Namespace -> dict
|
133 |
+
|
134 |
+
def update_name(s):
|
135 |
+
# Map the module names in checkpoints trained with internal code to
|
136 |
+
# the updated module names in open source code
|
137 |
+
s = s.replace("W_v", "embed_graph.embed_node")
|
138 |
+
s = s.replace("W_e", "embed_graph.embed_edge")
|
139 |
+
s = s.replace("embed_scores.0", "embed_confidence")
|
140 |
+
s = s.replace("embed_score.", "embed_graph.embed_confidence.")
|
141 |
+
s = s.replace("seq_logits_projection.", "")
|
142 |
+
s = s.replace("embed_ingraham_features", "embed_dihedrals")
|
143 |
+
s = s.replace("embed_gvp_in_local_frame.0", "embed_gvp_output")
|
144 |
+
s = s.replace("embed_features_in_local_frame.0", "embed_gvp_input_features")
|
145 |
+
return s
|
146 |
+
|
147 |
+
model_state = {
|
148 |
+
update_name(sname): svalue
|
149 |
+
for sname, svalue in model_data["model"].items()
|
150 |
+
if "version" not in sname
|
151 |
+
}
|
152 |
+
|
153 |
+
else:
|
154 |
+
raise ValueError("Unknown architecture selected")
|
155 |
+
|
156 |
+
model = model_type(
|
157 |
+
Namespace(**model_args),
|
158 |
+
alphabet,
|
159 |
+
)
|
160 |
+
|
161 |
+
return model, alphabet, model_state
|
162 |
+
|
163 |
+
|
164 |
+
def _load_model_and_alphabet_core_v2(model_data):
|
165 |
+
def upgrade_state_dict(state_dict):
|
166 |
+
"""Removes prefixes 'model.encoder.sentence_encoder.' and 'model.encoder.'."""
|
167 |
+
prefixes = ["encoder.sentence_encoder.", "encoder."]
|
168 |
+
pattern = re.compile("^" + "|".join(prefixes))
|
169 |
+
state_dict = {pattern.sub("", name): param for name, param in state_dict.items()}
|
170 |
+
return state_dict
|
171 |
+
|
172 |
+
cfg = model_data["cfg"]["model"]
|
173 |
+
state_dict = model_data["model"]
|
174 |
+
state_dict = upgrade_state_dict(state_dict)
|
175 |
+
alphabet = esm.data.Alphabet.from_architecture("ESM-1b")
|
176 |
+
model = ESM2(
|
177 |
+
num_layers=cfg.encoder_layers,
|
178 |
+
embed_dim=cfg.encoder_embed_dim,
|
179 |
+
attention_heads=cfg.encoder_attention_heads,
|
180 |
+
alphabet=alphabet,
|
181 |
+
token_dropout=cfg.token_dropout,
|
182 |
+
)
|
183 |
+
return model, alphabet, state_dict
|
184 |
+
|
185 |
+
|
186 |
+
def load_model_and_alphabet_core(model_name, model_data, regression_data=None):
|
187 |
+
if regression_data is not None:
|
188 |
+
model_data["model"].update(regression_data["model"])
|
189 |
+
|
190 |
+
if model_name.startswith("esm2"):
|
191 |
+
model, alphabet, model_state = _load_model_and_alphabet_core_v2(model_data)
|
192 |
+
else:
|
193 |
+
model, alphabet, model_state = _load_model_and_alphabet_core_v1(model_data)
|
194 |
+
|
195 |
+
expected_keys = set(model.state_dict().keys())
|
196 |
+
found_keys = set(model_state.keys())
|
197 |
+
|
198 |
+
if regression_data is None:
|
199 |
+
expected_missing = {"contact_head.regression.weight", "contact_head.regression.bias"}
|
200 |
+
error_msgs = []
|
201 |
+
missing = (expected_keys - found_keys) - expected_missing
|
202 |
+
if missing:
|
203 |
+
error_msgs.append(f"Missing key(s) in state_dict: {missing}.")
|
204 |
+
unexpected = found_keys - expected_keys
|
205 |
+
if unexpected:
|
206 |
+
error_msgs.append(f"Unexpected key(s) in state_dict: {unexpected}.")
|
207 |
+
|
208 |
+
if error_msgs:
|
209 |
+
raise RuntimeError(
|
210 |
+
"Error(s) in loading state_dict for {}:\n\t{}".format(
|
211 |
+
model.__class__.__name__, "\n\t".join(error_msgs)
|
212 |
+
)
|
213 |
+
)
|
214 |
+
if expected_missing - found_keys:
|
215 |
+
warnings.warn(
|
216 |
+
"Regression weights not found, predicting contacts will not produce correct results."
|
217 |
+
)
|
218 |
+
|
219 |
+
model.load_state_dict(model_state, strict=regression_data is not None)
|
220 |
+
|
221 |
+
return model, alphabet
|
222 |
+
|
223 |
+
|
224 |
+
def esm1_t34_670M_UR50S():
|
225 |
+
"""34 layer transformer model with 670M params, trained on Uniref50 Sparse.
|
226 |
+
|
227 |
+
Returns a tuple of (Model, Alphabet).
|
228 |
+
"""
|
229 |
+
return load_model_and_alphabet_hub("esm1_t34_670M_UR50S")
|
230 |
+
|
231 |
+
|
232 |
+
def esm1_t34_670M_UR50D():
|
233 |
+
"""34 layer transformer model with 670M params, trained on Uniref50 Dense.
|
234 |
+
|
235 |
+
Returns a tuple of (Model, Alphabet).
|
236 |
+
"""
|
237 |
+
return load_model_and_alphabet_hub("esm1_t34_670M_UR50D")
|
238 |
+
|
239 |
+
|
240 |
+
def esm1_t34_670M_UR100():
|
241 |
+
"""34 layer transformer model with 670M params, trained on Uniref100.
|
242 |
+
|
243 |
+
Returns a tuple of (Model, Alphabet).
|
244 |
+
"""
|
245 |
+
return load_model_and_alphabet_hub("esm1_t34_670M_UR100")
|
246 |
+
|
247 |
+
|
248 |
+
def esm1_t12_85M_UR50S():
|
249 |
+
"""12 layer transformer model with 85M params, trained on Uniref50 Sparse.
|
250 |
+
|
251 |
+
Returns a tuple of (Model, Alphabet).
|
252 |
+
"""
|
253 |
+
return load_model_and_alphabet_hub("esm1_t12_85M_UR50S")
|
254 |
+
|
255 |
+
|
256 |
+
def esm1_t6_43M_UR50S():
|
257 |
+
"""6 layer transformer model with 43M params, trained on Uniref50 Sparse.
|
258 |
+
|
259 |
+
Returns a tuple of (Model, Alphabet).
|
260 |
+
"""
|
261 |
+
return load_model_and_alphabet_hub("esm1_t6_43M_UR50S")
|
262 |
+
|
263 |
+
|
264 |
+
def esm1b_t33_650M_UR50S():
|
265 |
+
"""33 layer transformer model with 650M params, trained on Uniref50 Sparse.
|
266 |
+
This is our best performing model, which will be described in a future publication.
|
267 |
+
|
268 |
+
Returns a tuple of (Model, Alphabet).
|
269 |
+
"""
|
270 |
+
return load_model_and_alphabet_hub("esm1b_t33_650M_UR50S")
|
271 |
+
|
272 |
+
|
273 |
+
def esm_msa1_t12_100M_UR50S():
|
274 |
+
warnings.warn(
|
275 |
+
"This model had a minor bug in the positional embeddings, "
|
276 |
+
"please use ESM-MSA-1b: esm.pretrained.esm_msa1b_t12_100M_UR50S()",
|
277 |
+
)
|
278 |
+
return load_model_and_alphabet_hub("esm_msa1_t12_100M_UR50S")
|
279 |
+
|
280 |
+
|
281 |
+
def esm_msa1b_t12_100M_UR50S():
|
282 |
+
return load_model_and_alphabet_hub("esm_msa1b_t12_100M_UR50S")
|
283 |
+
|
284 |
+
|
285 |
+
def esm1v_t33_650M_UR90S():
|
286 |
+
"""33 layer transformer model with 650M params, trained on Uniref90.
|
287 |
+
This is model 1 of a 5 model ensemble.
|
288 |
+
|
289 |
+
Returns a tuple of (Model, Alphabet).
|
290 |
+
"""
|
291 |
+
return load_model_and_alphabet_hub("esm1v_t33_650M_UR90S_1")
|
292 |
+
|
293 |
+
|
294 |
+
def esm1v_t33_650M_UR90S_1():
|
295 |
+
"""33 layer transformer model with 650M params, trained on Uniref90.
|
296 |
+
This is model 1 of a 5 model ensemble.
|
297 |
+
|
298 |
+
Returns a tuple of (Model, Alphabet).
|
299 |
+
"""
|
300 |
+
return load_model_and_alphabet_hub("esm1v_t33_650M_UR90S_1")
|
301 |
+
|
302 |
+
|
303 |
+
def esm1v_t33_650M_UR90S_2():
|
304 |
+
"""33 layer transformer model with 650M params, trained on Uniref90.
|
305 |
+
This is model 2 of a 5 model ensemble.
|
306 |
+
|
307 |
+
Returns a tuple of (Model, Alphabet).
|
308 |
+
"""
|
309 |
+
return load_model_and_alphabet_hub("esm1v_t33_650M_UR90S_2")
|
310 |
+
|
311 |
+
|
312 |
+
def esm1v_t33_650M_UR90S_3():
|
313 |
+
"""33 layer transformer model with 650M params, trained on Uniref90.
|
314 |
+
This is model 3 of a 5 model ensemble.
|
315 |
+
|
316 |
+
Returns a tuple of (Model, Alphabet).
|
317 |
+
"""
|
318 |
+
return load_model_and_alphabet_hub("esm1v_t33_650M_UR90S_3")
|
319 |
+
|
320 |
+
|
321 |
+
def esm1v_t33_650M_UR90S_4():
|
322 |
+
"""33 layer transformer model with 650M params, trained on Uniref90.
|
323 |
+
This is model 4 of a 5 model ensemble.
|
324 |
+
|
325 |
+
Returns a tuple of (Model, Alphabet).
|
326 |
+
"""
|
327 |
+
return load_model_and_alphabet_hub("esm1v_t33_650M_UR90S_4")
|
328 |
+
|
329 |
+
|
330 |
+
def esm1v_t33_650M_UR90S_5():
|
331 |
+
"""33 layer transformer model with 650M params, trained on Uniref90.
|
332 |
+
This is model 5 of a 5 model ensemble.
|
333 |
+
|
334 |
+
Returns a tuple of (Model, Alphabet).
|
335 |
+
"""
|
336 |
+
return load_model_and_alphabet_hub("esm1v_t33_650M_UR90S_5")
|
337 |
+
|
338 |
+
|
339 |
+
def esm_if1_gvp4_t16_142M_UR50():
|
340 |
+
"""Inverse folding model with 142M params, with 4 GVP-GNN layers, 8
|
341 |
+
Transformer encoder layers, and 8 Transformer decoder layers, trained on
|
342 |
+
CATH structures and 12 million alphafold2 predicted structures from UniRef50
|
343 |
+
sequences.
|
344 |
+
|
345 |
+
Returns a tuple of (Model, Alphabet).
|
346 |
+
"""
|
347 |
+
return load_model_and_alphabet_hub("esm_if1_gvp4_t16_142M_UR50")
|
348 |
+
|
349 |
+
|
350 |
+
def esm2_t6_8M_UR50D():
|
351 |
+
"""6 layer ESM-2 model with 8M params, trained on UniRef50.
|
352 |
+
|
353 |
+
Returns a tuple of (Model, Alphabet).
|
354 |
+
"""
|
355 |
+
return load_model_and_alphabet_hub("esm2_t6_8M_UR50D")
|
356 |
+
|
357 |
+
|
358 |
+
def esm2_t12_35M_UR50D():
|
359 |
+
"""12 layer ESM-2 model with 35M params, trained on UniRef50.
|
360 |
+
|
361 |
+
Returns a tuple of (Model, Alphabet).
|
362 |
+
"""
|
363 |
+
return load_model_and_alphabet_hub("esm2_t12_35M_UR50D")
|
364 |
+
|
365 |
+
|
366 |
+
def esm2_t30_150M_UR50D():
|
367 |
+
"""30 layer ESM-2 model with 150M params, trained on UniRef50.
|
368 |
+
|
369 |
+
Returns a tuple of (Model, Alphabet).
|
370 |
+
"""
|
371 |
+
return load_model_and_alphabet_hub("esm2_t30_150M_UR50D")
|
372 |
+
|
373 |
+
|
374 |
+
def esm2_t33_650M_UR50D():
|
375 |
+
"""33 layer ESM-2 model with 650M params, trained on UniRef50.
|
376 |
+
|
377 |
+
Returns a tuple of (Model, Alphabet).
|
378 |
+
"""
|
379 |
+
return load_model_and_alphabet_hub("esm2_t33_650M_UR50D")
|
380 |
+
|
381 |
+
|
382 |
+
def esm2_t36_3B_UR50D():
|
383 |
+
"""36 layer ESM-2 model with 3B params, trained on UniRef50.
|
384 |
+
|
385 |
+
Returns a tuple of (Model, Alphabet).
|
386 |
+
"""
|
387 |
+
return load_model_and_alphabet_hub("esm2_t36_3B_UR50D")
|
388 |
+
|
389 |
+
|
390 |
+
def esm2_t48_15B_UR50D():
|
391 |
+
"""48 layer ESM-2 model with 15B params, trained on UniRef50.
|
392 |
+
If you have OOM while loading this model, please refer to README
|
393 |
+
on how to employ FSDP and ZeRO CPU offloading
|
394 |
+
|
395 |
+
Returns a tuple of (Model, Alphabet).
|
396 |
+
"""
|
397 |
+
return load_model_and_alphabet_hub("esm2_t48_15B_UR50D")
|
esm/esm/rotary_embedding.py
ADDED
@@ -0,0 +1,69 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Copyright (c) Facebook, Inc. and its affiliates.
|
2 |
+
#
|
3 |
+
# This source code is licensed under the MIT license found in the
|
4 |
+
# LICENSE file in the root directory of this source tree.
|
5 |
+
|
6 |
+
from typing import Tuple
|
7 |
+
|
8 |
+
import torch
|
9 |
+
|
10 |
+
|
11 |
+
def rotate_half(x):
|
12 |
+
x1, x2 = x.chunk(2, dim=-1)
|
13 |
+
return torch.cat((-x2, x1), dim=-1)
|
14 |
+
|
15 |
+
|
16 |
+
def apply_rotary_pos_emb(x, cos, sin):
|
17 |
+
cos = cos[:, : x.shape[-2], :]
|
18 |
+
sin = sin[:, : x.shape[-2], :]
|
19 |
+
|
20 |
+
return (x * cos) + (rotate_half(x) * sin)
|
21 |
+
|
22 |
+
|
23 |
+
class RotaryEmbedding(torch.nn.Module):
|
24 |
+
"""
|
25 |
+
The rotary position embeddings from RoFormer_ (Su et. al).
|
26 |
+
A crucial insight from the method is that the query and keys are
|
27 |
+
transformed by rotation matrices which depend on the relative positions.
|
28 |
+
Other implementations are available in the Rotary Transformer repo_ and in
|
29 |
+
GPT-NeoX_, GPT-NeoX was an inspiration
|
30 |
+
.. _RoFormer: https://arxiv.org/abs/2104.09864
|
31 |
+
.. _repo: https://github.com/ZhuiyiTechnology/roformer
|
32 |
+
.. _GPT-NeoX: https://github.com/EleutherAI/gpt-neox
|
33 |
+
.. warning: Please note that this embedding is not registered on purpose, as it is transformative
|
34 |
+
(it does not create the embedding dimension) and will likely be picked up (imported) on a ad-hoc basis
|
35 |
+
"""
|
36 |
+
|
37 |
+
def __init__(self, dim: int, *_, **__):
|
38 |
+
super().__init__()
|
39 |
+
# Generate and save the inverse frequency buffer (non trainable)
|
40 |
+
inv_freq = 1.0 / (10000 ** (torch.arange(0, dim, 2).float() / dim))
|
41 |
+
self.register_buffer("inv_freq", inv_freq)
|
42 |
+
|
43 |
+
self._seq_len_cached = None
|
44 |
+
self._cos_cached = None
|
45 |
+
self._sin_cached = None
|
46 |
+
|
47 |
+
def _update_cos_sin_tables(self, x, seq_dimension=1):
|
48 |
+
seq_len = x.shape[seq_dimension]
|
49 |
+
|
50 |
+
# Reset the tables if the sequence length has changed,
|
51 |
+
# or if we're on a new device (possibly due to tracing for instance)
|
52 |
+
if seq_len != self._seq_len_cached or self._cos_cached.device != x.device:
|
53 |
+
self._seq_len_cached = seq_len
|
54 |
+
t = torch.arange(x.shape[seq_dimension], device=x.device).type_as(self.inv_freq)
|
55 |
+
freqs = torch.einsum("i,j->ij", t, self.inv_freq)
|
56 |
+
emb = torch.cat((freqs, freqs), dim=-1).to(x.device)
|
57 |
+
|
58 |
+
self._cos_cached = emb.cos()[None, :, :]
|
59 |
+
self._sin_cached = emb.sin()[None, :, :]
|
60 |
+
|
61 |
+
return self._cos_cached, self._sin_cached
|
62 |
+
|
63 |
+
def forward(self, q: torch.Tensor, k: torch.Tensor) -> Tuple[torch.Tensor, torch.Tensor]:
|
64 |
+
self._cos_cached, self._sin_cached = self._update_cos_sin_tables(k, seq_dimension=-2)
|
65 |
+
|
66 |
+
return (
|
67 |
+
apply_rotary_pos_emb(q, self._cos_cached, self._sin_cached),
|
68 |
+
apply_rotary_pos_emb(k, self._cos_cached, self._sin_cached),
|
69 |
+
)
|
esm/esm/version.py
ADDED
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Copyright (c) Facebook, Inc. and its affiliates.
|
2 |
+
#
|
3 |
+
# This source code is licensed under the MIT license found in the
|
4 |
+
# LICENSE file in the root directory of this source tree.
|
5 |
+
|
6 |
+
version = "1.0.2"
|
esm/scripts/extract.py
ADDED
@@ -0,0 +1,142 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
#!/usr/bin/env python3 -u
|
2 |
+
# Copyright (c) Facebook, Inc. and its affiliates.
|
3 |
+
#
|
4 |
+
# This source code is licensed under the MIT license found in the
|
5 |
+
# LICENSE file in the root directory of this source tree.
|
6 |
+
|
7 |
+
import argparse
|
8 |
+
import pathlib
|
9 |
+
import sys
|
10 |
+
print("using", sys.executable)
|
11 |
+
|
12 |
+
sys.path.insert( 0,"/home/user/.local/lib/python3.8/site-packages")
|
13 |
+
sys.path.insert( 0,"/home/user/app/esm/")
|
14 |
+
import os
|
15 |
+
|
16 |
+
import torch
|
17 |
+
|
18 |
+
from esm import Alphabet, FastaBatchedDataset, ProteinBertModel, pretrained, MSATransformer
|
19 |
+
|
20 |
+
|
21 |
+
def create_parser():
|
22 |
+
parser = argparse.ArgumentParser(
|
23 |
+
description="Extract per-token representations and model outputs for sequences in a FASTA file" # noqa
|
24 |
+
)
|
25 |
+
|
26 |
+
parser.add_argument(
|
27 |
+
"model_location",
|
28 |
+
type=str,
|
29 |
+
help="PyTorch model file OR name of pretrained model to download (see README for models)",
|
30 |
+
)
|
31 |
+
parser.add_argument(
|
32 |
+
"fasta_file",
|
33 |
+
type=pathlib.Path,
|
34 |
+
help="FASTA file on which to extract representations",
|
35 |
+
)
|
36 |
+
parser.add_argument(
|
37 |
+
"output_dir",
|
38 |
+
type=pathlib.Path,
|
39 |
+
help="output directory for extracted representations",
|
40 |
+
)
|
41 |
+
|
42 |
+
parser.add_argument("--toks_per_batch", type=int, default=4096, help="maximum batch size")
|
43 |
+
parser.add_argument(
|
44 |
+
"--repr_layers",
|
45 |
+
type=int,
|
46 |
+
default=[-1],
|
47 |
+
nargs="+",
|
48 |
+
help="layers indices from which to extract representations (0 to num_layers, inclusive)",
|
49 |
+
)
|
50 |
+
parser.add_argument(
|
51 |
+
"--include",
|
52 |
+
type=str,
|
53 |
+
nargs="+",
|
54 |
+
choices=["mean", "per_tok", "bos", "contacts"],
|
55 |
+
help="specify which representations to return",
|
56 |
+
required=True,
|
57 |
+
)
|
58 |
+
parser.add_argument(
|
59 |
+
"--truncation_seq_length",
|
60 |
+
type=int,
|
61 |
+
default=1022,
|
62 |
+
help="truncate sequences longer than the given value",
|
63 |
+
)
|
64 |
+
|
65 |
+
parser.add_argument("--nogpu", action="store_true", help="Do not use GPU even if available")
|
66 |
+
return parser
|
67 |
+
|
68 |
+
|
69 |
+
def main(args):
|
70 |
+
model, alphabet = pretrained.load_model_and_alphabet(args.model_location)
|
71 |
+
model.eval()
|
72 |
+
if isinstance(model, MSATransformer):
|
73 |
+
raise ValueError(
|
74 |
+
"This script currently does not handle models with MSA input (MSA Transformer)."
|
75 |
+
)
|
76 |
+
if torch.cuda.is_available() and not args.nogpu:
|
77 |
+
model = model.cuda()
|
78 |
+
print("Transferred model to GPU")
|
79 |
+
|
80 |
+
dataset = FastaBatchedDataset.from_file(args.fasta_file)
|
81 |
+
batches = dataset.get_batch_indices(args.toks_per_batch, extra_toks_per_seq=1)
|
82 |
+
data_loader = torch.utils.data.DataLoader(
|
83 |
+
dataset, collate_fn=alphabet.get_batch_converter(args.truncation_seq_length), batch_sampler=batches
|
84 |
+
)
|
85 |
+
print(f"Read {args.fasta_file} with {len(dataset)} sequences")
|
86 |
+
|
87 |
+
args.output_dir.mkdir(parents=True, exist_ok=True)
|
88 |
+
return_contacts = "contacts" in args.include
|
89 |
+
|
90 |
+
assert all(-(model.num_layers + 1) <= i <= model.num_layers for i in args.repr_layers)
|
91 |
+
repr_layers = [(i + model.num_layers + 1) % (model.num_layers + 1) for i in args.repr_layers]
|
92 |
+
|
93 |
+
with torch.no_grad():
|
94 |
+
for batch_idx, (labels, strs, toks) in enumerate(data_loader):
|
95 |
+
print(
|
96 |
+
f"Processing {batch_idx + 1} of {len(batches)} batches ({toks.size(0)} sequences)"
|
97 |
+
)
|
98 |
+
if torch.cuda.is_available() and not args.nogpu:
|
99 |
+
toks = toks.to(device="cuda", non_blocking=True)
|
100 |
+
|
101 |
+
out = model(toks, repr_layers=repr_layers, return_contacts=return_contacts)
|
102 |
+
|
103 |
+
logits = out["logits"].to(device="cpu")
|
104 |
+
representations = {
|
105 |
+
layer: t.to(device="cpu") for layer, t in out["representations"].items()
|
106 |
+
}
|
107 |
+
if return_contacts:
|
108 |
+
contacts = out["contacts"].to(device="cpu")
|
109 |
+
|
110 |
+
for i, label in enumerate(labels):
|
111 |
+
args.output_file = args.output_dir / f"{label}.pt"
|
112 |
+
args.output_file.parent.mkdir(parents=True, exist_ok=True)
|
113 |
+
result = {"label": label}
|
114 |
+
# Call clone on tensors to ensure tensors are not views into a larger representation
|
115 |
+
# See https://github.com/pytorch/pytorch/issues/1995
|
116 |
+
if "per_tok" in args.include:
|
117 |
+
result["representations"] = {
|
118 |
+
layer: t[i, 1 : len(strs[i]) + 1].clone()
|
119 |
+
for layer, t in representations.items()
|
120 |
+
}
|
121 |
+
if "mean" in args.include:
|
122 |
+
result["mean_representations"] = {
|
123 |
+
layer: t[i, 1 : len(strs[i]) + 1].mean(0).clone()
|
124 |
+
for layer, t in representations.items()
|
125 |
+
}
|
126 |
+
if "bos" in args.include:
|
127 |
+
result["bos_representations"] = {
|
128 |
+
layer: t[i, 0].clone() for layer, t in representations.items()
|
129 |
+
}
|
130 |
+
if return_contacts:
|
131 |
+
result["contacts"] = contacts[i, : len(strs[i]), : len(strs[i])].clone()
|
132 |
+
|
133 |
+
torch.save(
|
134 |
+
result,
|
135 |
+
args.output_file,
|
136 |
+
)
|
137 |
+
|
138 |
+
|
139 |
+
if __name__ == "__main__":
|
140 |
+
parser = create_parser()
|
141 |
+
args = parser.parse_args()
|
142 |
+
main(args)
|