Skip to content

fuzzy module

hydrafloods.fuzzy

fuzzy_and(img_list)

Fuzzy And overlay returning the minimum value of the input images. This technique is useful when you want to identify the least common denominator for the membership of all the input criteria

Parameters:

Name Type Description Default
img_list list[ee.Image]

list of ee.Image objects to overlay together

required

Returns:

Type Description
ee.Image

output floating-point image with overlayed values

Source code in hydrafloods/fuzzy.py
def fuzzy_and(img_list):
    """Fuzzy And overlay returning the minimum value of the input images.
    This technique is useful when you want to identify the least common denominator
    for the membership of all the input criteria

    args:
        img_list (list[ee.Image]): list of ee.Image objects to overlay together

    returns:
        ee.Image: output floating-point image with overlayed values
    """
    in_img = ee.Image.cat([img_list])

    out_img = in_img.reduce(ee.Reducer.min()).rename("fuzzy_and")

    return out_img

fuzzy_gamma(img_list, gamma=0.5)

Fuzzy Gamma is an algebraic product of fuzzy Product and fuzzy Sum, which are both raised to the power of gamma. If the specified gamma is 1, the output is the same as fuzzy Sum; if gamma is 0, the output is the same as fuzzy Product

Parameters:

Name Type Description Default
img_list list[ee.Image]

list of ee.Image objects to overlay together

required
gamma float

the gamma value to be used when weighting Product vs Sum

0.5

Returns:

Type Description
ee.Image

output floating-point image with overlayed values

Source code in hydrafloods/fuzzy.py
def fuzzy_gamma(img_list, gamma=0.5):
    """Fuzzy Gamma is an algebraic product of fuzzy Product and fuzzy Sum,
    which are both raised to the power of gamma. If the specified gamma is 1,
    the output is the same as fuzzy Sum; if gamma is 0, the output is the same as fuzzy Product

    args:
        img_list (list[ee.Image]): list of ee.Image objects to overlay together
        gamma (float): the gamma value to be used when weighting Product vs Sum

    returns:
        ee.Image: output floating-point image with overlayed values
    """
    gamma = ee.Image.constant(gamma)
    one = ee.Image.constant(1)
    a = fuzzy_sum(img_list)
    b = fuzzy_product(img_list)

    out_img = a.pow(gamma).multiply(b.pow(one.subtract(gamma))).rename("fuzzy_gamma")

    return out_img

fuzzy_gaussian(img, midpoint, spread)

Fuzzy membership function through a Gaussian or normal distribution based around a user-specified midpoint (which is assigned a membership of 1) with a defined spread. https://desktop.arcgis.com/en/arcmap/10.3/analyze/arcpy-spatial-analyst/fuzzygaussian-class.htm

Parameters:

Name Type Description Default
img ee.Image

The input image whose values will be scaled from 0 to 1

required
midpoint float

user-defined value with a fuzzy membership of 1

required
spread float

the spread of the Gaussian function. The spread generally ranges from 0.01 to 1, with the larger the value results in a steeper distribution around the midpoint

required

Returns:

Type Description
ee.Image

output floating-point image with values ranging from 0 to 1

Source code in hydrafloods/fuzzy.py
@decorators.keep_attrs
def fuzzy_gaussian(img, midpoint, spread):
    """Fuzzy membership function through a Gaussian or normal distribution based around a
    user-specified midpoint (which is assigned a membership of 1) with a defined spread.
    https://desktop.arcgis.com/en/arcmap/10.3/analyze/arcpy-spatial-analyst/fuzzygaussian-class.htm

    args:
        img (ee.Image): The input image whose values will be scaled from 0 to 1
        midpoint (float): user-defined value with a fuzzy membership of 1
        spread (float): the spread of the Gaussian function. The spread generally
            ranges from 0.01 to 1, with the larger the value results in a steeper
            distribution around the midpoint

    returns:
        ee.Image: output floating-point image with values ranging from 0 to 1
    """
    bandNames = img.bandNames()

    spread = ee.Image.constant(spread)
    midpoint = ee.Image.constant(midpoint)
    e = ee.Image.constant(math.e)

    gauss = e.expression(
        "e ** (-s * (x-m)**2)", {"e": e, "x": img, "s": spread, "m": midpoint}
    )

    return gauss.rename(bandNames)

fuzzy_large(img, midpoint, spread)

Fuzzy membership function where the larger input values have membership closer to 1. The function is defined by a user-specified midpoint (which is assigned a membership of 0.5) with a defined spread. https://desktop.arcgis.com/en/arcmap/10.3/analyze/arcpy-spatial-analyst/fuzzylarge-class.htm

