Aller au contenu

Compute Plantability Raster

Command

Bases: BaseCommand

Source code in back/plantability/management/commands/compute_plantability_raster.py
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
class Command(BaseCommand):
    help = "Compute and save factors data."

    def handle(self, *args, **options):
        """Compute and save factor data for the selected city."""
        raster_directory = str(BASE_DIR) + "/media/rasters/"
        output_file = str(BASE_DIR) + "/media/rasters/plantability.tif"
        output_color_file = str(BASE_DIR) + "/media/rasters/plantability_colors.tif"

        # Init raster
        file_path = raster_directory + list(FACTORS.keys())[0] + ".tif"
        with rasterio.open(file_path) as ref_src:
            meta = ref_src.meta.copy()
            shape = ref_src.shape

        result = np.zeros(shape, dtype=np.float32)

        for factor_name, weight in FACTORS.items():
            compute_weighted_sum(
                raster_directory, output_file, meta, result, factor_name, weight
            )

        # Cut everything outside cities
        all_cities = select_city(None).union_all()
        result = cut_outside_cities(meta, result, all_cities)

        with rasterio.open(output_file, "w", **meta) as dst:
            dst.write(result, 1)

        # Convert to RGB and colors
        result_colors = threshold_and_convert_to_colors(result, rgb_colors, colors)

        color_meta = meta.copy()
        color_meta.update(dtype=rasterio.uint8, count=3, nodata=None)

        with rasterio.open(output_color_file, "w", **color_meta) as dst:
            for i in range(3):  # Write each RGB channel
                dst.write(result_colors[:, :, i], i + 1)

handle(*args, **options)

Compute and save factor data for the selected city.

Source code in back/plantability/management/commands/compute_plantability_raster.py
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
def handle(self, *args, **options):
    """Compute and save factor data for the selected city."""
    raster_directory = str(BASE_DIR) + "/media/rasters/"
    output_file = str(BASE_DIR) + "/media/rasters/plantability.tif"
    output_color_file = str(BASE_DIR) + "/media/rasters/plantability_colors.tif"

    # Init raster
    file_path = raster_directory + list(FACTORS.keys())[0] + ".tif"
    with rasterio.open(file_path) as ref_src:
        meta = ref_src.meta.copy()
        shape = ref_src.shape

    result = np.zeros(shape, dtype=np.float32)

    for factor_name, weight in FACTORS.items():
        compute_weighted_sum(
            raster_directory, output_file, meta, result, factor_name, weight
        )

    # Cut everything outside cities
    all_cities = select_city(None).union_all()
    result = cut_outside_cities(meta, result, all_cities)

    with rasterio.open(output_file, "w", **meta) as dst:
        dst.write(result, 1)

    # Convert to RGB and colors
    result_colors = threshold_and_convert_to_colors(result, rgb_colors, colors)

    color_meta = meta.copy()
    color_meta.update(dtype=rasterio.uint8, count=3, nodata=None)

    with rasterio.open(output_color_file, "w", **color_meta) as dst:
        for i in range(3):  # Write each RGB channel
            dst.write(result_colors[:, :, i], i + 1)

compute_weighted_sum(raster_directory, output_file, meta, result, factor_name, weight)

Compute the weighted sum of raster data and save the result to a file.

Parameters:

Name Type Description Default
raster_directory str

The directory containing the raster files.

required
output_file str

The path to the output file where the result will be saved.

required
meta Dict[str, Any]

Metadata for the output raster file.

required
result ndarray

The array to store the computed weighted sum.

required
factor_name str

The name of the factor to process.

required
weight float

The weight to apply to the factor data.

required

Returns:

Type Description
None

None

