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
import mtz_util # Avoid circular dependencies

[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) # See if reflections have been set aside for Rfree or if we need to calculate if not self.hasRfree: if self.reflnStatus: # cif2mtz will have added a useless FREE column so we remove it self.logger.info( "sfcif2mtz: no valid RFREE data so removing FREE column added by mtz2cif") mtzPath = mtz_util.del_column( mtzPath, 'FREE') # # If there are no RFREE # self.logger.info( "sfcif2mtz: no RFree flags so running uniqueify") # mtzPath = mtz_util.addRfree(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)