Example #1
0
def run(args=None):
    mixed_args = args or sys.argv[1:]
    if os.name != "nt":
        r, w, x = select.select([sys.stdin], [], [], 0)
        if len(r) > 0:
            mixed_args.extend([l.strip() for rr in r for l in rr.readlines()])

    filenames = []
    args = []
    for arg in mixed_args:
        if get_url_scheme(arg):
            # Make this look like a path. If you squint. And are looking away.
            filenames.append("/" + urllib.parse.quote(arg))
        else:
            if os.path.isfile(arg):
                filenames.append(arg)
            else:
                args.append(arg)

    interp = phil_scope.command_line_argument_interpreter()
    params, unhandled = interp.process_and_fetch(
        args, custom_processor="collect_remaining"
    )
    params = params.extract()

    if params.nproc is libtbx.Auto:
        nproc = None
        params.nproc = 1024
    else:
        nproc = params.nproc

    if len(unhandled) and unhandled[0] == "stop":
        stopped = stop(params.host, params.port, params.nproc)
        print("Stopped %d findspots processes" % stopped)
    elif len(unhandled) and unhandled[0] == "ping":
        url = "http://%s:%i" % (params.host, params.port)
        try:
            _ = urllib.request.urlopen(url).read()
            print("Success")
            sys.exit(0)
        except Exception:
            print("Failure")
            sys.exit(1)
    else:
        if len(filenames) == 1:
            response = work(params.host, params.port, filenames[0], unhandled)

            print(response_to_xml(json.loads(response)))
        else:
            work_all(
                params.host,
                params.port,
                filenames,
                unhandled,
                plot=params.plot,
                table=params.table,
                json_file=params.json,
                grid=params.grid,
                nproc=nproc,
            )
Example #2
0
    def try_read_experiments_from_images(
        self,
        args,
        verbose,
        compare_beam,
        compare_detector,
        compare_goniometer,
        scan_tolerance,
        format_kwargs,
        load_models=True,
    ):
        """
        Try to import images.

        :param args: The input arguments
        :param verbose: Print verbose output
        :param compare_beam:
        :param compare_detector:
        :param compare_goniometer:
        :param scan_tolerance:
        :param format_kwargs:
        :param load_models: Whether to load all models for ExperimentLists
        :return: Unhandled arguments
        """
        from dxtbx.model.experiment_list import ExperimentListFactory

        # If filenames contain wildcards, expand
        args_new = []
        for arg in args:
            # Don't expand wildcards if URI-style filename
            if "*" in arg and not get_url_scheme(arg):
                args_new.extend(glob(arg))
            else:
                args_new.append(arg)
        args = args_new

        unhandled = []
        experiments = ExperimentListFactory.from_filenames(
            args,
            verbose=verbose,
            unhandled=unhandled,
            compare_beam=compare_beam,
            compare_detector=compare_detector,
            compare_goniometer=compare_goniometer,
            scan_tolerance=scan_tolerance,
            format_kwargs=format_kwargs,
            load_models=load_models,
        )
        if experiments:
            self.experiments.append(
                FilenameDataWrapper(filename="<image files>", data=experiments)
            )
        return unhandled
Example #3
0
def get_format_class_for_file(image_file, format_hint=None):
    # type: (str, str) -> Maybe[Type[Format]]
    """Find the best format handler in the registry for given image file
    :param image_file: A string containing the file path to an image
    :param format_hint: An optional string of a format class name that should
                        be checked first
    :return: An uninstantiated format class, if a matching one was found,
             otherwise None
    """

    # Grab the scheme from this URI
    scheme = get_url_scheme(image_file)

    # If a format hint was given then find all paths through the DAG leading
    # to this format class. Create a set containing all format class names
    # on those paths (priority_formats), and use the information whether a
    # format name is in the set to prioritise it during the format search.
    priority_formats = set()
    if format_hint:
        priority_candidates = {format_hint}
        dagset = {f: set(subf) for f, subf in _format_dag.items()}
        while priority_candidates:
            priority_formats.update(priority_candidates)
            priority_candidates = {
                f
                for f, subf in dagset.items()
                if priority_candidates.intersection(subf)
            }

    def format_sort(format_name):
        return (0 if format_name in priority_formats else 1, format_name)

    def recurse(format_name, image_file):
        # Recursively check whether any of the children understand image_file,
        # in which case they are preferred over the parent format.
        for child in sorted(_format_dag.get(format_name, []), key=format_sort):
            format_class = get_format_class_for(child)
            if scheme in format_class.schemes and format_class.understand(
                    image_file):
                return recurse(child, image_file)
        return get_format_class_for(format_name)

    # Starting at "Format" and using any potential prioritisation information
    # look for any path through the DAG of formats, stopping at the first
    # accepting leaf node
    for format in sorted(_format_dag["Format"], key=format_sort):
        format_class = get_format_class_for(format)
        if scheme in format_class.schemes and format_class.understand(
                image_file):
            return recurse(format, image_file)
