diff --git a/u4py/plotting/axes.py b/u4py/plotting/axes.py index 054751744b0d4c31c14983be4792d995b017be22..f58bebaaeb2484f24b18f5248cd7f092c652d85b 100644 --- a/u4py/plotting/axes.py +++ b/u4py/plotting/axes.py @@ -918,7 +918,11 @@ def add_aspect_slope( @_add_or_create def add_gpkg_data_in_axis( - gpkg_path: os.PathLike, table: str, ax: Axes, **plot_kwargs + gpkg_path: os.PathLike, + table: str, + ax: Axes, + ax_crs: str = "EPSG:32632", + **plot_kwargs, ): """Adds data from a gpkg file to the plot using the boundaries of the axis as the extend of the geometry @@ -933,8 +937,8 @@ def add_gpkg_data_in_axis( """ crs = u4sql.get_crs(gpkg_path, table)[0] region = gp.GeoDataFrame( - geometry=[u4spatial.bounds_to_polygon(ax)], crs=crs - ) + geometry=[u4spatial.bounds_to_polygon(ax)], crs=ax_crs + ).to_crs(crs) data = u4gpkg.load_gpkg_data_region_ogr( region, gpkg_path, table, clip=False ) diff --git a/u4py/scripts/examples/algorithms/contouring.py b/u4py/scripts/examples/algorithms/contouring.py new file mode 100644 index 0000000000000000000000000000000000000000..e0c6cf4bb8a5c75397195d87f77bc2bd389d2c8e --- /dev/null +++ b/u4py/scripts/examples/algorithms/contouring.py @@ -0,0 +1,166 @@ +""" +This script shows how the contouring of the difference plans with the OSM data +works. +""" + +import logging +import os +from pathlib import Path + +import geopandas as gp +import matplotlib.pyplot as plt +import numpy as np + +import u4py.analysis.spatial as u4spatial +import u4py.io.gpkg as u4gpkg +import u4py.io.sql as u4sql +import u4py.plotting.axes as u4ax +import u4py.plotting.formatting as u4pltfmt +import u4py.utils.config as u4config + +u4config.start_logger() + + +def main(): + base_path = Path( + r"~\Documents\ArcGIS\EndberichtWorkflowPlots" + ).expanduser() + output_path = Path( + r"~\HESSENBOX-DA\Umwelt_4\Bericht_2024\images" + ).expanduser() + + fig, axes = plt.subplots( + nrows=2, ncols=3, figsize=(12, 8), sharex=True, sharey=True + ) + + # Original difference plan and boundary of plot + logging.info("Plotting Differenzenplan") + axes[0][0].set_title("Differenzenplan") + orig_folder = os.path.join(base_path, "original_tiffs") + orig_tiffs = [ + os.path.join(orig_folder, f) + for f in os.listdir(orig_folder) + if f.endswith(".tif") + ] + bounds = [] + for tile in orig_tiffs: + bds, crs = u4ax.add_tile(tile, ax=axes[0][0], vm=2, cmap="RdBu") + bounds.append(bds) + xmin = np.min([bds.left for bds in bounds]) + xmax = np.max([bds.right for bds in bounds]) + ymin = np.min([bds.bottom for bds in bounds]) + ymax = np.max([bds.top for bds in bounds]) + + axes[0][0].set_xlim(xmin, xmax) + axes[0][0].set_ylim(ymin, ymax) + + # region_gdf = gp.GeoDataFrame( + # geometry=[u4spatial.bounds_to_polygon((xmin, ymin, xmax, ymax))], + # crs=crs, + # ) + + # Get and plot buffered shapes + logging.info("Plotting Filter Masken") + axes[0][1].set_title("Filter Masken") + shp_cfg = u4config.get_shape_config() + shape_cache_folder = os.path.join(base_path, "shape_cache") + os.makedirs(shape_cache_folder, exist_ok=True) + for tile in orig_tiffs: + fname = os.path.splitext(os.path.split(tile)[-1])[0] + shppath = os.path.join(shape_cache_folder, fname + ".shp") + if os.path.exists(shppath): + bfshp = gp.read_file(shppath) + else: + bfshp = u4gpkg.load_and_buffer_gpkg( + os.path.join(base_path, "all_shapes.gpkg"), + tile, + shp_cfg=shp_cfg, + ) + bfshp.to_file(shppath) + bfshp.plot(ax=axes[0][1], color="k") + + # Plot Clipped tiffs + logging.info("Plotting Clipped Tiffs") + axes[0][2].set_title("Geschnittener Differenzenplan") + clip_folder = os.path.join(base_path, "clipped_tiffs") + clip_tiffs = [ + os.path.join(clip_folder, f) + for f in os.listdir(clip_folder) + if f.endswith(".tif") + ] + for tile in clip_tiffs: + u4ax.add_tile(tile, ax=axes[0][2], vm=2, cmap="RdBu") + + # Contours + logging.info("Plotting Contours") + axes[1][0].set_title("Konturierung") + u4ax.add_gpkg_data_in_axis( + os.path.join(base_path, "contours.gpkg"), + table="contours", + ax=axes[1][0], + ax_crs=crs, + column="color_levels", + fc="None", + cmap="RdBu", + ) + + # Groups + logging.info("Plotting Groups") + axes[1][1].set_title("Gruppierung") + u4ax.add_gpkg_data_in_axis( + os.path.join(base_path, "Classified_Shapes.gpkg"), + table="Classified_Shapes", + ax=axes[1][1], + ax_crs=crs, + column="group", + fc="None", + cmap="tab10", + ) + + # Klassifikation + logging.info("Plotting Classification") + axes[1][2].set_title("Klassifikation") + gpkg_crs = u4sql.get_crs( + os.path.join(base_path, "Filtered_Classified_Shapes_onlyLarge.gpkg"), + "Filtered_Classified_Shapes_2410", + )[0] + region = gp.GeoDataFrame( + geometry=[u4spatial.bounds_to_polygon(axes[1][2])], crs=crs + ).to_crs(gpkg_crs) + data = u4gpkg.load_gpkg_data_region_ogr( + region, + os.path.join(base_path, "Filtered_Classified_Shapes_onlyLarge.gpkg"), + "Filtered_Classified_Shapes_2410", + clip=False, + ) + data.plot(ax=axes[1][2], column="manual_class_1", fc="None", ec="C1") + data.apply( + lambda x: axes[1][2].annotate( + text=f"{x['manual_class_1']}\n{x['manual_class_2']}\n{x['manual_class_3']}", + xy=x.geometry.centroid.coords[0], + xytext=(1, 1), + textcoords="offset fontsize", + ha="center", + va="center", + ), + axis=1, + ) + + # Format and save + logging.info("Formatting and Saving") + u4ax.add_basemap(ax=axes[0][1], crs=crs) + u4ax.add_basemap(ax=axes[1][0], crs=crs) + u4ax.add_basemap(ax=axes[1][1], crs=crs) + u4ax.add_basemap(ax=axes[1][2], crs=crs) + fig.tight_layout() + axes[0][0].yaxis.set_major_formatter(u4pltfmt.coordinate_formatter) + axes[1][0].yaxis.set_major_formatter(u4pltfmt.coordinate_formatter) + axes[1][0].xaxis.set_major_formatter(u4pltfmt.coordinate_formatter) + axes[1][1].xaxis.set_major_formatter(u4pltfmt.coordinate_formatter) + axes[1][2].xaxis.set_major_formatter(u4pltfmt.coordinate_formatter) + fig.savefig(os.path.join(output_path, "ContourWorkflow.png")) + fig.savefig(os.path.join(output_path, "ContourWorkflow.pdf")) + + +if __name__ == "__main__": + main()