Example #1
0
    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
Example #2
0
    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,
        )
Example #5
0
    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())