Data mining Pubmed и Pubchem — баз медицинской и биохимической информации

habr.png

PubMed представляет собой более чем 28 миллионов цитированний (абстрактов и названий) биомедицинской литературы из журналов наук о жизни, онлайн книг и MEDLINE. Также цитирование может включать в себя полный текст статей. Типичный запрос в Пабмед — type 2 diabetes natural compound

Pubchem — база данных более 100 млн химический соединений и 236 млн веществ. Также в базе результаты биоактивности 1.25 млн соединений (например активность соединений против рака или ингибирования конкретного гена). На данный момент известно о 9 млн органических химических соединений (сложных веществ). Неорганических химических веществ может быть огромное количество — от 10**18

В этой статье я приведу примеры составления списка генов ответственных за плохой прогноз по выживаемости от рака и код поиска органических соединений и их номеров среди всех химических молекул базы ПабЧем. Никакого машинного обучения в этой статье не будет (машинное обучение понадобится в следующих статья по биомаркерам диабета, определения возраста человека по рнк-экспресии, скрининга противораковых веществ).
Для того, чтобы продолжить, установим необходимые python пакеты Biopython и pubchempy.

sudo conda install biopython 
pip install pubchempy


PubMed


Майнить мы будем гены на их овер-экспрессию и недо-экспрессию в сочетании с плохим прогнозом рака — вот так выглядит типичный титл, запрос в пабмед и целевой ген:

('High expression of DEK predicts poor prognosis of gastric adenocarcinoma.', 'DEK poor prognosis', 'DEK', 277, 15)

Для чего это нужно — по генам можно подсчитать фармакологическое действие молекул и их комбинаций на цели, которые связаны с плохим прогнозом рака. (Например по базе pubchem или LINCS).

Подгружаем файлы с именами генов (около 12000): Github

import csv
genes=[];

with open('/Users/andrejeremcuk/Downloads/genes.txt', 'r') as fp :
    reader = csv.reader(fp, delimiter='\t')
    for i in range(20000): 
     genes.append(reader.next())

import time
import numpy as np
genesq=np.genfromtxt('/Users/andrejeremcuk/Downloads/genesq.txt',dtype='str')


Для запроса в пабмед обязательно указать свою электронную почту:

from Bio import Entrez
from Bio import Medline

MAX_COUNT = 100
Entrez.email = '*@yandex.ru'
articles=[];genes_cancer_poor=[];genes_cancer_poor1=[];


Запросы и обработка результатов:

for u in range(0,len(genesq)):
 print u
 if u%100==0: 
  np.savetxt('/Users/andrejeremcuk/Downloads/genes_cancer_poor.txt', genes_cancer_poor,fmt='%s');
  np.savetxt('/Users/andrejeremcuk/Downloads/genes_cancer_poor1.txt', genes_cancer_poor1, fmt='%s')
 gene=genesq[u];genefullname=genes[u][2]
 TERM=gene+' '+'poor prognosis'
 try: h=Entrez.esearch(db='pubmed', retmax=MAX_COUNT, term=TERM)
 except: time.sleep(5);h=Entrez.esearch(db='pubmed', retmax=MAX_COUNT, term=TERM)
 result = Entrez.read(h)
 ids = result['IdList']
 h = Entrez.efetch(db='pubmed', id=ids, rettype='medline', retmode='text')
 ret = Medline.parse(h)
 fer=[];
 for re in ret:
  try: tr=re['TI'];
  except: tr='0';
  fer.append(tr);


