def parse_args( self, args, verbose=False, return_unhandled=False, quick_parse=False ): """ Parse the command line arguments. :param args: The input arguments :param verbose: Print verbose output :param return_unhandled: True/False also return unhandled arguments :param quick_parse: Return as fast as possible and without reading any data, ignoring class constructor options. :return: The options and parameters and (optionally) unhandled arguments """ from dxtbx.model.experiment_list import ( BeamComparison, DetectorComparison, GoniometerComparison, ) from dials.util.phil import parse # Parse the command line phil parameters user_phils = [] unhandled = [] interpretor = self.system_phil.command_line_argument_interpreter() def _is_a_phil_file(filename): return any( filename.endswith(phil_ext) for phil_ext in (".phil", ".param", ".params", ".eff", ".def") ) for arg in args: if ( _is_a_phil_file(arg) and os.path.isfile(arg) and os.path.getsize(arg) > 0 ): try: user_phils.append(parse(file_name=arg)) except Exception: if return_unhandled: unhandled.append(arg) else: raise # Treat "has a schema" as "looks like a URL (not phil) elif "=" in arg and not get_url_scheme(arg): try: user_phils.append(interpretor.process_arg(arg=arg)) except Exception: if return_unhandled: unhandled.append(arg) else: raise else: unhandled.append(arg) # Fetch the phil parameters self._phil, unused = self.system_phil.fetch( sources=user_phils, track_unused_definitions=True ) # Print if bad definitions if len(unused) > 0: msg = [item.object.as_str().strip() for item in unused] msg = "\n".join([" %s" % line for line in msg]) raise RuntimeError(f"The following definitions were not recognised\n{msg}") # Extract the parameters params = self._phil.extract() # Stop at this point if quick_parse is set. A second pass may be needed. if quick_parse: return params, unhandled # Create some comparison functions if self._read_experiments_from_images: compare_beam = BeamComparison( wavelength_tolerance=params.input.tolerance.beam.wavelength, direction_tolerance=params.input.tolerance.beam.direction, polarization_normal_tolerance=params.input.tolerance.beam.polarization_normal, polarization_fraction_tolerance=params.input.tolerance.beam.polarization_fraction, ) compare_detector = DetectorComparison( fast_axis_tolerance=params.input.tolerance.detector.fast_axis, slow_axis_tolerance=params.input.tolerance.detector.slow_axis, origin_tolerance=params.input.tolerance.detector.origin, ) compare_goniometer = GoniometerComparison( rotation_axis_tolerance=params.input.tolerance.goniometer.rotation_axis, fixed_rotation_tolerance=params.input.tolerance.goniometer.fixed_rotation, setting_rotation_tolerance=params.input.tolerance.goniometer.setting_rotation, ) scan_tolerance = params.input.tolerance.scan.oscillation # FIXME Should probably make this smarter since it requires editing here # and in dials.import phil scope try: format_kwargs = { "dynamic_shadowing": params.format.dynamic_shadowing, "multi_panel": params.format.multi_panel, } except AttributeError: format_kwargs = None else: compare_beam = None compare_detector = None compare_goniometer = None scan_tolerance = None format_kwargs = None try: load_models = params.load_models except AttributeError: load_models = True # Try to import everything importer = Importer( unhandled, read_experiments=self._read_experiments, read_reflections=self._read_reflections, read_experiments_from_images=self._read_experiments_from_images, check_format=self._check_format, verbose=verbose, compare_beam=compare_beam, compare_detector=compare_detector, compare_goniometer=compare_goniometer, scan_tolerance=scan_tolerance, format_kwargs=format_kwargs, load_models=load_models, ) # Grab a copy of the errors that occurred in case the caller wants them self.handling_errors = importer.handling_errors # Add the cached arguments for obj in importer.experiments: params.input.experiments.append(obj) for obj in importer.reflections: params.input.reflections.append(obj) # Convert to phil self._phil = self.system_phil.format(python_object=params) return params, importer.unhandled
def __call__(self, experiment): if self.tolerance: compare_beam = BeamComparison( wavelength_tolerance=self.tolerance.beam.wavelength, direction_tolerance=self.tolerance.beam.direction, polarization_normal_tolerance=self.tolerance.beam. polarization_normal, polarization_fraction_tolerance=self.tolerance.beam. polarization_fraction, ) compare_detector = DetectorComparison( fast_axis_tolerance=self.tolerance.detector.fast_axis, slow_axis_tolerance=self.tolerance.detector.slow_axis, origin_tolerance=self.tolerance.detector.origin, ) compare_goniometer = GoniometerComparison( rotation_axis_tolerance=self.tolerance.goniometer. rotation_axis, fixed_rotation_tolerance=self.tolerance.goniometer. fixed_rotation, setting_rotation_tolerance=self.tolerance.goniometer. setting_rotation, ) else: compare_beam = None compare_detector = None compare_goniometer = None if self.ref_beam: if compare_beam: if not compare_beam(self.ref_beam, experiment.beam): raise ComparisonError( compare.beam_diff( self.ref_beam, experiment.beam, wavelength_tolerance=self.tolerance.beam. wavelength, direction_tolerance=self.tolerance.beam.direction, polarization_normal_tolerance=self.tolerance.beam. polarization_normal, polarization_fraction_tolerance=self.tolerance. beam.polarization_fraction, )) beam = self.ref_beam else: beam = experiment.beam if self.ref_detector and self.average_detector: detector = self.ref_detector elif self.ref_detector and not self.average_detector: if compare_detector: if not compare_detector(self.ref_detector, experiment.detector): raise ComparisonError( compare.detector_diff( self.ref_detector, experiment.detector, fast_axis_tolerance=self.tolerance.detector. fast_axis, slow_axis_tolerance=self.tolerance.detector. slow_axis, origin_tolerance=self.tolerance.detector.origin, )) detector = self.ref_detector else: detector = experiment.detector if self.ref_goniometer: if compare_goniometer: if not compare_goniometer(self.ref_goniometer, experiment.goniometer): raise ComparisonError( compare.goniometer_diff( self.ref_goniometer, experiment.goniometer, rotation_axis_tolerance=self.tolerance.goniometer. rotation_axis, fixed_rotation_tolerance=self.tolerance.goniometer. fixed_rotation, setting_rotation_tolerance=self.tolerance. goniometer.setting_rotation, )) goniometer = self.ref_goniometer else: goniometer = experiment.goniometer if self.ref_scan: scan = self.ref_scan else: scan = experiment.scan if self.ref_crystal: crystal = self.ref_crystal else: crystal = experiment.crystal if self._last_imageset == experiment.imageset: imageset = self._last_imageset else: imageset = experiment.imageset self._last_imageset = imageset return Experiment( identifier=experiment.identifier, beam=beam, detector=detector, scan=scan, goniometer=goniometer, crystal=crystal, imageset=imageset, )
def load_imagesets( template, directory, id_image=None, image_range=None, use_cache=True, reversephi=False, ): global imageset_cache from dxtbx.model.experiment_list import ExperimentListFactory from xia2.Applications.xia2setup import known_hdf5_extensions from dxtbx.imageset import ImageSweep full_template_path = os.path.join(directory, template) if full_template_path not in imageset_cache or not use_cache: from dxtbx.model.experiment_list import BeamComparison from dxtbx.model.experiment_list import DetectorComparison from dxtbx.model.experiment_list import GoniometerComparison params = PhilIndex.params.xia2.settings compare_beam = BeamComparison( wavelength_tolerance=params.input.tolerance.beam.wavelength, direction_tolerance=params.input.tolerance.beam.direction, polarization_normal_tolerance=params.input.tolerance.beam.polarization_normal, polarization_fraction_tolerance=params.input.tolerance.beam.polarization_fraction, ) compare_detector = DetectorComparison( fast_axis_tolerance=params.input.tolerance.detector.fast_axis, slow_axis_tolerance=params.input.tolerance.detector.slow_axis, origin_tolerance=params.input.tolerance.detector.origin, ) compare_goniometer = GoniometerComparison( rotation_axis_tolerance=params.input.tolerance.goniometer.rotation_axis, fixed_rotation_tolerance=params.input.tolerance.goniometer.fixed_rotation, setting_rotation_tolerance=params.input.tolerance.goniometer.setting_rotation, ) scan_tolerance = params.input.tolerance.scan.oscillation format_kwargs = { "dynamic_shadowing": params.input.format.dynamic_shadowing, "multi_panel": params.input.format.multi_panel, } if os.path.splitext(full_template_path)[-1] in known_hdf5_extensions: # if we are passed the correct file, use this, else look for a master # file (i.e. something_master.h5) if os.path.exists(full_template_path) and os.path.isfile( full_template_path ): master_file = full_template_path else: import glob g = glob.glob(os.path.join(directory, "*_master.h5")) master_file = None for p in g: substr = longest_common_substring(template, p) if substr: if master_file is None or ( len(substr) > len(longest_common_substring(template, master_file)) ): master_file = p if master_file is None: raise RuntimeError("Can't find master file for %s" % full_template_path) unhandled = [] experiments = ExperimentListFactory.from_filenames( [master_file], verbose=False, unhandled=unhandled, compare_beam=compare_beam, compare_detector=compare_detector, compare_goniometer=compare_goniometer, scan_tolerance=scan_tolerance, format_kwargs=format_kwargs, ) assert len(unhandled) == 0, ( "unhandled image files identified: %s" % unhandled ) else: from dxtbx.sweep_filenames import locate_files_matching_template_string params = PhilIndex.get_python_object() read_all_image_headers = params.xia2.settings.read_all_image_headers if read_all_image_headers: paths = sorted( locate_files_matching_template_string(full_template_path) ) unhandled = [] experiments = ExperimentListFactory.from_filenames( paths, verbose=False, unhandled=unhandled, compare_beam=compare_beam, compare_detector=compare_detector, compare_goniometer=compare_goniometer, scan_tolerance=scan_tolerance, format_kwargs=format_kwargs, ) assert len(unhandled) == 0, ( "unhandled image files identified: %s" % unhandled ) else: from dxtbx.model.experiment_list import ExperimentListTemplateImporter importer = ExperimentListTemplateImporter( [full_template_path], format_kwargs=format_kwargs ) experiments = importer.experiments imagesets = [ iset for iset in experiments.imagesets() if isinstance(iset, ImageSweep) ] assert len(imagesets) > 0, "no imageset found" imageset_cache[full_template_path] = collections.OrderedDict() if reversephi: for imageset in imagesets: goniometer = imageset.get_goniometer() goniometer.set_rotation_axis( tuple(-g for g in goniometer.get_rotation_axis()) ) reference_geometry = PhilIndex.params.xia2.settings.input.reference_geometry if reference_geometry is not None and len(reference_geometry) > 0: update_with_reference_geometry(imagesets, reference_geometry) # Update the geometry params = PhilIndex.params.xia2.settings update_geometry = [] from dials.command_line.dials_import import ManualGeometryUpdater from dials.util.options import geometry_phil_scope # Then add manual geometry work_phil = geometry_phil_scope.format(params.input) diff_phil = geometry_phil_scope.fetch_diff(source=work_phil) if diff_phil.as_str() != "": update_geometry.append(ManualGeometryUpdater(params.input)) imageset_list = [] for imageset in imagesets: for updater in update_geometry: imageset = updater(imageset) imageset_list.append(imageset) imagesets = imageset_list from scitbx.array_family import flex for imageset in imagesets: scan = imageset.get_scan() exposure_times = scan.get_exposure_times() epochs = scan.get_epochs() if exposure_times.all_eq(0) or exposure_times[0] == 0: exposure_times = flex.double(exposure_times.size(), 1) scan.set_exposure_times(exposure_times) elif not exposure_times.all_gt(0): exposure_times = flex.double(exposure_times.size(), exposure_times[0]) scan.set_exposure_times(exposure_times) if epochs.size() > 1 and not epochs.all_gt(0): if epochs[0] == 0: epochs[0] = 1 for i in range(1, epochs.size()): epochs[i] = epochs[i - 1] + exposure_times[i - 1] scan.set_epochs(epochs) _id_image = scan.get_image_range()[0] imageset_cache[full_template_path][_id_image] = imageset if id_image is not None: return [imageset_cache[full_template_path][id_image]] elif image_range is not None: for imageset in imageset_cache[full_template_path].values(): scan = imageset.get_scan() scan_image_range = scan.get_image_range() if ( image_range[0] >= scan_image_range[0] and image_range[1] <= scan_image_range[1] ): imagesets = [ imageset[ image_range[0] - scan_image_range[0] : image_range[1] + 1 - scan_image_range[0] ] ] assert len(imagesets[0]) == image_range[1] - image_range[0] + 1, len( imagesets[0] ) return imagesets return imageset_cache[full_template_path].values()
def __call__(self, experiment): from dxtbx.model.experiment_list import BeamComparison from dxtbx.model.experiment_list import DetectorComparison from dxtbx.model.experiment_list import GoniometerComparison from dxtbx.datablock import BeamDiff from dxtbx.datablock import DetectorDiff from dxtbx.datablock import GoniometerDiff if self.tolerance: compare_beam = BeamComparison( wavelength_tolerance=self.tolerance.beam.wavelength, direction_tolerance=self.tolerance.beam.direction, polarization_normal_tolerance=self.tolerance.beam. polarization_normal, polarization_fraction_tolerance=self.tolerance.beam. polarization_fraction, ) compare_detector = DetectorComparison( fast_axis_tolerance=self.tolerance.detector.fast_axis, slow_axis_tolerance=self.tolerance.detector.slow_axis, origin_tolerance=self.tolerance.detector.origin, ) compare_goniometer = GoniometerComparison( rotation_axis_tolerance=self.tolerance.goniometer. rotation_axis, fixed_rotation_tolerance=self.tolerance.goniometer. fixed_rotation, setting_rotation_tolerance=self.tolerance.goniometer. setting_rotation, ) else: compare_beam = None compare_detector = None compare_goniometer = None if self.ref_beam: if compare_beam: if not compare_beam(self.ref_beam, experiment.beam): diff = BeamDiff( wavelength_tolerance=self.tolerance.beam.wavelength, direction_tolerance=self.tolerance.beam.direction, polarization_normal_tolerance=self.tolerance.beam. polarization_normal, polarization_fraction_tolerance=self.tolerance.beam. polarization_fraction, ) raise ComparisonError("\n".join( diff(self.ref_beam, experiment.beam))) beam = self.ref_beam else: beam = experiment.beam if self.ref_detector and self.average_detector: detector = self.ref_detector elif self.ref_detector and not self.average_detector: if compare_detector: if not compare_detector(self.ref_detector, experiment.detector): diff = DetectorDiff( fast_axis_tolerance=self.tolerance.detector.fast_axis, slow_axis_tolerance=self.tolerance.detector.slow_axis, origin_tolerance=self.tolerance.detector.origin, ) raise ComparisonError("\n".join( diff(self.ref_detector, experiment.detector))) detector = self.ref_detector else: detector = experiment.detector if self.ref_goniometer: if compare_goniometer: if not compare_goniometer(self.ref_goniometer, experiment.goniometer): diff = GoniometerDiff( rotation_axis_tolerance=self.tolerance.goniometer. rotation_axis, fixed_rotation_tolerance=self.tolerance.goniometer. fixed_rotation, setting_rotation_tolerance=self.tolerance.goniometer. setting_rotation, ) raise ComparisonError("\n".join( diff(self.ref_goniometer, experiment.goniometer))) goniometer = self.ref_goniometer else: goniometer = experiment.goniometer if self.ref_scan: scan = self.ref_scan else: scan = experiment.scan if self.ref_crystal: crystal = self.ref_crystal else: crystal = experiment.crystal if self._last_imageset == experiment.imageset: imageset = self._last_imageset else: imageset = experiment.imageset self._last_imageset = imageset from dxtbx.model.experiment_list import Experiment return Experiment( beam=beam, detector=detector, scan=scan, goniometer=goniometer, crystal=crystal, imageset=imageset, )
def _run_dials_import(self): """ Perform a minimal version of dials.import to get an experiment list. Use some filleted bits of dials.import and dials.util.options.Importer. """ # Get some key data format arguments. try: format_kwargs = { "dynamic_shadowing": self.params.dials_import.format.dynamic_shadowing, "multi_panel": self.params.dials_import.format.multi_panel, } except AttributeError: format_kwargs = {} # If filenames contain wildcards, expand args = [] for arg in self.params.dials_import.input.experiments: if "*" in arg: args.extend(glob(arg)) else: args.append(arg) if args: # Are compare{beam,detector,goniometer} and scan_tolerance necessary? # They are cargo-culted from the DIALS option parser. tol_params = self.params.dials_import.input.tolerance compare_beam = BeamComparison( wavelength_tolerance=tol_params.beam.wavelength, direction_tolerance=tol_params.beam.direction, polarization_normal_tolerance=tol_params.beam. polarization_normal, polarization_fraction_tolerance=tol_params.beam. polarization_fraction, ) compare_detector = DetectorComparison( fast_axis_tolerance=tol_params.detector.fast_axis, slow_axis_tolerance=tol_params.detector.slow_axis, origin_tolerance=tol_params.detector.origin, ) compare_goniometer = GoniometerComparison( rotation_axis_tolerance=tol_params.goniometer.rotation_axis, fixed_rotation_tolerance=tol_params.goniometer.fixed_rotation, setting_rotation_tolerance=tol_params.goniometer. setting_rotation, ) scan_tolerance = tol_params.scan.oscillation # Import an experiment list from image data. try: experiments = ExperimentListFactory.from_filenames( args, compare_beam=compare_beam, compare_detector=compare_detector, compare_goniometer=compare_goniometer, scan_tolerance=scan_tolerance, format_kwargs=format_kwargs, ) except IOError as e: warning("%s '%s'", e.strerror, e.filename) sys.exit(1) # Record the imported experiments for use elsewhere. # Quit if there aren't any. self.expts.extend(experiments) if not self.expts: warning("No images found.") sys.exit(1) else: # Use the template importer. if len(self.params.dials_import.input.template) > 0: importer = ExperimentListTemplateImporter( self.params.dials_import.input.template, format_kwargs=format_kwargs) # Record the imported experiments for use elsewhere. # Quit if there aren't any. self.expts.extend(importer.experiments) if not self.expts: warning("No images found matching template %s" % self.params.dials_import.input.template[0]) sys.exit(1) # Setup the metadata updater metadata_updater = MetaDataUpdater(self.params.dials_import) # Extract the experiments and loop through self.expts = metadata_updater(self.expts.imagesets())