Skip to content

Commit

Permalink
Merge pull request #92 from hlasimpk/master
Browse files Browse the repository at this point in the history
Changes for CCP4online & general fixes
  • Loading branch information
rmk65 committed Nov 8, 2018
2 parents 1e51d7b + 15161b8 commit 0293d9f
Show file tree
Hide file tree
Showing 6 changed files with 358 additions and 6 deletions.
2 changes: 1 addition & 1 deletion i2/SIMBAD_gui.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ class SIMBAD_gui(CTaskWidget):
TASKTITLE='Sequence Free Molecular Replacement - SIMBAD'
DESCRIPTION = '''This task is for running Molecular Replacement without a sequence'''
MGDISPLAYFILES = ['XYZIN']
WHATNEXT = ['coot_rebuild']
WHATNEXT = ['prosmart_refmac', 'coot_rebuild']

def __init__(self,parent):
CTaskWidget.__init__(self,parent)
Expand Down
6 changes: 5 additions & 1 deletion simbad/mr/phaser_mr.py
Original file line number Diff line number Diff line change
Expand Up @@ -301,8 +301,12 @@ def run(self):
shutil.move(r.getTopPdbFile(), self.pdbout)

# Output original mtz with a change of basis if needed
original_space_group, _, _ = mtz_util.crystal_data(self.hklin)
space_group, _, _ = mtz_util.crystal_data(r.getTopMtzFile())
mtz_util.reindex(self.hklin, self.hklout, space_group)
if original_space_group != space_group:
mtz_util.reindex(self.hklin, self.hklout, space_group)
else:
shutil.copyfile(self.hklin, self.hklout)

# Return to original working directory
os.chdir(current_work_dir)
Expand Down
2 changes: 0 additions & 2 deletions simbad/util/mtz_util.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,9 +84,7 @@ def reindex(hklin, hklout, sg):
"""Function to reindex input hkl using pointless"""

cmd = ["pointless" + EXE_EXT, "hklin", hklin, "hklout", hklout]

stdin = """
reindex k,h,-l
spacegroup {0}
"""

Expand Down
73 changes: 71 additions & 2 deletions simbad/util/pyrvapi_results.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
__date__ = "06 Oct 2017"
__version__ = "0.2"

import itertools
import json
import logging
import os
Expand All @@ -13,6 +14,7 @@
import uuid
import urlparse

from simbad.util import reference_manager
from simbad.util import SIMBAD_PYRVAPI_SHAREDIR

