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

    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): #<poor1,poor,poor2,poor3,poor4,poor5,poor6,poor7
       if (canc1!=-1)or(canc!=-1):
        if (poor!=-1)or(poor1!=-1)or(poor2!=-1)or(poor3!=-1)or(poor4!=-1)or(poor5!=-1)or(poor6!=-1)or(poor7!=-1): #
         genel=-1;
         if (gene1!=-1): genel=gene1;
         if (gene2!=-1): genel=gene2;
         gene1=genel;
         if (expr!=-1): #<poor1,poor,poor2,poor3,poor4,poor5,poor6,poor7
          if (gene1<expr): 
           articles.append((fer[i],TERM,gene,u,i));genes_cancer_poor.append((gene,u,i,1))
         if (low1!=-1)and(gene1!=-1):
          if (low1<gene1): 
           articles.append((fer[i],TERM,gene,u,i));genes_cancer_poor.append((gene,u,i,2))
         if (el1!=-1)and(gene1!=-1):
          if (el1<gene1): 
           articles.append((fer[i],TERM,gene,u,i));genes_cancer_poor.append((gene,u,i,3))
         if (Overe!=-1)and(gene1!=-1):
          if (Overe<gene1): 
           articles.append((fer[i],TERM,gene,u,i));genes_cancer_poor.append((gene,u,i,4))
         if (overe!=-1)and(gene1!=-1):
          articles.append((fer[i],TERM,gene,u,i));genes_cancer_poor.append((gene,u,i,5))
         if (expr1!=-1)and(gene1!=-1):
          if (expr1<gene1): 
           articles.append((fer[i],TERM,gene,u,i));genes_cancer_poor.append((gene,u,i,6))
         if (up1!=-1)and(gene1!=-1):
          if (up1<gene1): 
           articles.append((fer[i],TERM,gene,u,i));genes_cancer_poor.append((gene,u,i,7))
         if (highe!=-1)and(gene1!=-1):
          if (highe<gene1): 
           articles.append((fer[i],TERM,gene,u,i));genes_cancer_poor.append((gene,u,i,8))
         if (high!=-1)and(gene1!=-1)and(expr!=-1):
          if (high<gene1<expr): 
           articles.append((fer[i],TERM,gene,u,i));genes_cancer_poor.append((gene,u,i,9))
         if (gene1!=-1)and(expr1!=-1):
          if (expr1<gene1): 
           articles.append((fer[i],TERM,gene,u,i));genes_cancer_poor.append((gene,u,i,10))
         if (gene1!=-1)and(inc!=-1):
          if (inc<gene1): 
           articles.append((fer[i],TERM,gene,u,i));genes_cancer_poor.append((gene,u,i,11))
         ###########
         if (gene1!=-1)and(decr!=-1):
          if (decr<gene1): 
           articles.append((fer[i],TERM,gene,u,i,'low'));genes_cancer_poor1.append((gene,u,i,12))
         if (gene1!=-1)and(loss!=-1):
          if (loss<gene1): 
           articles.append((fer[i],TERM,gene,u,i,'low'));genes_cancer_poor1.append((gene,u,i,13))
         if (gene1!=-1)and(low1!=-1):
          if (low1<gene1): 
           articles.append((fer[i],TERM,gene,u,i,'low'));genes_cancer_poor1.append((gene,u,i,14))
         if (gene1!=-1)and(low2!=-1):
          if (low2<gene1): 
           articles.append((fer[i],TERM,gene,u,i,'low'));genes_cancer_poor1.append((gene,u,i,15))
         if (gene1!=-1)and(down1!=-1):
          if (down1<gene1): 
           articles.append((fer[i],TERM,gene,u,i,'low'));genes_cancer_poor1.append((gene,u,i,16))
         if (gene1!=-1)and(down2!=-1):
          if (down2<gene1): 
           articles.append((fer[i],TERM,gene,u,i,'low'));genes_cancer_poor1.append((gene,u,i,17))
         if (gene1!=-1)and(down3!=-1):
          if (down3<gene1): 
           articles.append((fer[i],TERM,gene,u,i,'low'));genes_cancer_poor1.append((gene,u,i,18))
     

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

    Всего нашлось 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
    Поддержать автора
    Поделиться публикацией
    AdBlock похитил этот баннер, но баннеры не зубы — отрастут

    Подробнее
    Реклама

    Комментарии 7

      +1
      Неорганических химических веществ может быть огромное количество — от 10**18

      Это не совсем так. Дело в том, что неорганические соединения с количеством химических элементов более 3 (кватернарные, квинтернарные и т.д.) склонны к вырождению, т.е. их свойства в основном определяются 2-3 элементами. Таким образом, формально ваше утверждение верно, но на практике — нет. С этим связана идея high-throughput materials design, поиска новых материалов путём простого перебора.

        +1
        blue_limon я наверное что-то не понимаю, но зачем майнить из пабмеда, если в NCBI это уже проиндексировано и поиск работает по индексу?
        вот пример
        www.ncbi.nlm.nih.gov/gene/?term=DEK%20poor%20prognosis

          +1
          Все-таки Вы майните *список работ* на тему генов, влияющих на прогноз, а не список таких генов.
            +1
            Малость позанудствую.
            В этой статье я приведу примеры составления списка генов ответственных за плохой прогноз по выживаемости от рака и код поиска органических соединений и их номеров среди всех химических молекул базы ПабЧем.

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

            Поскольку PubChem — база данных химических соединений и смесей, Chem — это, по идее, сокращение от слова chemical, которое читается приблизительно как «кемикл». Это я к тому, что PubChem читается как «пабкем».
              0
              А не проще ли молекулы искать через скафандр (scifinder.cas.org)
                0

                Чую, что при таком коде где-то обязательно должна быть ошибка )) статическим анализатором бы это проверить...

                  0

                  Data mining в pubmed существенно интереснее, если поднять его локально. Особенно метаанализ. Полная база данных и апдейты скачиваются с ftp.

                  Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                  Самое читаемое