Parameters:

Name Type Description Default
img ee.Image

The input image whose values will be scaled from 0 to 1

required
midpoint float

user-defined value with a fuzzy membership of 0.5

required
spread float

the spread of the Large function. The spread generally ranges from 1 to 10, with the larger the value results in a steeper distribution from the midpoint

required

Returns:

Type Description
ee.Image

output floating-point image with values ranging from 0 to 1

Source code in hydrafloods/fuzzy.py
@decorators.keep_attrs
def fuzzy_large(img, midpoint, spread):
    """Fuzzy membership function where the larger input values have membership closer to 1.
    The function is defined by a user-specified midpoint (which is assigned a membership of 0.5)
    with a defined spread.
    https://desktop.arcgis.com/en/arcmap/10.3/analyze/arcpy-spatial-analyst/fuzzylarge-class.htm

    args:
        img (ee.Image): The input image whose values will be scaled from 0 to 1
        midpoint (float): user-defined value with a fuzzy membership of 0.5
        spread (float): the spread of the Large function. The spread generally
            ranges from 1 to 10, with the larger the value results in a steeper
            distribution from the midpoint

    returns:
        ee.Image: output floating-point image with values ranging from 0 to 1
    """
    bandNames = img.bandNames()

    spread = ee.Image(spread)
    midpoint = ee.Image(midpoint)
    one = ee.Image.constant(1)

    large = one.expression(
        "o / ( o + (x / m) ** (s * -1))",
        {"o": one, "x": img, "s": spread, "m": midpoint},
    )

    return large.rename(bandNames)

fuzzy_linear(img, min_val, max_val)

Fuzzy membership function through a linear transformation between the user-specified minimum value, a membership of 0, to the user-defined maximum value, which is assigned a membership of 1. If the minimum value is less than the maximum, the linear function will have a positive slope. If the minimum value is greater than the maximum, the linear function will have a negative slope. https://desktop.arcgis.com/en/arcmap/10.3/analyze/arcpy-spatial-analyst/fuzzylinear-class.htm

Parameters:

Name Type Description Default
img ee.Image

The input image whose values will be scaled linearly from 0 to 1

required
minimum float

The value that will have a membership of 0

required
maximum float

The value that will have a membership of 1

required

Returns:

Type Description
ee.Image

output floating-point image with values ranging from 0 to 1

Source code in hydrafloods/fuzzy.py
@decorators.keep_attrs
def fuzzy_linear(img, min_val, max_val):
    """Fuzzy membership function through a linear transformation between the user-specified minimum
    value, a membership of 0, to the user-defined maximum value, which is assigned a membership of 1.
    If the minimum value is less than the maximum, the linear function will have a positive slope.
    If the minimum value is greater than the maximum, the linear function will have a negative slope.
    https://desktop.arcgis.com/en/arcmap/10.3/analyze/arcpy-spatial-analyst/fuzzylinear-class.htm

    args:
        img (ee.Image): The input image whose values will be scaled linearly from 0 to 1
        minimum (float): The value that will have a membership of 0
        maximum (float): The value that will have a membership of 1

    returns:
        ee.Image: output floating-point image with values ranging from 0 to 1
    """
    bandNames = img.bandNames()

    if ~isinstance(min_val, ee.Number):
        min_val = ee.Number(min_val)

    if ~isinstance(max_val, ee.Number):
        max_val = ee.Number(max_val)

    invert = min_val.gt(max_val)

    minimum = ee.Algorithms.If(invert, max_val, min_val)
    maximum = ee.Algorithms.If(invert, min_val, max_val)

    linear = img.unitScale(minimum, maximum)

    linear = ee.Algorithms.If(invert, ee.Image.constant(1).subtract(linear), linear)
    linear = ee.Image(linear).clamp(0, 1)

    return linear.rename(bandNames)

fuzzy_mslarge(img, mean_scaling, std_scaling, region=None, scale=90)

Fuzzy membership through a function based on the mean and standard deviation, with the larger values having a membership closer to 1. https://desktop.arcgis.com/en/arcmap/10.3/analyze/arcpy-spatial-analyst/fuzzymslarge-class.htm

Parameters:

Name Type Description Default
img ee.Image

The input image whose values will be scaled from 0 to 1

required
mean_scaling float

multiplier for the mean of the input values in the MSLarge function equation.

required
std_scaling float

multiplier for the standard deviation of the input values in the MSLarge function equation.

required
region ee.Geometry | None

region to calculate mean/stdDev image statistics, if set to None will use img.geometry(). default = None

None
scale int

scale at which to perform reduction operations, setting higher will prevent OOM errors. default = 90

