def SplitExperiments(DriverType=None): """A factory for CombineExperimentsWrapper classes.""" DriverInstance = DriverFactory.Driver(DriverType) class SplitExperimentsWrapper(DriverInstance.__class__): def __init__(self): DriverInstance.__class__.__init__(self) self.set_executable("dials.split_experiments") self._experiments_filename = [] self._reflections_filename = [] self._experiments_prefix = None self._reflections_prefix = None self._by_wavelength = False def add_experiments(self, experiments_filename): self._experiments_filename.append(experiments_filename) def add_reflections(self, reflections_filename): self._reflections_filename.append(reflections_filename) def get_experiments_filename(self): return self._experiments_filename def get_reflections_filename(self): return self._experiments_filename def set_by_wavelength(self, boolean): self._by_wavelength = boolean def run(self): logger.debug("Running dials.split_experiments") self.clear_command_line() assert len(self._experiments_filename) == 1 assert len(self._experiments_filename) == len( self._reflections_filename) self.add_command_line(self._experiments_filename) self.add_command_line(self._reflections_filename) if not self._experiments_prefix: self._experiments_prefix = "split" self.add_command_line("output.experiments_prefix=%s" % self._experiments_prefix) if not self._reflections_prefix: self._reflections_prefix = "split" self.add_command_line("output.reflections_prefix=%s" % self._reflections_prefix) if self._by_wavelength: self.add_command_line("by_wavelength=True") self.start() self.close_wait() self.check_for_errors() return SplitExperimentsWrapper()
def BrehmDiederichs(DriverType=None): '''A factory for BrehmDiederichsWrapper classes.''' from xia2.Driver.DriverFactory import DriverFactory DriverInstance = DriverFactory.Driver(DriverType) class BrehmDiederichsWrapper(DriverInstance.__class__): def __init__(self): DriverInstance.__class__.__init__(self) self.set_executable('cctbx.brehm_diederichs') self._input_filenames = [] self._asymmetric = None self._output_filenames = [] self._reindexing_dict = {} return def set_input_filenames(self, filenames): self._input_filenames = filenames return def set_asymmetric(self, asymmetric): self._asymmetric = asymmetric def get_output_filenames(self): return self._output_filenames def get_reindexing_dict(self): return self._reindexing_dict def run(self): from xia2.Handlers.Streams import Debug Debug.write('Running cctbx.brehm_diederichs') self.clear_command_line() if self._asymmetric is not None: assert isinstance(self._asymmetric, int) self.add_command_line('asymmetric=%i' % self._asymmetric) self.add_command_line('show_plot=False') self.add_command_line('save_plot=True') for filename in self._input_filenames: self.add_command_line(filename) self.start() self.close_wait() self.check_for_errors() import os results_filename = os.path.join(self.get_working_directory(), 'reindex.txt') assert os.path.exists(results_filename) with open(results_filename, 'rb') as f: for line in f.readlines(): filename, reindex_op = line.strip().rsplit(' ', 1) self._reindexing_dict[os.path.abspath( filename)] = reindex_op return return BrehmDiederichsWrapper()
def Xtriage(DriverType=None): """A factory for the Xtriage wrappers.""" DriverInstance = DriverFactory.Driver("simple") class XtriageWrapper(DriverInstance.__class__): """A wrapper class for phenix.xtriage.""" def __init__(self): DriverInstance.__class__.__init__(self) self.set_executable("mmtbx.xtriage") self._mtz = None return def set_mtz(self, mtz): self._mtz = mtz return def run(self): import os assert self._mtz is not None assert os.path.isfile(self._mtz) self.add_command_line(self._mtz) self.start() self.close_wait() self.check_for_errors() return XtriageWrapper()
def Header(DriverType=None): """A factory for HeaderWrapper(ipmosflm) classes.""" from xia2.Driver.DriverFactory import DriverFactory DriverInstance = DriverFactory.Driver(DriverType) class HeaderWrapper(DriverInstance.__class__): def __init__(self): DriverInstance.__class__.__init__(self) import os self.set_executable( os.path.join(os.environ["CCP4"], "bin", "ipmosflm")) from collections import defaultdict self._headers = defaultdict(dict) def __call__(self, fp, images=None): from xia2.Handlers.Streams import Debug if images is None: images = fp.get_matching_images() Debug.write("Running mosflm to read header from images %d to %d" % (min(images), max(images))) self.start() self.input('template "%s"' % fp.get_template()) self.input('directory "%s"' % fp.get_directory()) self.input("image %d" % images[0]) self.input("head") self.input("go") for image in images[1:]: self.input("image %d" % image) self.input("head brief") self.input("go") self.close_wait() image = -1 for record in self.get_all_output(): if "===> image" in record: image = int(record.split()[-1]) continue if "Start and end phi values" in record: tokens = record.split() start, end = float(tokens[-4]), float(tokens[-2]) image = int(tokens[7]) self._headers["phi-start"][image] = start self._headers["phi-end"][image] = end if "recognized as:" in record: self._headers["mosflm-detector"] = record.split()[-1] if "Wavelength of" in record: self._headers["wavelength"] = float( record.split()[2].replace("A", "")) return HeaderWrapper()
def ExportXDS(DriverType=None): """A factory for ExportXDSWrapper classes.""" from xia2.Driver.DriverFactory import DriverFactory DriverInstance = DriverFactory.Driver(DriverType) class ExportXDSWrapper(DriverInstance.__class__): def __init__(self): DriverInstance.__class__.__init__(self) self.set_executable("dials.export") self._sweep_filename = None self._crystal_filename = None def set_experiments_filename(self, experiments_filename): self._experiments_filename = experiments_filename def run(self): from xia2.Handlers.Streams import Debug Debug.write("Running dials.export") self.clear_command_line() self.add_command_line(self._experiments_filename) self.add_command_line("format=xds") self.start() self.close_wait() self.check_for_errors() return ExportXDSWrapper()
def Header(DriverType = None): '''A factory for HeaderWrapper(ipmosflm) classes.''' from xia2.Driver.DriverFactory import DriverFactory DriverInstance = DriverFactory.Driver(DriverType) class HeaderWrapper(DriverInstance.__class__): def __init__(self): DriverInstance.__class__.__init__(self) import os self.set_executable(os.path.join( os.environ['CCP4'], 'bin', 'ipmosflm')) from collections import defaultdict self._headers = defaultdict(dict) def __call__(self, fp, images = None): from xia2.Handlers.Streams import Debug if images is None: images = fp.get_matching_images() Debug.write('Running mosflm to read header from images %d to %d' % \ (min(images), max(images))) self.start() self.input('template "%s"' % fp.get_template()) self.input('directory "%s"' % fp.get_directory()) self.input('image %d' % images[0]) self.input('head') self.input('go') for image in images[1:]: self.input('image %d' % image) self.input('head brief') self.input('go') self.close_wait() image = -1 for record in self.get_all_output(): if '===> image' in record: image = int(record.split()[-1]) continue if 'Start and end phi values' in record: tokens = record.split() start, end = float(tokens[-4]), float(tokens[-2]) image = int(tokens[7]) self._headers['phi-start'][image] = start self._headers['phi-end'][image] = end if 'recognized as:' in record: self._headers['mosflm-detector'] = record.split()[-1] if 'Wavelength of' in record: self._headers['wavelength'] = float( record.split()[2].replace('A', '')) return HeaderWrapper()
def StereographicProjection(DriverType=None): '''A factory for StereographicProjectionWrapper classes.''' from xia2.Driver.DriverFactory import DriverFactory DriverInstance = DriverFactory.Driver(DriverType) class StereographicProjectionWrapper(DriverInstance.__class__): def __init__(self): DriverInstance.__class__.__init__(self) self.set_executable('dials.stereographic_projection') self._experiments_filenames = [] self._hkl = None self._plot_filename = None self._json_filename = None def add_experiments(self, experiments_filename): self._experiments_filenames.append(experiments_filename) def set_hkl(self, hkl): assert len(hkl) == 3 self._hkl = hkl def get_plot_filename(self): return self._plot_filename def get_json_filename(self): return self._json_filename def run(self): from xia2.Handlers.Streams import Debug Debug.write('Running dials.stereographic_projection') assert len(self._experiments_filenames) > 0 assert self._hkl is not None self.clear_command_line() for expt in self._experiments_filenames: self.add_command_line(expt) self.add_command_line('frame=laboratory') self.add_command_line('plot.show=False') self.add_command_line('hkl=%i,%i,%i' % self._hkl) self._plot_filename = '%i_stereographic_projection_%i%i%i.png' % ( self.get_xpid(), self._hkl[0], self._hkl[1], self._hkl[2]) self._json_filename = '%i_stereographic_projection_%i%i%i.json' % ( self.get_xpid(), self._hkl[0], self._hkl[1], self._hkl[2]) self.add_command_line('plot.filename=%s' % self._plot_filename) self.add_command_line('json.filename=%s' % self._json_filename) self.start() self.close_wait() self.check_for_errors() return StereographicProjectionWrapper()
def anvil_correction(driver_type=None): """A factory for AnvilCorrectionWrapper classes.""" driver_instance = DriverFactory.Driver(driver_type) class AnvilCorrectionWrapper(driver_instance.__class__): """Wrap dials.anvil_correction.""" def __init__(self): super(AnvilCorrectionWrapper, self).__init__() self.set_executable("dials.anvil_correction") # Input and output files. # None is a valid value only for the output experiment list filename. self.experiments_filenames = [] # type: List[str, ...] self.reflections_filenames = [] # type: List[str, ...] self.output_experiments_filename = None # type: Optional[str] self.output_reflections_filename = None # type: Optional[str] # Parameters to pass to dials.anvil_correction self.density = None # type: Optional[SupportsFloat] self.thickness = None # type: Optional[SupportsFloat] self.normal = None # type: Optional[Tuple[3 * (SupportsFloat,)]] def run(self): """Run dials.anvil_correction if the parameters are valid.""" # We should only start if the properties have been set. assert self.experiments_filenames assert self.reflections_filenames # None is a valid value for the output experiment list filename. assert self.output_reflections_filename assert self.density assert self.thickness assert self.normal self.clear_command_line() self.add_command_line(self.experiments_filenames) self.add_command_line(self.reflections_filenames) if self.output_experiments_filename: self.add_command_line("output.experiments=%s" % self.output_experiments_filename) self.add_command_line("output.reflections=%s" % self.output_reflections_filename) self.add_command_line("anvil.density=%s" % self.density) self.add_command_line("anvil.thickness=%s" % self.thickness) self.add_command_line("anvil.normal=%s,%s,%s" % tuple(self.normal)) self.start() self.close_wait() self.check_for_errors() assert os.path.exists(self.output_reflections_filename) return AnvilCorrectionWrapper()
def ExportSpotXDS(DriverType=None, params=None): DriverInstance = DriverFactory.Driver(DriverType) class ExportSpotXDSWrapper(DriverInstance.__class__, FrameProcessor): """A wrapper for wrapping dials.export_spot_xds.""" def __init__(self, params=None): super(ExportSpotXDSWrapper, self).__init__() # phil parameters if not params: params = master_params.extract() self._params = params # now set myself up... self.set_executable("dials.export_spot_xds") self._input_data_files = {} self._output_data_files = {} self._input_data_files_list = [] self._output_data_files_list = [] # getter and setter for input / output data def set_input_data_file(self, name, data): self._input_data_files[name] = data def get_output_data_file(self, name): return self._output_data_files[name] def run(self): """Run dials.spotfinder.""" self.add_command_line(self._input_data_files.keys()) self.start() self.close_wait() self.check_for_errors() self._output_data_files.setdefault( "SPOT.XDS", open( os.path.join(self.get_working_directory(), "SPOT.XDS"), "rb" ).read(), ) output = self.get_all_output() print("".join(output)) return ExportSpotXDSWrapper(params=params)
def Report(DriverType=None): '''A factory for ReportWrapper classes.''' from xia2.Driver.DriverFactory import DriverFactory DriverInstance = DriverFactory.Driver(DriverType) class ReportWrapper(DriverInstance.__class__): def __init__(self): DriverInstance.__class__.__init__(self) self.set_executable('xia2.report') self._mtz_filename = None self._html_filename = None self._chef_min_completeness = None return def set_mtz_filename(self, mtz_filename): self._mtz_filename = mtz_filename def set_html_filename(self, html_filename): self._html_filename = html_filename def get_html_filename(self, html_filename): return self._html_filename def set_chef_min_completeness(self, min_completeness): self._chef_min_completeness = min_completeness def run(self): from xia2.Handlers.Streams import Debug Debug.write('Running xia2.report') assert self._mtz_filename is not None self.clear_command_line() self.add_command_line(self._mtz_filename) if self._chef_min_completeness is not None: self.add_command_line('chef_min_completeness=%s' % self._chef_min_completeness) self.start() self.close_wait() self.check_for_errors() html_filename = os.path.join(self.get_working_directory(), 'xia2-report.html') assert os.path.exists(html_filename) if self._html_filename is None: self._html_filename = html_filename else: import shutil shutil.move(html_filename, self._html_filename) return return ReportWrapper()
def LabelitMosflmMatrix(DriverType=None): '''Factory for LabelitMosflmMatrix wrapper classes, with the specified Driver type.''' DriverInstance = DriverFactory.Driver(DriverType) class LabelitMosflmMatrixWrapper(DriverInstance.__class__): '''A wrapper for the program labelit.mosflm_matrix - which will calculate the matrix for mosflm integration.''' def __init__(self): DriverInstance.__class__.__init__(self) self.set_executable('labelit.mosflm_matrix') self._solution = None self._mosflm_beam = None def set_solution(self, solution): self._solution = solution def calculate(self): '''Compute matrix for solution #.''' if self._solution is None: raise RuntimeError('solution not selected') task = 'Compute matrix for solution %02d' % self._solution self.add_command_line('%d' % self._solution) self.start() self.close_wait() output = open( os.path.join(self.get_working_directory(), 'integration%02d.csh' % self._solution)).readlines() matrix = output[2:11] # also check for the beam centre in mosflm land! - ignoring # SWUNG OUT though I should probably check the two-theta # value too... for o in output: if 'BEAM' in o[:4]: self._mosflm_beam = map(float, o.split()[-2:]) return matrix def get_mosflm_beam(self): return self._mosflm_beam return LabelitMosflmMatrixWrapper()
def MultiCrystalAnalysis(DriverType=None): '''A factory for MultiCrystalAnalysisWrapper classes.''' from xia2.Driver.DriverFactory import DriverFactory DriverInstance = DriverFactory.Driver(DriverType) class MultiCrystalAnalysisWrapper(DriverInstance.__class__): def __init__(self): DriverInstance.__class__.__init__(self) self.set_executable('cctbx.python') self._argv = [] self._nproc = None self._njob = None self._mp_mode = None self._phil_file = None self._clusters = None return def add_command_line_args(self, args): self._argv.extend(args) def run(self): from xia2.Handlers.Streams import Debug Debug.write('Running MultiCrystalAnalysis.py') self.clear_command_line() from xia2.Modules import MultiCrystalAnalysis as mca_module self.add_command_line(mca_module.__file__) for arg in self._argv: self.add_command_line(arg) self.start() self.close_wait() self.check_for_errors() self._clusters_json = os.path.join(self.get_working_directory(), 'intensity_clusters.json') assert os.path.exists(self._clusters_json) import json with open(self._clusters_json, 'rb') as f: self._dict = json.load(f) self._clusters = self._dict['clusters'] return def get_clusters(self): return self._clusters def get_dict(self): return self._dict return MultiCrystalAnalysisWrapper()
def BrehmDiederichs(DriverType=None): """A factory for BrehmDiederichsWrapper classes.""" DriverInstance = DriverFactory.Driver(DriverType) class BrehmDiederichsWrapper(DriverInstance.__class__): def __init__(self): DriverInstance.__class__.__init__(self) self.set_executable("cctbx.brehm_diederichs") self._input_filenames = [] self._asymmetric = None self._output_filenames = [] self._reindexing_dict = {} def set_input_filenames(self, filenames): self._input_filenames = filenames def set_asymmetric(self, asymmetric): self._asymmetric = asymmetric def get_reindexing_dict(self): return self._reindexing_dict def run(self): logger.debug("Running cctbx.brehm_diederichs") self.clear_command_line() if self._asymmetric is not None: assert isinstance(self._asymmetric, int) self.add_command_line("asymmetric=%i" % self._asymmetric) self.add_command_line("show_plot=False") self.add_command_line("save_plot=True") for filename in self._input_filenames: self.add_command_line(filename) self.start() self.close_wait() self.check_for_errors() results_filename = os.path.join(self.get_working_directory(), "reindex.txt") assert os.path.exists(results_filename) with open(results_filename, "rb") as f: for line in f.readlines(): filename, reindex_op = line.strip().rsplit(" ", 1) self._reindexing_dict[os.path.abspath( filename)] = reindex_op return BrehmDiederichsWrapper()
def ShadowPlot(DriverType=None): """A factory for ShadowPlotWrapper classes.""" from xia2.Driver.DriverFactory import DriverFactory DriverInstance = DriverFactory.Driver(DriverType) class ShadowPlotWrapper(DriverInstance.__class__, FrameProcessor): def __init__(self): super(ShadowPlotWrapper, self).__init__() self.set_executable("dials.shadow_plot") self._sweep_filename = None self._json_filename = None def set_sweep_filename(self, sweep_filename): self._sweep_filename = sweep_filename def set_json_filename(self, json_filename): self._json_filename = json_filename def get_json_filename(self): return self._json_filename def get_results(self): assert self._json_filename is not None and os.path.isfile( self._json_filename ) import json with open(self._json_filename, "rb") as f: results = json.load(f) return results def run(self): self.clear_command_line() assert self._sweep_filename is not None self.add_command_line("%s" % self._sweep_filename) if self._json_filename is not None: self.add_command_line("json=%s" % self._json_filename) self.add_command_line("mode=1d") self.start() self.close_wait() self.check_for_errors() return ShadowPlotWrapper()
def ExportBest(DriverType=None): """A factory for ExportMtzWrapper classes.""" from xia2.Driver.DriverFactory import DriverFactory DriverInstance = DriverFactory.Driver(DriverType) class ExportBestWrapper(DriverInstance.__class__): def __init__(self): DriverInstance.__class__.__init__(self) self.set_executable("dials.export") self._experiments_filename = None self._reflections_filename = None self._prefix = "best" def set_experiments_filename(self, experiments_filename): self._experiments_filename = experiments_filename def get_experiments_filename(self): return self._experiments_filename def set_reflections_filename(self, reflections_filename): self._reflections_filename = reflections_filename def get_reflections_filename(self): return self._reflections_filename def set_prefix(self, prefix): self._prefix = prefix def get_prefix(self): return self._prefix def run(self): from xia2.Handlers.Streams import Debug Debug.write("Running dials.export") self.clear_command_line() self.add_command_line("experiments=%s" % self._experiments_filename) self.add_command_line("reflections=%s" % self._reflections_filename) self.add_command_line("format=best") self.add_command_line("best.prefix=%s" % self._prefix) self.start() self.close_wait() self.check_for_errors() return ExportBestWrapper()
def ExportXDSASCII(DriverType=None): """A factory for ExportXDSASCIISWrapper classes.""" from xia2.Driver.DriverFactory import DriverFactory DriverInstance = DriverFactory.Driver(DriverType) class ExportXDSASCIISWrapper(DriverInstance.__class__): def __init__(self): DriverInstance.__class__.__init__(self) self.set_executable("dials.export") self._experiments_filename = None self._reflections_filename = None self._hkl_filename = "DIALS.HKL" def set_experiments_filename(self, experiments_filename): self._experiments_filename = experiments_filename def set_reflections_filename(self, reflections_filename): self._reflections_filename = reflections_filename def set_hkl_filename(self, hkl_filename): self._hkl_filename = hkl_filename def get_hkl_filename(self): return self._hkl_filename def run(self): from xia2.Handlers.Streams import Debug Debug.write("Running dials.export") assert self._experiments_filename is not None assert self._reflections_filename is not None self.clear_command_line() self.add_command_line(self._experiments_filename) self.add_command_line(self._reflections_filename) if self._hkl_filename is not None: self.add_command_line("xds_ascii.hklout=%s" % self._hkl_filename) self.add_command_line("format=xds_ascii") self.start() self.close_wait() self.check_for_errors() return ExportXDSASCIISWrapper()
def GenerateRaster(DriverType=None): """A factory for GenerateRasterWrapper(ipmosflm) classes.""" from xia2.Driver.DriverFactory import DriverFactory DriverInstance = DriverFactory.Driver(DriverType) class GenerateRasterWrapper(DriverInstance.__class__): def __init__(self): DriverInstance.__class__.__init__(self) import os self.set_executable( os.path.join(os.environ["CCP4"], "bin", "ipmosflm")) def __call__(self, indxr, images): from xia2.Handlers.Streams import Debug Debug.write("Running mosflm to generate RASTER, SEPARATION") self.start() self.input('template "%s"' % indxr.get_template()) self.input('directory "%s"' % indxr.get_directory()) self.input("beam %f %f" % indxr.get_indexer_beam_centre()) self.input("distance %f" % indxr.get_indexer_distance()) self.input("wavelength %f" % indxr.get_wavelength()) self.input("findspots file spots.dat") for i in images: self.input("findspots find %d" % i) self.input("go") self.close_wait() p = {} # scrape from the output the values we want... for o in self.get_all_output(): if "parameters have been set to" in o: p["raster"] = map(int, o.split()[-5:]) if "(currently SEPARATION" in o: p["separation"] = map(float, o.replace(")", "").split()[-2:]) return p return GenerateRasterWrapper()
def Report(DriverType=None): """A factory for ReportWrapper classes.""" from xia2.Driver.DriverFactory import DriverFactory DriverInstance = DriverFactory.Driver(DriverType) class ReportWrapper(DriverInstance.__class__): def __init__(self): DriverInstance.__class__.__init__(self) self.set_executable("dials.report") self._experiments_filename = None self._reflections_filename = None self._html_filename = None def set_experiments_filename(self, experiments_filename): self._experiments_filename = experiments_filename def set_reflections_filename(self, reflections_filename): self._reflections_filename = reflections_filename def set_html_filename(self, html_filename): self._html_filename = html_filename def run(self, wait_for_completion=False): from xia2.Handlers.Streams import Debug Debug.write("Running dials.report") self.clear_command_line() assert (self._experiments_filename is not None or self._reflections_filename is not None) if self._experiments_filename is not None: self.add_command_line(self._experiments_filename) if self._reflections_filename is not None: self.add_command_line(self._reflections_filename) if self._html_filename is not None: self.add_command_line("output.html=%s" % self._html_filename) self.start() if wait_for_completion: self.close_wait() else: self.close() self.check_for_errors() return ReportWrapper()
def EstimateResolutionLimit(DriverType=None): """A factory for EstimateResolutionLimitWrapper classes.""" from xia2.Driver.DriverFactory import DriverFactory DriverInstance = DriverFactory.Driver(DriverType) class EstimateResolutionLimitWrapper(DriverInstance.__class__): def __init__(self): DriverInstance.__class__.__init__(self) self.set_executable("dials.estimate_resolution_limit") self._experiments_filename = None self._reflections_filename = None self._estimated_d_min = None def set_experiments_filename(self, experiments_filename): self._experiments_filename = experiments_filename def set_reflections_filename(self, reflections_filename): self._reflections_filename = reflections_filename def get_estimated_d_min(self): return self._estimated_d_min def run(self): from xia2.Handlers.Streams import Debug Debug.write("Running dials.estimate_resolution_limit") self.clear_command_line() self.add_command_line(self._experiments_filename) self.add_command_line(self._reflections_filename) self.start() self.close_wait() self.check_for_errors() for line in self.get_all_output(): if line.startswith("estimated d_min:"): self._estimated_d_min = float(line.split(":")[1]) return self._estimated_d_min return EstimateResolutionLimitWrapper()
def GenerateRaster(DriverType=None): '''A factory for GenerateRasterWrapper(ipmosflm) classes.''' from xia2.Driver.DriverFactory import DriverFactory DriverInstance = DriverFactory.Driver(DriverType) class GenerateRasterWrapper(DriverInstance.__class__): def __init__(self): DriverInstance.__class__.__init__(self) import os self.set_executable( os.path.join(os.environ['CCP4'], 'bin', 'ipmosflm')) def __call__(self, indxr, images): from xia2.Handlers.Streams import Debug Debug.write('Running mosflm to generate RASTER, SEPARATION') self.start() self.input('template "%s"' % indxr.get_template()) self.input('directory "%s"' % indxr.get_directory()) self.input('beam %f %f' % indxr.get_indexer_beam_centre()) self.input('distance %f' % indxr.get_indexer_distance()) self.input('wavelength %f' % indxr.get_wavelength()) self.input('findspots file spots.dat') for i in images: self.input('findspots find %d' % i) self.input('go') self.close_wait() p = {} # scrape from the output the values we want... for o in self.get_all_output(): if 'parameters have been set to' in o: p['raster'] = map(int, o.split()[-5:]) if '(currently SEPARATION' in o: p['separation'] = map(float, o.replace(')', '').split()[-2:]) return p return GenerateRasterWrapper()
def Report(DriverType=None): """A factory for ReportWrapper classes.""" DriverInstance = DriverFactory.Driver(DriverType) class ReportWrapper(DriverInstance.__class__): def __init__(self): DriverInstance.__class__.__init__(self) self.set_executable("xia2.report") self._mtz_filename = None self._html_filename = None self._chef_min_completeness = None def set_mtz_filename(self, mtz_filename): self._mtz_filename = mtz_filename def set_html_filename(self, html_filename): self._html_filename = html_filename def set_chef_min_completeness(self, min_completeness): self._chef_min_completeness = min_completeness def run(self): logger.debug("Running xia2.report") assert self._mtz_filename is not None self.clear_command_line() self.add_command_line(self._mtz_filename) if self._chef_min_completeness is not None: self.add_command_line("chef_min_completeness=%s" % self._chef_min_completeness) self.start() self.close_wait() self.check_for_errors() html_filename = os.path.join(self.get_working_directory(), "xia2-report.html") assert os.path.exists(html_filename) if self._html_filename is None: self._html_filename = html_filename else: shutil.move(html_filename, self._html_filename) return ReportWrapper()
def Freerflag(DriverType=None): """A factory for FreerflagWrapper classes.""" DriverInstance = DriverFactory.Driver(DriverType) CCP4DriverInstance = DecoratorFactory.Decorate(DriverInstance, "ccp4") class FreerflagWrapper(CCP4DriverInstance.__class__): """A wrapper for Freerflag, using the CCP4-ified Driver.""" def __init__(self): # generic things CCP4DriverInstance.__class__.__init__(self) Citations.cite("ccp4") self.set_executable( os.path.join(os.environ.get("CBIN", ""), "freerflag")) self._free_fraction = 0.05 def set_free_fraction(self, free_fraction): self._free_fraction = free_fraction def add_free_flag(self): self.check_hklin() self.check_hklout() self.start() self.input("freerfrac %.3f" % self._free_fraction) self.close_wait() self.check_for_errors() self.check_ccp4_errors() def complete_free_flag(self): self.check_hklin() self.check_hklout() free_column = FindFreeFlag(self.get_hklin()) self.start() self.input("freerfrac %.3f" % self._free_fraction) self.input("complete FREE=%s" % free_column) self.close_wait() self.check_for_errors() self.check_ccp4_errors() return FreerflagWrapper()
def EstimateGain(DriverType=None): """A factory for EstimateGainWrapper classes.""" from xia2.Driver.DriverFactory import DriverFactory DriverInstance = DriverFactory.Driver(DriverType) class EstimateGainWrapper(DriverInstance.__class__, FrameProcessor): def __init__(self): super(EstimateGainWrapper, self).__init__() self.set_executable("dials.estimate_gain") self._sweep_filename = None self._kernel_size = None self._gain = None def set_sweep_filename(self, sweep_filename): self._sweep_filename = sweep_filename def set_kernel_size(self, kernel_size): self._kernel_size = kernel_size def get_gain(self): return self._gain def run(self): self.clear_command_line() assert self._sweep_filename is not None self.add_command_line("%s" % self._sweep_filename) if self._kernel_size is not None: self.add_command_line("kernel_size=%i,%i" % self._kernel_size) self.start() self.close_wait() self.check_for_errors() for line in self.get_all_output(): if "Estimated gain:" in line: self._gain = float(line.split(":")[-1].strip()) return EstimateGainWrapper()
def Freerflag(DriverType=None): '''A factory for FreerflagWrapper classes.''' DriverInstance = DriverFactory.Driver(DriverType) CCP4DriverInstance = DecoratorFactory.Decorate(DriverInstance, 'ccp4') class FreerflagWrapper(CCP4DriverInstance.__class__): '''A wrapper for Freerflag, using the CCP4-ified Driver.''' def __init__(self): # generic things CCP4DriverInstance.__class__.__init__(self) self.set_executable( os.path.join(os.environ.get('CBIN', ''), 'freerflag')) self._free_fraction = 0.05 def set_free_fraction(self, free_fraction): self._free_fraction = free_fraction def add_free_flag(self): self.check_hklin() self.check_hklout() self.start() self.input('freerfrac %.3f' % self._free_fraction) self.close_wait() self.check_for_errors() self.check_ccp4_errors() def complete_free_flag(self): self.check_hklin() self.check_hklout() free_column = FindFreeFlag(self.get_hklin()) self.start() self.input('freerfrac %.3f' % self._free_fraction) self.input('complete FREE=%s' % free_column) self.close_wait() self.check_for_errors() self.check_ccp4_errors() return FreerflagWrapper()
def AlignCrystal(DriverType=None): """A factory for AlignCrystalWrapper classes.""" from xia2.Driver.DriverFactory import DriverFactory DriverInstance = DriverFactory.Driver(DriverType) class AlignCrystalWrapper(DriverInstance.__class__): def __init__(self): DriverInstance.__class__.__init__(self) self.set_executable("dials.align_crystal") self._experiments_filename = None self._json_filename = "align_crystal.json" def set_experiments_filename(self, experiments_filename): self._experiments_filename = experiments_filename def get_experiments_filename(self): return self._experiments_filename def set_json_filename(self, json_filename): self._json_filename = json_filename def get_json_filename(self): return self._json_filename def run(self): from xia2.Handlers.Streams import Debug Debug.write("Running dials.align_crystal") self.clear_command_line() self.add_command_line("experiments=%s" % self._experiments_filename) self.add_command_line("output.json=%s" % self._json_filename) self.start() self.close_wait() self.check_for_errors() return AlignCrystalWrapper()
def Findspots(DriverType=None): """A factory for FindspotsWrapper(ipmosflm) classes.""" from xia2.Driver.DriverFactory import DriverFactory DriverInstance = DriverFactory.Driver(DriverType) class FindspotsWrapper(DriverInstance.__class__): def __init__(self): DriverInstance.__class__.__init__(self) import os self.set_executable( os.path.join(os.environ["CCP4"], "bin", "ipmosflm")) def __call__(self, fp, images): from xia2.Handlers.Streams import Debug Debug.write("Running mosflm to find spots") self.start() self.input('template "%s"' % fp.get_template()) self.input('directory "%s"' % fp.get_directory()) self.input("beam %f %f" % fp.get_beam_centre()) self.input("distance %f" % fp.get_distance()) self.input("wavelength %f" % fp.get_wavelength()) self.input("findspots file spots.dat") for i in images: self.input("findspots find %d" % i) self.input("go") self.close_wait() # FIXME I should really gather some interesting information about # the spot finding in here... import os return os.path.join(self.get_working_directory(), "spots.dat") return FindspotsWrapper()
def Index(DriverType=None): """A factory for IndexWrapper classes.""" from xia2.Driver.DriverFactory import DriverFactory DriverInstance = DriverFactory.Driver(DriverType) class IndexWrapper(DriverInstance.__class__): def __init__(self): DriverInstance.__class__.__init__(self) self.set_executable("dials.index") self._sweep_filenames = [] self._spot_filenames = [] self._unit_cell = None self._space_group = None self._maximum_spot_error = None self._detector_fix = None self._beam_fix = None self._indexing_method = "fft3d" self._p1_cell = None self._indxr_input_cell = None self._indxr_input_lattice = None self._reflections_per_degree = None self._fft3d_n_points = None self._histogram_binning = None self._nearest_neighbor_percentile = None self._experiment_filename = None self._indexed_filename = None self._nref = None self._rmsd_x = None self._rmsd_y = None self._rmsd_z = None self._max_cell = None self._max_cell_max_height_fraction = None self._min_cell = None self._d_min_start = None self._phil_file = None self._outlier_algorithm = None self._close_to_spindle_cutoff = None def add_sweep_filename(self, sweep_filename): self._sweep_filenames.append(sweep_filename) def add_spot_filename(self, spot_filename): self._spot_filenames.append(spot_filename) def set_indexer_input_lattice(self, lattice): self._indxr_input_lattice = lattice def set_indexer_user_input_lattice(self, user): self._indxr_user_input_lattice = user def set_indexer_input_cell(self, cell): if not isinstance(cell, type(())) or len(cell) != 6: raise RuntimeError("cell must be a 6-tuple de floats") self._indxr_input_cell = tuple(map(float, cell)) def set_maximum_spot_error(self, maximum_spot_error): self._maximum_spot_error = maximum_spot_error def set_detector_fix(self, detector_fix): self._detector_fix = detector_fix def set_beam_fix(self, beam_fix): self._beam_fix = beam_fix def set_indexing_method(self, method): self._indexing_method = method def get_indexing_method(self): return self._indexing_method def set_reflections_per_degree(self, reflections_per_degree): self._reflections_per_degree = int(reflections_per_degree) def set_fft3d_n_points(self, n_points): self._fft3d_n_points = n_points def set_histogram_binning(self, histogram_binning): self._histogram_binning = histogram_binning def set_nearest_neighbor_percentile(self, nearest_neighbor_percentile): self._nearest_neighbor_percentile = nearest_neighbor_percentile def get_sweep_filenames(self): return self._sweep_filenames def get_experiments_filename(self): return self._experiment_filename def get_indexed_filename(self): return self._indexed_filename def get_p1_cell(self): return self._p1_cell def set_phil_file(self, phil_file): self._phil_file = phil_file def set_outlier_algorithm(self, outlier_algorithm): self._outlier_algorithm = outlier_algorithm def get_nref_rmsds(self): return self._nref, (self._rmsd_x, self._rmsd_y, self._rmsd_z) def set_max_cell(self, max_cell=None, max_height_fraction=None): if max_cell is not None: self._max_cell = max_cell if max_height_fraction is not None: self._max_cell_max_height_fraction = max_height_fraction def set_min_cell(self, min_cell): self._min_cell = min_cell def set_d_min_start(self, d_min_start): self._d_min_start = d_min_start def set_close_to_spindle_cutoff(self, close_to_spindle_cutoff): self._close_to_spindle_cutoff = close_to_spindle_cutoff def run(self, method): from xia2.Handlers.Streams import Debug Debug.write("Running dials.index") self.clear_command_line() for f in self._sweep_filenames: self.add_command_line(f) for f in self._spot_filenames: self.add_command_line(f) if len(self._sweep_filenames) > 1: self.add_command_line("auto_reduction.action=fix") self.add_command_line("indexing.method=%s" % method) nproc = PhilIndex.params.xia2.settings.multiprocessing.nproc self.set_cpu_threads(nproc) self.add_command_line("indexing.nproc=%i" % nproc) if PhilIndex.params.xia2.settings.small_molecule: self.add_command_line("filter_ice=false") if self._reflections_per_degree is not None: self.add_command_line("reflections_per_degree=%i" % self._reflections_per_degree) if self._fft3d_n_points is not None: self.add_command_line( "fft3d.reciprocal_space_grid.n_points=%i" % self._fft3d_n_points) if self._close_to_spindle_cutoff is not None: self.add_command_line("close_to_spindle_cutoff=%f" % self._close_to_spindle_cutoff) if self._outlier_algorithm: self.add_command_line("outlier.algorithm=%s" % self._outlier_algorithm) if self._max_cell: self.add_command_line("max_cell=%g" % self._max_cell) if self._max_cell_max_height_fraction is not None: self.add_command_line("max_height_fraction=%g" % self._max_cell_max_height_fraction) if self._min_cell: self.add_command_line("min_cell=%d" % self._min_cell) if self._histogram_binning is not None: self.add_command_line( "max_cell_estimation.histogram_binning=%s" % self._histogram_binning) if self._nearest_neighbor_percentile is not None: self.add_command_line( "max_cell_estimation.nearest_neighbor_percentile=%s" % self._nearest_neighbor_percentile) if self._d_min_start: self.add_command_line("d_min_start=%f" % self._d_min_start) if self._indxr_input_lattice is not None: from xia2.Experts.SymmetryExpert import lattice_to_spacegroup_number self._symm = lattice_to_spacegroup_number( self._indxr_input_lattice) self.add_command_line("known_symmetry.space_group=%s" % self._symm) if self._indxr_input_cell is not None: self.add_command_line( 'known_symmetry.unit_cell="%s,%s,%s,%s,%s,%s"' % self._indxr_input_cell) if self._maximum_spot_error: self.add_command_line("maximum_spot_error=%.f" % self._maximum_spot_error) if self._detector_fix: self.add_command_line("detector.fix=%s" % self._detector_fix) if self._beam_fix: self.add_command_line("beam.fix=%s" % self._beam_fix) if self._phil_file is not None: self.add_command_line("%s" % self._phil_file) self._experiment_filename = os.path.join( self.get_working_directory(), "%d_indexed.expt" % self.get_xpid()) self._indexed_filename = os.path.join( self.get_working_directory(), "%d_indexed.refl" % self.get_xpid()) self.add_command_line("output.experiments=%s" % self._experiment_filename) self.add_command_line("output.reflections=%s" % self._indexed_filename) self.start() self.close_wait() if not os.path.isfile( self._experiment_filename) or not os.path.isfile( self._indexed_filename): # Indexing failed with open(self.get_log_file(), "r") as fh: if "No suitable lattice could be found" in fh.read(): raise libtbx.utils.Sorry( "No suitable indexing solution could be found.\n\n" "You can view the reciprocal space with:\n" "dials.reciprocal_lattice_viewer %s" % " ".join( os.path.normpath( os.path.join(self.get_working_directory(), p)) for p in self._sweep_filenames + self._spot_filenames)) else: raise RuntimeError( "dials.index failed, see log file for more details: %s" % self.get_log_file()) self.check_for_errors() for record in self.get_all_output(): if "Too few reflections to parameterise" in record: Debug.write(record.strip()) from dials.array_family import flex from dxtbx.serialize import load self._experiment_list = load.experiment_list( self._experiment_filename) self._reflections = flex.reflection_table.from_file( self._indexed_filename) crystal = self._experiment_list.crystals()[0] self._p1_cell = crystal.get_unit_cell().parameters() refined_sel = self._reflections.get_flags( self._reflections.flags.used_in_refinement) refl = self._reflections.select(refined_sel) xc, yc, zc = refl["xyzcal.px"].parts() xo, yo, zo = refl["xyzobs.px.value"].parts() import math self._nref = refl.size() self._rmsd_x = math.sqrt(flex.mean(flex.pow2(xc - xo))) self._rmsd_y = math.sqrt(flex.mean(flex.pow2(yc - yo))) self._rmsd_z = math.sqrt(flex.mean(flex.pow2(zc - zo))) return IndexWrapper()
def LabelitDistl(DriverType=None): '''Factory for LabelitDistl wrapper classes, with the specified Driver type.''' DriverInstance = DriverFactory.Driver(DriverType) class LabelitDistlWrapper(DriverInstance.__class__): '''A wrapper for the program labelit.distl - which will provide functionality for looking for ice rings and screening diffraction images.''' def __init__(self): DriverInstance.__class__.__init__(self) self.set_executable('labelit.distl') self._images = [] self._statistics = {} def add_image(self, image): '''Add an image for indexing.''' if not image in self._images: self._images.append(image) return def distl(self): '''Actually analyse the images.''' self._images.sort() for i in self._images: self.add_command_line(i) task = 'Screen images:' for i in self._images: task += ' %s' % i self.set_task(task) self.start() self.close_wait() # check for errors self.check_for_errors() # ok now we're done, let's look through for some useful stuff output = self.get_all_output() current_image = None for o in output: if 'None' in o and 'Resolution' in o: l = o.replace('None', '0.0').split() else: l = o.split() if l[:1] == ['File']: current_image = l[2] self._statistics[current_image] = {} if l[:2] == ['Spot', 'Total']: self._statistics[current_image]['spots_total'] = int(l[-1]) if l[:2] == ['In-Resolution', 'Total']: self._statistics[current_image]['spots'] = int(l[-1]) if l[:3] == ['Good', 'Bragg', 'Candidates']: self._statistics[current_image]['spots_good'] = int(l[-1]) if l[:2] == ['Ice', 'Rings']: self._statistics[current_image]['ice_rings'] = int(l[-1]) if l[:3] == ['Method', '1', 'Resolution']: self._statistics[current_image]['resol_one'] = float(l[-1]) if l[:3] == ['Method', '2', 'Resolution']: self._statistics[current_image]['resol_two'] = float(l[-1]) if l[:3] == ['%Saturation,', 'Top', '50']: self._statistics[current_image]['saturation'] = float( l[-1]) return 'ok' # things to get results from the indexing def get_statistics(self, image): '''Get the screening statistics from image as dictionary. The keys are spots_total, spots, spots_good, ice_rings, resol_one, resol_two.''' return self._statistics[os.path.split(image)[-1]] return LabelitDistlWrapper()
def XScaleR(DriverType = None, correct_decay = True, correct_absorption = True, correct_modulation = True): DriverInstance = DriverFactory.Driver(DriverType) class XScaleWrapper(DriverInstance.__class__): '''A wrapper for wrapping XSCALE.''' def __init__(self): # set up the object ancestors... DriverInstance.__class__.__init__(self) # now set myself up... self._parallel = PhilIndex.params.xia2.settings.multiprocessing.nproc if self._parallel <= 1: self.set_executable('xscale') else: self.set_executable('xscale_par') self._version = 'new' # overall information self._resolution_shells = '' self._cell = None self._spacegroup_number = None self._reindex_matrix = None # corrections to apply - N.B. default values come from the # factory function default arguments... self._correct_decay = correct_decay self._correct_absorption = correct_absorption self._correct_modulation = correct_modulation # input reflections information - including grouping information # in the same way as the .xinfo files - through the wavelength # names, which will be used for the output files. self._input_reflection_files = [] self._input_reflection_wavelength_names = [] self._input_resolution_ranges = [] # these are generated at the run time self._transposed_input = { } self._transposed_input_keys = [] # output self._output_reflection_files = { } self._remove = [] # decisions about the scaling self._crystal = None self._zero_dose = PhilIndex.params.xds.xscale.zero_dose if self._zero_dose: Debug.write('Switching on zero-dose extrapolation') self._anomalous = True self._merge = False # scale factor output self._scale_factor = 1.0 # Rmerge values - for the scale model analysis - N.B. get # one for each data set, obviously... self._rmerges = { } def add_reflection_file(self, reflections, wavelength, resolution): self._input_reflection_files.append(reflections) self._input_reflection_wavelength_names.append(wavelength) self._input_resolution_ranges.append(resolution) def get_remove(self): return self._remove def set_crystal(self, crystal): self._crystal = crystal def set_anomalous(self, anomalous = True): self._anomalous = anomalous def set_correct_decay(self, correct_decay): self._correct_decay = correct_decay def set_correct_absorption(self, correct_absorption): self._correct_absorption = correct_absorption def set_correct_modulation(self, correct_modulation): self._correct_modulation = correct_modulation def get_output_reflection_files(self): '''Get a dictionary of output reflection files keyed by wavelength name.''' return copy.deepcopy(self._output_reflection_files) def _transform_input_files(self): '''Transform the input files to an order we can manage.''' for j in range(len(self._input_reflection_files)): hkl = self._input_reflection_files[j] wave = self._input_reflection_wavelength_names[j] resol = self._input_resolution_ranges[j] if wave not in self._transposed_input: self._transposed_input[wave] = {'hkl':[], 'resol':[]} self._transposed_input_keys.append(wave) self._transposed_input[wave]['hkl'].append(hkl) self._transposed_input[wave]['resol'].append(resol) def set_spacegroup_number(self, spacegroup_number): self._spacegroup_number = spacegroup_number def set_cell(self, cell): self._cell = cell def set_reindex_matrix(self, reindex_matrix): if not len(reindex_matrix) == 12: raise RuntimeError('reindex matrix must be 12 numbers') self._reindex_matrix = reindex_matrix def _write_xscale_inp(self): '''Write xscale.inp.''' self._transform_input_files() xscale_inp = open(os.path.join(self.get_working_directory(), 'XSCALE.INP'), 'w') # header information xscale_inp.write('MAXIMUM_NUMBER_OF_PROCESSORS=%d\n' % \ self._parallel) xscale_inp.write('SPACE_GROUP_NUMBER=%d\n' % \ self._spacegroup_number) xscale_inp.write('UNIT_CELL_CONSTANTS=') xscale_inp.write('%6.2f %6.2f %6.2f %6.2f %6.2f %6.2f\n' % \ tuple(self._cell)) xscale_inp.write( 'MINIMUM_I/SIGMA=%.1f\n' %PhilIndex.params.xds.xscale.min_isigma) if self._reindex_matrix: xscale_inp.write( 'REIDX=%d %d %d %d %d %d %d %d %d %d %d %d\n' % \ tuple(map(int, self._reindex_matrix))) # now information about the wavelengths for wave in self._transposed_input_keys: self._output_reflection_files[wave] = os.path.join( self.get_working_directory(), '%s.HKL' % wave) xscale_inp.write( 'OUTPUT_FILE=%s.HKL ' % wave) if self._version == 'new': xscale_inp.write('\n') if self._anomalous: xscale_inp.write('FRIEDEL\'S_LAW=FALSE MERGE=FALSE\n') xscale_inp.write('STRICT_ABSORPTION_CORRECTION=TRUE\n') else: xscale_inp.write('FRIEDEL\'S_LAW=TRUE MERGE=FALSE\n') if self._version == 'new': xscale_inp.write('\n') for j in range(len(self._transposed_input[wave]['hkl'])): # FIXME note to self, this should now be a local # file which has been placed in here by XDSScaler - # should check that the files exists though... resolution = self._transposed_input[wave]['resol'][j] if resolution[0]: xscale_inp.write( 'INPUT_FILE=%s XDS_ASCII\n' % \ self._transposed_input[wave]['hkl'][j]) xscale_inp.write( 'INCLUDE_RESOLUTION_RANGE= %.2f %.2f\n' % \ (resolution[1], resolution[0])) else: xscale_inp.write( 'INPUT_FILE=%s XDS_ASCII\n' % \ self._transposed_input[wave]['hkl'][j]) # FIXME this needs to be removed before being used again # in anger! # xscale_inp.write('CORRECTIONS=DECAY ABSORPTION\n') corrections = 'CORRECTIONS=' if self._correct_decay: corrections += ' DECAY' if self._correct_modulation: corrections += ' MODULATION' if self._correct_absorption: corrections += ' ABSORPTION' corrections += '\n' xscale_inp.write(corrections) if self._crystal and self._zero_dose: xscale_inp.write('CRYSTAL_NAME=%s\n' % self._crystal) xscale_inp.close() def run(self): '''Actually run XSCALE.''' self._write_xscale_inp() # copy the input file... shutil.copyfile(os.path.join(self.get_working_directory(), 'XSCALE.INP'), os.path.join(self.get_working_directory(), '%d_XSCALE.INP' % self.get_xpid())) self.start() self.close_wait() # copy the LP file shutil.copyfile(os.path.join(self.get_working_directory(), 'XSCALE.LP'), os.path.join(self.get_working_directory(), '%d_XSCALE.LP' % self.get_xpid())) # now look at XSCALE.LP xds_check_error(self.get_all_output()) dname = None # get the outlier reflections... and the overall scale factor for line in open(os.path.join( self.get_working_directory(), 'XSCALE.LP'), 'r').readlines(): if '"alien"' in line: h, k, l = tuple(map(int, line.split()[:3])) z = float(line.split()[4]) if not (h, k, l, z) in self._remove: self._remove.append((h, k, l, z)) if 'FACTOR TO PLACE ALL DATA SETS TO ' in line: self._scale_factor = float(line.split()[-1]) if 'STATISTICS OF SCALED OUTPUT DATA SET' in line: dname = line.split()[-1].replace('.HKL', '') if 'total' in line and not dname in self._rmerges: if len(line.split()) > 5: self._rmerges[dname] = float( line.replace('%', '').split()[5]) # trac #419 - if the data sets are not correctly indexed, # throw an exception. N.B. this will only work if the # data sets are moderately complete (i.e. there are more # than a handful of common reflections) - which may not be # the case in MULTICRYSTAL mode. if ' !!! WARNING !!! ' in line and \ 'CORRELATION FACTORS ARE DANGEROUSLY SMALL' in line: groups = get_correlation_coefficients_and_group( os.path.join(self.get_working_directory(), 'XSCALE.LP')) Debug.write('Low correlations - check data sets') for j, name in enumerate(groups): Debug.write('Group %d' % j) for file_name in groups[name]: Debug.write(file_name) raise RuntimeError('reindexing error: %s' % \ os.path.join(self.get_working_directory(), 'XSCALE.LP')) def get_scale_factor(self): return self._scale_factor def get_rmerges(self): return self._rmerges return XScaleWrapper()
def XDSIdxref(DriverType=None, params=None): DriverInstance = DriverFactory.Driver(DriverType) class XDSIdxrefWrapper(DriverInstance.__class__, FrameProcessor): """A wrapper for wrapping XDS in idxref mode.""" def __init__(self, params=None): super(XDSIdxrefWrapper, self).__init__() # phil parameters if not params: from xia2.Handlers.Phil import master_phil params = master_phil.extract().xds.index self._params = params # now set myself up... self._parallel = PhilIndex.params.xia2.settings.multiprocessing.nproc self.set_cpu_threads(self._parallel) if self._parallel <= 1: self.set_executable("xds") else: self.set_executable("xds_par") # generic bits self._data_range = (0, 0) self._spot_range = [] self._background_range = (0, 0) self._resolution_range = (0, 0) self._org = [0.0, 0.0] self._refined_origin = None self._refined_beam_vector = None self._refined_rotation_axis = None self._starting_angle = 0.0 self._starting_frame = 0 self._cell = None self._symm = 0 self._a_axis = None self._b_axis = None self._c_axis = None # results self._refined_beam = (0, 0) self._refined_distance = 0 self._indexing_solutions = {} self._indxr_input_lattice = None self._indxr_input_cell = None self._indxr_user_input_lattice = False self._indxr_lattice = None self._indxr_cell = None self._indxr_mosaic = None self._input_data_files = {} self._output_data_files = {} self._input_data_files_list = ["SPOT.XDS"] self._output_data_files_list = ["SPOT.XDS", "XPARM.XDS"] self._index_tree_problem = False self._fraction_rmsd_rmsphi = None # getter and setter for input / output data def set_starting_frame(self, starting_frame): self._starting_frame = starting_frame def set_starting_angle(self, starting_angle): self._starting_angle = starting_angle def set_indexer_input_lattice(self, lattice): self._indxr_input_lattice = lattice def set_indexer_user_input_lattice(self, user): self._indxr_user_input_lattice = user def set_indexer_input_cell(self, cell): if not isinstance(cell, type(())): raise RuntimeError("cell must be a 6-tuple de floats") if len(cell) != 6: raise RuntimeError("cell must be a 6-tuple de floats") self._indxr_input_cell = tuple(map(float, cell)) def set_a_axis(self, a_axis): self._a_axis = a_axis def set_b_axis(self, b_axis): self._b_axis = b_axis def set_c_axis(self, c_axis): self._c_axis = c_axis def set_input_data_file(self, name, data): self._input_data_files[name] = data def get_output_data_file(self, name): return self._output_data_files[name] def get_refined_beam(self): return self._refined_beam def get_refined_distance(self): return self._refined_distance def get_indexing_solutions(self): return self._indexing_solutions def get_indexing_solution(self): return self._indxr_lattice, self._indxr_cell, self._indxr_mosaic def get_index_tree_problem(self): return self._index_tree_problem def get_fraction_rmsd_rmsphi(self): return self._fraction_rmsd_rmsphi def _compare_cell(self, c_ref, c_test): """Compare two sets of unit cell constants: if they differ by less than 5% / 5 degrees return True, else False. Now configured by xia2.settings.xds_cell_deviation in Phil input.""" from xia2.Handlers.Phil import PhilIndex if PhilIndex.params.xia2.settings.xds_cell_deviation: dev_l, dev_a = PhilIndex.params.xia2.settings.xds_cell_deviation else: dev_l = 0.05 dev_a = 5.0 for j in range(3): if math.fabs((c_test[j] - c_ref[j]) / c_ref[j]) > dev_l: return False for j in range(3, 6): if math.fabs(c_test[j] - c_ref[j]) > dev_a: return False return True # this needs setting up from setup_from_image in FrameProcessor def set_beam_centre(self, x, y): self._org = float(x), float(y) # this needs setting up (optionally) from refined results from # elsewhere def set_refined_distance(self, refined_distance): self._refined_distance = refined_distance def set_refined_origin(self, refined_origin): self._refined_origin = refined_origin def get_refined_origin(self): return self._refined_origin def set_refined_beam_vector(self, refined_beam_vector): self._refined_beam_vector = refined_beam_vector def get_refined_beam_vector(self): return self._refined_beam_vector def set_refined_rotation_axis(self, refined_rotation_axis): self._refined_rotation_axis = refined_rotation_axis def get_refined_rotation_axis(self): return self._refined_rotation_axis def set_data_range(self, start, end): offset = self.get_frame_offset() self._data_range = (start - offset, end - offset) def add_spot_range(self, start, end): offset = self.get_frame_offset() self._spot_range.append((start - offset, end - offset)) def set_background_range(self, start, end): offset = self.get_frame_offset() self._background_range = (start - offset, end - offset) def run(self, ignore_errors=False): """Run idxref.""" # image_header = self.get_header() ## crank through the header dictionary and replace incorrect ## information with updated values through the indexer ## interface if available... ## need to add distance, wavelength - that should be enough... # if self.get_distance(): # image_header['distance'] = self.get_distance() # if self.get_wavelength(): # image_header['wavelength'] = self.get_wavelength() # if self.get_two_theta(): # image_header['two_theta'] = self.get_two_theta() header = imageset_to_xds( self.get_imageset(), refined_beam_vector=self._refined_beam_vector, refined_rotation_axis=self._refined_rotation_axis, refined_distance=self._refined_distance, ) xds_inp = open(os.path.join(self.get_working_directory(), "XDS.INP"), "w") # what are we doing? xds_inp.write("JOB=IDXREF\n") xds_inp.write("MAXIMUM_NUMBER_OF_PROCESSORS=%d\n" % self._parallel) # FIXME this needs to be calculated from the beam centre... if self._refined_origin: xds_inp.write("ORGX=%f ORGY=%f\n" % tuple(self._refined_origin)) else: xds_inp.write("ORGX=%f ORGY=%f\n" % tuple(self._org)) # FIXME in here make sure sweep is wider than 5 degrees # before specifying AXIS: if <= 5 degrees replace AXIS with # nothing - base this on the maximum possible angular separation min_frame = self._spot_range[0][0] max_frame = self._spot_range[-1][1] refine_params = [p for p in self._params.refine] phi_width = self.get_phi_width() if "AXIS" in refine_params and (max_frame - min_frame) * phi_width < 5.0: refine_params.remove("AXIS") xds_inp.write("REFINE(IDXREF)=%s\n" % " ".join(refine_params)) if self._starting_frame and self._starting_angle: xds_inp.write("STARTING_FRAME=%d\n" % self._starting_frame) xds_inp.write("STARTING_ANGLE=%f\n" % self._starting_angle) # FIXME this looks like a potential bug - what will # happen if the input lattice has not been set?? if self._indxr_input_cell: self._cell = self._indxr_input_cell if self._indxr_input_lattice: self._symm = lattice_to_spacegroup_number(self._indxr_input_lattice) if self._cell: xds_inp.write("SPACE_GROUP_NUMBER=%d\n" % self._symm) cell_format = "%6.2f %6.2f %6.2f %6.2f %6.2f %6.2f" xds_inp.write("UNIT_CELL_CONSTANTS=%s\n" % cell_format % self._cell) if self._a_axis: xds_inp.write("UNIT_CELL_A-AXIS=%.2f %.2f %.2f\n" % tuple(self._a_axis)) if self._b_axis: xds_inp.write("UNIT_CELL_B-AXIS=%.2f %.2f %.2f\n" % tuple(self._b_axis)) if self._c_axis: xds_inp.write("UNIT_CELL_C-AXIS=%.2f %.2f %.2f\n" % tuple(self._c_axis)) for record in header: xds_inp.write("%s\n" % record) name_template = template_to_xds( os.path.join(self.get_directory(), self.get_template()) ) record = "NAME_TEMPLATE_OF_DATA_FRAMES=%s\n" % name_template xds_inp.write(record) xds_inp.write("DATA_RANGE=%d %d\n" % self._data_range) for spot_range in self._spot_range: xds_inp.write("SPOT_RANGE=%d %d\n" % spot_range) xds_inp.write("BACKGROUND_RANGE=%d %d\n" % self._background_range) xds_inp.close() # copy the input file... shutil.copyfile( os.path.join(self.get_working_directory(), "XDS.INP"), os.path.join( self.get_working_directory(), "%d_IDXREF.INP" % self.get_xpid() ), ) # write the input data files... for file_name in self._input_data_files_list: src = self._input_data_files[file_name] dst = os.path.join(self.get_working_directory(), file_name) if src != dst: shutil.copyfile(src, dst) self.start() self.close_wait() xds_check_version_supported(self.get_all_output()) if not ignore_errors: xds_check_error(self.get_all_output()) # If xds_check_error detects any errors it will raise an exception # The caller can then continue using the run_continue_from_error() # function. If XDS does not throw any errors we just plow on. return self.continue_from_error() def continue_from_error(self): # copy the LP file shutil.copyfile( os.path.join(self.get_working_directory(), "IDXREF.LP"), os.path.join( self.get_working_directory(), "%d_IDXREF.LP" % self.get_xpid() ), ) # parse the output lp = open( os.path.join(self.get_working_directory(), "IDXREF.LP"), "r" ).readlines() self._fraction_rmsd_rmsphi = _parse_idxref_lp_quality(lp) self._idxref_data = _parse_idxref_lp(lp) if not self._idxref_data: raise RuntimeError("indexing failed") st = _parse_idxref_lp_subtree(lp) if 2 in st: if st[2] > st[1] / 10.0: Debug.write("Look closely at autoindexing solution!") self._index_tree_problem = True for j in sorted(st): Debug.write("%2d: %5d" % (j, st[j])) # print out some (perhaps dire) warnings about the beam centre # if there is really any ambiguity... origins = _parse_idxref_index_origin(lp) assert (0, 0, 0) in origins quality_0 = origins[(0, 0, 0)][0] alternatives = [] for hkl in origins: if hkl == (0, 0, 0): continue if origins[hkl][0] < 4 * quality_0: quality, delta, beam_x, beam_y = origins[hkl] alternatives.append( (hkl[0], hkl[1], hkl[2], quality, beam_x, beam_y) ) if alternatives: Debug.write("Alternative indexing possible:") for alternative in alternatives: Debug.write("... %3d %3d %3d %4.1f %6.1f %6.1f" % alternative) # New algorithm in here - now use iotbx.lattice_symmetry with the # P1 indexing solution (solution #1) to determine the list of # allowable solutions - only consider those lattices in this # allowed list (unless we have user input) from xia2.Wrappers.Phenix.LatticeSymmetry import LatticeSymmetry ls = LatticeSymmetry() ls.set_lattice("aP") ls.set_cell(tuple(self._idxref_data[44]["cell"])) ls.generate() allowed_lattices = ls.get_lattices() for j in range(1, 45): if j not in self._idxref_data: continue data = self._idxref_data[j] lattice = data["lattice"] fit = data["fit"] cell = data["cell"] mosaic = data["mosaic"] if self._symm and self._cell and self._indxr_user_input_lattice: if ( self._compare_cell(self._cell, cell) and lattice_to_spacegroup_number(lattice) == self._symm ): if lattice in self._indexing_solutions: if self._indexing_solutions[lattice]["goodness"] < fit: continue self._indexing_solutions[lattice] = { "goodness": fit, "cell": cell, } else: if lattice in allowed_lattices or (self._symm and fit < 200.0): # bug 2417 - if we have an input lattice then we # don't want to include anything higher symmetry # in the results table... if self._symm: if lattice_to_spacegroup_number(lattice) > self._symm: Debug.write( "Ignoring solution with lattice %s" % lattice ) continue if lattice in self._indexing_solutions: if self._indexing_solutions[lattice]["goodness"] < fit: continue self._indexing_solutions[lattice] = { "goodness": fit, "cell": cell, } # postprocess this list, to remove lattice solutions which are # lower symmetry but higher penalty than the putative correct # one, if self._symm is set... if self._symm: assert self._indexing_solutions, ( "No remaining indexing solutions (%s, %s)" % (s2l(self._symm), self._symm) ) else: assert self._indexing_solutions, "No remaining indexing solutions" if self._symm: max_p = 2.0 * self._indexing_solutions[s2l(self._symm)]["goodness"] to_remove = [] for lattice in self._indexing_solutions: if self._indexing_solutions[lattice]["goodness"] > max_p: to_remove.append(lattice) for lattice in to_remove: Debug.write("Ignoring solution with lattice %s" % lattice) del self._indexing_solutions[lattice] # get the highest symmetry "acceptable" solution items = [ (k, self._indexing_solutions[k]["cell"]) for k in self._indexing_solutions ] # if there was a preassigned cell and symmetry return now # with everything done, else select the "top" solution and # reindex, resetting the input cell and symmetry. if self._cell: # select the solution which matches the input unit cell # actually after the changes above this should now be the # only solution in the table.. Debug.write( "Target unit cell: %.2f %.2f %.2f %.2f %.2f %.2f" % self._cell ) for l in items: if lattice_to_spacegroup_number(l[0]) == self._symm: # this should be the correct solution... # check the unit cell... cell = l[1] cell_str = "%.2f %.2f %.2f %.2f %.2f %.2f" % cell Debug.write("Chosen unit cell: %s" % cell_str) self._indxr_lattice = l[0] self._indxr_cell = l[1] self._indxr_mosaic = mosaic else: # select the top solution as the input cell and reset the # "indexing done" flag sorted_list = SortLattices(items) # print sorted_list self._symm = lattice_to_spacegroup_number(sorted_list[0][0]) self._cell = sorted_list[0][1] return False # get the refined distance &c. beam, distance = _parse_idxref_lp_distance_etc(lp) self._refined_beam = beam self._refined_distance = distance # gather the output files for file in self._output_data_files_list: self._output_data_files[file] = os.path.join( self.get_working_directory(), file ) return True return XDSIdxrefWrapper(params)