"""Code to manage references"""
__author__ = "Adam Simpkin, Jens Thomas & Felix Simkovic"
__date__ = "7 November 2018"
from collections import OrderedDict
import copy
from enum import Enum
import os
[docs]class ReferenceManager():
#Section Names
[docs] class SECTIONS(Enum):
__order__ = 'GENERAL ROTATION MR REFINEMENT'
GENERAL = 'General'
ROTATION = 'Rotation Search'
MR = 'Molecular Replacement'
REFINEMENT = 'Refinement'
SEC_TAG = 'h3'
def __init__(self, d):
self.references = {}
self.ordered_labels = []
self.citation_file_path = None
self.section_labels = OrderedDict()
self.setup_references()
self.setup_sections(d)
[docs] def setup_references(self):
ref_fname = os.path.join(os.environ['CCP4'], "share", "simbad", "static", "simbad.bib")
if not os.path.isfile(ref_fname):
msg = "Cannot find BibTex file containing references. " \
"Please determine them yourself and cite SIMBAD."
return msg
article = {}
entry = False
with open(ref_fname, "r") as fhin:
for line in fhin.readlines():
line = line.strip()
if not line:
continue
elif line.startswith("@"):
# Beginning of all BibTex entry blocks
entry = True
unique_id = line.replace("@article{", "").replace(",", "")
article = {'unique_id': unique_id} # Reset the article dictionary
elif line == "}":
# End of all BibTex entry blocks
entry = False
self.references[article['label']] = article
elif entry:
# BibTex entry block
# Some dirty line handling.
# Not very bulletproof but should do for now
line = line.replace("{", "").replace("}", "")
key, value = [l.strip() for l in line.split("=")]
value = value.rstrip(",").replace("\"", "")
# Save the data to the article entry
article[key] = value
return
[docs] def setup_sections(self, d):
# Create default lists
for section in self.SECTIONS:
self.section_labels[section] = []
# Build up list of program reference labels, ordered by sections
for section in self.SECTIONS:
if section == self.SECTIONS.GENERAL:
self.section_labels[section] = ['SIMBAD', 'CCP4', 'CCTBX']
elif section == self.SECTIONS.ROTATION:
labels = []
if d.get('-rot_program') == 'phaser':
labels.append('PHASER_ROT')
else:
labels.append('AMORE')
self.section_labels[section] = labels
elif section == self.SECTIONS.MR:
labels = []
if d.get('-mr_program') == 'phaser':
labels.append('PHASER')
else:
labels.append('MOLREP')
self.section_labels[section] = labels
elif section == self.SECTIONS.REFINEMENT:
self.section_labels[self.SECTIONS.REFINEMENT] = ['REFMAC']
# Generate ordered list of all relevant reference labels
for section in self.SECTIONS:
if section in self.section_labels:
self.ordered_labels += self.section_labels[section]
return
@property
def methods_as_html(self):
html = "<p>This section lists the programs and algorithms that were used in this job and the references that should be cited. " + \
"Numbers in superscript next to program/reference names refer to the number of the program reference in the overall list of references.</p>"
for section in self.SECTIONS:
if section == self.SECTIONS.GENERAL:
html += '<p>SIMBAD<sup>1</sup>, CCP4<sup>2</sup> and CCTBX<sup>3</sup> references should be cited in all cases.</p>'
elif section == self.SECTIONS.ROTATION and len(self.section_labels[self.SECTIONS.ROTATION]):
standfirst = '<p>The rotation searches were carried out with the following programs:</p>'
html += self._methods_section_html(self.SECTIONS.ROTATION, standfirst)
elif section == self.SECTIONS.MR and len(self.section_labels[self.SECTIONS.MR]):
standfirst = '<p>Molecular Replacement was carried out with the following programs:</p>'
html += self._methods_section_html(self.SECTIONS.MR, standfirst)
elif section == self.SECTIONS.REFINEMENT and len(self.section_labels[self.SECTIONS.REFINEMENT]):
standfirst = '<p>Refinement of the MR solutions was carried out with the following programs:</p>'
html += self._methods_section_html(self.SECTIONS.REFINEMENT, standfirst)
return html
def _methods_section_html(self, section, standfirst):
mysec = self.SECTIONS(section)
html = '<{}>{}</{}>'.format(self.SEC_TAG, mysec.value, self.SEC_TAG)
html += standfirst
html += '<ul>'
for label in self.section_labels[mysec]:
html += "<li>{}<sup>{}</sup></li>".format(label, self.ordered_labels.index(label) + 1)
html += "</ul>"
return html
@property
def citations_as_html(self):
html = '<{}>References</{}>'.format(self.SEC_TAG, self.SEC_TAG)
html += '<ol>'
template_txt = "<li> {author} ({year}). {title}. {journal} {volume}({number}), {pages}. [doi:{doi}]</li>"
for label in self.ordered_labels:
ref = copy.copy(self.references[label])
ref['author'] = ref['author'].split(" and ")[0].split(",")[0] + " et al."
ref['pages'] = ref['pages'].replace("--", "-")
html += template_txt.format(**ref)
html += '</ol>'
return html
@property
def citations_as_text(self):
txt = """A number of programs and algorithms were used within the this run of SIMBAD.
The following is a list of citations for this run:
{0}
""".format(self.citation_list_as_text)
if self.citation_file_path:
txt += """
A bibtex file with these references has been saved to the following file:
{0}
""".format(self.citation_file_path)
return txt
@property
def citation_list_as_text(self):
template_txt = "* {author} ({year}). {title}. {journal} {volume}({number}), {pages}. [doi:{doi}]"
text = ""
for label in self.ordered_labels:
ref = copy.copy(self.references[label])
ref['author'] = ref['author'].split(" and ")[0].split(",")[0] + " et al."
ref['pages'] = ref['pages'].replace("--", "-")
text += template_txt.format(**ref) + os.linesep * 2
return text
[docs] def save_citations_to_file(self, work_dir):
# =========================================================================
# Somewhat a template of how we want to write each article in BibTex format
# =========================================================================
template_bib = "@article{{{unique_id},{sep}author = {{{author}}},{sep}doi = {{{doi}}},{sep}" \
"journal = {{{journal}}},{sep}number = {{{number}}},{sep}pages = {{{pages}}},{sep}" \
"title = {{{{{title}}}}},{sep}volume = {{{volume}}},{sep}year = {{{year}}},{sep}}}{sep}"
references_bib = [template_bib.format(sep=os.linesep, **self.references[l]) for l in self.ordered_labels]
ref_fname = os.path.join(work_dir, "references.bib")
with open(ref_fname, "w") as fhout:
fhout.write(os.linesep.join(references_bib))
self.citation_file_path = ref_fname
return ref_fname