.. DO NOT EDIT. .. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. .. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: .. "auto_examples/spatial/plot_spatial_roi_overview.py" .. LINE NUMBERS ARE GIVEN BELOW. .. only:: html .. note:: :class: sphx-glr-download-link-note :ref:`Go to the end ` to download the full example code. .. rst-class:: sphx-glr-example-title .. _sphx_glr_auto_examples_spatial_plot_spatial_roi_overview.py: Focus on a local map window with ``plot_spatial_roi`` ======================================================= This lesson explains how to use ``geoprior.plot.spatial.plot_spatial_roi`` when the full study area is too large and you want to inspect a smaller rectangular region of interest (ROI). Why this function matters ------------------------- A full-domain spatial map is good for the first overview, but many real questions are local: - Which neighborhood contains the strongest hotspot? - Does the same small zone stay active across years? - How do two mapped variables compare in the same local window? - Is a local anomaly still visible once we zoom into the ROI? This helper answers those questions by extracting a rectangular spatial window and plotting a **grid** where: - rows represent time slices, - columns represent different value columns, - and every panel shows only the requested ROI. This page is therefore written as a **teaching guide**, not only as an API demo. We will build a realistic table, define a local bounding box, inspect how the helper arranges the ROI grid, compare shared and per-panel colorbars, and finish with a checklist for using the function on your own data. .. GENERATED FROM PYTHON SOURCE LINES 38-55 .. code-block:: Python from __future__ import annotations import matplotlib.pyplot as plt import numpy as np import pandas as pd from geoprior.plot.spatial import plot_spatial_roi pd.set_option("display.max_columns", 20) pd.set_option("display.width", 110) pd.set_option( "display.float_format", lambda v: f"{v:0.4f}", ) .. GENERATED FROM PYTHON SOURCE LINES 56-75 What this function expects -------------------------- ``plot_spatial_roi`` expects a tidy DataFrame with: - two spatial coordinate columns, - one time column, - one or more numeric ``value_cols`` to display, - and a rectangular ROI defined by ``x_range`` and ``y_range``. Compared with ``plot_spatial``, the main conceptual difference is that this helper plots **multiple value columns at once**. The figure is a matrix: - one row per time slice, - one column per value column. The function returns a list containing one figure. That single figure can still be large, because it holds the full time-by-variable grid. .. GENERATED FROM PYTHON SOURCE LINES 78-93 Build a realistic demo table ---------------------------- A good ROI lesson needs two things: 1. a field with a broad background trend, 2. a stronger local hotspot worth zooming into. We create two map-ready variables: - ``subsidence_q50`` as the main forecasted value, - ``interval_width_80`` as a local uncertainty companion. We then define a local window around the moving hotspot so the zoomed view has something meaningful to teach. .. GENERATED FROM PYTHON SOURCE LINES 93-138 .. code-block:: Python rng = np.random.default_rng(19) x_coords = np.linspace(0.0, 10.0, 21) y_coords = np.linspace(0.0, 7.0, 15) years = [2023, 2024, 2025] rows: list[dict[str, float | int]] = [] for year in years: shift_x = 0.28 * (year - 2023) shift_y = 0.12 * (year - 2023) for x in x_coords: for y in y_coords: regional_plane = 3.8 + 0.22 * x + 0.10 * y hotspot = 7.0 * np.exp( -((x - (6.1 + shift_x)) ** 2) / 1.8 -((y - (3.6 + shift_y)) ** 2) / 1.2 ) ridge = 1.1 * np.exp(-((x - 3.1) ** 2) / 4.8) * np.cos(y / 1.2) noise = rng.normal(0.0, 0.18) value = regional_plane + hotspot + ridge + noise width80 = 0.9 + 0.15 * value + 0.08 * np.exp( -((x - (6.1 + shift_x)) ** 2) / 1.2 -((y - (3.6 + shift_y)) ** 2) / 0.9 ) rows.append( { "coord_x": x, "coord_y": y, "year": year, "subsidence_q50": value, "interval_width_80": width80, } ) roi_df = pd.DataFrame(rows) print("Demo ROI table") print(roi_df.head(10)) .. rst-class:: sphx-glr-script-out .. code-block:: none Demo ROI table coord_x coord_y year subsidence_q50 interval_width_80 0 0.0000 0.0000 2023 3.8820 1.4823 1 0.0000 0.5000 2023 4.1648 1.5247 2 0.0000 1.0000 2023 4.0747 1.5112 3 0.0000 1.5000 2023 3.8856 1.4828 4 0.0000 2.0000 2023 4.1068 1.5160 5 0.0000 2.5000 2023 3.7161 1.4574 6 0.0000 3.0000 2023 4.0878 1.5132 7 0.0000 3.5000 2023 3.9041 1.4856 8 0.0000 4.0000 2023 4.1678 1.5252 9 0.0000 4.5000 2023 4.2071 1.5311 .. GENERATED FROM PYTHON SOURCE LINES 139-150 Inspect the structure before zooming in --------------------------------------- Before using an ROI helper, it is worth checking: - which variables are available, - how many time slices exist, - and what the full coordinate extent looks like. This helps the user choose a bounding box that is meaningful rather than arbitrary. .. GENERATED FROM PYTHON SOURCE LINES 150-169 .. code-block:: Python print("\nColumns") print(list(roi_df.columns)) print("\nRows per year") print(roi_df.groupby("year").size()) print("\nFull spatial extent") print( roi_df[["coord_x", "coord_y"]].agg(["min", "max"]) ) print("\nVariable summary by year") print( roi_df.groupby("year")[["subsidence_q50", "interval_width_80"]] .mean() ) .. rst-class:: sphx-glr-script-out .. code-block:: none Columns ['coord_x', 'coord_y', 'year', 'subsidence_q50', 'interval_width_80'] Rows per year year 2023 315 2024 315 2025 315 dtype: int64 Full spatial extent coord_x coord_y min 0.0000 0.0000 max 10.0000 7.0000 Variable summary by year subsidence_q50 interval_width_80 year 2023 5.6537 1.7514 2024 5.6575 1.7519 2025 5.6423 1.7497 .. GENERATED FROM PYTHON SOURCE LINES 170-181 Define a local window of interest --------------------------------- The ROI is a simple rectangular bounding box. A good teaching habit is to make that choice explicit in the lesson, because users often have one of two goals: - zoom into a domain expert's known area, - or focus on the neighborhood around a hotspot seen in the full map. Here we choose a box that captures the strongest moving hotspot. .. GENERATED FROM PYTHON SOURCE LINES 181-189 .. code-block:: Python x_range = (4.6, 7.8) y_range = (2.2, 5.1) print("\nChosen ROI") print({"x_range": x_range, "y_range": y_range}) .. rst-class:: sphx-glr-script-out .. code-block:: none Chosen ROI {'x_range': (4.6, 7.8), 'y_range': (2.2, 5.1)} .. GENERATED FROM PYTHON SOURCE LINES 190-202 Start with the most useful ROI comparison: time by variable ----------------------------------------------------------- This is the main strength of ``plot_spatial_roi``. In one figure, we can compare: - how the local hotspot evolves over time, - and how two different variables behave inside exactly the same ROI. We use ``cbar='uniform'`` first, because shared color meaning is often the cleanest way to compare the same variable across rows. .. GENERATED FROM PYTHON SOURCE LINES 202-224 .. code-block:: Python figs_roi_uniform = plot_spatial_roi( df=roi_df, value_cols=["subsidence_q50", "interval_width_80"], x_range=x_range, y_range=y_range, dt_col="year", dt_values=years, cmap="viridis", marker_size=62, alpha=0.92, cbar="uniform", grid_props={"linestyle": ":", "alpha": 0.30}, ) print("\nNumber of returned figures:", len(figs_roi_uniform)) print( "Axes in the first figure (including colorbar axes):", len(figs_roi_uniform[0].axes), ) .. image-sg:: /auto_examples/spatial/images/sphx_glr_plot_spatial_roi_overview_001.png :alt: subsidence_q50 @ 2023, interval_width_80 @ 2023, subsidence_q50 @ 2024, interval_width_80 @ 2024, subsidence_q50 @ 2025, interval_width_80 @ 2025 :srcset: /auto_examples/spatial/images/sphx_glr_plot_spatial_roi_overview_001.png :class: sphx-glr-single-img .. rst-class:: sphx-glr-script-out .. code-block:: none Number of returned figures: 1 Axes in the first figure (including colorbar axes): 7 .. GENERATED FROM PYTHON SOURCE LINES 225-239 How to read the ROI grid ------------------------ A good reading order is: 1. move down one column to compare the same variable through time, 2. then move across one row to compare variables in the same year, 3. and finally check whether the uncertainty field follows the same local structure as the main forecast field. In this demo, the highest subsidence zone stays inside the ROI and shifts slightly across years. The width field broadly follows that same zone, which is a realistic pattern: the area with stronger signal can also be the area with wider intervals. .. GENERATED FROM PYTHON SOURCE LINES 242-254 Why this function is ideal for local side-by-side reading --------------------------------------------------------- If we tried to do this with ``plot_spatial`` alone, we would need one separate call per variable and then mentally align the subplots. Here, the helper gives us a direct *time × variable* matrix, which is much better for focused local comparison. This makes the function especially useful when the user wants to ask: *"Inside this specific area, do the forecast level and uncertainty tell the same story?"* .. GENERATED FROM PYTHON SOURCE LINES 257-268 Compare shared and per-panel colorbars -------------------------------------- Just as in the full-domain spatial lesson, the colorbar choice changes the comparison logic. - ``cbar='uniform'`` emphasizes direct comparison across panels, - per-panel colorbars emphasize local contrast inside each panel. The second option can be helpful when one variable has a much tighter numeric range than another. .. GENERATED FROM PYTHON SOURCE LINES 268-284 .. code-block:: Python figs_roi_individual = plot_spatial_roi( df=roi_df, value_cols=["subsidence_q50", "interval_width_80"], x_range=x_range, y_range=y_range, dt_col="year", dt_values=years, cmap="plasma", marker_size=56, alpha=0.94, cbar="individual", grid_props={"linestyle": "--", "alpha": 0.18}, ) .. image-sg:: /auto_examples/spatial/images/sphx_glr_plot_spatial_roi_overview_002.png :alt: subsidence_q50 @ 2023, interval_width_80 @ 2023, subsidence_q50 @ 2024, interval_width_80 @ 2024, subsidence_q50 @ 2025, interval_width_80 @ 2025 :srcset: /auto_examples/spatial/images/sphx_glr_plot_spatial_roi_overview_002.png :class: sphx-glr-single-img .. GENERATED FROM PYTHON SOURCE LINES 285-301 Teach the user when each colorbar mode is better ------------------------------------------------ Use a shared colorbar when your goal is statements such as: - "the hotspot is clearly stronger in 2025 than in 2023", - "the right column is narrower in magnitude than the left column". Use individual colorbars when your goal is statements such as: - "show me the internal structure of each panel clearly", - "this variable has subtle variation that disappears under a shared scale". The key teaching point is that the same data can answer different questions depending on the colorbar logic. .. GENERATED FROM PYTHON SOURCE LINES 304-310 Use custom coordinate names when your data does not use defaults ---------------------------------------------------------------- Real project tables often store spatial coordinates as longitude and latitude, Easting/Northing, or some custom export names. The helper is flexible enough to accept those names through ``spatial_cols``. .. GENERATED FROM PYTHON SOURCE LINES 310-330 .. code-block:: Python roi_df_ll = roi_df.rename( columns={"coord_x": "longitude", "coord_y": "latitude"} ) _ = plot_spatial_roi( df=roi_df_ll, value_cols=["subsidence_q50", "interval_width_80"], x_range=x_range, y_range=y_range, spatial_cols=("longitude", "latitude"), dt_col="year", dt_values=[2024, 2025], cmap="cividis", marker_size=58, alpha=0.95, cbar="uniform", ) .. image-sg:: /auto_examples/spatial/images/sphx_glr_plot_spatial_roi_overview_003.png :alt: subsidence_q50 @ 2024, interval_width_80 @ 2024, subsidence_q50 @ 2025, interval_width_80 @ 2025 :srcset: /auto_examples/spatial/images/sphx_glr_plot_spatial_roi_overview_003.png :class: sphx-glr-single-img .. GENERATED FROM PYTHON SOURCE LINES 331-337 Hide axes when the figure is mainly for presentation ---------------------------------------------------- Axis ticks are useful during analysis, but sometimes the user wants a clean visual panel for a report or slide. In that case, the helper can suppress the axes while preserving the overall grid structure. .. GENERATED FROM PYTHON SOURCE LINES 337-353 .. code-block:: Python _ = plot_spatial_roi( df=roi_df, value_cols=["subsidence_q50", "interval_width_80"], x_range=x_range, y_range=y_range, dt_col="year", dt_values=[2025], cmap="magma", marker_size=68, alpha=0.96, cbar="individual", show_axis="off", ) .. image-sg:: /auto_examples/spatial/images/sphx_glr_plot_spatial_roi_overview_004.png :alt: subsidence_q50 @ 2025, interval_width_80 @ 2025 :srcset: /auto_examples/spatial/images/sphx_glr_plot_spatial_roi_overview_004.png :class: sphx-glr-single-img .. GENERATED FROM PYTHON SOURCE LINES 354-378 Practical checklist for your own data ------------------------------------- When adapting this helper to your own results, use this checklist: 1. Start from a tidy DataFrame with two coordinate columns and one time column. 2. Decide which local window matters scientifically, not only visually. 3. Put variables you want to compare side by side into ``value_cols``. 4. Use ``cbar='uniform'`` when cross-panel comparison matters most. 5. Use ``cbar='individual'`` when each panel needs its own contrast. 6. Keep the same ROI when comparing variables, otherwise the columns do not tell a fair story. 7. If your column names differ from ``coord_x`` and ``coord_y``, pass them with ``spatial_cols``. A compact real-data pattern usually looks like: ``plot_spatial_roi(df, ['subsidence_q50', 'interval_width_80'],`` ``x_range=(xmin, xmax), y_range=(ymin, ymax), dt_col='year')`` That makes this helper one of the best local-reading tools in the spatial plotting family. .. GENERATED FROM PYTHON SOURCE LINES 378-380 .. code-block:: Python plt.show() .. rst-class:: sphx-glr-timing **Total running time of the script:** (0 minutes 2.379 seconds) .. _sphx_glr_download_auto_examples_spatial_plot_spatial_roi_overview.py: .. only:: html .. container:: sphx-glr-footer sphx-glr-footer-example .. container:: sphx-glr-download sphx-glr-download-jupyter :download:`Download Jupyter notebook: plot_spatial_roi_overview.ipynb ` .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: plot_spatial_roi_overview.py ` .. container:: sphx-glr-download sphx-glr-download-zip :download:`Download zipped: plot_spatial_roi_overview.zip ` .. only:: html .. rst-class:: sphx-glr-signature `Gallery generated by Sphinx-Gallery `_