90

Returns:

Type Description
ee.Image

output floating-point image with values ranging from 0 to 1

Source code in hydrafloods/fuzzy.py
@decorators.keep_attrs
def fuzzy_mslarge(img, mean_scaling, std_scaling, region=None, scale=90):
    """Fuzzy membership through a function based on the mean and standard deviation,
    with the larger values having a membership closer to 1.
    https://desktop.arcgis.com/en/arcmap/10.3/analyze/arcpy-spatial-analyst/fuzzymslarge-class.htm

    args:
        img (ee.Image): The input image whose values will be scaled from 0 to 1
        mean_scaling (float): multiplier for the mean of the input values in the MSLarge function equation.
        std_scaling (float): multiplier for the standard deviation of the input values in the MSLarge function equation.
        region (ee.Geometry | None, optional): region to calculate mean/stdDev image statistics,
            if set to None will use img.geometry(). default = None
        scale (int, optional): scale at which to perform reduction operations, setting higher will prevent OOM errors. default = 90

    returns:
        ee.Image: output floating-point image with values ranging from 0 to 1
    """
    if region is None:
        region = img.geometry()

    bandNames = img.bandNames()

    mean_scale = ee.Image.constant(mean_scaling)
    std_scale = ee.Image.constant(std_scaling)
    one = ee.Image.constant(1)

    reducer = ee.Reducer.mean().combine(ee.Reducer.stdDev(), None, True)

    stats = ee.Dictionary(
        img.reduceRegion(reducer, region, scale, bestEffort=True, tileScale=16)
    ).toImage()

    mslarge = one.expression(
        "o - (b * s ) / (x - (a * m) + (b * s))",
        {
            "o": one,
            "x": img,
            "a": stats.select(".*(mean)$"),
            "b": stats.select(".*(stdDev)$"),
            "m": mean_scale,
            "s": std_scale,
        },
    )

    mask = img.gte(stats.select(".*(mean)$").multiply(mean_scale))

    return mslarge.multiply(mask).rename(bandNames)

fuzzy_mssmall(img, mean_scale, std_scale, region=None, scale=90)

Fuzzy membership through a function based on the mean and standard deviation, with the smaller values having a membership closer to 1. https://desktop.arcgis.com/en/arcmap/10.3/analyze/arcpy-spatial-analyst/fuzzymssmall-class.htm

Parameters:

Name Type Description Default
img ee.Image

The input image whose values will be scaled from 0 to 1

required
mean_scaling float

multiplier for the mean of the input values in the MSSmall function equation.

required
std_scaling float

multiplier for the standard deviation of the input values in the MSSmall function equation.

required
region ee.Geometry | None

region to calculate mean/stdDev image statistics, if set to None will use img.geometry(). default = None

None
scale int

scale at which to perform reduction operations, setting higher will prevent OOM errors. default = 90

90

Returns:

Type Description
ee.Image

output floating-point image with values ranging from 0 to 1

Source code in hydrafloods/fuzzy.py
@decorators.keep_attrs
def fuzzy_mssmall(img, mean_scale, std_scale, region=None, scale=90):
    """Fuzzy membership through a function based on the mean and standard deviation,
    with the smaller values having a membership closer to 1.
    https://desktop.arcgis.com/en/arcmap/10.3/analyze/arcpy-spatial-analyst/fuzzymssmall-class.htm

    args:
        img (ee.Image): The input image whose values will be scaled from 0 to 1
        mean_scaling (float): multiplier for the mean of the input values in the MSSmall function equation.
        std_scaling (float): multiplier for the standard deviation of the input values in the MSSmall function equation.
        region (ee.Geometry | None, optional): region to calculate mean/stdDev image statistics,
            if set to None will use img.geometry(). default = None
        scale (int, optional): scale at which to perform reduction operations, setting higher will prevent OOM errors. default = 90

    returns:
        ee.Image: output floating-point image with values ranging from 0 to 1
    """
    if region is None:
        region = img.geometry()

    bandNames = img.bandNames()

    mean_scale = ee.Image.constant(mean_scale)
    std_scale = ee.Image.constant(std_scale)
    one = ee.Image.constant(1)

    reducer = ee.Reducer.mean().combine(ee.Reducer.stdDev(), None, True)

    stats = ee.Dictionary(
        img.reduceRegion(reducer, region, scale, bestEffort=True, tileScale=16)
    ).toImage()

    mssmall = one.expression(
        "(b * s ) / (x - (a * m) + (b * s))",
        {
            "o": one,
            "x": img,
            "a": stats.select(".*(mean)$"),
            "b": stats.select(".*(stdDev)$"),
            "m": mean_scale,
            "s": std_scale,
        },
    )

    mask = img.gte(stats.select(".*(mean)$").multiply(mean_scale))

    return mssmall.multiply(mask).rename(bandNames)