Example #4
0
 def _make_stills(self, imageset, format_kwargs=None):
     """Make a still imageset."""
     filenames = [
         resolve_path(p, directory=self._directory)
         if not get_url_scheme(p) else p for p in imageset["images"]
     ]
     indices = None
     if "single_file_indices" in imageset:
         indices = imageset["single_file_indices"]
         assert len(indices) == len(filenames)
     return ImageSetFactory.make_imageset(
         filenames,
         None,
         check_format=self._check_format,
         single_file_indices=indices,
         format_kwargs=format_kwargs,
     )
Example #5
0
 def recurse(parentformat, filename, level=0):
     known_format_class = None
     multiple_formats = False
     for subformat in dag.get(parentformat, []):
         format_class = dxtbx.format.Registry.get_format_class_for(subformat)
         if not get_url_scheme(filename) in format_class.schemes:
             print("Not matching ", filename, "to", format_class)
             continue
         understood = format_class.understand(filename)
         print("%s%s: %s" % ("  " * level, subformat, understood))
         if understood:
             recursive_format_class, subtree_multiple = recurse(
                 subformat, filename, level + 1
             )
             understood_format_class = recursive_format_class or subformat
             if known_format_class and known_format_class != understood_format_class:
                 print(
                     f"File can be understood as {known_format_class} and {understood_format_class}"
                 )
                 multiple_formats = True
             known_format_class = understood_format_class
             multiple_formats |= subtree_multiple
     return known_format_class, multiple_formats
Example #6
0
def _create_imageset(records, format_class, format_kwargs=None):
    # type: (Iterable[ImageMetadataRecord], Type[dxtbx.format.Format], Dict) -> dxtbx.imageset.ImageSet
    """
    Create an ImageSet object from a set of single-image records.

    Args:
        records: Single-image metadata records to merge into a single imageset
        format_class: The format class object for these image records
        format_kwargs: Extra arguments to pass to the format class when
            creating an ImageSet

    Returns:
        An imageset for all the image records
    """
    records = list(records)
    # Nothing here should have been assigned a template parameter
    assert all(x.template is None for x in records)
    # Extract the filenames from the records
    filenames = [
        x.filename
        if get_url_scheme(x.filename) else os.path.abspath(x.filename)
        for x in records
    ]
    # Create the imageset
    imageset = dxtbx.imageset.ImageSetFactory.make_imageset(
        filenames,
        format_class,
        format_kwargs=format_kwargs,
        check_format=False)
    # Update all of the metadata for each record
    for i, r in enumerate(records):
        imageset.set_beam(r.beam, i)
        imageset.set_detector(r.detector, i)
        imageset.set_goniometer(r.goniometer, i)
        imageset.set_scan(r.scan, i)
    return imageset
