Source code for ample.util.cif_parser
"""
Created on 28 May 2013
@author: jmht
"""
import logging
import os
import sys
# Our imports
from ample.util import ample_util
from iotbx.cif import reader as cif_reader
# TODO: Combine this with MTZ_util - make a reflection_file_util
[docs]class CifParser(object):
"""Class for manipulating CIF files."""
def __init__(self):
"""Initialise from a ciFile"""
self.hasRfree = False
self.hasAmplitudes = False
self.logger = logging.getLogger()
self.logger.setLevel(logging.DEBUG)
return
def _parseCif(self, cifFile):
self.hasRfree = False
self.reflnStatus = False
self.hasAmplitudes = False
cifObject = cif_reader(file_path=cifFile).model()
# For now assume only one dataSet
assert len(cifObject.keys()) == 1, "More than one data set in sf_cif - not sure what to do!"
data = cifObject[cifObject.keys()[0]]
# See if any of the _refln.status columns are 'f' - indicating they've been set aside for RFree
if "_refln.status" in data:
self.reflnStatus = True
self.hasRfree = any(map(lambda x: x == 'f', data["_refln.status"]))
# Need to check we have structure factor amplitudes. For now just check - we
# need to add code to use ctrunctate to convert if we only have intensities
#
# http://mmcif.pdb.org/dictionaries/mmcif_pdbx.dic/Categories/refln.html
if "_refln.F_meas" in data or "_refln.F_meas_au" in data:
self.hasAmplitudes = True
return
def _sfcif2mtz(self, cifPath, mtzPath):
"""Convert a CIF containing structure factors to an MTZ file."""
cmd = ["cif2mtz", "hklin", cifPath, "hklout", mtzPath]
logfile = os.path.join(os.getcwd(), "cif2mtz.log")
# Need empty stdin to trigger eof to get program to run
retcode = ample_util.run_command(cmd, stdin="", logfile=logfile)
if retcode != 0:
raise RuntimeError("Error running sfcif2mtz. Check the logfile: {0}".format(logfile))
[docs] def sfcif2mtz(self, cifPath):
"""Convert a CIF containing structure factors to an MTZ file."""
# Create a name for the mtz
name = os.path.splitext(os.path.basename(cifPath))[0]
mtzPath = os.path.join(os.getcwd(), name + ".mtz")
self.logger.info("sfcif2mtz: sf-cif file will be converted to mtz: {0}".format(cifPath))
# First parse the cif file - checks if amplitudes present and whether any reflections
# have been set aside for RFree
self._parseCif(cifPath)
if not self.hasAmplitudes:
raise RuntimeError("sfcif2mtz: no amplitudes in sf-cif - need to run ctruncate!")
# Convert to mtz - this might add a spurious FREE column
self._sfcif2mtz(cifPath, mtzPath)
self.logger.info("sfcif2mtz: created mtz file: {0}".format(mtzPath))
return mtzPath
if __name__ == '__main__':
assert len(sys.argv) == 2
cifpath = sys.argv[1]
cp = CifParser()
mtzPath = cp.sfcif2mtz(cifpath)