logger = logging.getLogger(__name__)
Expand Down Expand Up @@ -158,12 +160,14 @@ def __init__(self, rvapi_document, webserver_uri, display_gui, logfile, work_dir
self.morda_db_df = None
self.summary_tab_id = None
self.summary_tab_results_sec_id = None
self.citation_tab_id = None

self.lattice_search_results_displayed = False
self.contaminant_results_displayed = False
self.morda_results_displayed = False

self.jscofe_mode = False
self.ccp4online_mode = False
self.rhs_tab_id = None
self.rvapi_meta = RvapiMetadata()

Expand All @@ -189,7 +193,8 @@ def __init__(self, rvapi_document, webserver_uri, display_gui, logfile, work_dir
self.rvapi_document = os.path.join(self.jsrview_dir, "index.html")

if webserver_uri:
self._webserver_start = len(self.jsrview_dir) + 1
self._webserver_start = len(self.jsrview_dir) - 7
self.ccp4online_mode = True
elif not ccp4i2_xml:
# We start our own browser
jsrview = os.path.join(ccp4, "libexec", "jsrview")
Expand Down Expand Up @@ -271,6 +276,12 @@ def create_log_tab(self, logfile):
pyrvapi.rvapi_append_content(logurl, True, self.log_tab_id)
return self.log_tab_id

def _create_citation_tab(self):
"""Function to create citation tab"""
if not self.citation_tab_id:
self.citation_tab_id = self.tab_prefix + "citation_tab"
self._add_tab_to_pyrvapi(self.citation_tab_id, "Citations", False)

def _create_lattice_results_tab(self):
"""Function to create lattice results tab"""
if not self.lattice_results_tab_id:
Expand Down Expand Up @@ -662,7 +673,7 @@ def display_summary_tab(self):
An R/Rfree lower than 0.450 is indicative of a \
solution. Values above this may also be indicative of a correct solution \
but you should examine the maps through the graphical map viewer for \
verification'.format(pdb_code, r_fact, r_free)
verification.'.format(pdb_code, r_fact, r_free)

pyrvapi.rvapi_add_section(sec, section_title, tab, 0, 0, 1, 1, True)
pyrvapi.rvapi_add_text(msg, sec, 2, 0, 1, 1)
Expand All @@ -685,6 +696,38 @@ def display_summary_tab(self):
self.output_result_files(download_sec, dmap, map_, mtz, pdb)
self.output_log_files(logfile_sec, mr_log, ref_log)

def display_citation_tab(self):
"""Function to display citations for programs used within SIMBAD
Returns
-------
object
Section containing the relevant citations
"""

self._create_citation_tab()

args = self.get_arguments_from_log(self.logfile)

refMgr = reference_manager.ReferenceManager(args)
bibtex_file = refMgr.save_citations_to_file(self.work_dir)

if self.ccp4i2:
# The horror of ccp4i2 means that this all gets dumped into xml so we can't use any markup tags
tdata = refMgr.citations_as_text
else:
tdata = refMgr.methods_as_html
tdata += refMgr.citations_as_html
tdata += '<hr><p>A bibtex file with the relevant citations has been saved to: {}</p>'.format(bibtex_file)
pyrvapi.rvapi_add_text(tdata, self.citation_tab_id, 0, 0, 1, 1)
if not self.ccp4i2:
pyrvapi.rvapi_add_data("bibtex_file",
"Citations as BIBTEX",
self.fix_path(bibtex_file),
"text",
self.citation_tab_id,
2, 0, 1, 1, True)

def output_result_files(self, sec, diff_map, ref_map, ref_mtz, ref_pdb):
"""Function to display the result files for the result
Expand Down Expand Up @@ -870,8 +913,29 @@ def display_results(self, summarize, results_to_display):
if summarize:
self.display_summary_tab()

self.display_citation_tab()

pyrvapi.rvapi_flush()

@staticmethod
def get_arguments_from_log(log):
args = {}
with open(log) as f:
line = f.readline()
while line:
if line.startswith("Invoked with command-line:"):
line = f.readline()
fields = line.split()[1:-1]
# Check for -- args
for i in fields:
if i.startswith('--'):
fields.remove(i)
args[i] = None
# Take arguments from list and create dictionary
args.update(dict(itertools.izip_longest(*[iter(fields)] * 2, fillvalue=None)))
line = f.readline()
return args

def save_document(self):
pyrvapi.rvapi_put_meta(self.rvapi_meta.to_json())
pyrvapi.rvapi_store_document2(self.rvapi_document)
Expand All @@ -886,10 +950,15 @@ def fix_path(self, path):
def rel_path_for_jscofe(self, path):
return os.path.join("..", os.path.relpath(path, self.jsrview_dir))

def rel_path_for_ccp4online(self, path):
return os.path.relpath(path, self.jsrview_dir)

def adjust_paths_of_files(self, files):
for f in files:
if self.jscofe_mode:
f = self.rel_path_for_jscofe(f)
elif self.ccp4online_mode:
f = self.rel_path_for_ccp4online(f)
yield f

def store_entry_in_rvapi_meta(self, rank, source, name, pdb, mtz, map_, dmap, best):
Expand Down
173 changes: 173 additions & 0 deletions simbad/util/reference_manager.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
"""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


class ReferenceManager():

#Section Names
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)

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 AMPLE."
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

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>The first 2 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 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 AMPLE.
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

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

0 comments on commit 0293d9f

Please sign in to comment.