AlphaMWang commited on
Commit
adb3c1a
Β·
verified Β·
1 Parent(s): e2858c2

Update README.md

Browse files
Files changed (1) hide show
  1. README.md +1 -343
README.md CHANGED
@@ -4,347 +4,5 @@ license: afl-3.0
4
 
5
  Refer to [GitHub](https://github.com/Wang-Lin-boop/GeminiMol).
6
 
7
- This repository provides the official implementation of the GeminiMol model, training data, and utitiles.
8
-
9
- We also provide:
10
-
11
- 1. scripts for data collection, partitioning and analysis.
12
- 2. scripts for features analysis, visualisation and similarity calculation.
13
- 3. scripts, datasets and results for benchmarking molecular fingerprints and GeminiMol models on virtual screening, target identification, and QSAR (drug-target binding affinity, cellar activity, ADME, and toxicity).
14
-
15
- Please also refer to our paper for a detailed description of GeminiMol.
16
-
17
- ## πŸ’‘ Highlight
18
-
19
- * By capturing the intricate interplay between molecular structure and conformational space, our training strategy enhances the representational capacity of GeminiMol.
20
- * GeminiMol was pre-trained on only 37,336 molecular structures, yet it can generalize to zero-shot and QSAR tasks involving millions of molecules.
21
- * GeminiMol exhibits the capability to identify pairs of molecules with similar 3D active conformation, even in scenarios where their 2D structures exhibit significant differences.
22
-
23
- ## πŸ’— Motivation
24
-
25
- The **molecular representation model** is an emerging artificial intelligence technology for extracting features of small molecules. It has been **widely applied in drug discovery scenarios**, such as **virtual screening**, Quantitative Structure-Activity Relationship (**QSAR**) analysis, and **ADMET propteries prediction**. In previous work, molecular representation models were mostly trained on the static structure of molecules, however, the small molecules in solution are highly dynamic, and their flexible conformational changes endow them with the potential to bind to drug targets. Therefore, introducing information on small molecule conformational space into molecular representation models is a promising aim. In this work, a training strategy, named GeminiMol, was proposed to **incorporate the comprehension of conformational space into the molecular representation model**.
26
-
27
- ## πŸ”” News
28
-
29
- * 2023-12, our paper has been uploaded to BioRxiv, you can find it [here](https://www.biorxiv.org/content/10.1101/2023.12.14.571629).
30
-
31
- ## πŸ“• Installation
32
-
33
- GeminiMol is a pytorch-based AI model. To set up the GeminiMol model, we recommend using conda for Python environment configuration.
34
-
35
- > Installing MiniConda (skip if conda was installed)
36
-
37
- ``` shell
38
- wget https://repo.continuum.io/miniconda/Miniconda3-latest-Linux-x86_64.sh
39
- sh Miniconda3-latest-Linux-x86_64.sh
40
- ```
41
-
42
- > Creating GeminiMol environment
43
-
44
- ``` shell
45
- conda create -n GeminiMol python=3.8.16
46
- conda activate GeminiMol
47
- ```
48
-
49
- > Setting up GeminiMol PATH and configuration
50
-
51
- ``` shell
52
- git clone https://github.com/Wang-Lin-boop/GeminiMol
53
- cd GeminiMol/
54
- export PATH=${PWD}:\${PATH}" >> ~/.bashrc # optional, not required in the current version
55
- export GeminiMol=${PWD}" >> ~/.bashrc
56
- cd geminimol/
57
- export geminimol_app=${PWD}" >> ~/.bashrc
58
- cd ../model/
59
- export geminimol_lib=${PWD}" >> ~/.bashrc
60
- cd ../data/
61
- export geminimol_data=${PWD}" >> ~/.bashrc
62
- source ~/.bashrc
63
- ```
64
-
65
- ### Download datasets and models
66
-
67
- In this repository, we provide all the training, validation, and testing datasets used in our paper, as well as an optimal GeminiMol binary-encoder model, a series of CSS similarity decoder models, a molecular structure decoder model, and a variety of decoder models of basic ADMET properties.
68
-
69
- > Download all datasets, model parameters and weights via Zenodo
70
-
71
- ``` shell
72
- cd ${GeminiMol}/data
73
- wget https://zenodo.org/api/records/10273480/files-archive
74
- unzip *
75
- ```
76
-
77
- > Download model parameters and weights via [Google Driver](https://drive.google.com/drive/folders/183WGytS-zy_POlLxEvijEtarow56zmnz?usp=drive_link)
78
-
79
- Then, we need place the models to the `${GeminiMol}/models`.
80
-
81
- The expected structure of GeminiMol path is:
82
-
83
- ```
84
- GeminiMol
85
- β”œβ”€β”€ geminimol # all code for GeminiMol and CrossEncoder
86
- β”‚ β”œβ”€β”€ model # code for GeminiMol and CrossEncoder models
87
- β”‚ β”‚ β”œβ”€β”€ CrossEncoder.py # model and methods for CrossEncoder
88
- β”‚ β”‚ β”œβ”€β”€ GeminiMol.py # model and methods for GeminiMol models
89
- β”‚ β”œβ”€β”€ utils # utils in this work
90
- β”‚ β”‚ β”œβ”€β”€ chem.py # basic tools for cheminformatics
91
- β”‚ β”‚ β”œβ”€β”€ dataset_split.py # tools for dataset split
92
- β”‚ β”‚ β”œβ”€β”€ fingerprint.py # basic tools for molecular fingerprints
93
- β”‚ β”œβ”€β”€ Analyzer.py # analysis given molecules using presentation methods
94
- β”‚ β”œβ”€β”€ AutoQSAR.py # molecular proptery modeling by AutoGluon
95
- β”‚ β”œβ”€β”€ PropDecoder.py # molecular proptery modeling by our PropDcoder
96
- β”‚ β”œβ”€β”€ FineTuning.py # molecular proptery modeling by fine-tune GeminiMol models
97
- β”‚ β”œβ”€β”€ Screener.py # screening molecules by GeminiMol similarity
98
- β”‚ β”œβ”€β”€ CrossEncoder_Training.py # scripts for training the CrossEncoders.
99
- β”‚ β”œβ”€β”€ GeminiMol_Training.py # scripts for training the GeminiMol models.
100
- β”‚ β”œβ”€β”€ benchmark.py # benchmarking presentation methods on provide datasets
101
- β”œβ”€β”€ data # training and benchmark data in this work
102
- β”‚ β”œβ”€β”€ Benchmark_DUD-E # virtual screeening
103
- β”‚ β”œβ”€β”€ Benchmark_LIT-PCBA # virtual screeening
104
- β”‚ β”œβ”€β”€ Benchmark_TIBD # target identification
105
- β”‚ β”œβ”€β”€ Benchmark_QSAR # QSAR and ADMET
106
- β”‚ β”œβ”€β”€ Chem_SmELECTRA # text backbone of chemical language
107
- β”‚ β”œβ”€β”€ css_library # CSS training data
108
- β”‚ β”œβ”€β”€ benchmark.json # dataset index for benchmark tasks
109
- β”‚ β”œβ”€β”€ database.csv # molecular datasets in this work
110
- β”‚ β”œβ”€β”€ BindingDB_DATA.csv # dataset used in target identification
111
- β”‚ β”œβ”€β”€ ChemDiv.csv # library of common commercial compounds
112
- β”‚ β”œβ”€β”€ Specs.csv # library of common commercial compounds
113
- β”œβ”€β”€ models # CrossEncoder and GeminiMol models
114
- β”‚ β”œβ”€β”€ CrossEncoder # CrossEncoder
115
- β”‚ β”œβ”€β”€ GeminiMol # GeminiMol, recommended for zero-shot tasks
116
- β”‚ β”œβ”€β”€ GeminiMol-MOD # GeminiMol-MOD, recommended for QSAR tasks
117
- ```
118
-
119
- ### Installing the dependency packages
120
-
121
- If you intend to utilize molecular fingerprint baseline methods or conduct QSAR benchmarking, it is required to install RDKit and AutoGluon in advance.
122
-
123
- > Installing the RDkit for generating fingerprints
124
-
125
- ``` shell
126
- pip install rdkit
127
- ```
128
-
129
- > Installing the AutoGluon for performing AutoQSAR
130
-
131
- ``` shell
132
- pip3 install -U pip
133
- pip3 install -U setuptools wheel
134
- pip3 install torch==1.13.1+cu116 torchvision==0.14.1+cu116 \
135
- --extra-index-url https://download.pytorch.org/whl/cu116
136
- pip3 install autogluon==0.8.1
137
- ```
138
-
139
- > Installing the statatics and plot packages
140
-
141
- ``` shell
142
- pip install oddt scikit-learn matplotlib
143
- ```
144
-
145
- To re-train the model or make predictions using the models we provide, follow the steps below to install the dependencies in advance.
146
-
147
- > Installing the dependency packages of GeminiMol
148
-
149
- ``` shell
150
- pip install scipy dgllife
151
- pip install torch==1.13.1+cu116 torchvision==0.14.1+cu116 \
152
- --extra-index-url https://download.pytorch.org/whl/cu116
153
- pip install dgl -f https://data.dgl.ai/wheels/cu116/repo.html
154
- pip install dglgo -f https://data.dgl.ai/wheels-test/repo.html
155
- ```
156
-
157
- ## πŸ‘ Reproducing
158
-
159
- Here, we present the reproducible code for training the Cross-Encoder and GeminiMol models based on the conformational space similarity descriptors of 39,290 molecules described in the paper.
160
- Additionally, benchmark test scripts were provided. With this code, the community can reproduce the results reported in the paper, explore different model architectures, or incorporate additional molecular similarity data to further enhance the performance of the models.
161
-
162
- > Training the Cross-Encoder
163
-
164
- ``` shell
165
- conda activate GeminiMol
166
- export model_name="CrossEncoder"
167
- export batch_size_per_gpu=200 # batch size = 200 (batch_size_per_gpu) * 4 (gpu number)
168
- export epoch=20 # max epochs
169
- export lr="1.0e-3" # learning rate
170
- export label_list="MCMM1AM_MAX:LCMS2A1Q_MAX:MCMM1AM_MIN:LCMS2A1Q_MIN" # ShapeScore:ShapeAggregation:ShapeOverlap:CrossSim:CrossAggregation:CrossOverlap
171
- CUDA_VISIBLE_DEVICES=0,1,2,3 python ${geminimol_app}/CrossEncoder_Training.py "${geminimol_data}/css_library/" "${geminimol_data}/Chem_SmELECTRA" "${epoch}" "${lr}" "${batch_size_per_gpu}" "${model_name}" "${geminimol_data}/benchmark.json" "${label_list}"
172
- ```
173
-
174
- > Training the GeminiMol Encoder
175
-
176
- ``` shell
177
- conda activate GeminiMol
178
- export model_name="GeminiMol"
179
- export batch_size=512
180
- export epoch=20 # max epochs
181
- export patience=50 # for early stoping
182
- export GNN='WLN' # Weisfeiler-Lehman Network (WLN)
183
- export network="MeanMLP:2048:4:2048:None:0:5:0" # "Weighted:1024:12:2048:None:0:5:0" for GeminiMol-MOD
184
- export label_dict="ShapeScore:0.2,ShapeAggregation:0.2,ShapeOverlap:0.05,ShapeDistance:0.05,CrossSim:0.15,CrossAggregation:0.15,CrossDist:0.05,CrossOverlap:0.05,MCS:0.1"
185
- CUDA_VISIBLE_DEVICES=0 python -u ${geminimol_app}/GeminiMol_Training.py "${geminimol_data}/css_library/" "${epoch}" "${batch_size}" "${GNN}" "${network}" "${label_dict}" "${model_name}" "${patience}" "${geminimol_data}/benchmark.json"
186
- ```
187
-
188
- > Benchmarking molecular fingerprints and our models
189
-
190
- ``` shell
191
- conda activate GeminiMol
192
- # benchmarking Fixed GeminiMol models and Fingerprints
193
- for task in "DUDE" "LIT-PCBA" "TIBD" \
194
- "ADMET-C" "ADMET-R" \
195
- "LIT-QSAR" "CELLS-QSAR" "ST-QSAR" "PW-QSAR" \
196
- "PropDecoder-ADMET" "PropDecoder-QSAR"
197
- do
198
- for model_name in "CombineFP" \
199
- "FCFP6" "MACCS" "RDK" "ECFP6" "FCFP4" "TopologicalTorsion" "AtomPairs" "ECFP4" \
200
- "${geminimol_lib}/GeminiMol" "${geminimol_lib}/GeminiMol-MOD"
201
- do
202
- mkdir -p ${model_name}
203
- CUDA_VISIBLE_DEVICES=0 python -u ${geminimol_app}/benchmark.py "${model_name}" "${geminimol_data}/benchmark.json" "${task}"
204
- done
205
- done
206
- # benchmarking FineTuning GeminiMol models
207
- for task in "FineTuning-ADMET" "FineTuning-QSAR"; do
208
- for model_name in "${geminimol_lib}/GeminiMol" "${geminimol_lib}/GeminiMol-MOD"; do
209
- CUDA_VISIBLE_DEVICES=0 python -u ${geminimol_app}/benchmark.py "${model_name}" "${geminimol_data}/benchmark.json" "${task}"
210
- done
211
- done
212
- ```
213
-
214
- ## πŸ““ Application
215
-
216
- As a molecular representation model, GeminiMol finds applications in **ligand-based virtual screening, target identification, and quantitative structure-activity relationship (QSAR)** modeling of small molecular drugs.
217
-
218
- ![benchmark](imgs/benchmark.png)
219
-
220
- We have provided Cross-Encoder and GeminiMol models that can be used directly for inference. Here, we demonstrate the utilization of GeminiMol for virtual screening, target identification, and molecular property modeling.
221
-
222
- ### Virtual Screening
223
-
224
- In order to conduct virtual screening, it is essential to preassemble a collection of molecules that represent the pharmacological profile, including both active and non-active (optional) compounds, along with a library of compounds. These datasets should be saved in CSV format with specific column names.
225
-
226
- Note that the "**Label**" column is used to input the pharmacological profile. Ideally, you can input some **active** molecules and some **inactive** molecules that are similar to the active ones but lack activity. This will ensure that the selected molecules are as close as possible to the active molecules and simultaneously far from the inactive ones.
227
-
228
- Please note that the inactive molecules can refer to those lacking activity or those with **side effects** or **lower activity**.
229
-
230
- We have provided a processed version of the commercial Specs and ChemDiv compound library at the `${geminimol_data}/specs.csv` and `${geminimol_data}/ChemDiv.csv`, which contained 335,212 and 1,755,930 purchasable compounds. If you intend to utilize your own prepared compound library, please enable the "prepare" switch in the line 85 at the `Screener.py` script.
231
-
232
- ``` shell
233
- export job_name="Virtual_Screening"
234
- export decoy_set="decoys.csv" # SMILES, Title, and Label (optional)
235
- export compound_library="${geminimol_data}/ChemDiv.csv"
236
- export smiles_column="SMILES" # Specify the column name in the compound_library
237
- export id_column="Title" # Specify the column name in the compound_library
238
- export keep_top=1000
239
- CUDA_VISIBLE_DEVICES=0 python -u ${geminimol_app}/Screener.py "${geminimol_lib}/GeminiMol" "${job_name}" "${decoy_set}" "${compound_library}" "${keep_top}" "${smiles_column}" "${id_column}"
240
- ```
241
-
242
- The column denoting the SMILES representation of the compounds should be labeled as "**SMILES**", while the column indicating the activity label should be named "**Label**". Please assign the label "active" to the active molecules and "inactive" to the non-active molecules. Lastly, the column representing the molecule ID should be titled "**Title**".
243
-
244
- We restrict the use of column names to those specified in the designated compound library. This is primarily done to avoid confusion for novice users when modifying column names in large files. As for the decoy set, please ensure that the input CSV file contains at least two columns: SMILES and Title.
245
-
246
- ### Target Identification
247
-
248
- To conduct reverse virtual screening for target identification, it is essential to utilize a database that encompasses ligand-target relationships. This database should be structured with three columns: SMILES, Title, and **Targets**. The Targets column should specify the potential targets with which the drugs may interact.
249
-
250
- We have provided a processed version of the BindingDB database at the `${geminimol_data}/BindingDB_DATA.csv`, which contains 2,159,221 target-ligand paris.
251
-
252
- ``` shell
253
- export job_name="Target_Identification"
254
- export decoy_set="decoys.csv" # SMILES, Title, and Label (optional)
255
- export compound_library="${geminimol_data}/BindingDB_DATA.csv"
256
- export smiles_column="Ligand_SMILES" # Specify the column name in the compound_library
257
- export id_column="Monomer_ID" # Specify the column name in the compound_library
258
- export keep_top=100
259
- CUDA_VISIBLE_DEVICES=0 python -u ${geminimol_app}/Screener.py "${geminimol_lib}/GeminiMol" "${job_name}" "${decoy_set}" "${compound_library}" "${keep_top}" "${smiles_column}" "${id_column}"
260
- ```
261
-
262
- ### Molecular Proptery Modeling (QSAR and ADMET)
263
-
264
- > Prepare your datasets
265
-
266
- Before conducting molecular property modeling, it is crucial to carefully prepare your data, which includes compound structure pre-processing and dataset splitting.
267
-
268
- Firstly, you need to clarify the chirality and protonation states of molecules in the dataset, which can be done using chemical informatics tools such as RDKit or SchrΓΆdinger software package. The processed data should be saved in CSV file format, containing at least one column for **SMILES** and one column for **Labels**. Subsequently, utilize the following command for skeleton splitting. You can modify the script to change the splitting ratio, where by default, 70% of the dataset is used for training and 30% for validation and testing.
269
-
270
- ``` shell
271
- export dataset_path="data.csv"
272
- export dataset_name="My_QSAR"
273
- export smiles_column="SMILES" # Specify the column name in datasets
274
- export label_column="Label" # Specify the column name in datasets
275
- python -u ${geminimol_app}/utils/dataset_split.py "${dataset_path}" "${dataset_name}" "${smiles_column}" "${label_column}"
276
- mkdir ${dataset_name}
277
- mv ${dataset_name}_scaffold_*.csv ${dataset_name}/
278
- export task=${dataset_name}
279
- ```
280
-
281
- We have presented three approaches for molecular property modeling, namely AutoQSAR (broad applicability, slow speed), PropDecoder (fast speed), and FineTuning (optimal performance, moderate speed).
282
-
283
- In the majority of instances, the attainment of optimal performance can be accomplished through the utilization of the FineTuning script to invoke GeminiMol.
284
-
285
- > Fine-Tuning on downstream task
286
-
287
- ``` shell
288
- export task="Your_Dataset" # Specify a path to your datasets (train, valid, and test)
289
- export smiles_column="SMILES" # Specify the column name in datasets
290
- export label_column="Label" # Specify the column name in datasets
291
- CUDA_VISIBLE_DEVICES=${gpu_id} python -u ${geminimol_app}/FineTuning.py "${task}" "${geminimol_lib}/GeminiMol" "${smiles_column}" "${label_column}" "${task}_GeminiMol"
292
- ```
293
-
294
- If the integration of molecular fingerprints and a pre-trained GeminiMol model is desired for training a molecular property prediction model, either PropDecoder or AutoQSAR can be employed.
295
-
296
- > PropDecoder
297
-
298
- ``` shell
299
- export task="Your_Dataset" # Specify a path to your datasets (train, valid, and test)
300
- export fingerprints="ECFP4:AtomPairs:TopologicalTorsion:FCFP6:MACCS"
301
- export smiles_column="SMILES" # Specify the column name in datasets
302
- export label_column="Label" # Specify the column name in datasets
303
- CUDA_VISIBLE_DEVICES=${gpu_id} python -u ${geminimol_app}/PropDecoder.py "${task}" "${geminimol_lib}/GeminiMol:${fingerprints}" "${smiles_column}" "${label_column}" "${task}_GeminiMol"
304
- ```
305
-
306
- > AutoQSAR (AutoGluon)
307
-
308
- ``` shell
309
- export task="Your_Dataset" # Specify a path to your datasets (train, valid, and test)
310
- export fingerprints="ECFP4:AtomPairs:TopologicalTorsion:FCFP6:MACCS"
311
- export smiles_column="SMILES" # Specify the column name in datasets
312
- export label_column="Label" # Specify the column name in datasets
313
- CUDA_VISIBLE_DEVICES=${gpu_id} python -u ${geminimol_app}/AutoQSAR.py "${task}" "${geminimol_lib}/GeminiMol:${fingerprints}" "${smiles_column}" "${label_column}" "" "${task}_GeminiMol"
314
- ```
315
-
316
- ## ⭐ Citing this work
317
-
318
- **Conformational Space Profile Enhances Generic Molecular Representation Learning**
319
- Lin Wang, Shihang Wang, Hao Yang, Shiwei Li, Xinyu Wang, Yongqi Zhou, Siyuan Tian, Lu Liu, Fang Bai
320
- bioRxiv 2023.12.14.571629; doi: https://doi.org/10.1101/2023.12.14.571629
321
-
322
- ## βœ… License
323
-
324
- GeminiMol is released under the Academic Free Licence, which permits academic use, modification and distribution free of charge, but prohibits unauthorised commercial use, including commercial training and as part of a paid computational platform. However, communication and authorization with [our supervisor](baifang@shanghaitech.edu.cn) is permitted for its application in pipeline development and research activities within pharmaceutical R&D.
325
-
326
- ## πŸ’Œ Get in Touch
327
-
328
- We welcome community contributions of extension tools based on the GeminiMol model, etc. If you have any questions not covered in this overview, please contact the [GeminiMol Developer Team](wanglin3@shanghaitech.edu.cn). We would love to hear your feedback and understand how GeminiMol has been useful in your research. Share your stories with us at wanglin3@shanghaitech.edu.cn or baifang@shanghaitech.edu.cn.
329
-
330
- In addition to GitHub, we offer a WeChat community to provide a forum for discussion between users. You can access the community's QR code by following the "θ›‹η™½ηŸΏε·₯" on WeChat.
331
-
332
- ## πŸ˜ƒ Acknowledgements
333
-
334
- We appreciate the technical support provided by the engineers of the high-performance computing cluster of ShanghaiTech University. Lin Wang also thanks Jianxin Duan, Gaokeng Xiao, Quanwei Yu, Zheyuan Shen, Shenghao Dong, Huiqiong Li, Zongquan Li, and Fenglei Li for providing technical support, inspiration and help for this work.
335
-
336
- We appreciate the developers of AutoGluon and Deep Graph Library (DGL). We also thank the developers and maintainers of MarcoModel and PhaseShape modules in the SchrΓΆdinger package.
337
-
338
- Besides, GeminiMol communicates with and/or references the following separate libraries and packages, we thank all their contributors and maintainers!
339
-
340
- * [_RDKit_](https://www.rdkit.org/)
341
- * [_PyTorch_](https://pytorch.org/)
342
- * [_AutoGluon_](https://auto.gluon.ai/stable/index.html)
343
- * [_DGL-Life_](https://lifesci.dgl.ai/)
344
- * [_ODDT_](https://oddt.readthedocs.io/en/latest/)
345
- * [_SciPy_](https://scipy.org/)
346
- * [_scikit-learn_](https://scikit-learn.org/stable/)
347
- * [_matplotlib_](https://matplotlib.org/)
348
-
349
-
350
 
 
4
 
5
  Refer to [GitHub](https://github.com/Wang-Lin-boop/GeminiMol).
6
 
7
+ This model is deprecated and information about it can be found in our preprint paper: https://www.biorxiv.org/content/10.1101/2023.12.14.571629
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8