Нахождение в тексте титла ключевых слов:

 for i in range(len(fer)):
  gene1=fer[i].find(gene)
  gene2=fer[i].find(genefullname)
  #####
  inc=fer[i].find("Increased")
  highe=fer[i].find("High expression")
  high=fer[i].find("High")
  expr=fer[i].find("expression")
  Overe=fer[i].find("Overexpression")
  overe=fer[i].find("overexpression")
  up1=fer[i].find("Up-regulation")
  el1=fer[i].find("Elevated expression")
  expr1=fer[i].find("Expression of ")
  ####
  decr=fer[i].find("Decreased")
  loss=fer[i].find("Loss")
  low1=fer[i].find("Low expression")
  low2=fer[i].find("Low levels")
  down1=fer[i].find("Down-regulated")
  down2=fer[i].find("Down-regulated")
  down3=fer[i].find("Downregulation")
  #####
  acc=fer[i].find("accelerates")
  poor=fer[i].find("poor patient prognosis")
  poor1=fer[i].find("poor prognosis")
  poor2=fer[i].find("unfavorable clinical outcomes")
  poor3=fer[i].find("unfavorable prognosis")
  poor4=fer[i].find("poor outcome")
  poor5=fer[i].find("poor survival")
  poor6=fer[i].find("poor patient survival")
  poor7=fer[i].find("progression and prognosis")
  ###
  canc=fer[i].find("cancer")
  canc1=fer[i].find("carcinoma")


которые мы проверяем на порядок в титле и на присутствие по наиболее распространенным фразам.

  if (gene1!=-1)or(gene2!=-1): #


В результате получаем несколько списков: генов с низкой и с высокой экспрессией при плохом прогнозе рака.

Всего нашлось 913 статей с вхождение как ключевых слов так и целевых фраз.

PubChem


Эта база данных предоставляет два способа доступа к своей информации: через REST API в формате json где запрос выглядит так:

https://pubchem.ncbi.nlm.nih.gov/rest/pug/compound/cid/2516/description/json

Важно запросов через этот путь не может быть больше 5 в секунду, но пока превышение лимитов я не проверял, должны спасти прокси.

И через библиотеку pubchempy:

import pubchempy as pcp
c = pcp.Compound.from_cid(5090)
c.canonical_smiles


Импорт необходимых пакетов PUG REST API:

import re
import urllib, json, time
import numpy as np


Функция которая очищает текст от хтмл-тэгов:

def cleanhtml(raw_html):
  cleanr = re.compile('<.*?>')
  cleantext = re.sub(cleanr, '', raw_html)
  return cleantext


В следующем коде мы будем открывать англоязычные описание молекул от 1 до 100000 номера в pubchem и искать намеки, что эта молекула имеет органическую природу (от растения животного или в составе напитка), при этом оно не токсично и не канцерогенно.


natural=[];
for i in range(1,100000):
 url = "https://pubchem.ncbi.nlm.nih.gov/rest/pug/compound/cid/"+str(i)+"/description/json"
 time.sleep(0.2)
 try: response = urllib.urlopen(url)
 except: time.sleep(12);response = urllib.urlopen(url)
 data = json.loads(response.read())
 op=0;ol=0;ot=0;
 try:
  for u in range(1,len(data['InformationList']['Information'])):
   soup=str(data['InformationList']['Information'][u]['Description'])
   soup1=cleanhtml(soup) 
   if (soup1.find('carcinogen')!=-1)or(soup1.find('death')!=-1)or(soup1.find('damage')!=-1): break;
   if (soup1.find('toxic')!=-1): break;
   if (soup1.find(' plant')!=-1)and(op!=9)and(soup1.find('planting')==-1): 
    natural.append((i,'plant',str(data['InformationList']['Information'][0]['Title'])));op=9;
   if (soup1.find(' beverages')!=-1)and(ot!=9): 
    natural.append((i,'beverages',str(data['InformationList']['Information'][0]['Title'])));ot=9;
   if (soup1.find(' animal')!=-1)and(ol!=9): 
    natural.append((i,'animal',str(data['InformationList']['Information'][0]['Title'])));ol=9;
 except: ii=0;
 if i%100==0: print i;np.savetxt('/Users/andrejeremcuk/Downloads/natural.txt', natural,fmt='%s', delimiter='<')


Для поиска упоминаний в тексте растения используем .find (' plant'). В конце сохраняем файл с получившимися органическими соединениями и их номерами в ПабЧем-е.

→ Github

© Habrahabr.ru