Skip to content

Nodata utilities

convert_raster_nodata(input_raster, old_nodata=None, new_nodata=-9999)

Convert existing nodata values with a new nodata value for a raster.

Parameters:

Name Type Description Default
input_raster DatasetReader

Input raster dataset.

required
new_nodata Number

New nodata value that will be used to replace existing nodata for all bands. Defaults to -9999.

-9999

Returns:

Type Description
Tuple[ndarray, dict]

The input raster data and metadata updated with the new nodata.

Raises:

Type Description
InvalidParameterValueException

Nodata is not defined in raster metadata and old_nodata was not specified.

Source code in eis_toolkit/utilities/nodata.py
 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
@beartype
def convert_raster_nodata(
    input_raster: rasterio.io.DatasetReader,
    old_nodata: Optional[Number] = None,
    new_nodata: Number = -9999,
) -> Tuple[np.ndarray, dict]:
    """
    Convert existing nodata values with a new nodata value for a raster.

    Args:
        input_raster: Input raster dataset.
        new_nodata: New nodata value that will be used to replace existing nodata for all bands. Defaults to -9999.

    Returns:
        The input raster data and metadata updated with the new nodata.

    Raises:
        InvalidParameterValueException: Nodata is not defined in raster metadata and old_nodata was not specified.
    """
    if old_nodata is None and not input_raster.meta["nodata"]:
        raise InvalidParameterValueException(
            "Could not find old nodata value from raster metadata. Either define old_nodata or use \
            'set_raster_nodata' tool to fix broken raster metadata."
        )
    raster_arr = input_raster.read()
    old_nodata = input_raster.nodata if old_nodata is None else old_nodata
    out_image = replace_values(raster_arr, old_nodata, new_nodata)
    out_meta = input_raster.meta.copy()
    out_meta["nodata"] = new_nodata

    return out_image, out_meta

handle_nodata_as_nan(func)

Replace nodata_values with np.nan for function execution and reverses the replacement afterwards.

Source code in eis_toolkit/utilities/nodata.py
135
136
137
138
139
140
141
142
143
144
145
146
@beartype
def handle_nodata_as_nan(func: Callable) -> Callable:
    """Replace nodata_values with np.nan for function execution and reverses the replacement afterwards."""

    @functools.wraps(func)
    def wrapper(in_data: np.ndarray, *args: Any, nodata_value: Number, **kwargs: Any) -> np.ndarray:
        replaced_data = nodata_to_nan(in_data, nodata_value)
        result = func(replaced_data, *args, **kwargs)
        out_data = nan_to_nodata(result, nodata_value)
        return out_data

    return wrapper

nan_to_nodata(data, nodata_value)

Convert np.nan values to specified nodata_value.

Parameters:

Name Type Description Default
data ndarray

Input data as a numpy array.

required
nodata_value Number

Value that np.nan is converted to.

required

Returns:

Type Description
ndarray

Input array where np.nan has been converted to specified nodata.

Source code in eis_toolkit/utilities/nodata.py
121
122
123
124
125
126
127
128
129
130
131
132
@beartype
def nan_to_nodata(data: np.ndarray, nodata_value: Number) -> np.ndarray:
    """Convert np.nan values to specified nodata_value.

    Args:
        data: Input data as a numpy array.
        nodata_value: Value that np.nan is converted to.

    Returns:
        Input array where np.nan has been converted to specified nodata.
    """
    return np.where(np.isnan(data), nodata_value, data)

nodata_to_nan(data, nodata_value)

Convert specified nodata_value to np.nan.

Parameters:

Name Type Description Default
data ndarray

Input data as a numpy array.

required
nodata_value Number

Value that is converted to np.nan.

required

Returns:

Type Description
ndarray

Input array where specified nodata has been converted to np.nan.

Source code in eis_toolkit/utilities/nodata.py
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
@beartype
def nodata_to_nan(data: np.ndarray, nodata_value: Number) -> np.ndarray:
    """Convert specified nodata_value to np.nan.

    Args:
        data: Input data as a numpy array.
        nodata_value: Value that is converted to np.nan.

    Returns:
        Input array where specified nodata has been converted to np.nan.
    """
    if np.issubdtype(data.dtype, np.integer):
        data = data.astype(float)

    return np.where(np.isin(data, nodata_value), np.nan, data)

set_raster_nodata(raster_meta, new_nodata)

Set new nodata value for raster metadata or profile.

Note that this function does not convert any data values, it only changes the metadata. The inteded use case for this tool is fixing metadata with invalid nodata value.

Parameters:

Name Type Description Default
raster_meta Union[Dict, Profile]

Raster metadata or profile to be updated.

required
nodata_value

New nodata value.

required

Returns:

Type Description
Union[Dict, Profile]

Raster metadata / profile with updated nodata value.

Source code in eis_toolkit/utilities/nodata.py
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
@beartype
def set_raster_nodata(raster_meta: Union[Dict, profiles.Profile], new_nodata: Number) -> Union[Dict, profiles.Profile]:
    """
    Set new nodata value for raster metadata or profile.

    Note that this function does not convert any data values, it only changes the metadata.
    The inteded use case for this tool is fixing metadata with invalid nodata value.

    Args:
        raster_meta: Raster metadata or profile to be updated.
        nodata_value: New nodata value.

    Returns:
        Raster metadata / profile with updated nodata value.
    """
    out_meta = raster_meta.copy()
    out_meta.update({"nodata": new_nodata})
    return out_meta

unify_raster_nodata(input_rasters, new_nodata=-9999)

Unifies nodata for the input rasters.

All old nodata values in the input rasters are converted to the new nodata value. Raster metadatas is also updated with the new nodata value.

Parameters:

Name Type Description Default
input_rasters Sequence[DatasetReader]
required
new_nodata Number

New nodata value that will be used to replace existing nodata for all bands in all input rasters. Defaults to -9999.

-9999

Returns:

Type Description
Sequence[Tuple[ndarray, dict]]

Output raster list. List elements are tuples where first element is raster data and second element is raster metadata.

Raises:

Type Description
InvalidParameterValueException

Input raster list contains only one raster.

Source code in eis_toolkit/utilities/nodata.py
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
@beartype
def unify_raster_nodata(
    input_rasters: Sequence[rasterio.io.DatasetReader], new_nodata: Number = -9999
) -> Sequence[Tuple[np.ndarray, dict]]:
    """
    Unifies nodata for the input rasters.

    All old nodata values in the input rasters are converted to the new nodata value. Raster metadatas
    is also updated with the new nodata value.

    Args:
        input_rasters:
        new_nodata: New nodata value that will be used to replace existing nodata for all bands in all
            input rasters. Defaults to -9999.

    Returns:
        Output raster list. List elements are tuples where first element is raster data and second \
        element is raster metadata.

    Raises:
        InvalidParameterValueException: Input raster list contains only one raster.
    """

    if len(input_rasters) < 2:
        raise InvalidParameterValueException(
            f"Expected multiple rasters in the input_rasters list. Rasters: {len(input_rasters)}. \
            To convert nodata of one raster, use the 'convert_raster_nodata' tool."
        )

    out_rasters = []
    for raster in input_rasters:
        out_image, out_meta = convert_raster_nodata(raster, new_nodata=new_nodata)
        out_rasters.append((out_image, out_meta))

    return out_rasters