Пример #1
0
    def generate(self, imageset):
        """Generate the mask."""
        # Get the detector and beam
        detector = imageset.get_detector()
        beam = imageset.get_beam()

        # Get the first image
        image = imageset.get_raw_data(0)
        assert len(detector) == len(image)

        # Create the mask for each panel
        masks = []
        for index, (im, panel) in enumerate(zip(image, detector)):

            # Build a trusted mask by looking for pixels that are always outside
            # the trusted range. This identifies bad pixels, but does not include
            # pixels that are overloaded on some images.
            if self.params.use_trusted_range:
                warnings.warn(
                    "Checking for hot pixels using the trusted_range is"
                    " deprecated. https://github.com/dials/dials/issues/1156",
                    FutureWarning,
                )
                trusted_mask = None
                low, high = panel.get_trusted_range()

                # Take 10 evenly-spaced images from the imageset. Pixels outside
                # the trusted mask on all of these images are considered bad and
                # masked. https://github.com/dials/dials/issues/1061
                stride = max(int(len(imageset) / 10), 1)
                image_indices = range(0, len(imageset), stride)

                for image_index in image_indices:
                    image_data = imageset.get_raw_data(
                        image_index)[index].as_double()
                    frame_mask = (image_data > low) & (image_data < high)
                    if trusted_mask is None:
                        trusted_mask = frame_mask
                    else:
                        trusted_mask = trusted_mask | frame_mask

                    if trusted_mask.count(False) == 0:
                        break
                mask = trusted_mask
            else:
                mask = flex.bool(flex.grid(im.all()), True)

            # Add a border around the image
            if self.params.border > 0:
                logger.info("Generating border mask:")
                logger.info(" border = %d" % self.params.border)
                border = self.params.border
                height, width = mask.all()
                borderx = flex.bool(flex.grid(border, width), False)
                bordery = flex.bool(flex.grid(height, border), False)
                mask[0:border, :] = borderx
                mask[-border:, :] = borderx
                mask[:, 0:border] = bordery
                mask[:, -border:] = bordery

            # Apply the untrusted regions
            for region in self.params.untrusted:
                if region.panel is None:
                    region.panel = 0
                if region.panel == index:
                    if not any([
                            region.circle, region.rectangle, region.polygon,
                            region.pixel
                    ]):
                        mask[:, :] = flex.bool(flex.grid(mask.focus()), False)
                        continue

                    if region.circle is not None:
                        xc, yc, radius = region.circle
                        logger.info("Generating circle mask:")
                        logger.info(" panel = %d" % region.panel)
                        logger.info(" xc = %d" % xc)
                        logger.info(" yc = %d" % yc)
                        logger.info(" radius = %d" % radius)
                        mask_untrusted_circle(mask, xc, yc, radius)
                    if region.rectangle is not None:
                        x0, x1, y0, y1 = region.rectangle
                        logger.info("Generating rectangle mask:")
                        logger.info(" panel = %d" % region.panel)
                        logger.info(" x0 = %d" % x0)
                        logger.info(" y0 = %d" % y0)
                        logger.info(" x1 = %d" % x1)
                        logger.info(" y1 = %d" % y1)
                        mask_untrusted_rectangle(mask, x0, x1, y0, y1)
                    if region.polygon is not None:
                        assert (len(region.polygon) %
                                2 == 0), "Polygon must contain 2D coords"
                        vertices = []
                        for i in range(int(len(region.polygon) / 2)):
                            x = region.polygon[2 * i]
                            y = region.polygon[2 * i + 1]
                            vertices.append((x, y))
                        polygon = flex.vec2_double(vertices)
                        logger.info("Generating polygon mask:")
                        logger.info(" panel = %d" % region.panel)
                        for vertex in vertices:
                            logger.info(" coord = (%d, %d)" % (vertex))
                        mask_untrusted_polygon(mask, polygon)
                    if region.pixel is not None:
                        mask[region.pixel] = False

            # Generate high and low resolution masks
            if self.params.d_min is not None:
                logger.info("Generating high resolution mask:")
                logger.info(" d_min = %f" % self.params.d_min)
                _apply_resolution_mask(mask, beam, panel, 0, self.params.d_min)
            if self.params.d_max is not None:
                logger.info("Generating low resolution mask:")
                logger.info(" d_max = %f" % self.params.d_max)
                d_max = self.params.d_max
                d_inf = max(d_max + 1, 1e9)
                _apply_resolution_mask(mask, beam, panel, d_max, d_inf)

            try:
                # Mask out the resolution range
                for drange in self.params.resolution_range:
                    d_min = min(drange)
                    d_max = max(drange)
                    assert d_min < d_max, "d_min must be < d_max"
                    logger.info("Generating resolution range mask:")
                    logger.info(" d_min = %f" % d_min)
                    logger.info(" d_max = %f" % d_max)
                    _apply_resolution_mask(mask, beam, panel, d_min, d_max)
            except TypeError:
                # Catch the default value None of self.params.resolution_range
                if any(self.params.resolution_range):
                    raise

            # Mask out the resolution ranges for the ice rings
            for drange in generate_ice_ring_resolution_ranges(
                    beam, panel, self.params.ice_rings):
                d_min = min(drange)
                d_max = max(drange)
                assert d_min < d_max, "d_min must be < d_max"
                logger.info("Generating ice ring mask:")
                logger.info(" d_min = %f" % d_min)
                logger.info(" d_max = %f" % d_max)
                _apply_resolution_mask(mask, beam, panel, d_min, d_max)

            # Add to the list
            masks.append(mask)

        # Return the mask
        return tuple(masks)
