|
|
- ;;; org-ref-pubmed.el --- Links and functions for Pubmed and NIH databases -*- lexical-binding: t; -*-
-
- ;; Copyright (C) 2015 John Kitchin
-
- ;; Author: John Kitchin <jkitchin@andrew.cmu.edu>
- ;; Keywords: convenience
-
- ;; This program is free software; you can redistribute it and/or modify
- ;; it under the terms of the GNU General Public License as published by
- ;; the Free Software Foundation, either version 3 of the License, or
- ;; (at your option) any later version.
-
- ;; This program is distributed in the hope that it will be useful,
- ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
- ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- ;; GNU General Public License for more details.
-
- ;; You should have received a copy of the GNU General Public License
- ;; along with this program. If not, see <http://www.gnu.org/licenses/>.
-
- ;;; Commentary:
-
- ;;* Introduction
-
- ;; This document is an experiment at creating a literate program to provide
- ;; functions for interacting with pubmed databases.
-
- ;; This library provides links that go to pubmed resources, e.g.
-
- ;; pmcid:PMC3498956
- ;;
- ;; pmid:23162369
- ;;
- ;; and nihmsid:NIHMS395714
- ;;
- ;; See http://www.ncbi.nlm.nih.gov/pmc/about/public-access-info/#p3 for details
- ;; of these identifiers.
- ;;
- ;; For PMID there is one interactive function that inserts a bibtex entry:
- ;; pubmed-insert-bibtex-from-pmid.
-
- ;; This library is complementary to [[./doi-utils.org]].
-
- ;;; Code:
-
- ;;* PMID (from PubMed) link and functions
-
- ;; A PMID is a number that identifies an entry in the Pubmed database. The PMID
- ;; is a unique reference number for PubMed citations. The PMID is a distinctly
- ;; different number from the PMCID and is used only for PubMed records.
-
- (require 'dash)
- (require 'org)
- (require 'org-ref-utils)
-
- (org-ref-link-set-parameters "pmid"
- :follow (lambda (link-string) (browse-url (format "http://www.ncbi.nlm.nih.gov/pubmed/%s" link-string)))
- :export (lambda (keyword desc format)
- (cond
- ((eq format 'html)
- (format "<a href=\"http://www.ncbi.nlm.nih.gov/pmc/articles/mid/%s\">pmid:%s</a>" keyword (or desc keyword))) ; no output for html
- ((eq format 'latex)
- ;; write out the latex command
- (format "\\url{http://www.ncbi.nlm.nih.gov/pmc/articles/mid/%s}{%s}" keyword (or desc keyword))))))
-
- ;;** Get MEDLINE metadata
-
- ;; We can get bibliographic metadata from a pmid. Here we get the MEDLINE
- ;; text. The website wraps the data in <pre></pre> tags.
-
- (defun pubmed-get-medline (pmid)
- "Get MEDLINE text for PMID as a string."
- (with-current-buffer
- (url-retrieve-synchronously
- (format "http://www.ncbi.nlm.nih.gov/pubmed/%s/?report=medline&format=text" pmid))
- (goto-char (point-min))
- (let ((p1 (search-forward "<pre>"))
- (p2 (search-forward "</pre>")))
- (buffer-substring (+ 1 p1) (- p2 6)))))
-
- ;;** Parse the PMID MEDLINE data
-
- ;; We can parse this into a data structure.
-
- (defun pubmed-parse-medline (pmid)
- "Parse the medline text for PMID and return a list of cons cells."
- (let ((data '())
- (p1)
- (p2)
- (tag)
- (value))
- (with-temp-buffer (insert (pubmed-get-medline pmid))
- (goto-char (point-min))
- (while (re-search-forward "\\(^[A-Z]\\{2,4\\}\\)\\s-*- "
- nil t)
- (setq tag (match-string 1))
- ;; point is at end of the search
- (setq p1 (point))
- ;; now go to next tag
- (re-search-forward "\\(^[A-Z]\\{2,4\\}\\)\\s-*- " nil t)
- (setq p2 (- (match-beginning 1) 1))
- (setq value (buffer-substring p1 p2))
- (setq data (append data (list (cons tag value))))
- ;; now go back to last tag to get the next one
- (goto-char p1)))
- data))
-
- ;;** PMID to bibtex entry
-
- ;; The point of parsing the MEDLINE text is so we can make bibtex entries. We
- ;; only support Journal articles for now.
-
- (defun pubmed-pmid-to-bibtex (pmid)
- "Convert a PMID to a bibtex entry."
- (let* ((data (pubmed-parse-medline pmid))
- (type (downcase (cdr (assoc "PT" data))))
- (title (cdr (assoc "TI" data)))
- (authors (mapconcat 'cdr
- (-filter (lambda (x)
- (string= (car x) "FAU"))
- data)
- " and "))
- (abstract (cdr (assoc "AB" data)))
- (volume (cdr (assoc "VI" data)))
- (issue (cdr (assoc "IP" data)))
- (journal (cdr (assoc "JT" data)))
- (year (cdr (assoc "DP" data)))
- (pages (cdr (assoc "PG" data)))
- (aid (cdr (assoc "AID" data))))
-
- (cond
- ((string= type "journal article")
- (concat "@article{,
- author = {" authors "},
- title = {" title "},
- abstract = {" abstract "},
- journal = {" journal "},
- volume = {" volume "},
- number = {" issue "},
- year = {" (car (split-string year)) "},
- pages = {" pages "},
- doi = {" (replace-regexp-in-string " \\[doi\\]" "" (or aid "")) "},
- }"))
- (t
- (message "No conversion for type: %s" type)))))
-
- ;; And we probably want to be able to insert a bibtex entry
-
- ;;;###autoload
- (defun pubmed-insert-bibtex-from-pmid (pmid)
- "Insert a bibtex entry at point derived from PMID.
- You must clean the entry after insertion."
- (interactive "sPMID: ")
- (insert (pubmed-pmid-to-bibtex pmid)))
-
- ;;** PMID to xml
-
- ;; We can also get xml of the MEDLINE data. The web page here also wraps the xml
- ;; in a <pre> block and escapes the <> with < and >, which we have to
- ;; undo. I have not used this code for anything, so I am not sure how good the
- ;; xml code is.
-
- ;;;###autoload
- (defun pubmed-get-medline-xml (pmid)
- "Get MEDLINE xml for PMID as a string."
- (interactive)
- (with-current-buffer
- (url-retrieve-synchronously
- (format "http://www.ncbi.nlm.nih.gov/pubmed/%s/?report=xml&format=text" pmid))
- (goto-char (point-min))
- (while (search-forward "<" nil t)
- (replace-match "<"))
- (goto-char (point-min))
- (while (search-forward ">" nil t)
- (replace-match ">"))
- (goto-char (point-min))
-
- (let ((p1 (search-forward "<pre>"))
- (p2 (search-forward "</pre>")))
- (buffer-substring (+ 1 p1) (- p2 6)))))
-
- ;;* Pubmed Central (PMC) link
-
- ;; A PMCID starts with PMC and is followed by numbers. The PMCID is a unique
- ;; reference number or identifier that is assigned to every article that is
- ;; accepted into PMC. The PMCID is also used by recipients of NIH funding to
- ;; demonstrate compliance with the NIH Public Access policy. The PMCID can be
- ;; found in both PMC and PubMed.
-
- ;; Here we define a new link. Clicking on it simply opens a webpage to the
- ;; article.
-
- (org-ref-link-set-parameters "pmcid"
- :follow (lambda (link-string) (browse-url (format "http://www.ncbi.nlm.nih.gov/pmc/articles/%s" link-string)))
- :export (lambda (keyword desc format)
- (cond
- ((eq format 'html)
- (format "<a href=\"http://www.ncbi.nlm.nih.gov/pmc/articles/%s\">pmcid:%s</a>" keyword (or desc keyword)))
- ((eq format 'latex)
- (format "\\url{http://www.ncbi.nlm.nih.gov/pmc/articles/%s}{%s}" keyword (or desc keyword))))))
-
- ;;* NIHMSID
-
- ;; The NIHMSID is a preliminary article identifier that applies only to
- ;; manuscripts deposited through the NIHMS system. The NIHMSID is only valid for
- ;; compliance reporting for 90 days after the publication date of an
- ;; article. Once the Web version of the NIHMS submission is approved for
- ;; inclusion in PMC and the corresponding citation is in PubMed, the article
- ;; will also be assigned a PMCID.
-
- (org-ref-link-set-parameters "nihmsid"
- :follow (lambda (link-string) (browse-url (format "http://www.ncbi.nlm.nih.gov/pmc/articles/mid/%s" link-string)))
- :export (lambda (keyword desc format)
- (cond
- ((eq format 'html)
- (format "<a href=\"http://www.ncbi.nlm.nih.gov/pmc/articles/mid//%s\">nihmsid:%s</a>" keyword (or desc keyword)))
- ((eq format 'latex)
- ;; write out the latex command
- (format "\\url{http://www.ncbi.nlm.nih.gov/pmc/articles/mid/%s}{%s}" keyword (or desc keyword))))))
-
-
- ;;* Searching pubmed
-
- ;;;###autoload
- (defun pubmed ()
- "Open http://www.ncbi.nlm.nih.gov/pubmed in a browser."
- (interactive)
- (browse-url "http://www.ncbi.nlm.nih.gov/pubmed"))
-
-
- ;;;###autoload
- (defun pubmed-advanced ()
- "Open http://www.ncbi.nlm.nih.gov/pubmed/advanced in a browser."
- (interactive)
- (browse-url "http://www.ncbi.nlm.nih.gov/pubmed/advanced"))
-
-
- ;;;###autoload
- (defun pubmed-simple-search (query)
- "Open QUERY in Pubmed in a browser."
- (interactive "sQuery: ")
- (browse-url
- (format "http://www.ncbi.nlm.nih.gov/pubmed/?term=%s" (url-hexify-string query))))
-
-
- (org-ref-link-set-parameters "pubmed-search"
- :follow (lambda (query)
- "Open QUERY in a `pubmed-simple-search'."
- (pubmed-simple-search query))
- :export (lambda (query desc format)
- (let ((url (format "http://www.ncbi.nlm.nih.gov/pubmed/?term=%s" (url-hexify-string query))))
- (cond
- ((eq format 'html)
- (format "<a href=\"%s\">%s</a>" url (or desc (concat "pubmed-search:" query))))
- ((eq format 'latex)
- (format "\\href{%s}{%s}" url (or desc (concat "pubmed-search:" query))))))))
-
- ;; ** Pubmed clinical
- ;; These functions were suggested by Colin Melville <casm40@gmail.com>.
- ;;;###autoload
- (defun pubmed-clinical ()
- "Open http://www.ncbi.nlm.nih.gov/pubmed/clinical in a browser."
- (interactive)
- (browse-url "http://www.ncbi.nlm.nih.gov/pubmed/clinical"))
-
-
- ;;;###autoload
- (defun pubmed-clinical-search (query)
- "Open QUERY in pubmed-clinical."
- (interactive "sQuery: ")
- (browse-url
- (format "https://www.ncbi.nlm.nih.gov/pubmed/clinical?term=%s" (url-hexify-string query))))
-
-
- (org-ref-link-set-parameters "pubmed-clinical"
- :follow (lambda (query)
- "Open QUERY in a `pubmed-clinical-search'."
- (pubmed-clinical-search query))
- :export (lambda (query desc format)
- (let ((url (format "http://www.ncbi.nlm.nih.gov/pubmed/clinical?term=%s"
- (url-hexify-string query))))
- (cond
- ((eq format 'html)
- (format "<a href=\"%s\">%s</a>" url
- (or desc (concat "pubmed-clinical-search:" query))))
- ((eq format 'latex)
- (format "\\href{%s}{%s}" url
- (or desc (concat "pubmed-clinical-search:" query))))))))
-
-
- (provide 'org-ref-pubmed)
- ;;; org-ref-pubmed.el ends here
|