fuzzy_near(img, midpoint, spread)

Fuzzy membership function around a specific value which is defined by a user-defined midpoint (which is assigned a membership of 1), with a defined spread decreasing to zero. https://desktop.arcgis.com/en/arcmap/10.3/analyze/arcpy-spatial-analyst/fuzzylarge-class.htm

Parameters:

Name Type Description Default
img ee.Image

The input image whose values will be scaled from 0 to 1

required
midpoint float

user-defined value with a fuzzy membership of 1

required
spread float

the spread of the Near function. The spread generally ranges from 0.001 to 1, with the larger the value results in a steeper distribution from the midpoint

required

Returns:

Type Description
ee.Image

output floating-point image with values ranging from 0 to 1

Source code in hydrafloods/fuzzy.py
@decorators.keep_attrs
def fuzzy_near(img, midpoint, spread):
    """Fuzzy membership function around a specific value which is defined by a user-defined midpoint
     (which is assigned a membership of 1), with a defined spread decreasing to zero.
    https://desktop.arcgis.com/en/arcmap/10.3/analyze/arcpy-spatial-analyst/fuzzylarge-class.htm

    args:
        img (ee.Image): The input image whose values will be scaled from 0 to 1
        midpoint (float): user-defined value with a fuzzy membership of 1
        spread (float): the spread of the Near function. The spread generally
            ranges from 0.001 to 1, with the larger the value results in a steeper
            distribution from the midpoint

    returns:
        ee.Image: output floating-point image with values ranging from 0 to 1
    """
    bandNames = img.bandNames()

    spread = ee.Image.constant(spread)
    midpoint = ee.Image.constant(midpoint)
    one = ee.Image.constant(1)

    near = one.expression(
        "o / (o + s * (x - m)**2)", {"o": one, "x": img, "s": spread, "m": midpoint}
    )

    return near.rename(bandNames)

fuzzy_or(img_list)

Fuzzy Or overlay returning the maximum value of the input images. This technique is useful when you want to identify the highest membership values for any of the input criteria

Parameters:

Name Type Description Default
img_list list[ee.Image]

list of ee.Image objects to overlay together

required

Returns:

Type Description
ee.Image

output floating-point image with overlayed values

Source code in hydrafloods/fuzzy.py
def fuzzy_or(img_list):
    """Fuzzy Or overlay returning the maximum value of the input images.
    This technique is useful when you want to identify the highest membership values
    for any of the input criteria

    args:
        img_list (list[ee.Image]): list of ee.Image objects to overlay together

    returns:
        ee.Image: output floating-point image with overlayed values
    """
    in_img = ee.Image.cat([img_list])

    out_img = in_img.reduce(ee.Reducer.max()).rename("fuzzy_or")

    return out_img

fuzzy_product(img_list)

Fuzzy Product overlay which multiplies each of the fuzzy values togetherfor all the input images. The resulting product will be less than any of the input, and when a member of many sets is input, the value can be very small.

Parameters:

Name Type Description Default
img_list list[ee.Image]

list of ee.Image objects to overlay together

required

Returns:

Type Description
ee.Image

output floating-point image with overlayed values

Source code in hydrafloods/fuzzy.py
def fuzzy_product(img_list):
    """Fuzzy Product overlay which multiplies each of the fuzzy values togetherfor all the input images.
    The resulting product will be less than any of the input, and when a member of many sets is input,
    the value can be very small.

    args:
        img_list (list[ee.Image]): list of ee.Image objects to overlay together

    returns:
        ee.Image: output floating-point image with overlayed values
    """
    in_img = ee.Image.cat([img_list])

    out_img = in_img.reduce(ee.Reducer.product()).rename("fuzzy_product")

    return out_img

fuzzy_small(img, midpoint, spread)

Fuzzy membership function with the smaller input values having membership closer to 1. The function is defined by a user-specified midpoint (which is assigned a membership of 0.5) with a defined spread. https://desktop.arcgis.com/en/arcmap/10.3/analyze/arcpy-spatial-analyst/fuzzysmall-class.htm

Parameters:

Name Type Description Default
img ee.Image

The input image whose values will be scaled from 0 to 1

required
midpoint float

user-defined value with a fuzzy membership of 0.5

required
spread float

the spread of the Small function. The spread generally ranges from 1 to 10, with the larger the value results in a steeper distribution from the midpoint

required

