diff --git a/u4py/io/docx_report.py b/u4py/io/docx_report.py index 7e07a1484e6e12e2953623ae8707a6f408add440..87d78e53a2987a357f905c8b01939a55ea82bf3e 100644 --- a/u4py/io/docx_report.py +++ b/u4py/io/docx_report.py @@ -92,16 +92,18 @@ def site_report( # Volumina document = moved_volumes(row[1], document) - # Difference maps + # DEM if os.path.exists(img_path + f"_dem.{img_fmt}"): document = dem(img_path, img_fmt, document) # Topographie - if os.path.exists(img_path + f"_slope.{img_fmt}") or os.path.exists( - img_path + f"_aspect_slope.{img_fmt}" - ): + if os.path.exists(img_path + f"_slope.{img_fmt}"): document = topography(row[1], img_path, img_fmt, document) + # Difference Map + if os.path.exists(img_path + f"_diffplan.{img_fmt}"): + document = difference(img_path, img_fmt, document) + # PSI Data if os.path.exists(img_path + f"_psi.{img_fmt}"): document = psi_map(img_path, img_fmt, document) @@ -436,7 +438,7 @@ def dem(img_path: os.PathLike, img_fmt: str, document: Document) -> Document: prgph.alignment = WD_ALIGN_PARAGRAPH.CENTER run = prgph.add_run() run.add_picture( - img_path + f"_dem.{img_fmt}", width=docx.shared.Mm(140) + img_path + f"_dem.{img_fmt}", width=docx.shared.Mm(150) ) prgph = document.add_paragraph() prgph.add_run(f"Abbildung {FIGURENUM}: ").bold = True @@ -532,36 +534,24 @@ def topography( prgph.alignment = WD_ALIGN_PARAGRAPH.CENTER run = prgph.add_run() run.add_picture( - img_path + f"_slope.{img_fmt}", width=docx.shared.Mm(70) + img_path + f"_slope.{img_fmt}", width=docx.shared.Mm(150) ) + prgph = document.add_paragraph() + prgph.alignment = WD_ALIGN_PARAGRAPH.CENTER + run = prgph.add_run() run.add_picture( - img_path + f"_aspect.{img_fmt}", width=docx.shared.Mm(70) + img_path + f"_aspect.{img_fmt}", width=docx.shared.Mm(150) ) prgph = document.add_paragraph() prgph.add_run(f"Abbildung {FIGURENUM}: ").bold = True FIGURENUM += 1 prgph.add_run("Topographie im Gebiet. ") - prgph.add_run("Links: ").italic = True + prgph.add_run("Oben: ").italic = True prgph.add_run("Steigung. ") - prgph.add_run("Rechts: ").italic = True + prgph.add_run("Unten: ").italic = True prgph.add_run("Exposition.") - if os.path.exists(img_path + f"_aspect_slope.{img_fmt}"): - prgph = document.add_paragraph() - prgph.alignment = WD_ALIGN_PARAGRAPH.CENTER - run = prgph.add_run() - run.add_picture( - img_path + f"_aspect_slope.{img_fmt}", - width=docx.shared.Mm(150), - ) - prgph = document.add_paragraph() - prgph.add_run(f"Abbildung {FIGURENUM}: ").bold = True - FIGURENUM += 1 - prgph.add_run( - "Gemischte Darstellung von Steigung (Sättigung) und Exposition (Farbe)." - ) - return document @@ -700,3 +690,26 @@ def soils(img_path: os.PathLike, img_fmt: str, document: Document) -> Document: ) return document + + +def difference( + img_path: os.PathLike, img_fmt: str, document: Document +) -> Document: + """Adds the difference and slope maps. + :param img_path: The path to the image folder including group name. + :type img_path: os.PathLike + :rtype: str + """ + global FIGURENUM + + prgph = document.add_paragraph() + prgph.alignment = WD_ALIGN_PARAGRAPH.CENTER + run = prgph.add_run() + run.add_picture( + img_path + f"_diffplan.{img_fmt}", width=docx.shared.Mm(150) + ) + prgph = document.add_paragraph() + prgph.add_run(f"Abbildung {FIGURENUM}: ").bold = True + FIGURENUM += 1 + prgph.add_run("Differenzenplan im Gebiet.") + return document diff --git a/u4py/plotting/axes.py b/u4py/plotting/axes.py index 32b893224e60d08da47f14d9748e940f5b68f620..b5e5660deb4ce451694ddd18b9dcd4dd53a223c7 100644 --- a/u4py/plotting/axes.py +++ b/u4py/plotting/axes.py @@ -24,6 +24,7 @@ from typing import Callable, Iterable, Tuple import contextily import geopandas as gp import mapclassify # Keep for user defined chloropleths +import matplotlib.colors as mcolors import matplotlib.lines as mlines import matplotlib.patches as mpatches import matplotlib.path as mpath @@ -788,7 +789,12 @@ def add_dem(region: gp.GeoDataFrame, tiff_folder: os.PathLike, ax: Axes): @_add_or_create -def add_slope(region: gp.GeoDataFrame, tiff_folder: os.PathLike, ax: Axes): +def add_slope( + region: gp.GeoDataFrame, + tiff_folder: os.PathLike, + ax: Axes, + cmap: mcolors.Colormap = "inferno", +): """Adds a slope map to the axis. :param region: The region where to extract the data. @@ -797,6 +803,8 @@ def add_slope(region: gp.GeoDataFrame, tiff_folder: os.PathLike, ax: Axes): :type tiff_folder: os.PathLike :param ax: The axis to plot into. :type ax: Axes + :param cmap: The colormap to use for the plot. + :type cmap: mcolors.Colormap """ file_list = u4files.get_file_list_adf(tiff_folder) points = u4spatial.select_points_region(region, file_list) @@ -805,17 +813,17 @@ def add_slope(region: gp.GeoDataFrame, tiff_folder: os.PathLike, ax: Axes): for ii, fpath in enumerate(file_list): sl_fpath = u4tiff.get_terrain(fpath, terrain_feature="slope") if ii > 0: - add_tile(sl_fpath, ax=ax, cmap="inferno", vm=(0, 45)) + add_tile(sl_fpath, ax=ax, cmap=cmap, vm=(0, 60)) else: add_tile( sl_fpath, ax=ax, - cmap="inferno", - vm=(0, 45), + cmap=cmap, + vm=(0, 60), colorbar={ "label": "Hangneigung (°)", "shrink": 0.7, - "extend": "both", + "extend": "max", # "pad": 0.05, }, ) diff --git a/u4py/plotting/plots.py b/u4py/plotting/plots.py index f30d42c1125ee2b80e2d2416adcbbb617cd80189..7bb7c33fe1cda75f1f0cf2e410b53f303ad9cc70 100644 --- a/u4py/plotting/plots.py +++ b/u4py/plotting/plots.py @@ -13,6 +13,7 @@ import contextily import geopandas as gp import matplotlib.artist as martist import matplotlib.cm as mcm +import matplotlib.colors as mcolors import matplotlib.patches as mpatches import matplotlib.pyplot as plt import numpy as np @@ -1321,10 +1322,10 @@ def slope_map( region = gp.GeoDataFrame( geometry=[u4spatial.bounds_to_polygon(ax)], crs=crs ) - u4ax.add_slope(region, dem_path, ax=ax) # Plot other anomalies if not IS_HLNUG: - # For non HLNUG data use the thresholded contours + # For non HLNUG data use the thresholded contours and default colormap + u4ax.add_slope(region, dem_path, ax=ax) u4ax.add_gpkg_data_in_axis( contour_path, ax=ax, @@ -1334,7 +1335,24 @@ def slope_map( linewidth=2, ) else: - # For HLNUG data use the + # For HLNUG data use the classified shapes and custom colormap + # Color thresholds and corresponding named colors + bounds = [0, 5, 10, 20, 30, 45, 60] + mapping = [b / 60 for b in bounds] + color_names = [ + "lightgreen", # 0-5 + "green", # 5-10 + "lightyellow", # 10-20 + "yellow", # 20-30 + "orange", # 30-45 + "red", # 45-60 + "darkviolet", # 60-90 + ] + col_list = [(m, c) for m, c in zip(mapping, color_names)] + cmap = mcolors.LinearSegmentedColormap.from_list( + "custom", colors=col_list + ) + u4ax.add_slope(region, dem_path, ax=ax, cmap=cmap) u4ax.add_gpkg_data_in_axis( contour_path, ax=ax, diff --git a/u4py/scripts/gis_workflows/PostProcess_ClassifiedShapes.py b/u4py/scripts/gis_workflows/PostProcess_ClassifiedShapes.py index 5878dba56f2e9f3a365a59ebd494ba32d9ac5373..994ee8a5ba76b944506e1d6f5d7332e4a3cebc28 100644 --- a/u4py/scripts/gis_workflows/PostProcess_ClassifiedShapes.py +++ b/u4py/scripts/gis_workflows/PostProcess_ClassifiedShapes.py @@ -326,12 +326,21 @@ def map_worker( overwrite=overwrite_plots, ) else: + u4plots.diffplan_map( + row, + crs, + output_path, + "known_features", + project["paths"]["diff_plan_path"], + plot_buffer=100, + overwrite=overwrite_plots, + ) u4plots.dem_map( row, crs, output_path, "known_features", - dem_path, + project["paths"]["diff_plan_path"], contour_path, plot_buffer=100, overwrite=overwrite_plots, diff --git a/u4py/scripts/playground/custom_slope_cmap.py b/u4py/scripts/playground/custom_slope_cmap.py new file mode 100644 index 0000000000000000000000000000000000000000..64a608b49aca0f7fa146c6892024cffe4365e54d --- /dev/null +++ b/u4py/scripts/playground/custom_slope_cmap.py @@ -0,0 +1,40 @@ +"""Testing custom colormap as requested by HLNUG""" + +import matplotlib.pyplot as plt +import numpy as np +from matplotlib.colors import LinearSegmentedColormap + +# Data generation +x = np.linspace(0, 5, 400) +y = np.linspace(0, 5, 400) +X, Y = np.meshgrid(x, y) +Z = (np.sin(X) * np.cos(Y) + 1) * 45 # Values between 0 and 90 + +# Color thresholds and corresponding named colors +bounds = [0, 5, 10, 20, 30, 45, 60] +mapping = [b / 60 for b in bounds] +color_names = [ + "lightgreen", # 0-5 + "green", # 5-10 + "lightyellow", # 10-20 + "yellow", # 20-30 + "orange", # 30-45 + "red", # 45-60 + "darkviolet", # 60-90 +] +col_list = [(m, c) for m, c in zip(mapping, color_names)] +cmap = LinearSegmentedColormap.from_list("custom", colors=col_list) + +fig, ax = plt.subplots() +img = ax.imshow( + Z, + cmap=cmap, + vmin=0, + vmax=60, +) +# Add colorbar +cbar = fig.colorbar(img, ax=ax, extend="max") +cbar.set_label("Slope") + +fig.tight_layout() +fig.savefig("cmap_test.png")