Пример #2
0
def generate_mask(imageset: ImageSet,
                  params: libtbx.phil.scope_extract) -> Tuple[flex.bool]:
    """Generate a mask based on the input parameters.

    Args:
      imageset (ImageSet): The imageset for which to generate a mask
      params (libtbx.phil.scope_extract): The phil parameters for mask generation. This
        should be an extract of `dials.util.masking.phil_scope`
    """
    # Get the detector and beam
    detector = imageset.get_detector()
    beam = imageset.get_beam()

    # Create the mask for each panel
    masks = []
    for index, panel in enumerate(detector):

        mask = flex.bool(flex.grid(reversed(panel.get_image_size())), True)

        # Add a border around the image
        if params.border > 0:
            logger.debug(f"Generating border mask:\n border = {params.border}")
            border = params.border
            height, width = mask.all()
            borderx = flex.bool(flex.grid(border, width), False)
            bordery = flex.bool(flex.grid(height, border), False)
            mask[0:border, :] = borderx
            mask[-border:, :] = borderx
            mask[:, 0:border] = bordery
            mask[:, -border:] = bordery

        # Apply the untrusted regions
        for region in params.untrusted:
            if region.panel is None:
                region.panel = 0
            if region.panel == index:
                if not any([
                        region.circle, region.rectangle, region.polygon,
                        region.pixel
                ]):
                    mask[:, :] = flex.bool(flex.grid(mask.focus()), False)
                    continue

                if region.circle is not None:
                    xc, yc, radius = region.circle
                    logger.debug("Generating circle mask:\n" +
                                 f" panel = {region.panel}\n" +
                                 f" xc = {xc}\n" + f" yc = {yc}\n" +
                                 f" radius = {radius}")
                    mask_untrusted_circle(mask, xc, yc, radius)
                if region.rectangle is not None:
                    x0, x1, y0, y1 = region.rectangle
                    logger.debug("Generating rectangle mask:\n" +
                                 f" panel = {region.panel}\n" +
                                 f" x0 = {x0}\n" + f" y0 = {y0}\n" +
                                 f" x1 = {x1}\n" + f" y1 = {y1}")
                    mask_untrusted_rectangle(mask, x0, x1, y0, y1)
                if region.polygon is not None:
                    assert (len(region.polygon) %
                            2 == 0), "Polygon must contain 2D coords"
                    vertices = []
                    for i in range(int(len(region.polygon) / 2)):
                        x = region.polygon[2 * i]
                        y = region.polygon[2 * i + 1]
                        vertices.append((x, y))
                    polygon = flex.vec2_double(vertices)
                    logger.debug(
                        f"Generating polygon mask:\n panel = {region.panel}\n"
                        + "\n".join(f" coord = {vertex}"
                                    for vertex in vertices))
                    mask_untrusted_polygon(mask, polygon)
                if region.pixel is not None:
                    mask[region.pixel] = False

        # Generate high and low resolution masks
        if params.d_min is not None:
            logger.debug(
                f"Generating high resolution mask:\n d_min = {params.d_min}")
            _apply_resolution_mask(mask, beam, panel, 0, params.d_min)
        if params.d_max is not None:
            logger.debug(
                f"Generating low resolution mask:\n d_max = {params.d_max}")
            d_max = params.d_max
            d_inf = max(d_max + 1, 1e9)
            _apply_resolution_mask(mask, beam, panel, d_max, d_inf)

        try:
            # Mask out the resolution range
            for drange in params.resolution_range:
                d_min = min(drange)
                d_max = max(drange)
                assert d_min < d_max, "d_min must be < d_max"
                logger.debug("Generating resolution range mask:\n" +
                             f" d_min = {d_min}\n" + f" d_max = {d_max}")
                _apply_resolution_mask(mask, beam, panel, d_min, d_max)
        except TypeError:
            # Catch the default value None of params.resolution_range
            if any(params.resolution_range):
                raise

        # Mask out the resolution ranges for the ice rings
        for drange in generate_ice_ring_resolution_ranges(
                beam, panel, params.ice_rings):
            d_min = min(drange)
            d_max = max(drange)
            assert d_min < d_max, "d_min must be < d_max"
            logger.debug("Generating ice ring mask:\n" +
                         f" d_min = {d_min:.4f}\n" + f" d_max = {d_max:.4f}")
            _apply_resolution_mask(mask, beam, panel, d_min, d_max)

        # Add to the list
        masks.append(mask)

    # Return the mask
    return tuple(masks)
