def get_maxima(self, threshold = 5.0): '''Run diffdump, printpeaks to get a list of diffraction maxima at their image positions, to allow for further analysis.''' if not self._image: raise RuntimeError, 'image not set' if not os.path.exists(self._image): raise RuntimeError, 'image %s does not exist' % \ self._image dd = Diffdump() dd.set_image(self._image) header = dd.readheader() beam = header['raw_beam'] pixel = header['pixel'] template, directory = image2template_directory(self._image) image_number = image2image(os.path.split(self._image)[-1]) spot_file = '%s.spt' % template_number2image( template, image_number) self.start() self.input('template "%s"' % template) self.input('directory "%s"' % directory) self.input('findspots local find %d file %s' % \ (image_number, spot_file)) self.input('go') self.close_wait() self.check_for_errors() output = open(os.path.join(self.get_working_directory(), spot_file)).readlines() os.remove(os.path.join(self.get_working_directory(), spot_file)) peaks = [] for record in output[3:-2]: lst = record.split() x = float(lst[0]) y = float(lst[1]) i = float(lst[4]) / float(lst[5]) x /= pixel[0] y /= pixel[1] if i < threshold: continue # this is Mosflm right? Swap X & Y!! peaks.append((y, x, i)) return peaks
def get_template(f): global target_template if not is_image_name(f): return if is_xds_file(f): return # in here, check the permissions on the file... template = None directory = None if not os.access(f, os.R_OK): Debug.write('No read permission for %s' % f) try: template, directory = image2template_directory(f) template = os.path.join(directory, template) if target_template: if template not in target_template: return except Exception as e: Debug.write('Exception A: %s (%s)' % (str(e), f)) Debug.write(traceback.format_exc()) if template is None or directory is None: raise RuntimeError('template not recognised for %s' % f) return template
def _setup_from_image(self, image): """Configure myself from an image name.""" template, directory = image2template_directory(image) self._fp_matching_images = find_matching_images(template, directory) # trim this down to only allowed images... if self._fp_wedge: start, end = self._fp_wedge images = [] for j in self._fp_matching_images: if j < start or j > end: continue images.append(j) self._fp_matching_images = images from xia2.Schema import load_imagesets imagesets = load_imagesets( template, directory, image_range=(self._fp_matching_images[0], self._fp_matching_images[-1]), ) assert len(imagesets) == 1, "multiple imagesets match %s" % template imageset = imagesets[0] self._setup_from_imageset(imageset)
def get_maxima(self, threshold=5.0): '''Run diffdump, printpeaks to get a list of diffraction maxima at their image positions, to allow for further analysis.''' if not self._image: raise RuntimeError('image not set') if not os.path.exists(self._image): raise RuntimeError('image %s does not exist' % \ self._image) dd = Diffdump() dd.set_image(self._image) header = dd.readheader() beam = header['raw_beam'] pixel = header['pixel'] template, directory = image2template_directory(self._image) image_number = image2image(os.path.split(self._image)[-1]) spot_file = '%s.spt' % template_number2image( template, image_number) self.start() self.input('template "%s"' % template) self.input('directory "%s"' % directory) self.input('findspots local find %d file %s' % \ (image_number, spot_file)) self.input('go') self.close_wait() self.check_for_errors() output = open(os.path.join(self.get_working_directory(), spot_file)).readlines() os.remove(os.path.join(self.get_working_directory(), spot_file)) peaks = [] for record in output[3:-2]: lst = record.split() x = float(lst[0]) y = float(lst[1]) i = float(lst[4]) / float(lst[5]) x /= pixel[0] y /= pixel[1] if i < threshold: continue # this is Mosflm right? Swap X & Y!! peaks.append((y, x, i)) return peaks
def _setup_from_image(self, image): '''Configure myself from an image name.''' template, directory = image2template_directory(image) self._fp_matching_images = find_matching_images(template, directory) # trim this down to only allowed images... if self._fp_wedge: start, end = self._fp_wedge images = [] for j in self._fp_matching_images: if j < start or j > end: continue images.append(j) self._fp_matching_images = images from xia2.Schema import load_imagesets imagesets = load_imagesets( template, directory, image_range=(self._fp_matching_images[0], self._fp_matching_images[-1])) assert len(imagesets) == 1, 'multiple imagesets match %s' % template imageset = imagesets[0] self._setup_from_imageset(imageset) return
if scan is None: continue if imageset.get_scan().get_num_images() > max_images: best_sweep = imageset self._imageset = best_sweep return if __name__ == '__main__': if len(sys.argv) < 2: image = os.path.join(os.environ['XIA2_ROOT'], 'Data', 'Test', 'Images', '12287_1_E1_001.img') else: image = sys.argv[1] template, directory = image2template_directory(image) sl = SweepFactory(template, directory) for s in sl: t = s.get_collect() print 'Data collection took %s seconds' % (t[1] - t[0]) print 'For a total of %s seconds of exposure' % \ (s.get_exposure_time() * \ len(s.get_images())) print 'Images: %d to %d' % (min(s.get_images()), max(s.get_images())) print 'Template: %s' % s.get_template() print ''
def setup(self): """Set everything up...""" # check arguments are all ascii Debug.write("Start parsing command line: " + str(sys.argv)) for token in sys.argv: try: token.encode("ascii") except UnicodeDecodeError: raise RuntimeError("non-ascii characters in input") self._argv = copy.deepcopy(sys.argv) replacements = { "-2d": "pipeline=2d", "-2di": "pipeline=2di", "-3d": "pipeline=3d", "-3di": "pipeline=3di", "-3dii": "pipeline=3dii", "-3dd": "pipeline=3dd", "-dials": "pipeline=dials", "-quick": "dials.fast_mode=true", "-failover": "failover=true", "-small_molecule": "small_molecule=true", } for k, v in replacements.iteritems(): if k in self._argv: print( "***\nCommand line option %s is deprecated.\nPlease use %s instead\n***" % (k, v)) self._argv[self._argv.index(k)] = v if "-atom" in self._argv: idx = self._argv.index("-atom") element = self._argv[idx + 1] self._argv[idx:idx + 2] = ["atom=%s" % element] print( "***\nCommand line option -atom %s is deprecated.\nPlease use atom=%s instead\n***" % (element, element)) # first of all try to interpret arguments as phil parameters/files from xia2.Handlers.Phil import master_phil from libtbx.phil import command_line cmd_line = command_line.argument_interpreter(master_phil=master_phil) working_phil, self._argv = cmd_line.process_and_fetch( args=self._argv, custom_processor="collect_remaining") PhilIndex.merge_phil(working_phil) try: params = PhilIndex.get_python_object() except RuntimeError as e: raise Sorry(e) # sanity check / interpret Auto in input from libtbx import Auto if params.xia2.settings.input.atom is None: if params.xia2.settings.input.anomalous is Auto: PhilIndex.update("xia2.settings.input.anomalous=false") else: if params.xia2.settings.input.anomalous is False: raise Sorry( "Setting anomalous=false and atom type inconsistent") params.xia2.settings.input.anomalous = True PhilIndex.update("xia2.settings.input.anomalous=true") if params.xia2.settings.resolution.keep_all_reflections is Auto: if (params.xia2.settings.small_molecule is True and params.xia2.settings.resolution.d_min is None and params.xia2.settings.resolution.d_max is None): PhilIndex.update( "xia2.settings.resolution.keep_all_reflections=true") else: PhilIndex.update( "xia2.settings.resolution.keep_all_reflections=false") if params.xia2.settings.small_molecule is True: Debug.write("Small molecule selected") if params.xia2.settings.symmetry.chirality is None: PhilIndex.update("xia2.settings.symmetry.chirality=nonchiral") params = PhilIndex.get_python_object() # pipeline options self._read_pipeline() for (parameter, value) in ( ("project", params.xia2.settings.project), ("crystal", params.xia2.settings.crystal), ): validate_project_crystal_name(parameter, value) Debug.write("Project: %s" % params.xia2.settings.project) Debug.write("Crystal: %s" % params.xia2.settings.crystal) # FIXME add some consistency checks in here e.g. that there are # images assigned, there is a lattice assigned if cell constants # are given and so on params = PhilIndex.get_python_object() mp_params = params.xia2.settings.multiprocessing from xia2.Handlers.Environment import get_number_cpus if mp_params.mode == "parallel": if mp_params.type == "qsub": if which("qsub") is None: raise Sorry("qsub not available") if mp_params.njob is Auto: mp_params.njob = get_number_cpus() if mp_params.nproc is Auto: mp_params.nproc = 1 elif mp_params.nproc is Auto: mp_params.nproc = get_number_cpus() elif mp_params.mode == "serial": if mp_params.type == "qsub": if which("qsub") is None: raise Sorry("qsub not available") if mp_params.njob is Auto: mp_params.njob = 1 if mp_params.nproc is Auto: mp_params.nproc = get_number_cpus() PhilIndex.update("xia2.settings.multiprocessing.njob=%d" % mp_params.njob) PhilIndex.update("xia2.settings.multiprocessing.nproc=%d" % mp_params.nproc) params = PhilIndex.get_python_object() mp_params = params.xia2.settings.multiprocessing if mp_params.nproc > 1 and os.name == "nt": raise Sorry("nproc > 1 is not supported on Windows.") # #191 if params.xia2.settings.indexer is not None: add_preference("indexer", params.xia2.settings.indexer) if params.xia2.settings.refiner is not None: add_preference("refiner", params.xia2.settings.refiner) if params.xia2.settings.integrater is not None: add_preference("integrater", params.xia2.settings.integrater) if params.xia2.settings.scaler is not None: add_preference("scaler", params.xia2.settings.scaler) if params.xia2.settings.multi_sweep_indexing is Auto: if (params.xia2.settings.small_molecule is True and "dials" == params.xia2.settings.indexer): PhilIndex.update("xia2.settings.multi_sweep_indexing=True") else: PhilIndex.update("xia2.settings.multi_sweep_indexing=False") if (params.xia2.settings.multi_sweep_indexing is True and params.xia2.settings.multiprocessing.mode == "parallel"): Chatter.write( "Multi sweep indexing disabled:\nMSI is not available for parallel processing." ) PhilIndex.update("xia2.settings.multi_sweep_indexing=False") input_json = params.xia2.settings.input.json if input_json is not None and len(input_json): for json_file in input_json: assert os.path.isfile(json_file) load_experiments(json_file) reference_geometry = params.xia2.settings.input.reference_geometry if reference_geometry is not None and len(reference_geometry) > 0: reference_geometries = "\n".join([ "xia2.settings.input.reference_geometry=%s" % os.path.abspath(g) for g in params.xia2.settings.input.reference_geometry ]) Debug.write(reference_geometries) PhilIndex.update(reference_geometries) Debug.write("xia2.settings.trust_beam_centre=true") PhilIndex.update("xia2.settings.trust_beam_centre=true") params = PhilIndex.get_python_object() params = PhilIndex.get_python_object() if params.xia2.settings.input.xinfo is not None: xinfo_file = os.path.abspath(params.xia2.settings.input.xinfo) PhilIndex.update("xia2.settings.input.xinfo=%s" % xinfo_file) params = PhilIndex.get_python_object() self.set_xinfo(xinfo_file) # issue #55 if not set ATOM in xinfo but anomalous=true or atom= set # on commandline, set here, should be idempotent if params.xia2.settings.input.anomalous is True: crystals = self._xinfo.get_crystals() for xname in crystals: xtal = crystals[xname] Debug.write("Setting anomalous for crystal %s" % xname) xtal.set_anomalous(True) else: xinfo_file = "%s/automatic.xinfo" % os.path.abspath(os.curdir) PhilIndex.update("xia2.settings.input.xinfo=%s" % xinfo_file) params = PhilIndex.get_python_object() if params.dials.find_spots.phil_file is not None: PhilIndex.update( "dials.find_spots.phil_file=%s" % os.path.abspath(params.dials.find_spots.phil_file)) if params.dials.index.phil_file is not None: PhilIndex.update("dials.index.phil_file=%s" % os.path.abspath(params.dials.index.phil_file)) if params.dials.refine.phil_file is not None: PhilIndex.update("dials.refine.phil_file=%s" % os.path.abspath(params.dials.refine.phil_file)) if params.dials.integrate.phil_file is not None: PhilIndex.update("dials.integrate.phil_file=%s" % os.path.abspath(params.dials.integrate.phil_file)) if params.xds.index.xparm is not None: Flags.set_xparm(params.xds.index.xparm) if params.xds.index.xparm_ub is not None: Flags.set_xparm_ub(params.xds.index.xparm_ub) if params.xia2.settings.scale.freer_file is not None: freer_file = os.path.abspath(params.xia2.settings.scale.freer_file) if not os.path.exists(freer_file): raise RuntimeError("%s does not exist" % freer_file) from xia2.Modules.FindFreeFlag import FindFreeFlag column = FindFreeFlag(freer_file) Debug.write("FreeR_flag column in %s found: %s" % (freer_file, column)) PhilIndex.update("xia2.settings.scale.freer_file=%s" % freer_file) if params.xia2.settings.scale.reference_reflection_file is not None: reference_reflection_file = os.path.abspath( params.xia2.settings.scale.reference_reflection_file) if not os.path.exists(reference_reflection_file): raise RuntimeError("%s does not exist" % reference_reflection_file) PhilIndex.update( "xia2.settings.scale.reference_reflection_file=%s" % reference_reflection_file) params = PhilIndex.get_python_object() datasets = unroll_datasets(PhilIndex.params.xia2.settings.input.image) for dataset in datasets: start_end = None # here we only care about ':' which are later than C:\ if ":" in dataset[3:]: tokens = dataset.split(":") # cope with windows drives i.e. C:\data\blah\thing_0001.cbf:1:100 if len(tokens[0]) == 1: tokens = ["%s:%s" % (tokens[0], tokens[1])] + tokens[2:] if len(tokens) != 3: raise RuntimeError("/path/to/image_0001.cbf:start:end") dataset = tokens[0] start_end = int(tokens[1]), int(tokens[2]) from xia2.Applications.xia2setup import is_hd5f_name if os.path.exists(os.path.abspath(dataset)): dataset = os.path.abspath(dataset) else: directories = [os.getcwd()] + self._argv[1:] found = False for d in directories: if os.path.exists(os.path.join(d, dataset)): dataset = os.path.join(d, dataset) found = True break if not found: raise Sorry("Could not find %s in %s" % (dataset, " ".join(directories))) if is_hd5f_name(dataset): self._hdf5_master_files.append(dataset) if start_end: Debug.write("Image range: %d %d" % start_end) if dataset not in self._default_start_end: self._default_start_end[dataset] = [] self._default_start_end[dataset].append(start_end) else: Debug.write("No image range specified") else: template, directory = image2template_directory( os.path.abspath(dataset)) self._default_template.append(os.path.join( directory, template)) self._default_directory.append(directory) Debug.write("Interpreted from image %s:" % dataset) Debug.write("Template %s" % template) Debug.write("Directory %s" % directory) if start_end: Debug.write("Image range: %d %d" % start_end) key = os.path.join(directory, template) if key not in self._default_start_end: self._default_start_end[key] = [] self._default_start_end[key].append(start_end) else: Debug.write("No image range specified") # finally, check that all arguments were read and raise an exception # if any of them were nonsense. with open("xia2-working.phil", "wb") as f: f.write(PhilIndex.working_phil.as_str()) f.write( os.linesep ) # temporarily required for https://github.com/dials/dials/issues/522 with open("xia2-diff.phil", "wb") as f: f.write(PhilIndex.get_diff().as_str()) f.write( os.linesep ) # temporarily required for https://github.com/dials/dials/issues/522 Debug.write("\nDifference PHIL:") Debug.write(PhilIndex.get_diff().as_str(), strip=False) Debug.write("Working PHIL:") Debug.write(PhilIndex.working_phil.as_str(), strip=False) nonsense = "Unknown command-line options:" was_nonsense = False for j, argv in enumerate(self._argv): if j == 0: continue if argv[0] != "-" and "=" not in argv: continue if j not in self._understood: nonsense += " %s" % argv was_nonsense = True if was_nonsense: raise RuntimeError(nonsense)
if imageset.get_scan().get_num_images() > max_images: best_sweep = imageset self._imageset = best_sweep return if __name__ == '__main__': if len(sys.argv) < 2: image = os.path.join(os.environ['XIA2_ROOT'], 'Data', 'Test', 'Images', '12287_1_E1_001.img') else: image = sys.argv[1] template, directory = image2template_directory(image) sl = SweepFactory(template, directory) for s in sl: t = s.get_collect() print 'Data collection took %s seconds' % (t[1] - t[0]) print 'For a total of %s seconds of exposure' % \ (s.get_exposure_time() * \ len(s.get_images())) print 'Images: %d to %d' % (min(s.get_images()), max(s.get_images())) print 'Template: %s' % s.get_template() print ''
def __init__(self, name, wavelength, sample, directory = None, image = None, beam = None, reversephi = False, distance = None, gain = 0.0, dmin = 0.0, dmax = 0.0, polarization = 0.0, frames_to_process = None, user_lattice = None, user_cell = None, epoch = 0, ice = False, excluded_regions = None): '''Create a new sweep named name, belonging to XWavelength object wavelength, representing the images in directory starting with image, with beam centre optionally defined.''' if excluded_regions is None: excluded_regions = [] # + check the wavelength is an XWavelength object # raise an exception if not... or not... if not wavelength.__class__.__name__ == 'XWavelength': pass # FIXME bug 2221 if DIRECTORY starts with ~/ or ~graeme (say) need to # interpret this properly - e.g. map it to a full PATH. directory = expand_path(directory) self._name = name self._wavelength = wavelength self._sample = sample self._directory = directory self._image = image self._reversephi = reversephi self._epoch = epoch self._user_lattice = user_lattice self._user_cell = user_cell self._header = { } self._resolution_high = dmin self._resolution_low = dmax self._ice = ice self._excluded_regions = excluded_regions self._imageset = None # FIXME in here also need to be able to accumulate the total # dose from all experimental measurements (complex) and provide # a _epoch_to_dose dictionary or some such... may be fiddly as # this will need to parse across multiple templates. c/f Bug # 2798 self._epoch_to_image = { } self._image_to_epoch = { } # to allow first, last image for processing to be # set... c/f integrater interface self._frames_to_process = frames_to_process # + derive template, list of images params = PhilIndex.get_python_object() if directory and image: self._template, self._directory = \ image2template_directory(os.path.join(directory, image)) from xia2.Schema import load_imagesets imagesets = load_imagesets( self._template, self._directory, image_range=self._frames_to_process, reversephi=(params.xia2.settings.input.reverse_phi or self._reversephi)) assert len(imagesets) == 1, "one imageset expected, %d found" % \ len(imagesets) self._imageset = copy.deepcopy(imagesets[0]) start, end = self._imageset.get_array_range() self._images = list(range(start+1, end+1)) # FIXME in here check that (1) the list of images is continuous # and (2) that all of the images are readable. This should also # take into account frames_to_process if set. if self._frames_to_process is None: self._frames_to_process = min(self._images), max(self._images) start, end = self._frames_to_process error = False if params.general.check_image_files_readable: for j in range(start, end + 1): image_name = self.get_imageset().get_path(j-start) if not j in self._images: Debug.write('image %s missing' %image_name) error = True continue if not os.access(image_name, os.R_OK): Debug.write('image %s unreadable' %image_name) error = True continue if error: raise RuntimeError, 'problem with sweep %s' % self._name # + read the image header information into here? # or don't I need it? it would be useful for checking # against wavelength.getWavelength() I guess to make # sure that the plumbing is all sound. # check that they match by closer than 0.0001A, if wavelength # is not None beam_ = self._imageset.get_beam() scan = self._imageset.get_scan() if wavelength is not None: # FIXME 29/NOV/06 if the wavelength wavelength value # is 0.0 then first set it to the header value - note # that this assumes that the header value is correct # (a reasonable assumption) if wavelength.get_wavelength() == 0.0: wavelength.set_wavelength(beam_.get_wavelength()) # FIXME 08/DEC/06 in here need to allow for the fact # that the wavelength in the image header could be wrong and # in fact it should be replaced with the input value - # through the user will need to be warned of this and # also everything using the FrameProcessor interface # will also have to respect this! if math.fabs(beam_.get_wavelength() - wavelength.get_wavelength()) > 0.0001: # format = 'wavelength for sweep %s does not ' + \ # 'match wavelength %s' # raise RuntimeError, format % \ # (name, wavelength.get_name()) format = 'Header wavelength for sweep %s different' + \ ' to assigned value (%4.2f vs. %4.2f)' Chatter.write(format % (name, beam_.get_wavelength(), wavelength.get_wavelength())) # also in here look at the image headers to see if we can # construct a mapping between exposure epoch and image ... images = [] if self._frames_to_process: start, end = self._frames_to_process for j in self._images: if j >= start and j <= end: images.append(j) else: images = self._images for j in images: epoch = scan.get_image_epoch(j) if epoch == 0.0: epoch = float(os.stat(self._imageset.get_path(j-images[0])).st_mtime) self._epoch_to_image[epoch] = j self._image_to_epoch[j] = epoch epochs = self._epoch_to_image.keys() Debug.write('Exposure epoch for sweep %s: %d %d' % \ (self._template, min(epochs), max(epochs))) self._input_imageset = copy.deepcopy(self._imageset) # + get the lattice - can this be a pointer, so that when # this object updates lattice it is globally-for-this-crystal # updated? The lattice included directly in here includes an # exact unit cell for data reduction, the crystal lattice # contains an approximate unit cell which should be # from the unit cells from all sweeps contained in the # XCrystal. FIXME should I be using a LatticeInfo object # in here? See what the Indexer interface produces. ALT: # just provide an Indexer implementation "hook". # See Headnote 001 above. See also _get_indexer, # _get_integrater below. self._indexer = None self._refiner = None self._integrater = None # I don't need this - it is equivalent to self.getWavelength( # ).getCrystal().getLattice() # self._crystal_lattice = None # this means that this module will have to present largely the # same interface as Indexer and Integrater so that the calls # can be appropriately forwarded. # finally configure the beam if set if beam is not None: from dxtbx.model.detector_helpers import set_mosflm_beam_centre try: set_mosflm_beam_centre(self.get_imageset().get_detector(), self.get_imageset().get_beam(), beam) except AssertionError, e: Debug.write('Error setting mosflm beam centre: %s' % e)
def setup(self): '''Set everything up...''' # check arguments are all ascii Debug.write('Start parsing command line: ' + str(sys.argv)) for token in sys.argv: try: token.encode('ascii') except UnicodeDecodeError: raise RuntimeError('non-ascii characters in input') self._argv = copy.deepcopy(sys.argv) replacements = { '-2d': 'pipeline=2d', '-2di': 'pipeline=2di', '-3d': 'pipeline=3d', '-3di': 'pipeline=3di', '-3dii': 'pipeline=3dii', '-3dd': 'pipeline=3dd', '-dials': 'pipeline=dials', '-quick': 'dials.fast_mode=true', '-failover': 'failover=true', '-small_molecule': 'small_molecule=true' } for k, v in replacements.iteritems(): if k in self._argv: print "***\nCommand line option %s is deprecated.\nPlease use %s instead\n***" % ( k, v) self._argv[self._argv.index(k)] = v if '-atom' in self._argv: idx = self._argv.index('-atom') element = self._argv[idx + 1] self._argv[idx:idx + 2] = ['atom=%s' % element] print "***\nCommand line option -atom %s is deprecated.\nPlease use atom=%s instead\n***" % ( element, element) # first of all try to interpret arguments as phil parameters/files from xia2.Handlers.Phil import master_phil from libtbx.phil import command_line cmd_line = command_line.argument_interpreter(master_phil=master_phil) working_phil, self._argv = cmd_line.process_and_fetch( args=self._argv, custom_processor="collect_remaining") PhilIndex.merge_phil(working_phil) try: params = PhilIndex.get_python_object() except RuntimeError as e: raise Sorry(e) # sanity check / interpret Auto in input from libtbx import Auto if params.xia2.settings.input.atom is None: if params.xia2.settings.input.anomalous is Auto: PhilIndex.update("xia2.settings.input.anomalous=false") else: if params.xia2.settings.input.anomalous == False: raise Sorry( 'Setting anomalous=false and atom type inconsistent') params.xia2.settings.input.anomalous = True PhilIndex.update("xia2.settings.input.anomalous=true") if params.xia2.settings.resolution.keep_all_reflections is Auto: if params.xia2.settings.small_molecule == True and \ params.xia2.settings.resolution.d_min is None and \ params.xia2.settings.resolution.d_max is None: PhilIndex.update( "xia2.settings.resolution.keep_all_reflections=true") else: PhilIndex.update( "xia2.settings.resolution.keep_all_reflections=false") if params.xia2.settings.small_molecule == True: Debug.write('Small molecule selected') if params.ccp4.pointless.chirality is None: PhilIndex.update("ccp4.pointless.chirality=nonchiral") params = PhilIndex.get_python_object() # pipeline options self._read_pipeline() Debug.write('Project: %s' % params.xia2.settings.project) Debug.write('Crystal: %s' % params.xia2.settings.crystal) # FIXME add some consistency checks in here e.g. that there are # images assigned, there is a lattice assigned if cell constants # are given and so on params = PhilIndex.get_python_object() mp_params = params.xia2.settings.multiprocessing from xia2.Handlers.Environment import get_number_cpus if mp_params.mode == 'parallel': if mp_params.type == 'qsub': if which('qsub') is None: raise Sorry('qsub not available') if mp_params.njob is Auto: mp_params.njob = get_number_cpus() if mp_params.nproc is Auto: mp_params.nproc = 1 elif mp_params.nproc is Auto: mp_params.nproc = get_number_cpus() elif mp_params.mode == 'serial': if mp_params.type == 'qsub': if which('qsub') is None: raise Sorry('qsub not available') if mp_params.njob is Auto: mp_params.njob = 1 if mp_params.nproc is Auto: mp_params.nproc = get_number_cpus() PhilIndex.update("xia2.settings.multiprocessing.njob=%d" % mp_params.njob) PhilIndex.update("xia2.settings.multiprocessing.nproc=%d" % mp_params.nproc) params = PhilIndex.get_python_object() mp_params = params.xia2.settings.multiprocessing if params.xia2.settings.indexer is not None: add_preference("indexer", params.xia2.settings.indexer) if params.xia2.settings.refiner is not None: add_preference("refiner", params.xia2.settings.refiner) if params.xia2.settings.integrater is not None: add_preference("integrater", params.xia2.settings.integrater) if params.xia2.settings.scaler is not None: add_preference("scaler", params.xia2.settings.scaler) if params.xia2.settings.multi_sweep_indexing is Auto: if params.xia2.settings.small_molecule == True and 'dials' == params.xia2.settings.indexer: PhilIndex.update("xia2.settings.multi_sweep_indexing=True") else: PhilIndex.update("xia2.settings.multi_sweep_indexing=False") if params.xia2.settings.multi_sweep_indexing == True and \ params.xia2.settings.multiprocessing.mode == 'parallel': Chatter.write( 'Multi sweep indexing disabled:\nMSI is not available for parallel processing.' ) PhilIndex.update("xia2.settings.multi_sweep_indexing=False") input_json = params.xia2.settings.input.json if (input_json is not None and len(input_json)): for json_file in input_json: assert os.path.isfile(json_file) load_datablock(json_file) reference_geometry = params.xia2.settings.input.reference_geometry if reference_geometry is not None and len(reference_geometry) > 0: reference_geometries = "\n".join([ "xia2.settings.input.reference_geometry=%s" % os.path.abspath(g) for g in params.xia2.settings.input.reference_geometry ]) Debug.write(reference_geometries) PhilIndex.update(reference_geometries) Debug.write("xia2.settings.trust_beam_centre=true") PhilIndex.update("xia2.settings.trust_beam_centre=true") params = PhilIndex.get_python_object() params = PhilIndex.get_python_object() if params.xia2.settings.input.xinfo is not None: xinfo_file = os.path.abspath(params.xia2.settings.input.xinfo) PhilIndex.update("xia2.settings.input.xinfo=%s" % xinfo_file) params = PhilIndex.get_python_object() self.set_xinfo(xinfo_file) # issue #55 if not set ATOM in xinfo but anomalous=true or atom= set # on commandline, set here, should be idempotent if params.xia2.settings.input.anomalous is True: crystals = self._xinfo.get_crystals() for xname in crystals: xtal = crystals[xname] Debug.write("Setting anomalous for crystal %s" % xname) xtal.set_anomalous(True) else: xinfo_file = '%s/automatic.xinfo' % os.path.abspath(os.curdir) PhilIndex.update("xia2.settings.input.xinfo=%s" % xinfo_file) params = PhilIndex.get_python_object() if params.dials.find_spots.phil_file is not None: PhilIndex.update( "dials.find_spots.phil_file=%s" % os.path.abspath(params.dials.find_spots.phil_file)) if params.dials.index.phil_file is not None: PhilIndex.update("dials.index.phil_file=%s" % os.path.abspath(params.dials.index.phil_file)) if params.dials.refine.phil_file is not None: PhilIndex.update("dials.refine.phil_file=%s" % os.path.abspath(params.dials.refine.phil_file)) if params.dials.integrate.phil_file is not None: PhilIndex.update("dials.integrate.phil_file=%s" % os.path.abspath(params.dials.integrate.phil_file)) if params.xds.index.xparm is not None: Flags.set_xparm(params.xds.index.xparm) if params.xds.index.xparm_ub is not None: Flags.set_xparm_ub(params.xds.index.xparm_ub) if params.xia2.settings.scale.freer_file is not None: freer_file = os.path.abspath(params.xia2.settings.scale.freer_file) if not os.path.exists(freer_file): raise RuntimeError('%s does not exist' % freer_file) from xia2.Modules.FindFreeFlag import FindFreeFlag column = FindFreeFlag(freer_file) Debug.write('FreeR_flag column in %s found: %s' % \ (freer_file, column)) PhilIndex.update("xia2.settings.scale.freer_file=%s" % freer_file) if params.xia2.settings.scale.reference_reflection_file is not None: reference_reflection_file = os.path.abspath( params.xia2.settings.scale.reference_reflection_file) if not os.path.exists(reference_reflection_file): raise RuntimeError('%s does not exist' % reference_reflection_file) PhilIndex.update( "xia2.settings.scale.reference_reflection_file=%s" % reference_reflection_file) params = PhilIndex.get_python_object() datasets = unroll_datasets(PhilIndex.params.xia2.settings.input.image) for dataset in datasets: start_end = None if ':' in dataset: tokens = dataset.split(':') # cope with windows drives i.e. C:\data\blah\thing_0001.cbf:1:100 if len(tokens[0]) == 1: tokens = ['%s:%s' % (tokens[0], tokens[1])] + tokens[2:] if len(tokens) != 3: raise RuntimeError('/path/to/image_0001.cbf:start:end') dataset = tokens[0] start_end = int(tokens[1]), int(tokens[2]) from xia2.Applications.xia2setup import is_hd5f_name if os.path.exists(os.path.abspath(dataset)): dataset = os.path.abspath(dataset) else: directories = [os.getcwd()] + self._argv[1:] found = False for d in directories: if os.path.exists(os.path.join(d, dataset)): dataset = os.path.join(d, dataset) found = True break if not found: raise Sorry('Cound not find %s in %s' % \ (dataset, ' '.join(directories))) if is_hd5f_name(dataset): self._hdf5_master_files.append(dataset) if start_end: Debug.write('Image range: %d %d' % start_end) if not dataset in self._default_start_end: self._default_start_end[dataset] = [] self._default_start_end[dataset].append(start_end) else: Debug.write('No image range specified') else: template, directory = image2template_directory( os.path.abspath(dataset)) self._default_template.append(os.path.join( directory, template)) self._default_directory.append(directory) Debug.write('Interpreted from image %s:' % dataset) Debug.write('Template %s' % template) Debug.write('Directory %s' % directory) if start_end: Debug.write('Image range: %d %d' % start_end) key = os.path.join(directory, template) if not key in self._default_start_end: self._default_start_end[key] = [] self._default_start_end[key].append(start_end) else: Debug.write('No image range specified') # finally, check that all arguments were read and raise an exception # if any of them were nonsense. with open('xia2-working.phil', 'wb') as f: print >> f, PhilIndex.working_phil.as_str() with open('xia2-diff.phil', 'wb') as f: print >> f, PhilIndex.get_diff().as_str() Debug.write('\nDifference PHIL:') Debug.write(PhilIndex.get_diff().as_str(), strip=False) Debug.write('Working PHIL:') Debug.write(PhilIndex.working_phil.as_str(), strip=False) nonsense = 'Unknown command-line options:' was_nonsense = False for j, argv in enumerate(self._argv): if j == 0: continue if argv[0] != '-' and '=' not in argv: continue if not j in self._understood: nonsense += ' %s' % argv was_nonsense = True if was_nonsense: raise RuntimeError(nonsense)
def exercise_mosflm_index(): if not have_dials_regression: print "Skipping exercise_mosflm_index(): dials_regression not configured" return xia2_demo_data = os.path.join(dials_regression, "xia2_demo_data") template = os.path.join(xia2_demo_data, "insulin_1_%03i.img") from xia2.Wrappers.Mosflm.MosflmIndex import MosflmIndex # exercise basic indexing from two images cwd = os.path.abspath(os.curdir) tmp_dir = open_tmp_directory() os.chdir(tmp_dir) indexer = MosflmIndex() indexer.set_images((1,45)) from xia2.Experts.FindImages import image2template_directory templ, directory = image2template_directory(template %1) indexer.set_directory(directory) indexer.set_template(templ) indexer.run() output = ''.join(indexer.get_all_output()) print output assert approx_equal(indexer.get_refined_beam_centre(), (94.33, 94.58)) assert approx_equal(indexer.get_refined_unit_cell(), (78.655, 78.655, 78.655, 90.0, 90.0, 90.0), 1e-3) assert approx_equal(indexer.get_refined_distance(), 160.0) assert approx_equal(indexer.get_resolution_estimate(), 2.12) assert approx_equal(indexer.get_separation(), [0.57, 0.57]) assert approx_equal(indexer.get_raster(), [17, 17, 10, 5, 5]) assert approx_equal(indexer.get_mosaic_spreads(), [0.4, 0.4]) assert indexer.get_lattice() == 'cI' # now exercise indexing off multiple images and test more settings os.chdir(cwd) tmp_dir = open_tmp_directory() os.chdir(tmp_dir) indexer = MosflmIndex() indexer.set_images((5,15,25,35,45)) indexer.set_directory(directory) indexer.set_template(templ) indexer.set_unit_cell((78,78,78,90,90,90)) indexer.set_distance(159) indexer.set_space_group_number(197) indexer.run() output = ''.join(indexer.get_all_output()) print output assert approx_equal(indexer.get_refined_beam_centre(), (94.33, 94.57)) assert approx_equal(indexer.get_refined_unit_cell(), (78.2082, 78.2082, 78.2082, 90.0, 90.0, 90.0)) assert approx_equal(indexer.get_refined_distance(), 159.0) assert approx_equal(indexer.get_resolution_estimate(), 2.12) assert approx_equal(indexer.get_separation(), [0.48, 0.57]) assert approx_equal(indexer.get_raster(), [15, 17, 9, 5, 5]) assert approx_equal( indexer.get_mosaic_spreads(), [0.5, 0.35, 0.45, 0.65, 0.4], eps=1e-1) assert indexer.get_lattice() == 'cI'
def exercise_mosflm_refine_cell(): if not have_dials_regression: print "Skipping exercise_mosflm_refine_cell(): dials_regression not configured" return xia2_demo_data = os.path.join(dials_regression, "xia2_demo_data") template = os.path.join(xia2_demo_data, "insulin_1_%03i.img") from xia2.Wrappers.Mosflm.MosflmIndex import MosflmIndex from xia2.Wrappers.Mosflm.MosflmRefineCell import MosflmRefineCell # exercise basic indexing from two images cwd = os.path.abspath(os.curdir) tmp_dir = open_tmp_directory() os.chdir(tmp_dir) from xia2.Experts.FindImages import image2template_directory templ, directory = image2template_directory(template %1) indexer = MosflmIndex() indexer.set_images((1,45)) indexer.set_directory(directory) indexer.set_template(templ) indexer.run() refiner = MosflmRefineCell() refiner.set_images(((1,3),(21,23), (43,45))) refiner.set_input_mat_file("xiaindex.mat") refiner.set_output_mat_file("xiarefine.mat") refiner.set_directory(directory) refiner.set_template(templ) refiner.set_beam_centre(indexer.get_refined_beam_centre()) refiner.set_mosaic( sum(indexer.get_mosaic_spreads())/len(indexer.get_mosaic_spreads())) refiner.run() output = ''.join(refiner.get_all_output()) print output background_residual = refiner.get_background_residual() rms_values = refiner.get_rms_values() ref_residual = { 1: {1: 0.1, 2: 0.1, 3: 0.1, 43: 0.1, 44: 0.2, 45: 0.1, 21: 0.1, 22: 0.1, 23: 0.1}, 2: {1: 0.1, 2: 0.1, 3: 0.1, 43: 0.1, 44: 0.2, 45: 0.1, 21: 0.1, 22: 0.1, 23: 0.1}, 3: {1: 0.1, 2: 0.1, 3: 0.1, 43: 0.1, 44: 0.2, 45: 0.1, 21: 0.1, 22: 0.1, 23: 0.1} } for cycle in background_residual: for frame in background_residual[cycle]: assert abs(background_residual[cycle][frame] - ref_residual[cycle][frame]) <= 0.1, (cycle, frame) ref_values = { 1: [0.027, 0.029, 0.027, 0.025, 0.027, 0.025, 0.024, 0.022, 0.025], 2: [0.02, 0.021, 0.023, 0.021, 0.02, 0.017, 0.018, 0.019, 0.022], 3: [0.02, 0.021, 0.025, 0.022, 0.021, 0.019, 0.018, 0.019, 0.021] } for cycle in rms_values: for frame in range(len(rms_values[cycle])): assert abs(rms_values[cycle][frame] - ref_values[cycle][frame]) <= 0.05
def exercise_mosflm_integrate(): if not have_dials_regression: print "Skipping exercise_mosflm_integrate(): dials_regression not configured" return xia2_demo_data = os.path.join(dials_regression, "xia2_demo_data") template = os.path.join(xia2_demo_data, "insulin_1_%03i.img") from xia2.Wrappers.Mosflm.MosflmIndex import MosflmIndex from xia2.Wrappers.Mosflm.MosflmRefineCell import MosflmRefineCell from xia2.Wrappers.Mosflm.MosflmIntegrate import MosflmIntegrate # exercise basic indexing from two images cwd = os.path.abspath(os.curdir) tmp_dir = open_tmp_directory() os.chdir(tmp_dir) from xia2.Experts.FindImages import image2template_directory templ, directory = image2template_directory(template %1) indexer = MosflmIndex() indexer.set_images((1,45)) indexer.set_directory(directory) indexer.set_template(templ) indexer.run() refiner = MosflmRefineCell() refiner.set_images(((1,3),(21,23), (43,45))) refiner.set_input_mat_file("xiaindex.mat") refiner.set_output_mat_file("xiarefine.mat") refiner.set_directory(directory) refiner.set_template(templ) refiner.set_beam_centre(indexer.get_refined_beam_centre()) refiner.set_mosaic( sum(indexer.get_mosaic_spreads())/len(indexer.get_mosaic_spreads())) refiner.run() #output = ''.join(refiner.get_all_output()) #print output integrater = MosflmIntegrate() integrater.set_image_range((1,45)) integrater.set_input_mat_file("xiaindex.mat") #integrater.set_output_mat_file("xiarefine.mat") integrater.set_directory(directory) integrater.set_template(templ) integrater.set_beam_centre( tuple(float(x) for x in refiner.get_refined_beam_centre())) integrater.set_distance(refiner.get_refined_distance()) integrater.set_mosaic(refiner.get_refined_mosaic()) integrater.set_space_group_number(197) integrater.set_unit_cell(refiner.get_refined_unit_cell()) integrater.run() hklout = integrater.get_hklout() assert os.path.exists(hklout) from iotbx.reflection_file_reader import any_reflection_file miller_arrays = any_reflection_file(hklout).as_miller_arrays( merge_equivalents=False) for ma in miller_arrays: assert ma.size() == 81011, ma.size() assert len(miller_arrays) == 13, len(miller_arrays) assert not integrater.get_bgsig_too_large() assert not integrater.get_getprof_error() assert integrater.get_batches_out() == (1, 45) assert integrater.get_mosaic_spreads() == [ 0.43, 0.42, 0.42, 0.41, 0.41, 0.41, 0.42, 0.42, 0.42, 0.42, 0.42, 0.42, 0.41, 0.41, 0.41, 0.41, 0.41, 0.41, 0.41, 0.41, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.39, 0.39, 0.39, 0.39, 0.39] assert integrater.get_nref() == 81011 assert len(integrater.get_postref_result()) == 45 assert integrater.get_postref_result()[1] == { 'ovrl': 0.0, 'full': 507.0, 'dist': 158.6, 'ccx': -0.01, 'yscale': 1.0, 'sdrat': 7.5, 'tilt': 25.0, 'rsym': 0.027, 'bad': 0.0, 'i/sigi': 18.1, 'i/sigi_out': 1.6, 'twist': 13.0, 'resid': 0.021, 'wresid': 1.1, 'part': 1309.0, 'nsym': 18.0, 'neg': 158.0, 'ccy': -0.01, 'ccom': -0.01, 'toff': 0.0, 'roff': 0.0} assert integrater.get_residuals() == [ 1.1, 0.9, 1.0, 1.0, 0.8, 0.9, 1.0, 0.8, 0.9, 0.9, 0.9, 0.9, 1.0, 1.0, 1.0, 0.9, 0.9, 0.9, 0.9, 0.8, 1.0, 0.9, 0.8, 0.9, 1.0, 0.8, 1.0, 0.9, 0.8, 0.8, 0.9, 0.9, 0.9, 0.9, 0.9, 1.0, 0.8, 0.9, 1.0, 0.7, 0.8, 0.9, 0.8, 0.9, 1.0] assert integrater.get_spot_status() \ == 'ooooooooooooooooooooooooooooooooooooooooooooo'
def get_template_and_directory(dials_data): xia2_demo_data = dials_data("insulin") template = xia2_demo_data.join("insulin_1_%03i.img").strpath with mock.patch.object(sys, "argv", []): return image2template_directory(template % 1)
def get_template_and_directory(xia2_regression_build): xia2_demo_data = os.path.join(xia2_regression_build, "test_data", "insulin") template = os.path.join(xia2_demo_data, "insulin_1_%03i.img") with mock.patch.object(sys, 'argv', []): return image2template_directory(template % 1)
def __init__( self, name, wavelength, sample, directory=None, image=None, beam=None, reversephi=False, distance=None, gain=0.0, dmin=0.0, dmax=0.0, polarization=0.0, frames_to_process=None, user_lattice=None, user_cell=None, epoch=0, ice=False, excluded_regions=None, ): """Create a new sweep named name, belonging to XWavelength object wavelength, representing the images in directory starting with image, with beam centre optionally defined.""" if excluded_regions is None: excluded_regions = [] # FIXME bug 2221 if DIRECTORY starts with ~/ or ~graeme (say) need to # interpret this properly - e.g. map it to a full PATH. directory = expand_path(directory) self._name = name self._wavelength = wavelength self.sample = sample self._directory = directory self._image = image self._reversephi = reversephi self._epoch = epoch self._user_lattice = user_lattice self._user_cell = user_cell self._header = {} self._resolution_high = dmin self._resolution_low = dmax self._ice = ice self._excluded_regions = excluded_regions self._imageset = None # FIXME in here also need to be able to accumulate the total # dose from all experimental measurements (complex) and provide # a _epoch_to_dose dictionary or some such... may be fiddly as # this will need to parse across multiple templates. c/f Bug # 2798 self._epoch_to_image = {} self._image_to_epoch = {} # to allow first, last image for processing to be # set... c/f integrater interface self._frames_to_process = frames_to_process # + derive template, list of images params = PhilIndex.get_python_object() if directory and image: self._template, self._directory = image2template_directory( os.path.join(directory, image)) from xia2.Schema import load_imagesets imagesets = load_imagesets( self._template, self._directory, image_range=self._frames_to_process, reversephi=(params.xia2.settings.input.reverse_phi or self._reversephi), ) assert len( imagesets ) == 1, "one imageset expected, %d found" % len(imagesets) self._imageset = copy.deepcopy(imagesets[0]) start, end = self._imageset.get_array_range() self._images = list(range(start + 1, end + 1)) # FIXME in here check that (1) the list of images is continuous # and (2) that all of the images are readable. This should also # take into account frames_to_process if set. if self._frames_to_process is None: self._frames_to_process = min(self._images), max(self._images) start, end = self._frames_to_process error = False if params.general.check_image_files_readable: for j in range(start, end + 1): if j not in self._images: logger.debug("image %i missing for %s" % (j, self.get_imageset().get_template())) error = True continue image_name = self.get_imageset().get_path(j - start) if not os.access(image_name, os.R_OK): logger.debug("image %s unreadable" % image_name) error = True continue if error: raise RuntimeError("problem with sweep %s" % self._name) beam_ = self._imageset.get_beam() scan = self._imageset.get_scan() if wavelength is not None: # If the wavelength value is 0.0 then first set it to the header # value - note that this assumes that the header value is correct # (a reasonable assumption) if wavelength.get_wavelength() == 0.0: wavelength.set_wavelength(beam_.get_wavelength()) # FIXME 08/DEC/06 in here need to allow for the fact # that the wavelength in the image header could be wrong and # in fact it should be replaced with the input value - # through the user will need to be warned of this and # also everything using the FrameProcessor interface # will also have to respect this! if (math.fabs(beam_.get_wavelength() - wavelength.get_wavelength()) > 0.0001): logger.info( "Header wavelength for sweep %s different" " to assigned value (%4.2f vs. %4.2f)", name, beam_.get_wavelength(), wavelength.get_wavelength(), ) # also in here look at the image headers to see if we can # construct a mapping between exposure epoch and image ... images = [] if self._frames_to_process: start, end = self._frames_to_process for j in self._images: if j >= start and j <= end: images.append(j) else: images = self._images for j in images: epoch = scan.get_image_epoch(j) if epoch == 0.0: epoch = float( os.stat(self._imageset.get_path(j - images[0])).st_mtime) self._epoch_to_image[epoch] = j self._image_to_epoch[j] = epoch epochs = self._epoch_to_image logger.debug("Exposure epoch for sweep %s: %d %d" % (self._template, min(epochs), max(epochs))) self._input_imageset = copy.deepcopy(self._imageset) # + get the lattice - can this be a pointer, so that when # this object updates lattice it is globally-for-this-crystal # updated? The lattice included directly in here includes an # exact unit cell for data reduction, the crystal lattice # contains an approximate unit cell which should be # from the unit cells from all sweeps contained in the # XCrystal. FIXME should I be using a LatticeInfo object # in here? See what the Indexer interface produces. ALT: # just provide an Indexer implementation "hook". # See Headnote 001 above. See also _get_indexer, # _get_integrater below. self._indexer = None self._refiner = None self._integrater = None # I don't need this - it is equivalent to self.getWavelength( # ).getCrystal().getLattice() # self._crystal_lattice = None # this means that this module will have to present largely the # same interface as Indexer and Integrater so that the calls # can be appropriately forwarded. # finally configure the beam if set if beam is not None: from dxtbx.model.detector_helpers import set_mosflm_beam_centre try: set_mosflm_beam_centre( self.get_imageset().get_detector(), self.get_imageset().get_beam(), beam, ) except AssertionError as e: logger.debug("Error setting mosflm beam centre: %s" % e) self._beam_centre = beam self._distance = distance self._gain = gain self._polarization = polarization self._add_detector_identification_to_cif()