Example #7
0
    def get_imageset(
        Class,
        input_filenames,
        beam=None,
        detector=None,
        goniometer=None,
        scan=None,
        as_imageset=False,
        as_sequence=False,
        single_file_indices=None,
        format_kwargs=None,
        template=None,
        check_format=True,
    ):
        """
        Factory method to create an imageset

        """
        # Import here to avoid cyclic imports
        from dxtbx.imageset import ImageSequence, ImageSet, ImageSetData

        # Get filename absolute paths, for entries that are filenames
        filenames = [
            os.path.abspath(x) if not get_url_scheme(x) else x
            for x in input_filenames
        ]

        # Make it a dict
        if format_kwargs is None:
            format_kwargs = {}

        # Get some information from the format class
        reader = Class.get_reader()(filenames, **format_kwargs)

        # Get the format instance
        if check_format is True:
            Class._current_filename_ = None
            Class._current_instance_ = None
            format_instance = Class.get_instance(filenames[0], **format_kwargs)
        else:
            format_instance = None

        # Read the vendor type
        if check_format is True:
            vendor = format_instance.get_vendortype()
        else:
            vendor = ""

        # Get the format kwargs
        params = format_kwargs

        # Make sure only 1 or none is set
        assert [as_imageset, as_sequence].count(True) < 2
        if as_imageset:
            is_sequence = False
        elif as_sequence:
            is_sequence = True
        else:
            if scan is None and format_instance is None:
                raise RuntimeError("""
          One of the following needs to be set
            - as_imageset=True
            - as_sequence=True
            - scan
            - check_format=True
      """)
            if scan is None:
                test_scan = format_instance.get_scan()
            else:
                test_scan = scan
            if test_scan is not None and test_scan.get_oscillation()[1] != 0:
                is_sequence = True
            else:
                is_sequence = False

        # Create an imageset or sequence
        if not is_sequence:

            # Create the imageset
            iset = ImageSet(
                ImageSetData(
                    reader=reader,
                    masker=None,
                    vendor=vendor,
                    params=params,
                    format=Class,
                ))

            # If any are None then read from format
            if [beam, detector, goniometer, scan].count(None) != 0:

                # Get list of models
                beam = []
                detector = []
                goniometer = []
                scan = []
                for f in filenames:
                    format_instance = Class(f, **format_kwargs)
                    beam.append(format_instance.get_beam())
                    detector.append(format_instance.get_detector())
                    goniometer.append(format_instance.get_goniometer())
                    scan.append(format_instance.get_scan())

            # Set the list of models
            for i in range(len(filenames)):
                iset.set_beam(beam[i], i)
                iset.set_detector(detector[i], i)
                iset.set_goniometer(goniometer[i], i)
                iset.set_scan(scan[i], i)

        else:

            # Get the template
            if template is None:
                template = template_regex(filenames[0])[0]
            else:
                template = str(template)

            # Check scan makes sense
            if scan:
                if check_format is True:
                    assert scan.get_num_images() == len(filenames)

            # If any are None then read from format
            if beam is None and format_instance is not None:
                beam = format_instance.get_beam()
            if detector is None and format_instance is not None:
                detector = format_instance.get_detector()
            if goniometer is None and format_instance is not None:
                goniometer = format_instance.get_goniometer()
            if scan is None and format_instance is not None:
                scan = format_instance.get_scan()
                if scan is not None:
                    for f in filenames[1:]:
                        format_instance = Class(f, **format_kwargs)
                        scan += format_instance.get_scan()

            assert beam is not None, "Can't create Sequence without beam"
            assert detector is not None, "Can't create Sequence without detector"
            assert goniometer is not None, "Can't create Sequence without goniometer"
            assert scan is not None, "Can't create Sequence without scan"

            # Create the masker
            if format_instance is not None:
                masker = format_instance.get_masker(goniometer=goniometer)
            else:
                masker = None

            # Create the sequence
            iset = ImageSequence(
                ImageSetData(
                    reader=reader,
                    masker=masker,
                    vendor=vendor,
                    params=params,
                    format=Class,
                    template=template,
                ),
                beam=beam,
                detector=detector,
                goniometer=goniometer,
                scan=scan,
            )

        if format_instance is not None:
            static_mask = format_instance.get_static_mask()
            if static_mask is not None:
                if not iset.external_lookup.mask.data.empty():
                    for m1, m2 in zip(static_mask,
                                      iset.external_lookup.mask.data):
                        m1 &= m2.data()
                    iset.external_lookup.mask.data = ImageBool(static_mask)
                else:
                    iset.external_lookup.mask.data = ImageBool(static_mask)

        return iset
Example #8
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