Пример #3
0
    def generate(self, imageset):
        """ Generate the mask. """
        # Get the detector and beam
        detector = imageset.get_detector()
        beam = imageset.get_beam()

        # Get the first image
        image = imageset.get_raw_data(0)
        assert len(detector) == len(image)

        # Create the mask for each image
        masks = []
        for index, (im, panel) in enumerate(zip(image, detector)):

            # Create the basic mask from the trusted range
            if self.params.use_trusted_range:
                low, high = panel.get_trusted_range()
                imd = im.as_double()
                mask = (imd > low) & (imd < high)
            else:
                mask = flex.bool(flex.grid(im.all()), True)

            # Add a border around the image
            if self.params.border > 0:
                logger.info("Generating border mask:")
                logger.info(" border = %d" % self.params.border)
                border = self.params.border
                height, width = mask.all()
                borderx = flex.bool(flex.grid(border, width), False)
                bordery = flex.bool(flex.grid(height, border), False)
                mask[0:border, :] = borderx
                mask[-border:, :] = borderx
                mask[:, 0:border] = bordery
                mask[:, -border:] = bordery

            # Apply the untrusted regions
            for region in self.params.untrusted:
                if region.panel == index:
                    if region.circle is not None:
                        xc, yc, radius = region.circle
                        logger.info("Generating circle mask:")
                        logger.info(" panel = %d" % region.panel)
                        logger.info(" xc = %d" % xc)
                        logger.info(" yc = %d" % yc)
                        logger.info(" radius = %d" % radius)
                        mask_untrusted_circle(mask, xc, yc, radius)
                    if region.rectangle is not None:
                        x0, x1, y0, y1 = region.rectangle
                        logger.info("Generating rectangle mask:")
                        logger.info(" panel = %d" % region.panel)
                        logger.info(" x0 = %d" % x0)
                        logger.info(" y0 = %d" % y0)
                        logger.info(" x1 = %d" % x1)
                        logger.info(" y1 = %d" % y1)
                        mask_untrusted_rectangle(mask, x0, x1, y0, y1)
                    if region.polygon is not None:
                        assert (
                            len(region.polygon) % 2 == 0
                        ), "Polygon must contain 2D coords"
                        vertices = []
                        for i in range(int(len(region.polygon) / 2)):
                            x = region.polygon[2 * i]
                            y = region.polygon[2 * i + 1]
                            vertices.append((x, y))
                        polygon = flex.vec2_double(vertices)
                        logger.info("Generating polygon mask:")
                        logger.info(" panel = %d" % region.panel)
                        for vertex in vertices:
                            logger.info(" coord = (%d, %d)" % (vertex))
                        mask_untrusted_polygon(mask, polygon)
                    if region.pixel is not None:
                        mask[region.pixel] = False

            # Create the resolution mask generator
            class ResolutionMaskGeneratorGetter(object):
                def __init__(self, beam, panel):
                    self.beam = beam
                    self.panel = panel
                    self.result = None

                def __call__(self):
                    if self.result is None:
                        self.result = ResolutionMaskGenerator(beam, panel)
                    return self.result

            get_resolution_mask_generator = ResolutionMaskGeneratorGetter(beam, panel)

            # Generate high and low resolution masks
            if self.params.d_min is not None:
                logger.info("Generating high resolution mask:")
                logger.info(" d_min = %f" % self.params.d_min)
                get_resolution_mask_generator().apply(mask, 0, self.params.d_min)
            if self.params.d_max is not None:
                logger.info("Generating low resolution mask:")
                logger.info(" d_max = %f" % self.params.d_max)
                d_min = self.params.d_max
                d_max = max(d_min + 1, 1e9)
                get_resolution_mask_generator().apply(mask, d_min, d_max)

            try:
                # Mask out the resolution range
                for drange in self.params.resolution_range:
                    d_min = min(drange)
                    d_max = max(drange)
                    assert d_min < d_max, "d_min must be < d_max"
                    logger.info("Generating resolution range mask:")
                    logger.info(" d_min = %f" % d_min)
                    logger.info(" d_max = %f" % d_max)
                    get_resolution_mask_generator().apply(mask, d_min, d_max)
            except TypeError:
                # Catch the default value None of self.params.resolution_range
                if any(self.params.resolution_range):
                    raise
                else:
                    pass

            # Mask out the resolution ranges for the ice rings
            for drange in generate_ice_ring_resolution_ranges(
                beam, panel, self.params.ice_rings
            ):
                d_min = min(drange)
                d_max = max(drange)
                assert d_min < d_max, "d_min must be < d_max"
                logger.info("Generating ice ring mask:")
                logger.info(" d_min = %f" % d_min)
                logger.info(" d_max = %f" % d_max)
                get_resolution_mask_generator().apply(mask, d_min, d_max)

            # Add to the list
            masks.append(mask)

        # Return the mask
        return tuple(masks)