Klimi's new dotfiles with stow.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

292 lines
10 KiB

5 years ago
  1. ;;; org-ref-pubmed.el --- Links and functions for Pubmed and NIH databases -*- lexical-binding: t; -*-
  2. ;; Copyright (C) 2015 John Kitchin
  3. ;; Author: John Kitchin <jkitchin@andrew.cmu.edu>
  4. ;; Keywords: convenience
  5. ;; This program is free software; you can redistribute it and/or modify
  6. ;; it under the terms of the GNU General Public License as published by
  7. ;; the Free Software Foundation, either version 3 of the License, or
  8. ;; (at your option) any later version.
  9. ;; This program is distributed in the hope that it will be useful,
  10. ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. ;; GNU General Public License for more details.
  13. ;; You should have received a copy of the GNU General Public License
  14. ;; along with this program. If not, see <http://www.gnu.org/licenses/>.
  15. ;;; Commentary:
  16. ;;* Introduction
  17. ;; This document is an experiment at creating a literate program to provide
  18. ;; functions for interacting with pubmed databases.
  19. ;; This library provides links that go to pubmed resources, e.g.
  20. ;; pmcid:PMC3498956
  21. ;;
  22. ;; pmid:23162369
  23. ;;
  24. ;; and nihmsid:NIHMS395714
  25. ;;
  26. ;; See http://www.ncbi.nlm.nih.gov/pmc/about/public-access-info/#p3 for details
  27. ;; of these identifiers.
  28. ;;
  29. ;; For PMID there is one interactive function that inserts a bibtex entry:
  30. ;; pubmed-insert-bibtex-from-pmid.
  31. ;; This library is complementary to [[./doi-utils.org]].
  32. ;;; Code:
  33. ;;* PMID (from PubMed) link and functions
  34. ;; A PMID is a number that identifies an entry in the Pubmed database. The PMID
  35. ;; is a unique reference number for PubMed citations. The PMID is a distinctly
  36. ;; different number from the PMCID and is used only for PubMed records.
  37. (require 'dash)
  38. (require 'org)
  39. (require 'org-ref-utils)
  40. (org-ref-link-set-parameters "pmid"
  41. :follow (lambda (link-string) (browse-url (format "http://www.ncbi.nlm.nih.gov/pubmed/%s" link-string)))
  42. :export (lambda (keyword desc format)
  43. (cond
  44. ((eq format 'html)
  45. (format "<a href=\"http://www.ncbi.nlm.nih.gov/pmc/articles/mid/%s\">pmid:%s</a>" keyword (or desc keyword))) ; no output for html
  46. ((eq format 'latex)
  47. ;; write out the latex command
  48. (format "\\url{http://www.ncbi.nlm.nih.gov/pmc/articles/mid/%s}{%s}" keyword (or desc keyword))))))
  49. ;;** Get MEDLINE metadata
  50. ;; We can get bibliographic metadata from a pmid. Here we get the MEDLINE
  51. ;; text. The website wraps the data in <pre></pre> tags.
  52. (defun pubmed-get-medline (pmid)
  53. "Get MEDLINE text for PMID as a string."
  54. (with-current-buffer
  55. (url-retrieve-synchronously
  56. (format "http://www.ncbi.nlm.nih.gov/pubmed/%s/?report=medline&format=text" pmid))
  57. (goto-char (point-min))
  58. (let ((p1 (search-forward "<pre>"))
  59. (p2 (search-forward "</pre>")))
  60. (buffer-substring (+ 1 p1) (- p2 6)))))
  61. ;;** Parse the PMID MEDLINE data
  62. ;; We can parse this into a data structure.
  63. (defun pubmed-parse-medline (pmid)
  64. "Parse the medline text for PMID and return a list of cons cells."
  65. (let ((data '())
  66. (p1)
  67. (p2)
  68. (tag)
  69. (value))
  70. (with-temp-buffer (insert (pubmed-get-medline pmid))
  71. (goto-char (point-min))
  72. (while (re-search-forward "\\(^[A-Z]\\{2,4\\}\\)\\s-*- "
  73. nil t)
  74. (setq tag (match-string 1))
  75. ;; point is at end of the search
  76. (setq p1 (point))
  77. ;; now go to next tag
  78. (re-search-forward "\\(^[A-Z]\\{2,4\\}\\)\\s-*- " nil t)
  79. (setq p2 (- (match-beginning 1) 1))
  80. (setq value (buffer-substring p1 p2))
  81. (setq data (append data (list (cons tag value))))
  82. ;; now go back to last tag to get the next one
  83. (goto-char p1)))
  84. data))
  85. ;;** PMID to bibtex entry
  86. ;; The point of parsing the MEDLINE text is so we can make bibtex entries. We
  87. ;; only support Journal articles for now.
  88. (defun pubmed-pmid-to-bibtex (pmid)
  89. "Convert a PMID to a bibtex entry."
  90. (let* ((data (pubmed-parse-medline pmid))
  91. (type (downcase (cdr (assoc "PT" data))))
  92. (title (cdr (assoc "TI" data)))
  93. (authors (mapconcat 'cdr
  94. (-filter (lambda (x)
  95. (string= (car x) "FAU"))
  96. data)
  97. " and "))
  98. (abstract (cdr (assoc "AB" data)))
  99. (volume (cdr (assoc "VI" data)))
  100. (issue (cdr (assoc "IP" data)))
  101. (journal (cdr (assoc "JT" data)))
  102. (year (cdr (assoc "DP" data)))
  103. (pages (cdr (assoc "PG" data)))
  104. (aid (cdr (assoc "AID" data))))
  105. (cond
  106. ((string= type "journal article")
  107. (concat "@article{,
  108. author = {" authors "},
  109. title = {" title "},
  110. abstract = {" abstract "},
  111. journal = {" journal "},
  112. volume = {" volume "},
  113. number = {" issue "},
  114. year = {" (car (split-string year)) "},
  115. pages = {" pages "},
  116. doi = {" (replace-regexp-in-string " \\[doi\\]" "" (or aid "")) "},
  117. }"))
  118. (t
  119. (message "No conversion for type: %s" type)))))
  120. ;; And we probably want to be able to insert a bibtex entry
  121. ;;;###autoload
  122. (defun pubmed-insert-bibtex-from-pmid (pmid)
  123. "Insert a bibtex entry at point derived from PMID.
  124. You must clean the entry after insertion."
  125. (interactive "sPMID: ")
  126. (insert (pubmed-pmid-to-bibtex pmid)))
  127. ;;** PMID to xml
  128. ;; We can also get xml of the MEDLINE data. The web page here also wraps the xml
  129. ;; in a <pre> block and escapes the <> with &lt; and &gt;, which we have to
  130. ;; undo. I have not used this code for anything, so I am not sure how good the
  131. ;; xml code is.
  132. ;;;###autoload
  133. (defun pubmed-get-medline-xml (pmid)
  134. "Get MEDLINE xml for PMID as a string."
  135. (interactive)
  136. (with-current-buffer
  137. (url-retrieve-synchronously
  138. (format "http://www.ncbi.nlm.nih.gov/pubmed/%s/?report=xml&format=text" pmid))
  139. (goto-char (point-min))
  140. (while (search-forward "&lt;" nil t)
  141. (replace-match "<"))
  142. (goto-char (point-min))
  143. (while (search-forward "&gt;" nil t)
  144. (replace-match ">"))
  145. (goto-char (point-min))
  146. (let ((p1 (search-forward "<pre>"))
  147. (p2 (search-forward "</pre>")))
  148. (buffer-substring (+ 1 p1) (- p2 6)))))
  149. ;;* Pubmed Central (PMC) link
  150. ;; A PMCID starts with PMC and is followed by numbers. The PMCID is a unique
  151. ;; reference number or identifier that is assigned to every article that is
  152. ;; accepted into PMC. The PMCID is also used by recipients of NIH funding to
  153. ;; demonstrate compliance with the NIH Public Access policy. The PMCID can be
  154. ;; found in both PMC and PubMed.
  155. ;; Here we define a new link. Clicking on it simply opens a webpage to the
  156. ;; article.
  157. (org-ref-link-set-parameters "pmcid"
  158. :follow (lambda (link-string) (browse-url (format "http://www.ncbi.nlm.nih.gov/pmc/articles/%s" link-string)))
  159. :export (lambda (keyword desc format)
  160. (cond
  161. ((eq format 'html)
  162. (format "<a href=\"http://www.ncbi.nlm.nih.gov/pmc/articles/%s\">pmcid:%s</a>" keyword (or desc keyword)))
  163. ((eq format 'latex)
  164. (format "\\url{http://www.ncbi.nlm.nih.gov/pmc/articles/%s}{%s}" keyword (or desc keyword))))))
  165. ;;* NIHMSID
  166. ;; The NIHMSID is a preliminary article identifier that applies only to
  167. ;; manuscripts deposited through the NIHMS system. The NIHMSID is only valid for
  168. ;; compliance reporting for 90 days after the publication date of an
  169. ;; article. Once the Web version of the NIHMS submission is approved for
  170. ;; inclusion in PMC and the corresponding citation is in PubMed, the article
  171. ;; will also be assigned a PMCID.
  172. (org-ref-link-set-parameters "nihmsid"
  173. :follow (lambda (link-string) (browse-url (format "http://www.ncbi.nlm.nih.gov/pmc/articles/mid/%s" link-string)))
  174. :export (lambda (keyword desc format)
  175. (cond
  176. ((eq format 'html)
  177. (format "<a href=\"http://www.ncbi.nlm.nih.gov/pmc/articles/mid//%s\">nihmsid:%s</a>" keyword (or desc keyword)))
  178. ((eq format 'latex)
  179. ;; write out the latex command
  180. (format "\\url{http://www.ncbi.nlm.nih.gov/pmc/articles/mid/%s}{%s}" keyword (or desc keyword))))))
  181. ;;* Searching pubmed
  182. ;;;###autoload
  183. (defun pubmed ()
  184. "Open http://www.ncbi.nlm.nih.gov/pubmed in a browser."
  185. (interactive)
  186. (browse-url "http://www.ncbi.nlm.nih.gov/pubmed"))
  187. ;;;###autoload
  188. (defun pubmed-advanced ()
  189. "Open http://www.ncbi.nlm.nih.gov/pubmed/advanced in a browser."
  190. (interactive)
  191. (browse-url "http://www.ncbi.nlm.nih.gov/pubmed/advanced"))
  192. ;;;###autoload
  193. (defun pubmed-simple-search (query)
  194. "Open QUERY in Pubmed in a browser."
  195. (interactive "sQuery: ")
  196. (browse-url
  197. (format "http://www.ncbi.nlm.nih.gov/pubmed/?term=%s" (url-hexify-string query))))
  198. (org-ref-link-set-parameters "pubmed-search"
  199. :follow (lambda (query)
  200. "Open QUERY in a `pubmed-simple-search'."
  201. (pubmed-simple-search query))
  202. :export (lambda (query desc format)
  203. (let ((url (format "http://www.ncbi.nlm.nih.gov/pubmed/?term=%s" (url-hexify-string query))))
  204. (cond
  205. ((eq format 'html)
  206. (format "<a href=\"%s\">%s</a>" url (or desc (concat "pubmed-search:" query))))
  207. ((eq format 'latex)
  208. (format "\\href{%s}{%s}" url (or desc (concat "pubmed-search:" query))))))))
  209. ;; ** Pubmed clinical
  210. ;; These functions were suggested by Colin Melville <casm40@gmail.com>.
  211. ;;;###autoload
  212. (defun pubmed-clinical ()
  213. "Open http://www.ncbi.nlm.nih.gov/pubmed/clinical in a browser."
  214. (interactive)
  215. (browse-url "http://www.ncbi.nlm.nih.gov/pubmed/clinical"))
  216. ;;;###autoload
  217. (defun pubmed-clinical-search (query)
  218. "Open QUERY in pubmed-clinical."
  219. (interactive "sQuery: ")
  220. (browse-url
  221. (format "https://www.ncbi.nlm.nih.gov/pubmed/clinical?term=%s" (url-hexify-string query))))
  222. (org-ref-link-set-parameters "pubmed-clinical"
  223. :follow (lambda (query)
  224. "Open QUERY in a `pubmed-clinical-search'."
  225. (pubmed-clinical-search query))
  226. :export (lambda (query desc format)
  227. (let ((url (format "http://www.ncbi.nlm.nih.gov/pubmed/clinical?term=%s"
  228. (url-hexify-string query))))
  229. (cond
  230. ((eq format 'html)
  231. (format "<a href=\"%s\">%s</a>" url
  232. (or desc (concat "pubmed-clinical-search:" query))))
  233. ((eq format 'latex)
  234. (format "\\href{%s}{%s}" url
  235. (or desc (concat "pubmed-clinical-search:" query))))))))
  236. (provide 'org-ref-pubmed)
  237. ;;; org-ref-pubmed.el ends here