Returns:

Type Description
ee.Image

output floating-point image with values ranging from 0 to 1

Source code in hydrafloods/fuzzy.py
@decorators.keep_attrs
def fuzzy_small(img, midpoint, spread):
    """Fuzzy membership function with the smaller input values having membership closer to 1.
    The function is defined by a user-specified midpoint (which is assigned a membership of 0.5)
    with a defined spread.
    https://desktop.arcgis.com/en/arcmap/10.3/analyze/arcpy-spatial-analyst/fuzzysmall-class.htm

    args:
        img (ee.Image): The input image whose values will be scaled from 0 to 1
        midpoint (float): user-defined value with a fuzzy membership of 0.5
        spread (float): the spread of the Small function. The spread generally
            ranges from 1 to 10, with the larger the value results in a steeper
            distribution from the midpoint

    returns:
        ee.Image: output floating-point image with values ranging from 0 to 1
    """
    bandNames = img.bandNames()

    spread = ee.Image(spread)
    midpoint = ee.Image(midpoint)
    one = ee.Image.constant(1)

    small = one.expression(
        "o / (o + (x / m) ** s)", {"o": one, "x": img, "s": spread, "m": midpoint}
    )

    return small.rename(bandNames)

fuzzy_sum(img_list)

Fuzzy Product overlay add the fuzzy values for all the input images. The resulting sum is an increasing linear combination function that is based on the number of criteria entered into the analysis

Parameters:

Name Type Description Default
img_list list[ee.Image]

list of ee.Image objects to overlay together

required

Returns:

Type Description
ee.Image

output floating-point image with overlayed values

Source code in hydrafloods/fuzzy.py
def fuzzy_sum(img_list):
    """Fuzzy Product overlay add the fuzzy values for all the input images.
    The resulting sum is an increasing linear combination function that is based on the number of
    criteria entered into the analysis

    args:
        img_list (list[ee.Image]): list of ee.Image objects to overlay together

    returns:
        ee.Image: output floating-point image with overlayed values
    """
    one = ee.Image.constant(1)

    in_img = one.subtract(ee.Image.cat([img_list]))

    out_img = one.subtract(in_img.reduce(ee.Reducer.product())).rename("fuzzy_sum")

    return out_img

fuzzy_weighted(img_list, weights)

Overlays several rasters, multiplying each by their given weight and summing them together.

Parameters:

Name Type Description Default
img_list list[ee.Image]

list of ee.Image objects to overlay together

required
weights list[float]

list of weight values to assign images, must be in order

required

Returns:

Type Description
ee.Image

output floating-point image with overlayed values

Source code in hydrafloods/fuzzy.py
def fuzzy_weighted(img_list, weights):
    """Overlays several rasters, multiplying each by their given weight and summing them together.

    args:
        img_list (list[ee.Image]): list of ee.Image objects to overlay together
        weights (list[float]): list of weight values to assign images, must be in order

    returns:
        ee.Image: output floating-point image with overlayed values
    """
    weights = ee.Image.constant(weights)

    in_img = ee.Image.cat([img_list])

    out_img = in_img.multiply(weights).reduce(ee.Reducer.sum()).rename("fuzzy_weighted")

    return out_img

fuzzy_zmf(img, min_val, max_val)

Z-function fuzzy membership generator.

Source code in hydrafloods/fuzzy.py
def fuzzy_zmf(img, min_val, max_val):

    """
    Z-function fuzzy membership generator.
    """
    bandNames = img.bandNames()

    if ~isinstance(min_val, ee.Number):
        min_val = ee.Number(min_val)

    if ~isinstance(max_val, ee.Number):
        max_val = ee.Number(max_val)

    invert = min_val.gt(max_val)

    a = ee.Image.constant(ee.Algorithms.If(invert, max_val, min_val))
    b = ee.Image.constant(ee.Algorithms.If(invert, min_val, max_val))

    zmf = ee.Image(1)

    m1 = a.lte(img).And(img.lt(a.add(b).divide(2)))
    y1 = img.expression(
        "1 - 2 * ((img - a) / (b - a)) ** 2", {"img": img, "a": a, "b": b}
    )

    m2 = a.add(b).divide(2).lte(img).And(img.lte(b))
    y2 = img.expression("2 * ((img - b) / (b - a)) ** 2", {"img": img, "a": a, "b": b})

    m3 = img.gte(b)

    zmf = zmf.where(m1, y1).where(m2, y2).where(m3, ee.Image(0))

    zmf = ee.Image(ee.Algorithms.If(invert, ee.Image(1).subtract(zmf), zmf))

    return zmf.rename(bandNames)