<jupyter_start><jupyter_text>Text Mining NCBI PubmedThis session will cover the use of the Entrez module located within the popular package BioPython. You will learn how to query the NCBI's Pubmed database from a Python3 script (e.g. the Jupyter notebook herein) using key terms before filtering the results to find relevant literature for a given investigation. Although not explored here, the Entrez package works well alongside the natural language processing module, NLTK. Therefore, this session is designed to introduce the novice Python programmer to a few of the initial steps required for a project involving literature searches, natural language processing and/or machine learning.Before starting this session, you will need to be familiar with Pandas and Matplotlib. Take a look at our previous sessions on Python for the Central Dogma and An Introduction to Pandas/Matplotlib to get yourself up to speed.   ---Let's start by importing the Entrez module from BioPython. Entrez will sometimes return an error message if you do not specify your ```email``` but it will not affect how your code runs.<jupyter_code>from Bio import Entrez

Entrez.email = '<EMAIL>'  # Optional. Typically for large-scale searches involving thousands of queries<jupyter_output><empty_output><jupyter_text>The line of code below will use Entrez to search for the five most recent entries in the NCBI Pubmed (```pubmed```) database that cite the term ```bioinformatics``` somewhere in the manuscript.<jupyter_code>search = Entrez.esearch(db='pubmed',            # Sets NCBI Pubmed as the database
                        term='bioinformatics',  # Searches for papers including the term 'bioinformatics'
                        retmax='5'              # Sets the maximum number of hits returned
                       )<jupyter_output><empty_output><jupyter_text>Our ```search``` variable is currently stored as a class object somewhere in your computer's memory and simply printing it will display a cryptic line of alphanumeric characters. Try it yourself; use the ```print()``` function on the class variable ```search```. We, therefore, need to run the ```read()``` function on our ```search``` variable, which can be done using the following:<jupyter_code>search_results = Entrez.read(search)  # Returns a dictionary of data from the search

print(search_results)<jupyter_output><empty_output><jupyter_text>The output of printing the ```search``` results using ```read()``` is a dictionary containing metadata on your query. ```Count``` is the number of documented papers containing your search term(s), ```IdList``` is the list of the Pubmed IDs returned from the search, and so on. For a fuller description of the output keys from Entrez, refer to [the documentation](https://biopython.readthedocs.io/en/latest/api/Bio.Entrez.html). ---We will continue this session by looking at the Pubmed IDs from our search.<jupyter_code>print(search_results['IdList'])   # Prints the Pubmed IDs from search. Set retmax to a higher integer to get more results.<jupyter_output><empty_output><jupyter_text>Entrez has a useful function called ```efetch()``` that takes a Pubmed ID and returns data the paper it refers to. Let's try this using a loop and our five Pubmed IDs. Depending on your internet speed, this can take a few seconds to minutes.<jupyter_code>literature_list = []     # Initialise empty list to store abstracts

for entry in search_results['IdList']:
    
    entry_details = Entrez.efetch(id=entry,             # Pubmed ID
                                  db='pubmed',          # Database
                                  rettype='Abstract',   # Return type = abstract. Refer to Entrez documentation for other rettypes
                                  retmode='text')       # Return output as human-readable text
    
    literature_list.append(entry_details.read().lower())    # Adds fetched abstracts to list
                                                            # Converted to lower case
print(literature_list)<jupyter_output><empty_output><jupyter_text>Now we have a list of paper abstracts citing the term bioinformatics somewhere in the text (not necessarily in the abstract).  Task 1Iterate through this list, print out each paper's abstract and its index in the list.<jupyter_code>### Task 1 ###<jupyter_output><empty_output><jupyter_text>As seen from the output of the code above, ```Entrez.efetch()``` supplies metadata and author information along with the paper's abstract. For the purpose of this session (and many other applications of text mining), including this information in tandem with the abstract's text does not much matter. ---Excellent! We now have a list of abstracts all somehow related to bioinformatics. Let's explore our results a little further.  Task 2Write some code in the block below to print the number of occurrences of the word "gene" in each paper's abstract. What is the index of the paper with the highest number of occurrences?<jupyter_code>### Tasks 2 ###<jupyter_output><empty_output><jupyter_text>---Simply finding the word count for particular terms in a paper's abstract can often be an effective way to quickly guess the context of a paper and assess its relevance to the study. For example, a paper prevalently containing the word "gene" in its abstract after a search for the term "bioinformatics" could suggest the paper reports a genomics study. Finer context can be assessed by finding the counts for more words within the abstract.  Task 3By using a Python dictionary, find the frequency occurrence for the terms ```gene```, ```protein``` and ```RNA``` in each abstact and print the results. What does this tell you about the first, fourth and fifth abstracts? How might you use this to narrow down a literature search?<jupyter_code>### Task 3 ###<jupyter_output><empty_output><jupyter_text>Another operation we might want to perform is finding the total counts for certain key terms over all of our reported abstracts. In this case, let's find how prevalent the key terms ```gene```, ```protein``` and ```RNA``` occur in our abstracts from papers citing the term 'bioinformatics'. Our example of five papers makes this task trivial - we could simply add up the counts from task 3 - but scaling the literature search up to hundreds or thousands of papers quickly becomes cumbersome.  Task 4Modify the code above to find the total frequency of the terms ```gene```, ```protein``` and ```RNA``` across all abstracts in the ```literature_list```. What could this tell you about published papers citing the term 'bioinformatics'?<jupyter_code>### Task 4 ###<jupyter_output><empty_output><jupyter_text>--- Task 5Based on some of the examples from the previous session, plot an appropriate graph for this data.<jupyter_code>### Task 5 ###<jupyter_output><empty_output><jupyter_text>--- Task 6Using all the necessary tools we have covered in this session, produce a barchart for the frequency of the terms in the list below from the abstracts of the latest 50 publications that contain the term 'systems biology' in the NCBI Pubmed database. Terms to look for in the abstract:- gene- protein- rna- metabolite- genomic- proteomic- transcriptomic- metabolomicNote: The ```term``` argument in Entrez's ```esearch()``` function requires spaces to be written with the ```+``` symbol (e.g. ```term='Hello+wolrd``` means search for the term ```Hello world```).Fetching the abstracts from all 50 queries might take several minutes. Therefore, suitably reduce this number if you have either slow internet or need the results quickly.<jupyter_code>### Task 6 ###<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.07401100340581608, 'fraction_numerical': 0.0024888656012575323, 'mean_word_length': 4.313152400835073, 'pattern_counts': {'":': 0, '<': 46, '<?xml version=': 0, '>': 46, 'https://': 1, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 5, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '11', 'dir': 'jupyter-structured-clean-dedup', 'id': '235147', 'license': 'MIT', 'n_tokens_mistral': 1953, 'n_tokens_neox': 1847, 'n_words': 993, 'path': 'text_mining_tutorial_using_Entrez.ipynb', 'repo_name': 'IC-Computational-Biology-Society/NCBI_text_mining_session', 'size': '7656'}