Source code in back/plantability/management/commands/compute_plantability_raster.py
13
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
def compute_weighted_sum(
    raster_directory: str,
    output_file: str,
    meta: Dict[str, Any],
    result: np.ndarray,
    factor_name: str,
    weight: float,
) -> None:
    """
    Compute the weighted sum of raster data and save the result to a file.

    Args:
        raster_directory (str): The directory containing the raster files.
        output_file (str): The path to the output file where the result will be saved.
        meta (Dict[str, Any]): Metadata for the output raster file.
        result (np.ndarray): The array to store the computed weighted sum.
        factor_name (str): The name of the factor to process.
        weight (float): The weight to apply to the factor data.

    Returns:
        None
    """
    factor_file = raster_directory + factor_name + ".tif"
    log_progress(
        f"Processing: {factor_file.split('/')[-1].split('.')[0]} with weight {weight}"
    )
    with rasterio.open(factor_file) as src:
        factor_data = src.read(1).astype(np.float32)
        result += weight * factor_data / 100
    del factor_data

    meta.update(dtype=np.float32, count=1, compress="lzw", nodata=-9999)
    with rasterio.open(output_file, "w", **meta) as dst:
        dst.write(result.astype(np.float32), 1)

    log_progress(f"Weighted sum written to {output_file}")

cut_outside_cities(meta, result, all_cities_union)

Cut everything outside the cities and set nodata values for areas outside the cities.

Parameters:

Name Type Description Default
meta Dict[str, Any]

Metadata for the output raster file.

required
result ndarray

The array to store the computed weighted sum.

required
all_cities_union Any

The union of all city geometries.

required

Returns:

Type Description
ndarray

np.ndarray: The updated result array with nodata values outside the cities.

Source code in back/plantability/management/commands/compute_plantability_raster.py
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
def cut_outside_cities(
    meta: Dict[str, Any], result: np.ndarray, all_cities_union: Any
) -> np.ndarray:
    """
    Cut everything outside the cities and set nodata values for areas outside the cities.

    Args:
        meta (Dict[str, Any]): Metadata for the output raster file.
        result (np.ndarray): The array to store the computed weighted sum.
        all_cities_union (Any): The union of all city geometries.

    Returns:
        np.ndarray: The updated result array with nodata values outside the cities.
    """
    shape = result.shape
    mask = features.geometry_mask(
        [all_cities_union],
        out_shape=shape,
        transform=meta["transform"],
        all_touched=True,
        invert=True,
    )
    nodata_value = meta.get("nodata", -9999)
    result = np.where(mask, result, nodata_value)
    return result

threshold_and_convert_to_colors(result, rgb_colors, colors)

Apply thresholding to the result array and convert it to RGB colors.

Parameters:

Name Type Description Default
result ndarray

The array containing the computed weighted sum.

required
rgb_colors Dict[float, ndarray]

A dictionary mapping threshold values to RGB color arrays.

required
colors Dict[float, str]

A dictionary mapping threshold values to color names.

required

Returns:

Type Description
ndarray

np.ndarray: The array with RGB color values.

Source code in back/plantability/management/commands/compute_plantability_raster.py
 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
def threshold_and_convert_to_colors(
    result: np.ndarray, rgb_colors: Dict[float, np.ndarray], colors: Dict[float, str]
) -> np.ndarray:
    """
    Apply thresholding to the result array and convert it to RGB colors.

    Args:
        result (np.ndarray): The array containing the computed weighted sum.
        rgb_colors (Dict[float, np.ndarray]): A dictionary mapping threshold values to RGB color arrays.
        colors (Dict[float, str]): A dictionary mapping threshold values to color names.

    Returns:
        np.ndarray: The array with RGB color values.
    """
    thresholds = sorted(colors.keys())
    result_colors = np.zeros(result.shape + (3,), dtype=np.uint8)  # RGB output

    # Apply thresholds and convert to colors
    mask = result <= thresholds[0]
    result_colors[mask] = rgb_colors[thresholds[0]]

    for i in range(0, len(thresholds) - 1):
        lower = thresholds[i]
        upper = thresholds[i + 1]
        mask = (result > lower) & (result <= upper)
        result_colors[mask] = rgb_colors[upper]

    mask = result > thresholds[-1]
    result_colors[mask] = rgb_colors[thresholds[-1]]
    nodata_mask = result == -9999
    result_colors[nodata_mask] = np.array([255, 255, 255], dtype=np.uint8)

    return result_colors