Example #1
0
def profile_line(img, src=None, dst=None, linewidth=1, order=1, mode="constant", cval=0.0, constrain=True, **kargs):
    """Wrapper for sckit-image method of the same name to get a line_profile.

    Parameters:
        img(ImageArray): Image data to take line section of
        src, dst (2-tuple of int or float): start and end of line profile. If the co-ordinates
            are given as intergers then they are assumed to be pxiel co-ordinates, floats are
            assumed to be real-space co-ordinates using the embedded metadata.
        linewidth (int): the wideth of the profile to be taken.
        order (int 1-3): Order of interpolation used to find image data when not aligned to a point
        mode (str): How to handle data outside of the image.
        cval (float): The constant value to assume for data outside of the image is mode is "constant"
        constrain (bool): Ensure the src and dst are within the image (default True).

    Returns:
        A :py:class:`Stoner.Data` object containing the line profile data and the metadata from the image.
    """
    scale = img.get("MicronsPerPixel", 1.0)
    r, c = img.shape
    if src is None and dst is None:
        if "x" in kargs:
            src = (kargs["x"], 0)
            dst = (kargs["x"], r)
        if "y" in kargs:
            src = (0, kargs["y"])
            dst = (c, kargs["y"])
    if isinstance(src, float):
        src = (src, src)
    if isinstance(dst, float):
        dst = (dst, dst)
    dst = _scale(dst, scale)
    src = _scale(src, scale)
    if not istuple(src, int, int):
        raise ValueError("src co-ordinates are not a 2-tuple of ints.")
    if not istuple(dst, int, int):
        raise ValueError("dst co-ordinates are not a 2-tuple of ints.")

    if constrain:
        fix = lambda x, mx: int(round(sorted([0, x, mx])[1]))
        r, c = img.shape
        src = list(src)
        src = (fix(src[0], r), fix(src[1], c))
        dst = (fix(dst[0], r), fix(dst[1], c))

    result = measure.profile_line(img, src, dst, linewidth, order, mode, cval)
    points = measure.profile._line_profile_coordinates(src, dst, linewidth)[:, :, 0]
    ret = Data()
    ret.data = points.T
    ret.setas = "xy"
    ret &= np.sqrt(ret.x ** 2 + ret.y ** 2) * scale
    ret &= result
    ret.column_headers = ["X", "Y", "Distance", "Intensity"]
    ret.setas = "..xy"
    ret.metadata = img.metadata.copy()
    return ret
Example #2
0
def profile_line(img, src=None, dst=None, linewidth=1, order=1, mode="constant", cval=0.0, constrain=True, **kargs):
    """Wrapper for sckit-image method of the same name to get a line_profile.

    Parameters:
        img(ImageArray): Image data to take line section of
        src, dst (2-tuple of int or float): start and end of line profile. If the co-ordinates
            are given as intergers then they are assumed to be pxiel co-ordinates, floats are
            assumed to be real-space co-ordinates using the embedded metadata.
        linewidth (int): the wideth of the profile to be taken.
        order (int 1-3): Order of interpolation used to find image data when not aligned to a point
        mode (str): How to handle data outside of the image.
        cval (float): The constant value to assume for data outside of the image is mode is "constant"
        constrain (bool): Ensure the src and dst are within the image (default True).

    Returns:
        A :py:class:`Stoner.Data` object containing the line profile data and the metadata from the image.
    """
    scale = img.get("MicronsPerPixel", 1.0)
    r, c = img.shape
    if src is None and dst is None:
        if "x" in kargs:
            src = (kargs["x"], 0)
            dst = (kargs["x"], r)
        if "y" in kargs:
            src = (0, kargs["y"])
            dst = (c, kargs["y"])
    if isinstance(src, float):
        src = (src, src)
    if isinstance(dst, float):
        dst = (dst, dst)
    dst = _scale(dst, scale)
    src = _scale(src, scale)
    if not istuple(src, int, int):
        raise ValueError("src co-ordinates are not a 2-tuple of ints.")
    if not istuple(dst, int, int):
        raise ValueError("dst co-ordinates are not a 2-tuple of ints.")

    if constrain:
        fix = lambda x, mx: int(round(sorted([0, x, mx])[1]))
        r, c = img.shape
        src = list(src)
        src = (fix(src[0], r), fix(src[1], c))
        dst = (fix(dst[0], r), fix(dst[1], c))

    result = measure.profile_line(img, src, dst, linewidth, order, mode, cval)
    points = measure.profile._line_profile_coordinates(src, dst, linewidth)[:, :, 0]
    ret = Data()
    ret.data = points.T
    ret.setas = "xy"
    ret &= np.sqrt(ret.x ** 2 + ret.y ** 2) * scale
    ret &= result
    ret.column_headers = ["X", "Y", "Distance", "Intensity"]
    ret.setas = "..xy"
    ret.metadata = img.metadata.copy()
    return ret
