Beispiel #1
0
    def test_axis(self):
        """ Test that iprod(axis = 0) yields 0d arrays """
        source = [np.ones((16,), dtype=np.float) for _ in range(10)]

        with self.subTest("axis = 0"):
            summed = prod(source, axis=0)
            self.assertTrue(np.all(summed == 1))

        with self.subTest("axis = None"):
            summed = prod(source, axis=None)
            self.assertTrue(np.allclose(summed, np.ones_like(summed)))
Beispiel #2
0
def combine_masks(*masks):
    """
    Combine multiple pixel masks into one. This assumes that pixel masks evaluate
    to ``True`` on valid pixels and ``False`` on invalid pixels.

    Returns
    -------
    combined : `~numpy.ndarray`, dtype bool
    """
    # By multiplying boolean arrays, values of False propagate
    return prod(masks, dtype=bool)
Beispiel #3
0
    def test_against_numpy(self):
        """ Test that iprod() returns the same as numpy.prod() for various axis inputs """

        stream = [np.random.random((16, 16)) for _ in range(10)]
        stack = np.dstack(stream)

        for axis in (0, 1, 2, None):
            with self.subTest("axis = {}".format(axis)):
                from_numpy = np.prod(stack, axis=axis)
                from_stream = prod(stream, axis=axis)
                self.assertTrue(np.allclose(from_stream, from_numpy))
Beispiel #4
0
 def test_dtype(self):
     """ Test that dtype argument is working """
     source = [np.ones((16,), dtype=np.float) for _ in range(10)]
     product = prod(source, dtype=np.int)
     self.assertTrue(np.allclose(product, np.ones_like(product)))
     self.assertEqual(product.dtype, np.int)
Beispiel #5
0
 def test_ignore_nans(self):
     """ Test that NaNs are ignored. """
     source = [np.ones((16,), dtype=np.float) for _ in range(10)]
     source.append(np.full_like(source[0], np.nan))
     product = prod(source, ignore_nan=True)
     self.assertTrue(np.allclose(product, np.ones_like(product)))
Beispiel #6
0
 def test_trivial(self):
     """ Test a product of ones """
     source = [np.ones((16,), dtype=np.float) for _ in range(10)]
     product = prod(source)
     self.assertTrue(np.allclose(product, np.ones_like(product)))
Beispiel #7
0
def nfold(im, mod, center=None, mask=None, fill_value=0.0):
    """
    Returns an images averaged according to n-fold rotational symmetry. This can be used to
    boost the signal-to-noise ratio on an image with known symmetry, e.g. a diffraction pattern.

    Parameters
    ----------
    im : array_like, ndim 2
        Image to be azimuthally-symmetrized.
    center : array_like, shape (2,) or None, optional
        Coordinates of the center (in pixels) in the format ``center=[col, row]``. If ``center=None``,
        the image is rotated around the center of the array, i.e. ``center=(cols / 2 - 0.5, rows / 2 - 0.5)``.
    mod : int
        Fold symmetry number. Valid numbers must be a divisor of 360.
    mask : `~numpy.ndarray` or None, optional
        Mask of `image`. The mask should evaluate to `True` (or 1) on valid pixels.
        If None (default), no mask is used.
    fill_value : float, optional
        In the case of a mask that overlaps with itself when rotationally averaged,
        the overlapping regions will be filled with this value.

    Returns
    -------
    out : `~numpy.ndarray`, dtype float
        Symmetrized image.

    Raises
    ------
    ValueError : If `mod` is not a divisor of 360 deg.
    """
    if 360 % mod:
        raise ValueError(
            f"{mod}-fold rotational symmetry is not valid (not a divisor of 360)."
        )
    angles = range(0, 360, int(360 / mod))

    im = np.array(im, copy=True)

    kwargs = {
        "center": center,
        "mode": "constant",
        "cval": 0,
        "preserve_range": True
    }

    if mask is None:
        return ns.average(rotate(im, angle, **kwargs) for angle in angles)

    # Use weights because edges of the pictures, which might be cropped by the rotation
    # should not count in the average
    wt = np.ones_like(mask, dtype=im.dtype)
    wt[np.logical_not(mask)] = 0

    weights = (rotate(wt, angle, **kwargs) for angle in angles)
    imgs = (rotate(im, angle, **kwargs) for angle in angles)

    avg = ns.average(imgs, weights=weights)

    # Mask may overlap with itself during symmetrization. At those points, the average
    # will be zero (because the weights are 0 there)
    # However, because users may want to change that value to `fill_value != 0`, we need
    # to know where is the overlap
    if fill_value != 0.0:
        invalid_pixels = np.logical_not(mask)
        masks = (rotate(invalid_pixels, angle, **kwargs) for angle in angles)
        overlap = ns.prod(masks).astype(bool)  # equivalent to logical_and
        avg[overlap] = fill_value

    return ns.nan_to_num(avg, fill_value=fill_value)