Skip to content

Clip

clip_transform(raster, limits, bands=None, nodata=None)

Clips data based on specified upper and lower limits.

Takes one nodata value that will be ignored in calculations. Replaces values below the lower limit and above the upper limit with provided values, respecively. Works both one-sided and two-sided but raises error if no limits provided.

If no band/column selection specified, all bands/columns will be used. If a parameter contains only 1 entry, it will be applied for all bands. The limits can be set for each band individually.

Parameters:

Name Type Description Default
raster DatasetReader

Data object to be transformed.

required
bands Optional[Sequence[int]]

Selection of bands to be transformed.

None
limits Sequence[Tuple[Optional[Number], Optional[Number]]]

Lower and upper limits (lower, upper) as real values.

required
nodata Optional[Number]

Nodata value to be considered.

None

Returns:

Name Type Description
out_array ndarray

The transformed data.

out_meta dict

Updated metadata.

out_settings dict

Log of input settings and calculated statistics if available.

Raises:

Type Description
InvalidRasterBandException

The input contains invalid band numbers.

NonMatchingParameterLengthsException

The input does not match the number of selected bands.

InvalidParameterValueException

The input does not match the requirements (values, order of values).

Source code in eis_toolkit/transformations/clip.py
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
@beartype
def clip_transform(  # type: ignore[no-any-unimported]
    raster: rasterio.io.DatasetReader,
    limits: Sequence[Tuple[Optional[Number], Optional[Number]]],
    bands: Optional[Sequence[int]] = None,
    nodata: Optional[Number] = None,
) -> Tuple[np.ndarray, dict, dict]:
    """
    Clips data based on specified upper and lower limits.

    Takes one nodata value that will be ignored in calculations.
    Replaces values below the lower limit and above the upper limit with provided values, respecively.
    Works both one-sided and two-sided but raises error if no limits provided.

    If no band/column selection specified, all bands/columns will be used.
    If a parameter contains only 1 entry, it will be applied for all bands.
    The limits can be set for each band individually.

    Args:
        raster: Data object to be transformed.
        bands: Selection of bands to be transformed.
        limits: Lower and upper limits (lower, upper) as real values.
        nodata: Nodata value to be considered.

    Returns:
        out_array: The transformed data.
        out_meta: Updated metadata.
        out_settings: Log of input settings and calculated statistics if available.

    Raises:
        InvalidRasterBandException: The input contains invalid band numbers.
        NonMatchingParameterLengthsException: The input does not match the number of selected bands.
        InvalidParameterValueException: The input does not match the requirements (values, order of values).
    """
    bands = list(range(1, raster.count + 1)) if bands is None else bands
    nodata = raster.nodata if nodata is None else nodata

    if check_raster_bands(raster, bands) is False:
        raise InvalidRasterBandException("Invalid band selection")

    if check_parameter_length(bands, limits) is False:
        raise NonMatchingParameterLengthsException("Invalid limit length.")

    for item in limits:
        if item.count(None) == len(item):
            raise InvalidParameterValueException(f"Limit values all None: {item}.")

        if not check_minmax_position(item):
            raise InvalidParameterValueException(f"Invalid min-max values provided: {item}.")

    expanded_args = expand_and_zip(bands, limits)
    limits = [element[1] for element in expanded_args]

    out_settings = {}

    for i in range(0, len(bands)):
        band_array = raster.read(bands[i])
        inital_dtype = band_array.dtype

        band_array = cast_array_to_float(band_array, cast_int=True)
        band_array = nodata_to_nan(band_array, nodata_value=nodata)

        band_array = _clip_transform(band_array, limits=limits[i])

        band_array = nan_to_nodata(band_array, nodata_value=nodata)
        band_array = cast_array_to_int(band_array, scalar=nodata, initial_dtype=inital_dtype)

        band_array = np.expand_dims(band_array, axis=0)

        if i == 0:
            out_array = band_array.copy()
        else:
            out_array = np.vstack((out_array, band_array))

        current_transform = f"transformation {i + 1}"
        current_settings = {
            "band_origin": bands[i],
            "limit_lower": cast_scalar_to_int(limits[i][0]),
            "limit_upper": cast_scalar_to_int(limits[i][1]),
            "nodata": cast_scalar_to_int(nodata),
        }

        out_settings[current_transform] = current_settings

    out_meta = raster.meta.copy()
    out_meta.update({"count": len(bands), "nodata": nodata, "dtype": out_array.dtype.name})

    return out_array, out_meta, out_settings