Example #3
0
def normalise(im, scale=None, sample=None, limits=(0.0, 1.0)):
    """Norm alise the data to a fixed scale.

    Keyword Arguements:
        scale (2-tuple): The range to scale the image to, defaults to -1 to 1.
        saple (box): Only use a section of the input image to calculate the new scale over.
        limits (low,high): Take the input range from the *high* and *low* fraction of the input when sorted.

    Returns:
        A scaled version of the data. The ndarray min and max methods are used to allow masked images
        to be operated on only on the unmasked areas.

    Notes:
        The *sample* keyword controls the area in which the range of input values is calculated, the actual scaling is
        done on the whole image.

        The *limits* parameter is used to set the input scale being normalised from - if an image has a few outliers then
        this setting can be used to clip the input range before normalising. The parameters in the limit are the values at
        the *low* and *high* fractions of the cumulative distribution functions.
    """
    mask = im.mask
    cls = im.__class__
    im = im.astype(float)
    if scale is None:
        scale = (-1.0, 1.0)
    if sample is not None:
        section = im[im._box(sample)]
    else:
        section = im
    if limits != (0.0, 1.0):
        low, high = limits
        low = np.sort(section.ravel())[int(low * section.size)]
        high = np.sort(section.ravel())[int(high * section.size)]
        im.clip_intensity(limits=(low, high))
    else:
        high = section.max()
        low = section.min()

    if not istuple(scale, float, float, strict=False):
        raise ValueError("scale should be a 2-tuple of floats.")
    scaled = (im.data - low) / (high - low)
    delta = scale[1] - scale[0]
    offset = scale[0]
    im = scaled * delta + offset
    im = im.view(cls)
    im.mask = mask
    return im
Example #4
0
def normalise(im, scale=None, sample=None, limits=(0.0, 1.0)):
    """Norm alise the data to a fixed scale.

    Keyword Arguements:
        scale (2-tuple): The range to scale the image to, defaults to -1 to 1.
        saple (box): Only use a section of the input image to calculate the new scale over.
        limits (low,high): Take the input range from the *high* and *low* fraction of the input when sorted.

    Returns:
        A scaled version of the data. The ndarray min and max methods are used to allow masked images
        to be operated on only on the unmasked areas.

    Notes:
        The *sample* keyword controls the area in which the range of input values is calculated, the actual scaling is
        done on the whole image.

        The *limits* parameter is used to set the input scale being normalised from - if an image has a few outliers then
        this setting can be used to clip the input range before normalising. The parameters in the limit are the values at
        the *low* and *high* fractions of the cumulative distribution functions.
    """
    mask = im.mask
    cls = im.__class__
    im = im.astype(float)
    if scale is None:
        scale = (-1.0, 1.0)
    if sample is not None:
        section = im[im._box(sample)]
    else:
        section = im
    if limits != (0.0, 1.0):
        low, high = limits
        low = np.sort(section.ravel())[int(low * section.size)]
        high = np.sort(section.ravel())[int(high * section.size)]
        im.clip_intensity(limits=(low, high))
    else:
        high = section.max()
        low = section.min()

    if not istuple(scale, float, float, strict=False):
        raise ValueError("scale should be a 2-tuple of floats.")
    scaled = (im.data - low) / (high - low)
    delta = scale[1] - scale[0]
    offset = scale[0]
    im = scaled * delta + offset
    im = im.view(cls)
    im.mask = mask
    return im