first add
This commit is contained in:
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
test/
|
||||||
1
assets/ring16.smi
Executable file
1
assets/ring16.smi
Executable file
@@ -0,0 +1 @@
|
|||||||
|
CC[C@H]1OC(=O)[*][*sugar*][C@H](C)[*sugar*][*]C[*]C(=O)[*][C@@H](O)[*]1
|
||||||
40
docker/Dockerfile
Executable file
40
docker/Dockerfile
Executable file
@@ -0,0 +1,40 @@
|
|||||||
|
FROM mambaorg/micromamba:cuda12.4.1-ubuntu22.04
|
||||||
|
ARG ROOT_PASSWD="micromamba"
|
||||||
|
ENV ROOT_PASSWD=${ROOT_PASSWD}
|
||||||
|
|
||||||
|
USER root
|
||||||
|
RUN <<EOT
|
||||||
|
#!/bin/bash
|
||||||
|
apt update
|
||||||
|
apt install vim git sudo bash-completion wget curl htop jq bzip2 npm unzip libz-dev libgomp1 libblas-dev liblapack-dev libzmq3-dev -y
|
||||||
|
echo "mambauser ALL=(ALL) NOPASSWD: ALL" | sudo tee -a /etc/sudoers > /dev/null
|
||||||
|
echo "mambauser:${ROOT_PASSWD}" | chpasswd
|
||||||
|
EOT
|
||||||
|
|
||||||
|
USER mambauser
|
||||||
|
ENV LILLYMOL_HOME=/home/mambauser/LillyMol \
|
||||||
|
BUILD_DIR=Linux \
|
||||||
|
BUILD_BDB=1 \
|
||||||
|
BUILD_PYTHON=1
|
||||||
|
RUN <<EOT
|
||||||
|
#!/bin/bash
|
||||||
|
echo "alias conda=micromamba" >> /home/mambauser/.bashrc
|
||||||
|
echo "alias mamba=micromamba" >> /home/mambauser/.bashrc
|
||||||
|
micromamba create -n lillymol python=3.10 pybind11 absl-py protobuf pandas scipy -y
|
||||||
|
echo "mamba activate lillymol" >> /home/mambauser/.bashrc
|
||||||
|
git clone https://github.com/IanAWatson/LillyMol /home/mambauser/LillyMol
|
||||||
|
EOT
|
||||||
|
|
||||||
|
WORKDIR /home/mambauser/LillyMol
|
||||||
|
RUN <<EOT
|
||||||
|
#!/bin/bash
|
||||||
|
npm install -g @bazel/bazelisk
|
||||||
|
cd src
|
||||||
|
bash ./build_third_party.sh
|
||||||
|
python update_python_in_workspace.py /home/mambauser/LillyMol/src/WORKSPACE
|
||||||
|
bazelisk -h
|
||||||
|
make all
|
||||||
|
EOT
|
||||||
|
|
||||||
|
# /home/mambauser/LillyMol/src/Molecule_Lib/linear_fingerprint_test.cc
|
||||||
|
# line 373 EXPECT_EQ(_sfc.nbits(), 5l);
|
||||||
14
docker/docker-compose.yml
Executable file
14
docker/docker-compose.yml
Executable file
@@ -0,0 +1,14 @@
|
|||||||
|
version: '3'
|
||||||
|
services:
|
||||||
|
app:
|
||||||
|
build:
|
||||||
|
context: .
|
||||||
|
dockerfile: Dockerfile
|
||||||
|
args:
|
||||||
|
CUDA_VERSION: 12.4
|
||||||
|
image: hotwa/lillymol:20250213
|
||||||
|
container_name: lilly_mol
|
||||||
|
volumes:
|
||||||
|
- ../test:/LillyMol/test
|
||||||
|
command: >
|
||||||
|
bash -c "tail -f /dev/null"
|
||||||
1136
utils/main.ipynb
Executable file
1136
utils/main.ipynb
Executable file
File diff suppressed because one or more lines are too long
83
utils/ring_analysis.py
Executable file
83
utils/ring_analysis.py
Executable file
@@ -0,0 +1,83 @@
|
|||||||
|
from rdkit import Chem
|
||||||
|
from joblib import Parallel, delayed
|
||||||
|
import logging
|
||||||
|
from collections import Counter
|
||||||
|
|
||||||
|
# 定义日志配置
|
||||||
|
logging.basicConfig(
|
||||||
|
filename="rgroup_matching.log",
|
||||||
|
level=logging.INFO,
|
||||||
|
format="%(asctime)s - %(levelname)s - %(message)s",
|
||||||
|
)
|
||||||
|
|
||||||
|
# 定义 SMARTS 模式
|
||||||
|
macro = Chem.MolFromSmarts("[r12,r13,r14,r15,r16,r17,r18,r19,r20]([#8][#6](=[#8]))")
|
||||||
|
|
||||||
|
# 读取 SMI 文件
|
||||||
|
smi_file = "/home/mambauser/LillyMol/test/1M_stratsampled_V1B.smi"
|
||||||
|
with open(smi_file, 'r') as f:
|
||||||
|
SMILES_list = [line.strip() for line in f if line.strip()]
|
||||||
|
|
||||||
|
logging.info(f"Loaded {len(SMILES_list)} molecules from {smi_file}.")
|
||||||
|
|
||||||
|
# 匹配和最大环统计函数
|
||||||
|
def match_and_ring_analysis(smiles):
|
||||||
|
mol = Chem.MolFromSmiles(smiles)
|
||||||
|
if mol is None:
|
||||||
|
return smiles, None, 0 # 无效分子
|
||||||
|
|
||||||
|
result = mol.GetSubstructMatches(macro)
|
||||||
|
ri = mol.GetRingInfo()
|
||||||
|
largest_ring_size = max((len(r) for r in ri.AtomRings()), default=0)
|
||||||
|
|
||||||
|
return smiles, result, largest_ring_size
|
||||||
|
|
||||||
|
# 使用 joblib 并行处理
|
||||||
|
logging.info("Starting SMARTS matching and ring analysis...")
|
||||||
|
results = Parallel(n_jobs=-1)(delayed(match_and_ring_analysis)(s) for s in SMILES_list)
|
||||||
|
|
||||||
|
# 分离成功、失败的分子以及最大环大小
|
||||||
|
success = [smiles for smiles, result, _ in results if result]
|
||||||
|
fail = [smiles for smiles, result, _ in results if not result]
|
||||||
|
ring_sizes = [largest_ring_size for _, _, largest_ring_size in results]
|
||||||
|
|
||||||
|
# 统计最大环频数
|
||||||
|
ring_size_counter = Counter(ring_sizes)
|
||||||
|
|
||||||
|
# 统计结果
|
||||||
|
total = len(success) + len(fail)
|
||||||
|
success_rate = len(success) / total * 100 if total > 0 else 0
|
||||||
|
|
||||||
|
# 保存日志信息
|
||||||
|
logging.info(f"Total molecules: {total}")
|
||||||
|
logging.info(f"Success: {len(success)}")
|
||||||
|
logging.info(f"Fail: {len(fail)}")
|
||||||
|
logging.info(f"Success rate: {success_rate:.2f}%")
|
||||||
|
logging.info(f"Ring size distribution: {dict(ring_size_counter)}")
|
||||||
|
|
||||||
|
print(f"Total molecules: {total}")
|
||||||
|
print(f"Success: {len(success)}")
|
||||||
|
print(f"Fail: {len(fail)}")
|
||||||
|
print(f"Success rate: {success_rate:.2f}%")
|
||||||
|
print("Ring size distribution:")
|
||||||
|
for size, count in sorted(ring_size_counter.items()):
|
||||||
|
print(f" Ring size {size}: {count}")
|
||||||
|
|
||||||
|
# 将失败的分子写入到一个 SMI 文件
|
||||||
|
fail_smi_file = "fail_molecules.smi"
|
||||||
|
with open(fail_smi_file, "w") as ff:
|
||||||
|
for smiles in fail:
|
||||||
|
ff.write(smiles + "\n")
|
||||||
|
|
||||||
|
logging.info(f"Failed molecules written to {fail_smi_file}.")
|
||||||
|
print(f"Failed molecules written to {fail_smi_file}.")
|
||||||
|
|
||||||
|
# 将环大小分布写入文件
|
||||||
|
ring_size_file = "ring_size_distribution.txt"
|
||||||
|
with open(ring_size_file, "w") as rf:
|
||||||
|
rf.write("Ring Size\tCount\n")
|
||||||
|
for size, count in sorted(ring_size_counter.items()):
|
||||||
|
rf.write(f"{size}\t{count}\n")
|
||||||
|
|
||||||
|
logging.info(f"Ring size distribution written to {ring_size_file}.")
|
||||||
|
print(f"Ring size distribution written to {ring_size_file}.")
|
||||||
182
utils/search.ipynb
Normal file
182
utils/search.ipynb
Normal file
@@ -0,0 +1,182 @@
|
|||||||
|
{
|
||||||
|
"cells": [
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"id": "34ca5db2",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"name": "stderr",
|
||||||
|
"output_type": "stream",
|
||||||
|
"text": [
|
||||||
|
"/root/micromamba/envs/qsar/lib/python3.11/site-packages/tqdm/auto.py:21: TqdmWarning: IProgress not found. Please update jupyter and ipywidgets. See https://ipywidgets.readthedocs.io/en/stable/user_install.html\n",
|
||||||
|
" from .autonotebook import tqdm as notebook_tqdm\n"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "stdout",
|
||||||
|
"output_type": "stream",
|
||||||
|
"text": [
|
||||||
|
"ChEMBL 数据库存储路径: /srv/project/LillyMol/test/data/35/data/chembl_35/chembl_35_sqlite/chembl_35.db\n"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"source": [
|
||||||
|
"import chembl_downloader\n",
|
||||||
|
"# 指定存储目录\n",
|
||||||
|
"prefix = '/srv/project/LillyMol/test/data'\n",
|
||||||
|
"version = chembl_downloader.latest() # version 35\n",
|
||||||
|
"\n",
|
||||||
|
"# 下载并提取 ChEMBL 数据库,存放到指定目录\n",
|
||||||
|
"path = chembl_downloader.download_extract_sqlite(version=version, prefix=[prefix])\n",
|
||||||
|
"# chembl_downloader.download_sqlite(version)\n",
|
||||||
|
"\n",
|
||||||
|
"print(f\"ChEMBL 数据库存储路径: {path}\")"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 2,
|
||||||
|
"id": "dd6f3b25",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"name": "stdout",
|
||||||
|
"output_type": "stream",
|
||||||
|
"text": [
|
||||||
|
"(0, 'molregno', 'BIGINT', 1, None, 0)\n",
|
||||||
|
"(1, 'syn_type', 'VARCHAR(50)', 1, None, 0)\n",
|
||||||
|
"(2, 'molsyn_id', 'BIGINT', 1, None, 1)\n",
|
||||||
|
"(3, 'res_stem_id', 'BIGINT', 0, None, 0)\n",
|
||||||
|
"(4, 'synonyms', 'VARCHAR(250)', 0, None, 0)\n"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"source": [
|
||||||
|
"import chembl_downloader\n",
|
||||||
|
"\n",
|
||||||
|
"with chembl_downloader.connect(version='35', prefix=['/srv/project/LillyMol/test/data']) as conn:\n",
|
||||||
|
" cursor = conn.cursor()\n",
|
||||||
|
" cursor.execute(\"PRAGMA table_info(molecule_synonyms);\")\n",
|
||||||
|
" columns = cursor.fetchall()\n",
|
||||||
|
" for col in columns:\n",
|
||||||
|
" print(col)\n"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 4,
|
||||||
|
"id": "c8390d91",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"data": {
|
||||||
|
"text/html": [
|
||||||
|
"<div>\n",
|
||||||
|
"<style scoped>\n",
|
||||||
|
" .dataframe tbody tr th:only-of-type {\n",
|
||||||
|
" vertical-align: middle;\n",
|
||||||
|
" }\n",
|
||||||
|
"\n",
|
||||||
|
" .dataframe tbody tr th {\n",
|
||||||
|
" vertical-align: top;\n",
|
||||||
|
" }\n",
|
||||||
|
"\n",
|
||||||
|
" .dataframe thead th {\n",
|
||||||
|
" text-align: right;\n",
|
||||||
|
" }\n",
|
||||||
|
"</style>\n",
|
||||||
|
"<table border=\"1\" class=\"dataframe\">\n",
|
||||||
|
" <thead>\n",
|
||||||
|
" <tr style=\"text-align: right;\">\n",
|
||||||
|
" <th></th>\n",
|
||||||
|
" <th>molregno</th>\n",
|
||||||
|
" <th>syn_type</th>\n",
|
||||||
|
" <th>molsyn_id</th>\n",
|
||||||
|
" <th>res_stem_id</th>\n",
|
||||||
|
" <th>synonyms</th>\n",
|
||||||
|
" </tr>\n",
|
||||||
|
" </thead>\n",
|
||||||
|
" <tbody>\n",
|
||||||
|
" <tr>\n",
|
||||||
|
" <th>0</th>\n",
|
||||||
|
" <td>27340</td>\n",
|
||||||
|
" <td>TRADE_NAME</td>\n",
|
||||||
|
" <td>3001861</td>\n",
|
||||||
|
" <td>None</td>\n",
|
||||||
|
" <td>Brolene antibiotic</td>\n",
|
||||||
|
" </tr>\n",
|
||||||
|
" <tr>\n",
|
||||||
|
" <th>1</th>\n",
|
||||||
|
" <td>27340</td>\n",
|
||||||
|
" <td>TRADE_NAME</td>\n",
|
||||||
|
" <td>3001879</td>\n",
|
||||||
|
" <td>None</td>\n",
|
||||||
|
" <td>Golden eye antibiotic</td>\n",
|
||||||
|
" </tr>\n",
|
||||||
|
" </tbody>\n",
|
||||||
|
"</table>\n",
|
||||||
|
"</div>"
|
||||||
|
],
|
||||||
|
"text/plain": [
|
||||||
|
" molregno syn_type molsyn_id res_stem_id synonyms\n",
|
||||||
|
"0 27340 TRADE_NAME 3001861 None Brolene antibiotic\n",
|
||||||
|
"1 27340 TRADE_NAME 3001879 None Golden eye antibiotic"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"execution_count": 4,
|
||||||
|
"metadata": {},
|
||||||
|
"output_type": "execute_result"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"source": [
|
||||||
|
"import chembl_downloader\n",
|
||||||
|
"\n",
|
||||||
|
"sql = \"\"\"\n",
|
||||||
|
"SELECT *\n",
|
||||||
|
"FROM molecule_synonyms\n",
|
||||||
|
"WHERE syn_type='TRADE_NAME' AND synonyms LIKE '%antibiotic%'\n",
|
||||||
|
"\"\"\"\n",
|
||||||
|
"\n",
|
||||||
|
"\n",
|
||||||
|
"# version 一般也建议加上,保证和你本地一致\n",
|
||||||
|
"df = chembl_downloader.query(\n",
|
||||||
|
" sql,\n",
|
||||||
|
" version='35', # 或者 version=version\n",
|
||||||
|
" prefix=['/srv/project/LillyMol/test/data']\n",
|
||||||
|
")\n",
|
||||||
|
"df\n"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"id": "d0c56718",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"metadata": {
|
||||||
|
"kernelspec": {
|
||||||
|
"display_name": "qsar",
|
||||||
|
"language": "python",
|
||||||
|
"name": "python3"
|
||||||
|
},
|
||||||
|
"language_info": {
|
||||||
|
"codemirror_mode": {
|
||||||
|
"name": "ipython",
|
||||||
|
"version": 3
|
||||||
|
},
|
||||||
|
"file_extension": ".py",
|
||||||
|
"mimetype": "text/x-python",
|
||||||
|
"name": "python",
|
||||||
|
"nbconvert_exporter": "python",
|
||||||
|
"pygments_lexer": "ipython3",
|
||||||
|
"version": "3.11.11"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nbformat": 4,
|
||||||
|
"nbformat_minor": 5
|
||||||
|
}
|
||||||
17
utils/search.py
Normal file
17
utils/search.py
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
import sqlite3
|
||||||
|
|
||||||
|
# 连接到数据库
|
||||||
|
conn = sqlite3.connect('../test/data/35/data/chembl_35/chembl_35_sqlite/chembl_35.db')
|
||||||
|
|
||||||
|
# 查询抗生素相关分子 (修正版)
|
||||||
|
query = """
|
||||||
|
SELECT m.chembl_id, m.pref_name, cs.molecule_synonym
|
||||||
|
FROM molecule_synonyms cs
|
||||||
|
JOIN molecule_dictionary m ON cs.molregno = m.molregno
|
||||||
|
WHERE cs.molecule_synonym LIKE '%antibiotic%'
|
||||||
|
LIMIT 10
|
||||||
|
"""
|
||||||
|
|
||||||
|
cursor = conn.execute(query)
|
||||||
|
for row in cursor.fetchall():
|
||||||
|
print(row)
|
||||||
60
utils/test_smart.py
Executable file
60
utils/test_smart.py
Executable file
@@ -0,0 +1,60 @@
|
|||||||
|
from rdkit import Chem
|
||||||
|
from joblib import Parallel, delayed
|
||||||
|
import logging
|
||||||
|
|
||||||
|
# 定义日志配置
|
||||||
|
logging.basicConfig(
|
||||||
|
filename="rgroup_matching.log",
|
||||||
|
level=logging.INFO,
|
||||||
|
format="%(asctime)s - %(levelname)s - %(message)s",
|
||||||
|
)
|
||||||
|
|
||||||
|
# 定义 SMARTS 模式
|
||||||
|
macro = Chem.MolFromSmarts("[r12,r13,r14,r15,r16,r17,r18,r19,r20]([#8][#6](=[#8]))")
|
||||||
|
|
||||||
|
# 读取 SMI 文件
|
||||||
|
smi_file = "/home/mambauser/LillyMol/test/1M_stratsampled_V1B.smi"
|
||||||
|
with open(smi_file, 'r') as f:
|
||||||
|
SMILES_list = [line.strip() for line in f if line.strip()]
|
||||||
|
|
||||||
|
logging.info(f"Loaded {len(SMILES_list)} molecules from {smi_file}.")
|
||||||
|
|
||||||
|
# 匹配函数
|
||||||
|
def match_smarts(smiles):
|
||||||
|
mol = Chem.MolFromSmiles(smiles)
|
||||||
|
if mol is None:
|
||||||
|
return smiles, None # 无效分子
|
||||||
|
result = mol.GetSubstructMatches(macro)
|
||||||
|
return smiles, result
|
||||||
|
|
||||||
|
# 使用 joblib 并行处理
|
||||||
|
logging.info("Starting SMARTS matching...")
|
||||||
|
results = Parallel(n_jobs=-1)(delayed(match_smarts)(s) for s in SMILES_list)
|
||||||
|
|
||||||
|
# 分离成功和失败的分子
|
||||||
|
success = [smiles for smiles, result in results if result]
|
||||||
|
fail = [smiles for smiles, result in results if not result]
|
||||||
|
|
||||||
|
# 统计结果
|
||||||
|
total = len(success) + len(fail)
|
||||||
|
success_rate = len(success) / total * 100 if total > 0 else 0
|
||||||
|
|
||||||
|
# 保存日志信息
|
||||||
|
logging.info(f"Total molecules: {total}")
|
||||||
|
logging.info(f"Success: {len(success)}")
|
||||||
|
logging.info(f"Fail: {len(fail)}")
|
||||||
|
logging.info(f"Success rate: {success_rate:.2f}%")
|
||||||
|
|
||||||
|
print(f"Total molecules: {total}")
|
||||||
|
print(f"Success: {len(success)}")
|
||||||
|
print(f"Fail: {len(fail)}")
|
||||||
|
print(f"Success rate: {success_rate:.2f}%")
|
||||||
|
|
||||||
|
# 将失败的分子写入到一个 SMI 文件
|
||||||
|
fail_smi_file = "fail_molecules.smi"
|
||||||
|
with open(fail_smi_file, "w") as ff:
|
||||||
|
for smiles in fail:
|
||||||
|
ff.write(smiles + "\n")
|
||||||
|
|
||||||
|
logging.info(f"Failed molecules written to {fail_smi_file}.")
|
||||||
|
print(f"Failed molecules written to {fail_smi_file}.")
|
||||||
Reference in New Issue
Block a user