From 1b3abd933adb7d782bca5314ac222c8727aff54c Mon Sep 17 00:00:00 2001 From: Jody Klymak Date: Sat, 2 Nov 2024 15:04:41 -0700 Subject: [PATCH 1/4] DOC: just new labels --- galleries/examples/images_contours_and_fields/contour_demo.py | 2 ++ .../examples/images_contours_and_fields/contourf_demo.py | 1 + galleries/examples/images_contours_and_fields/contourf_log.py | 2 ++ .../examples/images_contours_and_fields/image_antialiasing.py | 4 ++++ galleries/examples/images_contours_and_fields/image_demo.py | 2 ++ galleries/examples/images_contours_and_fields/pcolor_demo.py | 2 ++ .../examples/images_contours_and_fields/pcolormesh_grids.py | 2 ++ .../examples/images_contours_and_fields/plot_streamplot.py | 2 ++ .../examples/images_contours_and_fields/tricontour_demo.py | 2 ++ .../images_contours_and_fields/tricontour_smooth_delaunay.py | 2 ++ .../images_contours_and_fields/tricontour_smooth_user.py | 2 ++ .../examples/images_contours_and_fields/tripcolor_demo.py | 2 ++ galleries/examples/images_contours_and_fields/triplot_demo.py | 2 ++ .../examples/lines_bars_and_markers/categorical_variables.py | 2 ++ galleries/examples/lines_bars_and_markers/eventplot_demo.py | 2 ++ .../examples/lines_bars_and_markers/fill_between_demo.py | 2 ++ galleries/examples/lines_bars_and_markers/step_demo.py | 2 ++ galleries/examples/mplot3d/bars3d.py | 2 ++ galleries/examples/mplot3d/box3d.py | 2 ++ galleries/examples/mplot3d/custom_shaded_3d_surface.py | 2 ++ galleries/examples/mplot3d/intersecting_planes.py | 2 ++ galleries/examples/mplot3d/quiver3d.py | 2 ++ galleries/examples/mplot3d/stem3d_demo.py | 2 ++ galleries/examples/mplot3d/surface3d.py | 2 ++ galleries/examples/mplot3d/surface3d_2.py | 2 ++ galleries/examples/mplot3d/surface3d_3.py | 2 ++ galleries/examples/mplot3d/trisurf3d.py | 2 ++ galleries/examples/mplot3d/trisurf3d_2.py | 2 ++ galleries/examples/statistics/boxplot.py | 2 ++ galleries/examples/statistics/boxplot_color.py | 2 ++ galleries/examples/statistics/boxplot_demo.py | 2 ++ galleries/examples/statistics/boxplot_vs_violin.py | 2 ++ galleries/examples/statistics/customized_violin.py | 2 ++ galleries/examples/statistics/hexbin_demo.py | 2 ++ galleries/examples/statistics/histogram_histtypes.py | 2 ++ galleries/examples/statistics/histogram_multihist.py | 2 ++ galleries/examples/statistics/histogram_normalization.py | 1 + galleries/examples/statistics/violinplot.py | 2 ++ galleries/plot_types/3D/bar3d_simple.py | 2 ++ galleries/plot_types/3D/surface3d_simple.py | 2 ++ galleries/plot_types/3D/trisurf3d_simple.py | 2 ++ galleries/plot_types/arrays/pcolormesh.py | 3 +++ galleries/users_explain/artists/index.rst | 2 ++ galleries/users_explain/axes/index.rst | 2 ++ 44 files changed, 89 insertions(+) diff --git a/galleries/examples/images_contours_and_fields/contour_demo.py b/galleries/examples/images_contours_and_fields/contour_demo.py index 05fd3d5e3be8..02db17d9cdd4 100644 --- a/galleries/examples/images_contours_and_fields/contour_demo.py +++ b/galleries/examples/images_contours_and_fields/contour_demo.py @@ -1,4 +1,6 @@ """ +.. _contour_demo: + ============ Contour Demo ============ diff --git a/galleries/examples/images_contours_and_fields/contourf_demo.py b/galleries/examples/images_contours_and_fields/contourf_demo.py index 18c13d922e38..a0068718ad41 100644 --- a/galleries/examples/images_contours_and_fields/contourf_demo.py +++ b/galleries/examples/images_contours_and_fields/contourf_demo.py @@ -1,4 +1,5 @@ """ +.. _contourf_demo: ============= Contourf demo ============= diff --git a/galleries/examples/images_contours_and_fields/contourf_log.py b/galleries/examples/images_contours_and_fields/contourf_log.py index 408976adb9c2..841ea5ae60f2 100644 --- a/galleries/examples/images_contours_and_fields/contourf_log.py +++ b/galleries/examples/images_contours_and_fields/contourf_log.py @@ -1,4 +1,6 @@ """ +.. _contourf_log: + ============================ Contourf and log color scale ============================ diff --git a/galleries/examples/images_contours_and_fields/image_antialiasing.py b/galleries/examples/images_contours_and_fields/image_antialiasing.py index 10f563875767..05fafb065756 100644 --- a/galleries/examples/images_contours_and_fields/image_antialiasing.py +++ b/galleries/examples/images_contours_and_fields/image_antialiasing.py @@ -1,4 +1,8 @@ """ +.. _image_antialiasing: + +.. _image_resampling: + ================ Image resampling ================ diff --git a/galleries/examples/images_contours_and_fields/image_demo.py b/galleries/examples/images_contours_and_fields/image_demo.py index 768eedb20778..d7876e7c029f 100644 --- a/galleries/examples/images_contours_and_fields/image_demo.py +++ b/galleries/examples/images_contours_and_fields/image_demo.py @@ -1,4 +1,6 @@ """ +.. _image_demo: + ======================== Many ways to plot images ======================== diff --git a/galleries/examples/images_contours_and_fields/pcolor_demo.py b/galleries/examples/images_contours_and_fields/pcolor_demo.py index 7a8ef35caf96..1300dfee7ec7 100644 --- a/galleries/examples/images_contours_and_fields/pcolor_demo.py +++ b/galleries/examples/images_contours_and_fields/pcolor_demo.py @@ -1,4 +1,6 @@ """ +.. _pcolor_demo: + ============= pcolor images ============= diff --git a/galleries/examples/images_contours_and_fields/pcolormesh_grids.py b/galleries/examples/images_contours_and_fields/pcolormesh_grids.py index 212b807dbf90..91cc60720e71 100644 --- a/galleries/examples/images_contours_and_fields/pcolormesh_grids.py +++ b/galleries/examples/images_contours_and_fields/pcolormesh_grids.py @@ -1,4 +1,6 @@ """ +.. _pcolormesh_grids: + ============================ pcolormesh grids and shading ============================ diff --git a/galleries/examples/images_contours_and_fields/plot_streamplot.py b/galleries/examples/images_contours_and_fields/plot_streamplot.py index 0128b6369b4a..f9eaff7bd80e 100644 --- a/galleries/examples/images_contours_and_fields/plot_streamplot.py +++ b/galleries/examples/images_contours_and_fields/plot_streamplot.py @@ -1,4 +1,6 @@ """ +.. _plot_streamplot: + ========== Streamplot ========== diff --git a/galleries/examples/images_contours_and_fields/tricontour_demo.py b/galleries/examples/images_contours_and_fields/tricontour_demo.py index 3459382caad6..2cf36ba50618 100644 --- a/galleries/examples/images_contours_and_fields/tricontour_demo.py +++ b/galleries/examples/images_contours_and_fields/tricontour_demo.py @@ -1,4 +1,6 @@ """ +.. _tricontour_demo: + =============== Tricontour Demo =============== diff --git a/galleries/examples/images_contours_and_fields/tricontour_smooth_delaunay.py b/galleries/examples/images_contours_and_fields/tricontour_smooth_delaunay.py index 0f1ee4938f8d..6ad8b452ac27 100644 --- a/galleries/examples/images_contours_and_fields/tricontour_smooth_delaunay.py +++ b/galleries/examples/images_contours_and_fields/tricontour_smooth_delaunay.py @@ -1,4 +1,6 @@ """ +.. _tricontour_smooth_delaunay: + ========================== Tricontour Smooth Delaunay ========================== diff --git a/galleries/examples/images_contours_and_fields/tricontour_smooth_user.py b/galleries/examples/images_contours_and_fields/tricontour_smooth_user.py index 2d973c0de108..d58b7172d7ee 100644 --- a/galleries/examples/images_contours_and_fields/tricontour_smooth_user.py +++ b/galleries/examples/images_contours_and_fields/tricontour_smooth_user.py @@ -1,4 +1,6 @@ """ +.. _tricontour_smooth_user: + ====================== Tricontour Smooth User ====================== diff --git a/galleries/examples/images_contours_and_fields/tripcolor_demo.py b/galleries/examples/images_contours_and_fields/tripcolor_demo.py index a1c011a1224c..0672d086d943 100644 --- a/galleries/examples/images_contours_and_fields/tripcolor_demo.py +++ b/galleries/examples/images_contours_and_fields/tripcolor_demo.py @@ -1,4 +1,6 @@ """ +.. _tripcolor_demo: + ============== Tripcolor Demo ============== diff --git a/galleries/examples/images_contours_and_fields/triplot_demo.py b/galleries/examples/images_contours_and_fields/triplot_demo.py index e1151b37ac4a..9db21628fcce 100644 --- a/galleries/examples/images_contours_and_fields/triplot_demo.py +++ b/galleries/examples/images_contours_and_fields/triplot_demo.py @@ -1,4 +1,6 @@ """ +.. _triplot_demo: + ============ Triplot Demo ============ diff --git a/galleries/examples/lines_bars_and_markers/categorical_variables.py b/galleries/examples/lines_bars_and_markers/categorical_variables.py index a19a30eda2b2..2435417fe608 100644 --- a/galleries/examples/lines_bars_and_markers/categorical_variables.py +++ b/galleries/examples/lines_bars_and_markers/categorical_variables.py @@ -1,4 +1,6 @@ """ +.. _categorical_variables: + ============================== Plotting categorical variables ============================== diff --git a/galleries/examples/lines_bars_and_markers/eventplot_demo.py b/galleries/examples/lines_bars_and_markers/eventplot_demo.py index 17797c2f697a..eba72f17d29e 100644 --- a/galleries/examples/lines_bars_and_markers/eventplot_demo.py +++ b/galleries/examples/lines_bars_and_markers/eventplot_demo.py @@ -1,4 +1,6 @@ """ +.. _eventplot_demo: + ============== Eventplot demo ============== diff --git a/galleries/examples/lines_bars_and_markers/fill_between_demo.py b/galleries/examples/lines_bars_and_markers/fill_between_demo.py index feb325a3f9db..108e0fa20d21 100644 --- a/galleries/examples/lines_bars_and_markers/fill_between_demo.py +++ b/galleries/examples/lines_bars_and_markers/fill_between_demo.py @@ -1,4 +1,6 @@ """ +.. _fill_between_demo: + =============================== Fill the area between two lines =============================== diff --git a/galleries/examples/lines_bars_and_markers/step_demo.py b/galleries/examples/lines_bars_and_markers/step_demo.py index f74a069e52f3..2aba2cb6d37b 100644 --- a/galleries/examples/lines_bars_and_markers/step_demo.py +++ b/galleries/examples/lines_bars_and_markers/step_demo.py @@ -1,4 +1,6 @@ """ +.. _step_demo: + ========= Step Demo ========= diff --git a/galleries/examples/mplot3d/bars3d.py b/galleries/examples/mplot3d/bars3d.py index 3ea4a100c2f6..ba732e7e15cb 100644 --- a/galleries/examples/mplot3d/bars3d.py +++ b/galleries/examples/mplot3d/bars3d.py @@ -1,4 +1,6 @@ """ +.. _bars3d: + ======================================== Create 2D bar graphs in different planes ======================================== diff --git a/galleries/examples/mplot3d/box3d.py b/galleries/examples/mplot3d/box3d.py index 4d75c8bc2809..f53149f42d56 100644 --- a/galleries/examples/mplot3d/box3d.py +++ b/galleries/examples/mplot3d/box3d.py @@ -1,4 +1,6 @@ """ +.. _box3d: + =================== 3D box surface plot =================== diff --git a/galleries/examples/mplot3d/custom_shaded_3d_surface.py b/galleries/examples/mplot3d/custom_shaded_3d_surface.py index e8d1a4f33d87..3dd254226b59 100644 --- a/galleries/examples/mplot3d/custom_shaded_3d_surface.py +++ b/galleries/examples/mplot3d/custom_shaded_3d_surface.py @@ -1,4 +1,6 @@ """ +.. _custom_shaded_3d_surface: + ======================================= Custom hillshading in a 3D surface plot ======================================= diff --git a/galleries/examples/mplot3d/intersecting_planes.py b/galleries/examples/mplot3d/intersecting_planes.py index 4f42e7bbeb94..abf3378be00e 100644 --- a/galleries/examples/mplot3d/intersecting_planes.py +++ b/galleries/examples/mplot3d/intersecting_planes.py @@ -1,4 +1,6 @@ """ +.. _intersecting_planes: + =================== Intersecting planes =================== diff --git a/galleries/examples/mplot3d/quiver3d.py b/galleries/examples/mplot3d/quiver3d.py index adc58c2e9d89..5655f12c734d 100644 --- a/galleries/examples/mplot3d/quiver3d.py +++ b/galleries/examples/mplot3d/quiver3d.py @@ -1,4 +1,6 @@ """ +.. _quiver3d: + ============== 3D quiver plot ============== diff --git a/galleries/examples/mplot3d/stem3d_demo.py b/galleries/examples/mplot3d/stem3d_demo.py index 82b45ff19068..a87a0ac69823 100644 --- a/galleries/examples/mplot3d/stem3d_demo.py +++ b/galleries/examples/mplot3d/stem3d_demo.py @@ -1,4 +1,6 @@ """ +.. _stem3d_demo: + ======= 3D stem ======= diff --git a/galleries/examples/mplot3d/surface3d.py b/galleries/examples/mplot3d/surface3d.py index 6c51a69c0d1f..5af89f876e1b 100644 --- a/galleries/examples/mplot3d/surface3d.py +++ b/galleries/examples/mplot3d/surface3d.py @@ -1,4 +1,6 @@ """ +.. _surface3d: + ===================== 3D surface (colormap) ===================== diff --git a/galleries/examples/mplot3d/surface3d_2.py b/galleries/examples/mplot3d/surface3d_2.py index 2a4406abc259..82365174c86d 100644 --- a/galleries/examples/mplot3d/surface3d_2.py +++ b/galleries/examples/mplot3d/surface3d_2.py @@ -1,4 +1,6 @@ """ +.. _surface3d_2: + ======================== 3D surface (solid color) ======================== diff --git a/galleries/examples/mplot3d/surface3d_3.py b/galleries/examples/mplot3d/surface3d_3.py index c129ef6d3635..57e541f249c2 100644 --- a/galleries/examples/mplot3d/surface3d_3.py +++ b/galleries/examples/mplot3d/surface3d_3.py @@ -1,4 +1,6 @@ """ +.. _surface3d_3: + ========================= 3D surface (checkerboard) ========================= diff --git a/galleries/examples/mplot3d/trisurf3d.py b/galleries/examples/mplot3d/trisurf3d.py index f4e7444a4311..3e754c217b05 100644 --- a/galleries/examples/mplot3d/trisurf3d.py +++ b/galleries/examples/mplot3d/trisurf3d.py @@ -1,4 +1,6 @@ """ +.. _trisurf3d: + ====================== Triangular 3D surfaces ====================== diff --git a/galleries/examples/mplot3d/trisurf3d_2.py b/galleries/examples/mplot3d/trisurf3d_2.py index 0e757140c20e..e597173fbca0 100644 --- a/galleries/examples/mplot3d/trisurf3d_2.py +++ b/galleries/examples/mplot3d/trisurf3d_2.py @@ -1,4 +1,6 @@ """ +.. _trisurf3d_2: + =========================== More triangular 3D surfaces =========================== diff --git a/galleries/examples/statistics/boxplot.py b/galleries/examples/statistics/boxplot.py index 6d30cbd4b5f0..10255182fe34 100644 --- a/galleries/examples/statistics/boxplot.py +++ b/galleries/examples/statistics/boxplot.py @@ -1,4 +1,6 @@ """ +.. _boxplot_artists: + ================================= Artist customization in box plots ================================= diff --git a/galleries/examples/statistics/boxplot_color.py b/galleries/examples/statistics/boxplot_color.py index acdb37d7d520..1475480e802e 100644 --- a/galleries/examples/statistics/boxplot_color.py +++ b/galleries/examples/statistics/boxplot_color.py @@ -1,4 +1,6 @@ """ +.. _boxplot_color: + ================================= Box plots with custom fill colors ================================= diff --git a/galleries/examples/statistics/boxplot_demo.py b/galleries/examples/statistics/boxplot_demo.py index b642d7e9f658..0f5c7f44403d 100644 --- a/galleries/examples/statistics/boxplot_demo.py +++ b/galleries/examples/statistics/boxplot_demo.py @@ -1,4 +1,6 @@ """ +.. _boxplot_demo: + ======== Boxplots ======== diff --git a/galleries/examples/statistics/boxplot_vs_violin.py b/galleries/examples/statistics/boxplot_vs_violin.py index 06aa2693f446..9c0d9720a3f4 100644 --- a/galleries/examples/statistics/boxplot_vs_violin.py +++ b/galleries/examples/statistics/boxplot_vs_violin.py @@ -1,4 +1,6 @@ """ +.. _boxplot_vs_violin: + =================================== Box plot vs. violin plot comparison =================================== diff --git a/galleries/examples/statistics/customized_violin.py b/galleries/examples/statistics/customized_violin.py index cc18e47ebd67..4ec9f4b11c1b 100644 --- a/galleries/examples/statistics/customized_violin.py +++ b/galleries/examples/statistics/customized_violin.py @@ -1,4 +1,6 @@ """ +.. _customized_violin: + ========================= Violin plot customization ========================= diff --git a/galleries/examples/statistics/hexbin_demo.py b/galleries/examples/statistics/hexbin_demo.py index bd1522772aae..879d92cd8d37 100644 --- a/galleries/examples/statistics/hexbin_demo.py +++ b/galleries/examples/statistics/hexbin_demo.py @@ -1,4 +1,6 @@ """ +.. _hexbin_demo: + ===================== Hexagonal binned plot ===================== diff --git a/galleries/examples/statistics/histogram_histtypes.py b/galleries/examples/statistics/histogram_histtypes.py index 53d6425cf4dc..c365b1ed9e93 100644 --- a/galleries/examples/statistics/histogram_histtypes.py +++ b/galleries/examples/statistics/histogram_histtypes.py @@ -1,4 +1,6 @@ """ +.. _histogram_histtypes: + ================================================================ Demo of the histogram function's different ``histtype`` settings ================================================================ diff --git a/galleries/examples/statistics/histogram_multihist.py b/galleries/examples/statistics/histogram_multihist.py index a85ec2acfa8d..36b770deff49 100644 --- a/galleries/examples/statistics/histogram_multihist.py +++ b/galleries/examples/statistics/histogram_multihist.py @@ -1,4 +1,6 @@ """ +.. _histogram_multihist: + ===================================================== The histogram (hist) function with multiple data sets ===================================================== diff --git a/galleries/examples/statistics/histogram_normalization.py b/galleries/examples/statistics/histogram_normalization.py index 2c423edad208..f511809f6ae3 100644 --- a/galleries/examples/statistics/histogram_normalization.py +++ b/galleries/examples/statistics/histogram_normalization.py @@ -1,5 +1,6 @@ """ .. redirect-from:: /gallery/statistics/histogram_features +.. _histogram_normalization: =================================== Histogram bins, density, and weight diff --git a/galleries/examples/statistics/violinplot.py b/galleries/examples/statistics/violinplot.py index 7f4725ff7a8c..e0becd10ddf7 100644 --- a/galleries/examples/statistics/violinplot.py +++ b/galleries/examples/statistics/violinplot.py @@ -1,4 +1,6 @@ """ +.. _violinplot: + ================== Violin plot basics ================== diff --git a/galleries/plot_types/3D/bar3d_simple.py b/galleries/plot_types/3D/bar3d_simple.py index aa75560de8f2..db0ca2c8a712 100644 --- a/galleries/plot_types/3D/bar3d_simple.py +++ b/galleries/plot_types/3D/bar3d_simple.py @@ -1,4 +1,6 @@ """ +.. _bar3d_simple: + ========================== bar3d(x, y, z, dx, dy, dz) ========================== diff --git a/galleries/plot_types/3D/surface3d_simple.py b/galleries/plot_types/3D/surface3d_simple.py index c887b042da94..c46f442a224e 100644 --- a/galleries/plot_types/3D/surface3d_simple.py +++ b/galleries/plot_types/3D/surface3d_simple.py @@ -1,4 +1,6 @@ """ +.. _surface3d_simple: + ===================== plot_surface(X, Y, Z) ===================== diff --git a/galleries/plot_types/3D/trisurf3d_simple.py b/galleries/plot_types/3D/trisurf3d_simple.py index f5252699ac23..970ee5bfdc57 100644 --- a/galleries/plot_types/3D/trisurf3d_simple.py +++ b/galleries/plot_types/3D/trisurf3d_simple.py @@ -1,4 +1,6 @@ """ +.. _trisurf3d_simple: + ===================== plot_trisurf(x, y, z) ===================== diff --git a/galleries/plot_types/arrays/pcolormesh.py b/galleries/plot_types/arrays/pcolormesh.py index 4f0913f62521..8ac1fcdf35f2 100644 --- a/galleries/plot_types/arrays/pcolormesh.py +++ b/galleries/plot_types/arrays/pcolormesh.py @@ -1,7 +1,10 @@ """ +.. _pcolormesh: + =================== pcolormesh(X, Y, Z) =================== + Create a pseudocolor plot with a non-regular rectangular grid. `~.axes.Axes.pcolormesh` is more flexible than `~.axes.Axes.imshow` in that diff --git a/galleries/users_explain/artists/index.rst b/galleries/users_explain/artists/index.rst index d3f2918c9a91..dacfa9f13aa7 100644 --- a/galleries/users_explain/artists/index.rst +++ b/galleries/users_explain/artists/index.rst @@ -1,3 +1,5 @@ +.. _users-guide-artists: + +++++++ Artists +++++++ diff --git a/galleries/users_explain/axes/index.rst b/galleries/users_explain/axes/index.rst index a3683d69ec5a..08662e89f44c 100644 --- a/galleries/users_explain/axes/index.rst +++ b/galleries/users_explain/axes/index.rst @@ -1,3 +1,5 @@ +.. _users_guide_axes: + +++++++++++++++++ Axes and subplots +++++++++++++++++ From 5bcff6604112a900167c7ef7d67c7069e0a18391 Mon Sep 17 00:00:00 2001 From: Jody Klymak Date: Sun, 12 Apr 2026 21:20:37 -0700 Subject: [PATCH 2/4] DOC: User guide plotting section --- doc/devel/anchor_label_mapping.csv | 46 +++ doc/users/index.rst | 10 +- galleries/users_explain/plotting/gridded.py | 275 ++++++++++++++ galleries/users_explain/plotting/index.rst | 169 +++++++++ galleries/users_explain/plotting/pairwise.py | 337 ++++++++++++++++++ .../users_explain/plotting/statistical.py | 282 +++++++++++++++ galleries/users_explain/plotting/threed.py | 249 +++++++++++++ .../plotting/unstructuredgrid.py | 127 +++++++ 8 files changed, 1494 insertions(+), 1 deletion(-) create mode 100644 doc/devel/anchor_label_mapping.csv create mode 100644 galleries/users_explain/plotting/gridded.py create mode 100644 galleries/users_explain/plotting/index.rst create mode 100644 galleries/users_explain/plotting/pairwise.py create mode 100644 galleries/users_explain/plotting/statistical.py create mode 100644 galleries/users_explain/plotting/threed.py create mode 100644 galleries/users_explain/plotting/unstructuredgrid.py diff --git a/doc/devel/anchor_label_mapping.csv b/doc/devel/anchor_label_mapping.csv new file mode 100644 index 000000000000..30cc372f47ca --- /dev/null +++ b/doc/devel/anchor_label_mapping.csv @@ -0,0 +1,46 @@ +old_label,new_label +_contour_demo,_examples-contour-demo +_contourf_demo,_examples-contourf-demo +_contourf_log,_examples-contourf-log +_image_antialiasing,_examples-image-antialiasing +_image_resampling,_examples-image-resampling +_image_demo,_examples-image-demo +_pcolor_demo,_examples-pcolor-demo +_pcolormesh_grids,_examples-pcolormesh-grids +_plot_streamplot,_examples-plot-streamplot +_tricontour_demo,_examples-tricontour-demo +_tricontour_smooth_delaunay,_examples-tricontour-smooth-delaunay +_tricontour_smooth_user,_examples-tricontour-smooth-user +_tripcolor_demo,_examples-tripcolor-demo +_triplot_demo,_examples-triplot-demo +_categorical_variables,_examples-categorical-variables +_eventplot_demo,_examples-eventplot-demo +_fill_between_demo,_examples-fill-between-demo +_step_demo,_examples-step-demo +_bars3d,_examples-bars3d +_box3d,_examples-box3d +_custom_shaded_3d_surface,_examples-custom-shaded-3d-surface +_intersecting_planes,_examples-intersecting-planes +_quiver3d,_examples-quiver3d +_stem3d_demo,_examples-stem3d-demo +_surface3d,_examples-surface3d +_surface3d_2,_examples-surface3d-2 +_surface3d_3,_examples-surface3d-3 +_trisurf3d,_examples-trisurf3d +_trisurf3d_2,_examples-trisurf3d-2 +_boxplot_artists,_examples-boxplot-artists +_boxplot_color,_examples-boxplot-color +_boxplot_demo,_examples-boxplot-demo +_boxplot_vs_violin,_examples-boxplot-vs-violin +_customized_violin,_examples-customized-violin +_hexbin_demo,_examples-hexbin-demo +_histogram_histtypes,_examples-histogram-histtypes +_histogram_multihist,_examples-histogram-multihist +_histogram_normalization,_examples-histogram-normalization +_violinplot,_examples-violinplot +_bar3d_simple,_plot-types-bar3d-simple +_surface3d_simple,_plot-types-surface3d-simple +_trisurf3d_simple,_plot-types-trisurf3d-simple +_pcolormesh,_plot-types-pcolormesh +_users-guide-artists,_users-explain-users-guide-artists +_users_guide_axes,_users-explain-users-guide-axes diff --git a/doc/users/index.rst b/doc/users/index.rst index b98bda824a7e..4ed5ae680fdf 100644 --- a/doc/users/index.rst +++ b/doc/users/index.rst @@ -40,8 +40,16 @@ Using Matplotlib :maxdepth: 2 :includehidden: - explain/axes/index + explain/plotting/index + .. grid-item-card:: + :padding: 2 + + .. toctree:: + :maxdepth: 2 + :includehidden: + + explain/axes/index .. grid-item-card:: :padding: 2 diff --git a/galleries/users_explain/plotting/gridded.py b/galleries/users_explain/plotting/gridded.py new file mode 100644 index 000000000000..0c8d7bf7c829 --- /dev/null +++ b/galleries/users_explain/plotting/gridded.py @@ -0,0 +1,275 @@ +""" +.. _plot_gridded: + +Gridded data +============ + +This section discusses data that mapped onto a two-dimensional grid. The data +usually has structured coordinates defined by arrays of x and y values, and data +mapped onto those coordinates :math:`Data(x, y)` in a two-dimensional array. The grid +can either be regular, in which case the x and y arrays are 1D and the Data is 2D, +or the grid can be irregular, and X, Y, and Data are all 2D arrays. + +""" + +import matplotlib.pyplot as plt +import numpy as np + +import warnings + +plt.rcParams['figure.constrained_layout.use'] = True +plt.rcParams['figure.figsize'] = (5, 4) + +# %% +# imshow +# ------ +# +# `~.axes.Axes.imshow` is a simple way to plot a 2D array as an image. By +# default, the aspect ratio is set to be equal, so the pixels are square, and +# the origin of the data is the upper-left corner. The values of the array are +# mapped to colors using a colormap. + +# create a square matrix of data: +X, Y = np.meshgrid(np.linspace(-3, 3, 128), np.linspace(-3, 3, 128)) +Z = (1 - X/2 + X**5 + Y**3) * np.exp(-X**2 - Y**2) + +fig, ax = plt.subplots() +im = ax.imshow(Z) +fig.colorbar(im, ax=ax) +ax.set_xlabel('pixels in x') +ax.set_ylabel('pixels in y') + +# %% +# +# Note how the origin is in the upper left and the x and y axises are in units +# of pixels. These behaviors can be changed with the *origin* and *extent* +# arguments. This is discussed in detail in :ref:`imshow_extent`. +# +# Other colormaps can be chosen through the *cmap* argument (see +# :ref:`colormaps`), and the color limits can be set with the *vmin* and *vmax* +# arguments, or by using the *norm* parameter (see :ref:`colormapnorms`). An example +# of using *vmin* and *vmax* is shown below: + +fig, ax = plt.subplots() +im = ax.imshow(Z, cmap='RdBu_r', vmin=-1, vmax=1) +fig.colorbar(im, ax=ax) +ax.set_xlabel('pixels in x') +ax.set_ylabel('pixels in y') + +# %% +# +# There are many options for resampling the data when it is displayed. See +# :ref:`image_antialiasing` for more information, but note the the default attempts +# to remove aliasing artifacts from data that is "downsampled" (i.e., when the +# number of pixels in the data array is greater than the number of pixels in the +# displayed image). +# +# .. seealso:: +# - :ref:`image_demo` +# - :ref:`imshow_extent` +# - :ref:`image_antialiasing` + + +# %% +# pcolormesh (and pcolor, pcolorfast) +# ----------------------------------- +# +# `~.axes.Axes.pcolormesh` is more flexible than `~.axes.Axes.imshow` in that +# the x and y vectors need not be equally spaced (indeed they can be skewed). +# In the example below, the x values are unevenly spaced, and much less finely +# sampled than the y values. The x and y data are orthogonal, so we can pass +# x and y directly to `~.axes.Axes.pcolormesh`: + +x = np.array([-3, -2, -1.6, -1.2, -.8, -.5, -.2, .1, .3, .5, .8, 1.1, 1.5, 1.9, 2.3, 3]) +y = np.linspace(-3, 3, 128) +X, Y = np.meshgrid(x, y) +Z = (1 - X/2 + X**5 + Y**3) * np.exp(-X**2 - Y**2) + +fig, ax = plt.subplots() + +ax.pcolormesh(x, y, Z, vmin=-0.5, vmax=1.0) + +ax.set_xlabel('x') +ax.set_ylabel('y') + +# %% +# As noted, `~.axes.Axes.pcolormesh` need not be on an orthogonal grid. Here +# is an example with the y grid points varying with x. Note that we need to +# give the grids as 2D arrays for this to work: + +# make a 2D array of y values that where the y dimension varies in x: +Yn = Y + 0.3 * np.abs(x) + +fig, ax = plt.subplots() +with warnings.catch_warnings(): + warnings.simplefilter("ignore") + ax.pcolormesh(X, Yn, Z, vmin=-0.5, vmax=1.0) +ax.set_xlabel('x') +ax.set_ylabel('skewed y') + +# %% +# Note that the above returns a warning because the y grid is not strictly increasing: +# +# UserWarning: The input coordinates to pcolormesh are +# interpreted as cell centers, but are not monotonically +# increasing or decreasing. +# +# To avoid that warning, we can give `.Axes.pcolormesh` the cell edges rather +# than the cell centers: + + +def midpoints_plus_ends(x): + """Given a 1D array, return a new array with the midpoints and the two ends.""" + return np.concatenate(([x[0] - (x[1] - x[0]) / 2], + x[:-1] + np.diff(x) / 2, + [x[-1] - (x[-1] - x[-2]) / 2])) + +yn = midpoints_plus_ends(y) +xn = midpoints_plus_ends(x) +Xn, Yn = np.meshgrid(xn, yn) +Yn = Yn + 0.3 * np.abs(xn) + +fig, ax = plt.subplots() +ax.pcolormesh(Xn, Yn, Z, vmin=-0.5, vmax=1.0) + +# %% +# Two similar methods are `~.axes.Axes.pcolor` and `~.axes.Axes.pcolorfast`. There are +# some differences in the way they handle the data, but they are largely the same and +# are not as commonly used as `~.axes.Axes.pcolormesh`. See +# :ref:`Differences between pcolor() and pcolormesh() ` +# for a discussion of the differences. +# +# `~.axes.Axes.pcolorfast` is not as flexible as `~.axes.Axes.pcolormesh`, but can be +# faster for large datasets. + +# %% +# .. seealso:: +# - :ref:`pcolormesh_grids` +# - :ref:`pcolor_demo` + +# %% +# contour and contourf +# -------------------- +# +# `~.axes.Axes.contour` and `~.axes.Axes.contourf` create contour plots. They accept +# a 2D array of data, and create a plot with contour lines or filled regions enclosing +# data that is in the same contour level. The example below shows a simple contour +# plot using the data from above. Note that as before, the x and y data are not +# necessarily evenly spaced, but in this case they are orthogonal. + +fig, axs = plt.subplots(2, 1, figsize=(5, 5)) +ax = axs[0] +ax.contour(x, y, Z, levels=10) +ax.set_xlabel('x') +ax.set_ylabel('y') +ax.set_title('contour plot') + +ax = axs[1] +cf = ax.contourf(x, y, Z, levels=10) +ax.set_xlabel('x') +ax.set_ylabel('y') +ax.set_title('contourf plot') +fig.colorbar(cf, ax=ax) + +# %% +# Note that like for `.Axes.pcolormesh`, the grid need not be orthogonal. In +# the following example the the same data is plotted as above, but with the y +# grid points varying with x. The contour *levels* are also manually specified +# in this example with a list of levels, (see :ref:`contourf_log` for an +# example of using a tick locator instead of a list), and the colormap set with +# the *cmap* argument (see :ref:`colormaps`). + +Yn = Y + 0.3 * np.abs(x) + +fig, ax = plt.subplots() + +cf = ax.contourf(X, Yn, Z, levels=np.arange(-1.3, 1.31, 0.2), cmap='RdBu_r') +ax.set_xlabel('x') +ax.set_ylabel('y') +ax.set_title('contour plot') +fig.colorbar(cf, ax=ax) + +# %% +# .. seealso:: +# +# - :ref:`contour_demo` +# - :ref:`contourf_demo` + +# %% +# barbs and quiver +# ---------------- +# `~.axes.Axes.barbs` and `~.axes.Axes.quiver` allow us to represent gridded +# vector fields specified at points on an x-y grid by two-dimensional arrays U, +# V. The arrays must be the same shape as x and y and the arrows are placed at +# the corresponding points in the grid. The main difference between the two +# functions is that `~.axes.Axes.barbs` plots barbs, which are a more +# traditional representation of wind speed and direction, while +# `~.axes.Axes.quiver` plots arrows with a uniform size and the direction is +# given by the vector U, V. + +# make data +x = np.linspace(-4, 4, 20) +y = np.linspace(-4, 4, 20) +X, Y = np.meshgrid(x, y) +U = X + Y +V = Y - X + +# plot +fig, ax = plt.subplots() + +ax.quiver(X, Y, U, V, color="C0", angles='xy', + scale_units='xy', scale=8, width=.005) + +ax.set_xlabel('x') +ax.set_ylabel('y') +ax.set_title('barbs') + +fig, ax = plt.subplots() +ax.barbs(X, Y, U, V, color="C0", barbcolor='C0', flagcolor='C0', length=4, + linewidth=1.0) + +ax.set_xlabel('x') +ax.set_ylabel('y') +ax.set_title('quiver') + +# %% +# streamplot +# ---------- +# +# `~.axes.Axes.streamplot` is used to plot the streamlines of a vector field. It +# makes traces of where a massless particle would go if it followed the vector field +# at each point. The example below shows the streamlines of the vector field from +# above: + +fig, ax = plt.subplots() +ax.streamplot(x, y, U, V) + +ax.set_xlabel('x') +ax.set_ylabel('y') +ax.set_title('streamplot') + +# %% +# `~.axes.Axes.streamplot` performs an interpolation and the streamlines are +# not guaranteed to be accurate. For more accurate streamlines, the data grid +# could be refined. +# +# .. note:: +# +# `~.axes.Axes.streamplot` does not accept 2D arrays for the x and y data: +# the x and y data must be 1D arrays, and the spacing between the points must +# be uniform. +# +# .. seealso:: :ref:`Streamplot demo ` +# +# .. admonition:: References +# +# The use of the following functions, methods, classes and modules is shown +# in this example: +# +# - `matplotlib.axes.Axes.imshow` / `matplotlib.pyplot.imshow` +# - `matplotlib.axes.Axes.pcolormesh` / `matplotlib.pyplot.pcolormesh` +# - `matplotlib.axes.Axes.contour` / `matplotlib.pyplot.contour` +# - `matplotlib.axes.Axes.contourf` / `matplotlib.pyplot.contourf` +# - `matplotlib.axes.Axes.barbs` / `matplotlib.pyplot.barbs` +# - `matplotlib.axes.Axes.quiver` / `matplotlib.pyplot.quiver` +# - `matplotlib.axes.Axes.streamplot` / `matplotlib.pyplot.streamplot` diff --git a/galleries/users_explain/plotting/index.rst b/galleries/users_explain/plotting/index.rst new file mode 100644 index 000000000000..03fb2db1f149 --- /dev/null +++ b/galleries/users_explain/plotting/index.rst @@ -0,0 +1,169 @@ ++++++++++++++ +Plotting data ++++++++++++++ + +.. _users-guide-plotting: + +Matplotlib can create a wide variety of data visualizations, many of which are +previewed in the :ref:`plot_types` gallery. This section provides an overview +on working with these visualizations. More details and examples can be found +in the :ref:`gallery` gallery, and general advice about :ref:`users_guide_axes` +and :ref:`users-guide-artists` can be found in other sections of :ref:`the +user's guide `. + +.. grid:: 1 1 2 2 + + .. grid-item-card:: + :padding: 2 + + .. toctree:: + :maxdepth: 2 + :includehidden: + + pairwise + + .. grid-item-card:: + :padding: 2 + + .. plot:: + :height: 7em + + import matplotlib.pyplot as plt + import numpy as np + + fig, ax = plt.subplots(figsize=(3, 1.7), layout="constrained") + rng = np.random.default_rng(seed=19680801) + ax.plot(np.arange(200), np.cumsum(rng.normal(size=200))) + ax.set_xlabel('time') + ax.set_ylabel('random walk') + + .. grid-item-card:: + :padding: 2 + + + .. toctree:: + :maxdepth: 2 + :includehidden: + + statistical + + .. grid-item-card:: + :padding: 2 + + .. plot:: + :height: 7em + + import matplotlib.pyplot as plt + import numpy as np + + fig, ax = plt.subplots(figsize=(3.5, 1.7), layout="constrained") + rng = np.random.default_rng(seed=19680801) + ax.hist(rng.normal(size=200), density=True) + ax.set_xlabel('x') + ax.set_ylabel('pdf') + + .. grid-item-card:: + :padding: 2 + + .. toctree:: + :maxdepth: 2 + :includehidden: + + gridded + + .. grid-item-card:: + :padding: 2 + + + .. plot:: + :height: 7em + + import matplotlib.pyplot as plt + import numpy as np + + + # make data with uneven sampling in x + x = [-3, -2, -1.6, -1.2, -.8, -.5, -.2, .1, .3, .5, .8, 1.1, 1.5, 1.9, 2.3, 3] + X, Y = np.meshgrid(x, np.linspace(-3, 3, 128)) + Z = (1 - X/2 + X**5 + Y**3) * np.exp(-X**2 - Y**2) + + fig, ax = plt.subplots(figsize=(3.5, 1.7), layout="constrained") + + ax.pcolormesh(X, Y, Z, vmin=-0.5, vmax=1.0) + ax.set_xlabel('x') + ax.set_ylabel('y') + + ax.contour(X, Y, Z, vmin=-0.5, vmax=1.0, linewidths=2, cmap='RdBu_r') + + + .. grid-item-card:: + :padding: 2 + + .. toctree:: + :maxdepth: 2 + :includehidden: + + unstructuredgrid + + .. grid-item-card:: + :padding: 2 + + .. plot:: + :height: 7em + + import matplotlib.pyplot as plt + import numpy as np + + # make data: + np.random.seed(1) + x = np.random.uniform(-3, 3, 256) + y = np.random.uniform(-3, 3, 256) + z = (1 - x/2 + x**5 + y**3) * np.exp(-x**2 - y**2) + + # plot: + fig, ax = plt.subplots(figsize=(3.5, 1.7), layout='constrained') + + ax.plot(x, y, 'o', markersize=2, color='grey') + ax.tripcolor(x, y, z) + ax.tricontour(x, y, z, cmap='RdBu_r', linewidths=2) + ax.set_xlabel('x') + ax.set_ylabel('y') + ax.set(xlim=(-3, 3), ylim=(-3, 3)) + + plt.show() + + + .. grid-item-card:: + :padding: 2 + + .. toctree:: + :maxdepth: 2 + :includehidden: + + threed + + + .. grid-item-card:: + :padding: 2 + + + .. plot:: + :height: 7em + + import matplotlib.pyplot as plt + import numpy as np + + # Make data + X = np.arange(-5, 5, 0.25) + Y = np.arange(-5, 5, 0.25) + X, Y = np.meshgrid(X, Y) + R = np.sqrt(X**2 + Y**2) + Z = np.sin(R) + + # Plot the surface + fig, ax = plt.subplots(subplot_kw={"projection": "3d"}, + layout='constrained', figsize=(4*0.8, 2.7*0.8)) + ax.plot_surface(X, Y, Z, vmin=Z.min() * 2) + ax.set_xlabel('x') + ax.set_ylabel('y') + ax.set_zlabel('z') diff --git a/galleries/users_explain/plotting/pairwise.py b/galleries/users_explain/plotting/pairwise.py new file mode 100644 index 000000000000..0bedcdfdcb78 --- /dev/null +++ b/galleries/users_explain/plotting/pairwise.py @@ -0,0 +1,337 @@ +""" +.. _plotting_pairwise: + +Pairwise data +============= + +The most common plot type is a simple y versus x plot. Typically we +will have arrays :math:`x_i` and :math:`y_i` of equal size that we want to plot +against each other. +""" + +import matplotlib.pyplot as plt +import numpy as np + +plt.rcParams['figure.constrained_layout.use'] = True +plt.rcParams['figure.figsize'] = (5, 4) + + +# %% +# +# plot +# ---- +# +# The most simple way to plot x and y data versus each other is to use the +# `~.Axes.plot` method. + +x = np.linspace(-2 * np.pi, 2 * np.pi, 30) +y = np.sinc(x) + +fig, ax = plt.subplots() +ax.plot(x, y) +ax.set_xlabel('x') +ax.set_ylabel('sinc(x)') + +# %% +# By default, `~.Axes.plot` joins data points with a solid straight line, as +# shown in the jagged nature of the plot above. We can style that line, +# with dashes, plot the data with symbols, or both styles, as demonstrated below. + +fig, axs = plt.subplots(3, 1, sharex=True) +ax = axs[0] +ax.plot(x, y, '--') +ax.set_ylabel('sinc(x)') +ax = axs[1] +ax.plot(x, y, 'd') +ax = axs[2] +ax.plot(x, y, 'd--') +ax.set_xlabel('x') + +# %% +# Multiple datasets can be plotted simultaneously against a single ``x`` array +# if the shape of ``Y`` is compatible. In this example, ``Y`` has the shape ``(30, 3)``, +# meaning each column has the same length as ``x``. +# Each column in ``Y`` is assigned a different color according to the +# default :ref:`color cycle `. A legend for each column in +# ``Y`` is generated by providing a **label** with a list of column names: + +Y = np.arange(30*3).reshape(3, 30).T +fig, ax = plt.subplots(figsize=(5, 3)) +ax.plot(x, Y, label=['column 1', 'column 2', 'column 3']) +ax.legend() +ax.set_xlabel('x') + +# %% +# fill_between, fill_betweenx, and stackplot +# ----------------------------------------- +# +# The `~.Axes.fill_between` method is useful to indicate a confidence interval +# around a line plot. In this example, the confidence interval is imagined to +# grow with distance in the x direction from the origin, but typically this +# would be based on data. `~.Axes.fill_betweenx` does the same thing but for +# the y direction. + +fig, axs = plt.subplots(1, 2) +ax = axs[0] +ax.plot(x, y) +ax.set_title("fill_between") +ax.fill_between(x, y - np.abs(x) / 20, y + np.abs(x) / 20, color='C0', alpha=0.5) +ax.set_ylabel('x') +ax.set_xlabel('sinc(x)') + +ax = axs[1] +ax.plot(y, x) +ax.set_title("fill_betweenx") +ax.fill_betweenx(x, y - np.abs(x) / 20, y + np.abs(x) / 20, color='C0', alpha=0.5) +ax.set_ylabel('y') +ax.set_xlabel('sinc(y)') + +# %% +# `~.Axes.fill_between` can also be used to fill between two lines, and can +# have conditions set on when to fill. Here we fill between two lines where +# the condition is met that the line with the larger y value is above the line +# with the smaller y value. The *where* keyword is used to set this condition. +# The *interpolate* keyword is used to linearly interpolate the fill to +# where the condition is just met. +# + +fig, ax = plt.subplots() +ax.plot(x, y, label='sinc(x)') +y2 = 2.0 * np.sinc(x + 0.3) +ax.plot(x, y2, label='2.0 sinc(x + 0.3)') +ax.fill_between(x, y, y2, where=(y >= y2), color='C0', alpha=0.3, interpolate=True) +ax.fill_between(x, y, y2, where=(y < y2), color='C1', alpha=0.3, interpolate=True) +ax.legend() +ax.set_xlabel('x') +ax.set_ylabel('sinc(x)') +ax.set_title("fill_between with condition") + +# %% +# .. seealso:: +# :ref:`fill_between_demo` for more `~.Axes.fill_between` examples. +# +# `~.Axes.stackplot` is useful for plotting series of data that stack on top of +# each other, often when the data represents a sum of different components. +# Here we plot three series of data and then that we then sum them up in the stackplot. + +fig, axs = plt.subplots(2, 1) +rng = np.random.default_rng(seed=19680801) + +data = rng.random(size=(30, 3)) +x = np.arange(30) +ax = axs[0] +ax.plot(x, data, label=['A', 'B', 'C']) +ax.legend() +ax.set_ylabel('data') +ax = axs[1] +ax.stackplot(x, data.cumsum(axis=1).T, labels=['A', 'A+B', 'A+B+C'], alpha=0.8) +ax.legend() +ax.set_xlabel('x') +ax.set_ylabel('stacked data') +ax.set_title("stackplot") + +# %% +# errorbar +# -------- +# +# Confidence intervals in both x and y can be shown using the `~.Axes.errorbar` method. +# The `~.Axes.errorbar` method has many options to control the appearance of the plot. +# The error bars can be specified as a scalar or as an array for each data point. + +x = np.linspace(0, 10, 50) +dy = 0.8 +y = np.sin(x) + dy * np.random.randn(50) +errx = 0.2 + np.random.rand(50) / 3 +erry = 0.2 + np.random.rand(50) / 3 + +fig, ax = plt.subplots() +ax.errorbar(x, y, xerr=errx, yerr=erry, fmt='o') + +ax.set_title("errorbar") +ax.set_xlabel("x") +ax.set_ylabel("sin(x) plus noise") + +# %% +# +# `~.Axes.errorbar` inherits from `~.Axes.plot`, allowing the use of the same +# format to control the marker's appearance. The appearance of error bars is +# controlled by keyword arguments such as *ecolor* for the color of the error +# bar lines, **capsize** for the length of the error bar caps, and *elinewidth* +# for the thickness of the error bar lines. Error bars can also be asymmetric +# if *yerr* or *xerr* are provided as 2D arrays. + +fig, ax = plt.subplots() +ax.errorbar(x, y, yerr=[erry, 2*erry], xerr=[errx, 2*errx], fmt='o', + ecolor='lightgray', elinewidth=2, capsize=5) +ax.set_title("Asymmetric error bars") +ax.set_xlabel("x") +ax.set_ylabel("sin(x) plus noise") +# %% +# +# scatter +# ------- +# +# The `~.Axes.scatter` method is similar to `~.Axes.plot` in that it plots two +# arrays of data against each other, but differs in the following ways: +# +# * there is no option to connect markers with lines, +# * the size and color of markers can vary according to the values of other data arrays. +# +# This example demonstrates how to create a scatter plot with varying point sizes using +# the *s* keyword and and colors using the *c* keyword. + +y = np.sin(x) + +sizes = np.linspace(20, 200, len(x)) # Varying point sizes +colors = y # Use y-values to map to color + +fig, ax = plt.subplots() +scatter = ax.scatter(x, y, c=colors, s=sizes, cmap='viridis', alpha=0.6, + edgecolor='black') +ax.set_title("Scatter Plot using scatter()") +ax.set_xlabel("x") +ax.set_ylabel("sin(x)") +fig.colorbar(scatter, label="Value of sin(x)") + +####################################################################################### +# The marker style can be changed (see :mod:`matplotlib.markers` for a full +# list), but each call to `~.Axes.scatter` can only accept one *marker* type. +# To code data by different marker shapes, make multiple calls to +# `~.Axes.scatter`. + +y2 = np.cos(x) +colors2 = y2 + +fig, ax = plt.subplots() +# Two scatter calls, one for each data set: +scatter = ax.scatter(x, y, c=colors, s=36, cmap='YlGn_r', alpha=0.6, + edgecolor='black', label='sin(x)') +scatter2 = ax.scatter(x, y2, marker='d', c=colors2, s=36, cmap='RdBu_r', + alpha=0.6, edgecolor='black', label='cos(x)') + +ax.set_title("Coding by marker type") +ax.set_xlabel("x") +ax.set_facecolor('0.8') +ax.legend(fontsize='small') +ax.set_ylabel("sin(x), cos(x)") + +# add some colorbars below plot +cax1 = ax.inset_axes([0.05, -0.25, 0.4, 0.05]) +fig.colorbar(scatter2, cax=cax1, label="Value of cos(x)", location='bottom') +cax2 = ax.inset_axes([0.55, -0.25, 0.4, 0.05]) +fig.colorbar(scatter, cax=cax2, label="Value of sin(x)", location='bottom') + + +# %% +# bar and stem +# ------------ +# +# `~.Axes.bar`, `~.Axes.stairs`, and `~.Axes.stem` are useful for plotting data +# that deviates from a zero or mean value. These methods are often used to plot +# histograms. + +x = x[::2] +y = y[::2] +fig, axs = plt.subplots(1, 2, sharex=True, sharey=True) + +ax = axs[0] +# need to specify a width so the bars don't overlap. +ax.bar(x, y, width=0.8*np.median(np.diff(x))) +ax.set_title("bar") +ax.set_xlabel('x') + +ax = axs[1] +ax.stem(x, y) +ax.set_title("stem") +ax.set_xlabel('x') +ax.set_ylabel('sin(x)') + +# %% +# `~.Axes.bar` does not automatically calculate the *width* of the bars, so it +# typically needs to be calculated manually to achieve the correct spacing. The *width* +# can also be specified as an array with the same length as *x* to set the width of each +# bar individually. + +fig, ax = plt.subplots() +width = np.concatenate(([np.diff(x)[0]], np.diff(x))) +ax.bar(x, y, width=width * 0.8) +ax.set_title("bar with widths") + +# %% +# step and stairs +# --------------- +# +# `~.Axes.step` and `~.Axes.stairs` are similar to `~.Axes.plot` but plot a +# step between each data point. They accept differently shaped data depending +# on the use case. +# +# `~.Axes.step` particularly useful as it accepts the same data shape as +# `~.Axes.plot`. + +fig, ax = plt.subplots() + +ax.plot(x, y, '-o', color='gray', alpha=0.5) +ax.step(x, y) +ax.set_ylabel('sin(x)') +ax.set_title('step') + +# %% + +# The steps can be centered on the data in different ways using the **where** +# keyword. The default is **where='pre'**, which means the step extends to the +# left of the data point. **where='mid'** means the step extends halfway to the +# next data point, and **where='post'** means the step extends to the right of +# the data point: + +fig, axs = plt.subplots(3, 1, sharex=True, sharey=True, figsize=(4.5, 5)) + +todo = ['pre', 'mid', 'post'] +for ax, where in zip(axs, todo): + ax.plot(x, y, '-o', color='gray', alpha=0.5) + ax.step(x, y, where=where) + ax.set_title(f'step where={where}') + +# %% +# .. seealso:: +# :ref:`step_demo` for more step examples. + +# %% +# +# `~.Axes.stairs` is useful for plotting histograms, and specifies the edges of +# steps rather than the centers, so can directly be used with the result from +# `~numpy.histogram`. + +data = rng.normal(size=1000) +hist, bin_edges = np.histogram(data, bins=np.arange(-4, 4, 0.2), density=True) + +data2 = rng.uniform(low=-4, high=4, size=300) +hist2, bin_edges2 = np.histogram(data2, bins=np.arange(-4, 4, 0.4), density=True) + +fig, ax = plt.subplots() +ax.stairs(hist, bin_edges, fill=True, alpha=0.4, orientation='vertical', + label='normal') + +ax.stairs(hist2, bin_edges2, fill=True, alpha=0.4, orientation='vertical', + label='uniform') +ax.set_title('stairs from histogram') +ax.set_xlabel('data') +ax.set_ylabel('probability density function') +ax.legend() + +# %% +# .. admonition:: References +# +# The use of the following functions, methods, classes and modules is shown +# in this example: +# +# - `matplotlib.axes.Axes.plot` / `matplotlib.pyplot.plot` +# - `matplotlib.axes.Axes.fill_between` / `matplotlib.pyplot.fill_between` +# - `matplotlib.axes.Axes.fill_betweenx` / `matplotlib.pyplot.fill_betweenx` +# - `matplotlib.axes.Axes.stackplot` / `matplotlib.pyplot.stackplot` +# - `matplotlib.axes.Axes.errorbar` / `matplotlib.pyplot.errorbar` +# - `matplotlib.axes.Axes.scatter` / `matplotlib.pyplot.scatter` +# - `matplotlib.axes.Axes.bar` / `matplotlib.pyplot.bar` +# - `matplotlib.axes.Axes.stem` / `matplotlib.pyplot.stem` +# - `matplotlib.axes.Axes.step` / `matplotlib.pyplot.step` +# - `matplotlib.axes.Axes.stairs` / `matplotlib.pyplot.stairs` +# - `matplotlib.figure.Figure.colorbar` diff --git a/galleries/users_explain/plotting/statistical.py b/galleries/users_explain/plotting/statistical.py new file mode 100644 index 000000000000..f479a3224d24 --- /dev/null +++ b/galleries/users_explain/plotting/statistical.py @@ -0,0 +1,282 @@ +""" + +Statistical plots +================= + +Matplotlib has a few of the most common statistical plots built in, such as +histograms, boxplots, and violin plots. These methods take data, compute +statistics, and then visualize the statistics. When possible, these functions +will automatically calculate the statistics for you, such as binning and +aggregating the data for histograms, or quartiles and outliers for boxplots. +Statistical computation is usually done by underlying `numpy` methods. + +""" + +# %% +# hist +# ---- +# +# The `~.axes.Axes.hist` method is used to plot a histogram. The data is +# binned and the frequency of each bin is plotted. The default number of bins +# is 10, but this can be adjusted with the *bins* keyword. + +import matplotlib.pyplot as plt +import numpy as np + +plt.rcParams['figure.constrained_layout.use'] = True +plt.rcParams['figure.figsize'] = (5, 4) + +rng = np.random.default_rng(19680801) +# collect samples from the normal distribution" +data = rng.standard_normal(1000) + +fig, axs = plt.subplots(2, 1) +ax = axs[0] +ax.plot(data, '.') +ax.set_title('data') +ax.set_ylabel('data values') +ax.set_xlabel('sample number') +ax = axs[1] +ax.hist(data, bins=30) +ax.set_title('histogram of the data') +ax.set_xlabel('data values') +ax.set_ylabel('frequency') + +# %% +# Sometime it is useful to normalize the histogram so that the total area under +# the histogram is 1. This is known as a probability density function (pdf). +# The *density* argument to `~.axes.Axes.hist` can be set to ``True`` to +# normalize the histogram. The total area of the histogram will integrate +# to 1 (taking into account the widths of the bins as well as the heights). + +fig, ax = plt.subplots() +ax.hist(data, bins=30, density=True) +ax.set_title('normalized histogram of the data') +ax.set_xlabel('data values') +ax.set_ylabel('probability density') + +# %% +# Other normalizations are possible using the *weights* argument. See +# :ref:`histogram_normalization` for more details. +# +# It is possible to plot multiple histograms in the same figure by passing +# a 2D array to ``hist``. The columns of the array are the data values for +# each histogram. + +# make three sets of data, with each set in a column of the array: +data = rng.standard_normal((1000, 3)) + +fig, ax = plt.subplots() +ax.hist(data, bins=30, density=True, label=['set1', 'set2', 'set3']) +ax.legend(fontsize='small') +ax.set_title('multiple histograms') +ax.set_xlabel('data values') +ax.set_ylabel('probability density') + +# %% +# .. seealso:: +# +# There are many styling and processing options for histograms. For details, +# see: +# +# - :ref:`histogram_normalization` +# - :ref:`histogram_histtypes` +# - :ref:`histogram_multihist` + + +# %% +# hist2d and hexbin +# ----------------- +# +# If the data has two coordinates, eg arrays of :math:`(x_i, y_i)` pairs, you +# can use the `~.axes.Axes.hist2d` or `~.axes.Axes.hexbin` methods to visualize +# the frequency that the data occurs in a 2D space. + +# make data: correlated + noise +x = rng.normal(size=5000) +y = 1.2 * x + rng.normal(size=5000) / 2 + +# plot: +fig, axs = plt.subplots(2, 1, figsize=(5, 7), sharex=True, sharey=True) +ax = axs[0] +ax.plot(x, y, '.', alpha=0.5, markeredgecolor='none') +ax.set_title('data') +ax.set_ylabel('y') + +ax = axs[1] +bins = (np.arange(-3, 3.1, 0.2), np.arange(-3, 3.1, 0.2)) +N, xbins, ybin, pc = ax.hist2d(x, y, bins=bins, vmax=30, cmap='plasma') +ax.contour(xbins[1:], ybin[1:], N.T, levels=4, colors='c', alpha=0.7) +ax.set_ylabel('y') +ax.set_xlabel('x') + +ax.set(xlim=(-3, 3), ylim=(-3, 3)) +fig.colorbar(pc, ax=ax, label='counts') + +# %% +# Note that `~.axes.Axes.hist2d` returns the histogram values ``N`` above, but +# does so transposed from the typical Matplotlib convention. We have used this +# transposed form to plot the contours of the density over the two-dimensional +# histogram. +# +# The *density* argument to `~.axes.Axes.hist2d` can be set to ``True`` to plot +# a normalized 2D histogram. Again the normalization is such that the area +# integral of the histogram is one. Like with `~.axes.Axes.hist`, other +# normalizations are possible using the *weights* argument. + +fig, axs = plt.subplots(2, 1, figsize=(5, 7), sharex=True, sharey=True) +ax = axs[0] +ax.plot(x, y, '.', alpha=0.5, markeredgecolor='none') +ax.set_title('data') +ax.set_ylabel('y') + +ax = axs[1] +bins = (np.arange(-3, 3.1, 0.2), np.arange(-3, 3.1, 0.2)) +N, xbins, ybin, pc = ax.hist2d(x, y, bins=bins, density=True, cmap='plasma') +ax.set_ylabel('y') +ax.set_xlabel('x') + +ax.set(xlim=(-3, 3), ylim=(-3, 3)) +fig.colorbar(pc, ax=ax, label='Probability density') + +# %% +# The `~.axes.Axes.hexbin` method is similar to `~.axes.Axes.hist2d`, but uses +# hexagonal bins instead of rectangular bins. This can be useful when the data +# is sparse or the distribution is uneven. The hexagonal bins are arranged in +# a hexagonal lattice, and the density of data in each hexagon is computed. + +fig, ax = plt.subplots() + +ax.hexbin(x, y, cmap='plasma', gridsize=20) +ax.set_ylabel('y') +ax.set_xlabel('x') +ax.set_title('hexbin plot') + +ax.set(xlim=(-3, 3), ylim=(-3, 3)) + +# %% +# .. seealso:: +# +# - :ref:`hexbin_demo` +# +# boxplot and violinplot +# ---------------------- +# +# The `~.axes.Axes.boxplot` and `~.axes.Axes.violinplot` methods are used to +# visualize the distribution of data in discrete bins. If :math:`X_{ij}` is +# the data set, the statistics are calculated for each column in +# :math:`X_{ij}`, and a box or violin is drawn for each column. +# +# The boxplot usually shows the quartiles of the data distribution in each +# column, and is typically used to see if data sets are statistically distinct. +# A violin plot is similar to a boxplot, but shows the density of the data at +# different values. The width of the violin is proportional to the density of +# the data at that value, using a smoothed `kernel density estimation +# `_ of the # +# underlying distribution. +# +# Below, we compare the data plotted as dots with a degree of transparency to +# give a feel for the raw data in each column. A histogram of all three data +# sets is also shown, demonstrating the distribution of the data. The boxplot +# and violin plot are then shown for the same data. By default, +# `~.axes.Axes.boxplot` shows the median, quartiles, and outliers, while +# `~.axes.Axes.violinplot` shows a kernel density estimate of the data. + +# make three categories of data +data = np.zeros((100, 3)) +data[:, 0] = rng.normal(loc=0, scale=1, size=100) +data[:, 1] = rng.normal(loc=1.1, scale=1.5, size=100) +data[:, 2] = rng.normal(loc=-1.5, scale=0.7, size=100) + +fig, axs = plt.subplot_mosaic([['plot', 'hist'], ['box', 'violin']], figsize=(5, 5)) + +ax = axs['plot'] +for i in range(3): + ax.plot(i + 1 + 0 * data[:, i], data[:, i], '.', label=f'col. {i}', alpha=0.2, + markeredgecolor='none') +ax.set_xlabel('column number') +ax.set_ylabel('data values') +ax.set_title('plot of data') +ax.set_xlim(0.5, 3.5) + +ax = axs['hist'] +ax.hist(data, bins=np.arange(-4, 4.1, 0.25), density=True, + label=['column 0', 'column 1', 'column 2'], histtype='step', + orientation='horizontal') +ax.set_ylabel('data values') +ax.set_xlabel('probability density') +ax.legend(fontsize='small') +ax.set_title('histograms') + +ax = axs['box'] +ax.boxplot(data) +ax.set_xlabel('column number') +ax.set_ylabel('data values') +ax.set_title('boxplot') + +ax = axs['violin'] +ax.violinplot(data) +ax.set_xlabel('column number') +ax.set_ylabel('data values') +ax.set_title('violin plot') + +# %% +# +# `~.axes.Axes.boxplot` and `~.axes.Axes.violinplot` can be customized in many +# ways. For example, the *showmeans*, *showmedians*, *showextrema*, and +# *showcaps* arguments can be used to show or hide the mean, median, extrema, +# and caps. The *vert* argument can be used to make the boxplot horizontal, +# and the *positions* argument can be used to set the positions of the boxes. +# The *widths* argument can be used to set the width of the boxes. +# +# .. seealso:: +# +# - :ref:`boxplot_demo` +# - :ref:`boxplot_color` +# - :ref:`boxplot_artists` +# - :ref:`boxplot_vs_violin` +# - :ref:`violinplot` +# - :ref:`customized_violin` +# +# eventplot +# --------- +# +# An `~.axes.Axes.eventplot` draws a vertical line at every data point in a 1D +# array, :math:`x_i`, often to compare even timing. Usually the events are +# passed into the method as a sequence of 1D arrays because the events being +# timed usually have a different number of occurrences. +# +# Note in the below, we can label the events by making *lineoffsets* a list of +# strings. This will make the y-axis a :ref:`categorical +# ` axis, with the labels given in the list. + +# make some data + +len = [100, 75] +dataA = np.cumsum(rng.rayleigh(scale=0.1, size=30)) +dataB = np.cumsum(rng.rayleigh(scale=0.1 * 3 / 2, size=20)) +data = [dataA, dataB] + +fig, ax = plt.subplots() +ax.eventplot(data, orientation='horizontal', linelengths=0.9, + color=['C0', 'C1'], lineoffsets=['data A', 'data B']) + +ax.set_xlabel('time') +ax.set_ylabel('event type') + +# %% +# .. seealso:: +# - :ref:`eventplot_demo` +# +# .. admonition:: References +# +# The use of the following functions, methods, classes and modules is shown +# in this example: +# +# - `matplotlib.axes.Axes.hist` / `matplotlib.pyplot.hist` +# - `matplotlib.axes.Axes.hist2d` / `matplotlib.pyplot.hist2d` +# - `matplotlib.axes.Axes.hexbin` / `matplotlib.pyplot.hexbin` +# - `matplotlib.axes.Axes.boxplot` / `matplotlib.pyplot.boxplot` +# - `matplotlib.axes.Axes.violinplot` / `matplotlib.pyplot.violinplot` +# - `matplotlib.axes.Axes.eventplot` / `matplotlib.pyplot.eventplot` +# - `matplotlib.axes.Axes.plot` / `matplotlib.pyplot.plot` diff --git a/galleries/users_explain/plotting/threed.py b/galleries/users_explain/plotting/threed.py new file mode 100644 index 000000000000..17b7076c9e37 --- /dev/null +++ b/galleries/users_explain/plotting/threed.py @@ -0,0 +1,249 @@ +""" +.. _plotting_threed: + +3D and volumetric data +====================== + +Matplotlib has support for three-dimensional plots, including surface plots, +wireframes, and 3D scatter plots. + +Note, however, that Matplotlib does not do true 3D rendering with depth +buffering, and hence multiple surfaces in one visualization will not occlude +one another correctly; the last surface drawn will cover previous surfaces, +regardless of their distance from the viewer. Either try to combine surfaces +into one (which is possible for simple plots, see :ref:`intersecting_planes` +and :ref:`box3d`), or for true 3D, consider using `Mayavi +`_. + +Plotting in 3D can be done using the `.mpl_toolkits.mplot3d` toolkit by +declaring an axes is three dimensional, instead of the default two-dimensional. +After that, most of the methods are the same as their two-dimensional +counterparts, except a third array is added to represent the data along the +z-axis. +""" + +# %% +# plot and scatter +# ---------------- +# +# The most basic 3D plot is a line or collection of scatter plot created from +# sets of (x, y, z) triples. In analogy with the more common 2D plots, the +# 3D plots are simple to create. We use the *subplot_kw* argument to create a +# 3D projection for the plot. + +import matplotlib.pyplot as plt +import numpy as np + +plt.rcParams['figure.figsize'] = (5, 4) + +# make data +n = 100 +xs = np.linspace(0, 1, n) +ys = np.sin(xs * 6 * np.pi) +zs = np.cos(xs * 6 * np.pi) + +# Make an axes with a 3d projection +fig, ax = plt.subplots(subplot_kw={"projection": "3d"}) + +# plot +ax.plot(xs, ys, zs) + +# label +ax.set_xlabel('x') +ax.set_ylabel('y') +ax.set_zlabel('z') +ax.set_title('3d plot') + + +# %% +# For 3D plots, it is possible to rotate the plot by clicking and dragging in +# an interactive backend. For a static backend, the view can be changed by +# setting the elevation and azimuth angles. The elevation is the angle above +# the x-y plane, and the azimuth is the rotation around the z-axis. The +# default view is elevation of 30 degrees and an azimuth of -60 degrees. The +# azimuth is zero looking along the positive x-axis at the y-z plane, and if +# elevation is positive, then increasing azimuth rotates the view in a +# clockwise direction. + +# Make an axes with a 3d projection +fig, axs = plt.subplots(2, 3, figsize=(8.5, 6.5), subplot_kw={"projection": "3d"}) + +for nn, ax in enumerate(axs.flat): + + # change the view + ax.view_init(elev=30, azim=((-60 + nn*20))) + + ax.plot([0, 1], [0, 0], -1, 'r') + ax.plot([1], [0], -1, 'dr') + ax.plot(xs, ys, zs) + ax.plot(xs[0], ys[0], zs[0], 'go') + ax.plot(xs[-1], ys[-1], zs[-1], 'ro') + + ax.set_title(f'view_init(30, {(-60 + nn*20)})') + + # label + ax.set_xlabel('x') + ax.set_ylabel('y') + ax.set_zlabel('z') + +# %% +# We can also create a 3D scatter plot, analogous to a 2D scatter plot, by +# passing arrays of x, y, and z coordinates to the *scatter* method, and +# specifying *c* and *s* to set the color and size of the +# points, if desired. Here we set the color to be the same as the x value, and +# the size as the absolute value of the z value. + +# make data +c = xs +s = np.abs(zs) * 100 + +fig, ax = plt.subplots(subplot_kw={"projection": "3d"}) +sc = ax.scatter(xs, ys, zs, c=c, s=s) +# label +fig.colorbar(sc, ax=ax, location='left', shrink=0.4) +ax.set_xlabel('x') +ax.set_ylabel('y') +ax.set_zlabel('z') + +# %% +# plot_wireframe, plot_surface +# ---------------------------- +# +# The `~.Axes3D.plot_wireframe` method can be used to plot a wireframe +# version of a surface. Wireframe spacing is set by the underlying data, but +# can be adjusted by setting the *rstride* (row-stride) and *cstride* +# (column-stride) of the plot if needed. + +X = np.arange(-5, 5, 0.25) +Y = np.arange(-5, 5, 0.25) +X, Y = np.meshgrid(X, Y) +R = np.sqrt(X**2 + Y**2) +Z = np.sin(R) + +fig, axs = plt.subplots(1, 2, figsize=(6, 3.5), subplot_kw={"projection": "3d"}) +axs[0].plot_wireframe(X, Y, Z) +axs[0].set_title('plot_wireframe') + +axs[1].plot_wireframe(X, Y, Z, rstride=3, cstride=3, color='C2') +axs[1].set_title('rstride=3, cstride=3') + +# %% +# The `.Axes3D.plot_surface` method can be used in the same way to plot a +# surface plot. If the colormap is not specified then the surface is colored +# with one color, but shading is applied to the surface to give it a 3D +# appearance. If a colormap via the *cmap* keyword is specified then the +# surface will be colored by the Z value of the surface. It is possible to +# shade a color-mapped surface by passing the rgba values of the surface colors +# via the *facecolors* keyword (see :ref:`custom_shaded_3d_surface` for +# details). + +fig, axs = plt.subplots(1, 2, figsize=(6, 3.5), subplot_kw={"projection": "3d"}) +axs[0].plot_surface(X, Y, Z) +axs[0].set_title('plot_surface') + +axs[1].plot_surface(X, Y, Z, cmap='viridis') +axs[1].set_title('cmap="viridis"') + + +# %% +# .. seealso:: +# - :ref:`surface3d` +# - :ref:`surface3d_2` +# - :ref:`surface3d_3` +# + +# The `~mpl_toolkits.mplot3d.axes3d.Axes3D.plot_trisurf` method can be used +# just like `~.axes.Axes.tripcolor` when the x and y data is not on a Cartesian +# grid. It makes a triangulation in x and y and plots the surface in 3D. + +rng = np.random.default_rng(19680801) +x = rng.uniform(-5, 5, size=128) +y = rng.uniform(-5, 5, size=128) +r = np.sqrt(x**2 + y**2) +z = np.sin(r) + +fig, ax = plt.subplots(subplot_kw={"projection": "3d"}) + +ax.plot_trisurf(x, y, z) +ax.set_title('plot_trisurf') + +# %% +# +# .. seealso:: +# - :ref:`trisurf3d` +# - :ref:`trisurf3d_2` +# +# stem and bar3d +# -------------- +# +# The `~mpl_toolkits.mplot3d.axes3d.Axes3D.bar3d` and +# `~mpl_toolkits.mplot3d.axes3d.Axes3D.stem` methods can give an idea of +# two-dimensional data counts, similar to `~.axes.Axes.hist2d`. So for +# instance if we histogram a random array of data: + +x = rng.normal(size=5000) +y = rng.normal(size=5000) + +H, xedges, yedges, = np.histogram2d(x, y, bins=10) +X, Y = np.meshgrid(xedges[:-1], yedges[:-1]) + +X = X.flatten() +Y = Y.flatten() +H = H.flatten() + + +fig, axs = plt.subplots(1, 2, figsize=(8, 4), subplot_kw={"projection": "3d"}) + +axs[0].bar3d(X, Y, np.zeros_like(X), + dx=0.2 * np.ones_like(X), dy=0.2 * np.ones_like(X), + dz=H.flatten(), shade=True) + +axs[0].set_title('bar3d') + +axs[1].stem(X.flat, Y.flat, H.flatten()) +axs[1].set_title('stem') + +# %% +# +# .. seealso:: +# - :ref:`bars3d` +# - :ref:`stem3d_demo` +# +# quiver +# ------ +# +# There is a three-dimensional `.Axes3D.quiver` equivalent of +# `~.axes.Axes.quiver` that is called the same way, but with a third array for +# the z direction. Here we plot a 3D field of arrows: + +# Make data +n = 4 +x = np.linspace(-1, 1, n) +y = np.linspace(-1, 1, n) +z = np.linspace(-1, 1, n) +X, Y, Z = np.meshgrid(x, y, z) +U = (X + Y)/5 +V = (Y - X)/5 +W = Z*0 + +# Plot +fig, ax = plt.subplots(subplot_kw={"projection": "3d"}) +ax.quiver(X, Y, Z, U, V, W) + +# %% +# .. seealso:: +# - :ref:`quiver3d` +# +# .. admonition:: References +# +# The use of the following functions, methods, classes and modules is shown +# in this document: +# +# - `.Axes3D.plot` +# - `.Axes3D.scatter` +# - `.Axes3D.plot_wireframe` +# - `.Axes3D.plot_surface` +# - `.Axes3D.plot_trisurf` +# - `.Axes3D.bar3d` +# - `.Axes3D.stem` +# - `.Axes3D.quiver` diff --git a/galleries/users_explain/plotting/unstructuredgrid.py b/galleries/users_explain/plotting/unstructuredgrid.py new file mode 100644 index 000000000000..17132f35f3a2 --- /dev/null +++ b/galleries/users_explain/plotting/unstructuredgrid.py @@ -0,0 +1,127 @@ +""" +.. _plot_unstructuredgrid: + +Unstructured data +================= + +Unlike :ref:`structured grids `, unstructured data are not +sampled on a regular grid. In this case, :math:`x` and :math:`y` are +one-dimensional arrays of the same length, and :math:`z = f(x, y)` is also +one-dimensional. For example, consider a temperature field +:math:`T(\\text{longitude}, \\text{latitude})` measured at 120 weather stations, +with each station at a different latitude and longitude. + +You can interpolate this kind of data onto a regular grid (for example with +`scipy.interpolate.griddata`), but if the sampling is suitable it can often be +plotted directly in Matplotlib. + +Matplotlib supports this through triangulation routines in +:mod:`matplotlib.tri`. The `Qhull `_ library is used to +build a triangulation from the input points via +`~matplotlib.tri.Triangulation`, which can then be used for faceted +pseudocolor and contour plots. + +The triangulation treats the points :math:`(x, y)` as unordered, connecting +points based on proximity. + +""" + +# %% +# triplot +# ------- +# +# The most basic plot is the `~.axes.Axes.triplot` method, which plots the +# edges of triangles in a triangulation. Here we create a simple triangulation +# on a set of points, and plot the edges of the triangles that are created. + +import matplotlib.pyplot as plt +import numpy as np + +plt.rcParams['figure.constrained_layout.use'] = True +plt.rcParams['figure.figsize'] = (5, 4) + +# make data: +np.random.seed(19680801) +x = np.random.uniform(-3, 3, 256) +y = np.random.uniform(-3, 3, 256) +z = (1 - x/2 + x**5 + y**3) * np.exp(-x**2 - y**2) + +fig, ax = plt.subplots() + +# plot the points: +ax.plot(x, y, 'm.') + +# plot the triangulation: +ax.triplot(x, y) + +ax.set_xlabel('x') +ax.set_ylabel('y') +ax.set_title('triplot') + +# %% +# In advanced usage, one could pass a `~matplotlib.tri.Triangulation` object to +# the `~.axes.Axes.triplot` method. See :ref:`triplot_demo` for more details. +# +# tripcolor +# --------- +# +# The `~.axes.Axes.tripcolor` method can be used to plot a surface by coloring +# each triangle based on the value of a colormap. Here we plot the same +# triangulation as above, but color the triangles based on the values of +# :math:`z` on the corners. The default shading is "flat", which averages the +# values of :math:`z` on each triangle, but `~.axes.Axes.tripcolor` can also perform +# Gouraud shading for a smoother appearance. + +fig, axs = plt.subplots(2, 1, figsize=(5, 7)) +for ax, shade in zip(axs, ['flat', 'gouraud']): + ax.plot(x, y, 'm.') + pc = ax.tripcolor(x, y, z, cmap='RdBu_r', vmin=-1, vmax=1, shading=shade) + fig.colorbar(pc, ax=ax, label='z') + ax.set_title(f'tripcolor shading = "{shade}"') + ax.set_xlabel('x') + ax.set_ylabel('y') + ax.set_facecolor('lightgray') + +# %% +# It is also possible to set the values on the face of each triangle, but this +# is better done if you have a `~matplotlib.tri.Triangulation` object rather +# than the raw x, y, z arrays. See :ref:`tripcolor_demo` for more details. +# +# tricontour and tricontourf +# -------------------------- +# +# The `~.axes.Axes.tricontour` and `~.axes.Axes.tricontourf` methods can be +# used to plot contours of unstructured data, where the underlying +# triangulation is used to interpolate the contour locations. Here we plot +# contours of the same data as above. + +fig, ax = plt.subplots() +ax.plot(x, y, 'm.') +pc = ax.tricontourf(x, y, z, cmap='RdBu_r', vmin=-1, vmax=1, levels=15) +fig.colorbar(pc, ax=ax, label='z') + +ax.set_xlabel('x') +ax.set_ylabel('y') +ax.set_facecolor('lightgray') + +# %% +# As with `~.axes.Axes.tripcolor`, a `~matplotlib.tri.Triangulation` object can be +# passed instead of the raw x and y arrays. +# +# .. seealso:: +# For more advanced use of `~.axes.Axes.tricontour` and +# `~.axes.Axes.tricontourf`, see: +# +# - :ref:`tricontour_demo` +# - :ref:`tricontour_smooth_user` +# - :ref:`tricontour_smooth_delaunay` +# +# .. admonition:: References +# +# The use of the following functions, methods, classes and modules is shown +# in this example: +# +# - `matplotlib.axes.Axes.triplot` / `matplotlib.pyplot.triplot` +# - `matplotlib.axes.Axes.tripcolor` / `matplotlib.pyplot.tripcolor` +# - `matplotlib.axes.Axes.tricontour` / `matplotlib.pyplot.tricontour` +# - `matplotlib.axes.Axes.tricontourf` / `matplotlib.pyplot.tricontourf` From 3e0fa4b553dd832f415a3542ff9384da2c03d99a Mon Sep 17 00:00:00 2001 From: Jody Klymak Date: Mon, 13 Apr 2026 16:30:35 -0700 Subject: [PATCH 3/4] DOC: add document on how to document guidelines [ci-doc] --- doc/devel/document.rst | 140 +++++++++++++++++++++++++++++++++-------- 1 file changed, 114 insertions(+), 26 deletions(-) diff --git a/doc/devel/document.rst b/doc/devel/document.rst index bea4771af383..921d2ebd212c 100644 --- a/doc/devel/document.rst +++ b/doc/devel/document.rst @@ -26,7 +26,7 @@ when the documentation is built. See :ref:`writing-docstrings`. Second, our example pages, tutorials, and some of the user guide are created by `Sphinx Gallery`_. Sphinx Gallery converts Python files in :file:`galleries` to ``*.rst`` files that contain the results of Matplotlib plot calls as embedded images. -See :ref:`writing-examples-and-tutorials`. +See :ref:`create-examples-and-tutorials`. Third, Matplotlib has informative documentation written in ReST in subdirectories of :file:`doc`. General and historical information about the project is in :file:`doc/project`, @@ -955,10 +955,10 @@ Example: .. inheritance-diagram:: matplotlib.patches matplotlib.lines matplotlib.text :parts: 2 -.. _writing-examples-and-tutorials: +.. _create-examples-and-tutorials: -Write examples and tutorials -============================ +Create examples and tutorials +============================= Examples and tutorials are Python scripts that are run by `Sphinx Gallery`_. Sphinx Gallery finds ``*.py`` files in source directories and runs the files to @@ -967,25 +967,43 @@ location of the :file:`doc/` directory. Files in the build location should not be directly edited as they will be overwritten by Sphinx gallery. Currently Matplotlib has four galleries as follows: -=============================== ========================== -Source location Build location -=============================== ========================== -:file:`galleries/plot_types` :file:`doc/plot_types` -:file:`galleries/examples` :file:`doc/gallery` -:file:`galleries/tutorials` :file:`doc/tutorials` -:file:`galleries/users_explain` :file:`doc/users/explain` -=============================== ========================== - -The first three are traditional galleries. The last, -:file:`galleries/users_explain`, is a mixed gallery where some of the files are -raw ``*.rst`` files and some are ``*.py`` files; Sphinx Gallery just copies -these ``*.rst`` files from the source location to the build location (see -:ref:`raw_restructured_gallery`, below). +.. list-table:: + :widths: 20 28 22 30 + :header-rows: 1 + + * - Gallery + - Source location + - Build location + - Purpose + * - ``users_explain`` + - :file:`galleries/users_explain` + - :file:`doc/users/explain` + - User guide narrative explanations of how to use Matplotlib. + * - ``plot_types`` + - :file:`galleries/plot_types` + - :file:`doc/plot_types` + - A curated overview of the plot types Matplotlib provides out of the box. + * - ``examples`` + - :file:`galleries/examples` + - :file:`doc/gallery` + - Visual examples that demonstrate features and usage patterns. + * - ``tutorials`` + - :file:`galleries/tutorials` + - :file:`doc/tutorials` + - Step-by-step guides for learning broader workflows in more depth. + +See :ref:`organization-of-examples-and-tutorials` for more guidance about what +gallery to use for what purpose. + +In terms of how they are created, the first three are traditional Sphinx +galleries. The last, :file:`galleries/users_explain`, is a mixed gallery where +some of the files are raw ``*.rst`` files and some are ``*.py`` files; Sphinx +Gallery just copies these ``*.rst`` files from the source location to the build +location (see :ref:`raw_restructured_gallery`, below). In the Python files, to exclude an example from having a plot generated, insert "sgskip" somewhere in the filename. - The format of these files is relatively straightforward. Properly formatted comment blocks are treated as ReST_ text, the code is displayed, and figures are put into the built page. Matplotlib uses the @@ -1142,8 +1160,56 @@ subdirectory, but :file:`galleries/users_explain/artists` has a mix of any ``*.rst`` files to a ``:toctree:``, either in the ``README.txt`` or in a manual ``index.rst``. -Examples guidelines -------------------- +.. _organization-of-examples-and-tutorials: + +Organization of examples and tutorials +-------------------------------------- + +Matplotlib's documentation has a summary of :ref:`plot_types`, a +:ref:`user_guide`, a large gallery of :ref:`examples-index`, and a small set of +:ref:`tutorials`. While this material overlaps in some ways, each section has +a different overall purpose and audience. The following guidelines are meant +to help authors decide where to place new material. + +User's guide guidelines +^^^^^^^^^^^^^^^^^^^^^^^ + +The user's guide is a collection of pages that explain how to use Matplotlib to +create visualizations. It should help readers understand the main concepts, +workflow, and decisions involved in making plots with Matplotlib. A reader +should have a solid understanding of how to approach common plotting tasks +after working through the user's guide, but it is not meant to be a +comprehensive API reference. + +The user's guide should be organized as a coherent narrative so that pages can +be read linearly and build on previously introduced concepts. It should +contain more explanation and instruction than the gallery of examples, while +still being concise and to the point. Cross-link related documentation +(e.g. tutorials, gallery examples, and API entries) and tag the page with +related concepts. + +The user's guide should be organized into sections that cover related topics. +For example, a section on "Customizing Plots" might include pages on how to +change colors, fonts, and line styles. Each page should have a clear title that +describes the content of the page. The code examples should be minimal and +focused on the concept being explained. Avoid including extraneous code that +does not directly contribute to the explanation. + +The material should stay relatively balanced and move between basic and more +advanced concepts in as natural a manner as possible. The goal is for a user to +read the material without having to spend too much effort trying to understand +the examples. Deep dives into one feature set should usually live elsewhere and +be linked as further reading when appropriate. + +.. note:: + + The user's guide contains some older material that was ported over from + Tutorials, so some of the content may not yet conform to the suggestions + above. + + +Examples gallery guidelines +^^^^^^^^^^^^^^^^^^^^^^^^^^^ The gallery of examples contains visual demonstrations of matplotlib features. Gallery examples exist so that users can scan through visual examples. Unlike tutorials or user @@ -1157,7 +1223,7 @@ documentation (e.g. tutorials, user guides and API entries) and tag the example related concepts. Format -^^^^^^ +~~~~~~ All :ref:`examples-index` should aim to follow these guidelines: @@ -1198,15 +1264,36 @@ makes it easier for the reader to map which parts of code correspond to which pa the plot. Figure size -^^^^^^^^^^^ +~~~~~~~~~~~ When customizing figure sizes, we aim to avoid downscaling in rendered HTML docs. The current width limit (induced by *pydata-sphinx-theme*) is 720px, i.e. ``figsize=(7.2, ...)``, or 896px if the page does not have subsections and thus does not have the "On this page" navigation on the right-hand side. +Tutorials guidelines +^^^^^^^^^^^^^^^^^^^^ -Plot types guidelines ---------------------- +Tutorials are step-by-step guides for learning broader workflows in more depth. +They should contain explanation and instruction, and can be more cross-cutting +than individual sections of the user's guide and more in-depth than an +example. Tutorials need not be limited to assuming basic Matplotlib knowledge, +but should clearly state the assumed level of knowledge and learning goals in +the introduction. + +Long-form tutorials should be organized as a coherent narrative, with sections +that build on one another and contribute to a clear end result. Break the +material into stages with clear subsections, and make it easy for readers to see +what each section adds and when to refer to other documentation for deeper +detail on a specific feature. A table of contents may be helpful for longer +tutorials. + +Formatting guidelines are the same as for Examples above. Cross-link +related documentation (e.g. user guides, gallery examples, and API entries) and +tag the page with related concepts. + + +Plot types gallery guidelines +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ The :ref:`plot_types` gallery provides an overview of the types of visualizations that Matplotlib provides out of the box, meaning that there is a high-level API for @@ -1215,7 +1302,8 @@ because this gallery is heavily curated and tightly scoped to methods on `matplotlib.axes.Axes`. Format -^^^^^^ +~~~~~~ + :title: Method signature with required arguments, e.g. ``plot(x, y)`` :description: In one sentence, describe the visualization that the method produces and link to the API documentation, e.g. *Draws a bar chart. See ~Axes.bar*. From e1f2e64bb387cabcea671189e7e69656149529c0 Mon Sep 17 00:00:00 2001 From: Jody Klymak Date: Tue, 14 Apr 2026 08:58:29 -0700 Subject: [PATCH 4/4] DOC: fix --- doc/users/index.rst | 4 ++-- galleries/users_explain/plotting/gridded.py | 11 ++++++----- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/doc/users/index.rst b/doc/users/index.rst index 4ed5ae680fdf..2c4d4bf50970 100644 --- a/doc/users/index.rst +++ b/doc/users/index.rst @@ -31,7 +31,7 @@ Using Matplotlib :maxdepth: 2 :includehidden: - explain/figure/index + explain/plotting/index .. grid-item-card:: :padding: 2 @@ -40,7 +40,7 @@ Using Matplotlib :maxdepth: 2 :includehidden: - explain/plotting/index + explain/figure/index .. grid-item-card:: :padding: 2 diff --git a/galleries/users_explain/plotting/gridded.py b/galleries/users_explain/plotting/gridded.py index 0c8d7bf7c829..025f0003b339 100644 --- a/galleries/users_explain/plotting/gridded.py +++ b/galleries/users_explain/plotting/gridded.py @@ -4,11 +4,12 @@ Gridded data ============ -This section discusses data that mapped onto a two-dimensional grid. The data -usually has structured coordinates defined by arrays of x and y values, and data -mapped onto those coordinates :math:`Data(x, y)` in a two-dimensional array. The grid -can either be regular, in which case the x and y arrays are 1D and the Data is 2D, -or the grid can be irregular, and X, Y, and Data are all 2D arrays. +This section discusses plotting data that is mapped onto a two-dimensional grid +using either colors or contours. The data usually has structured coordinates +defined by arrays of x and y values, and data mapped onto those coordinates +:math:`Data(x, y)` in a two-dimensional array. The grid can either be regular, +in which case the x and y arrays are 1D and the Data is 2D, or the grid can be +irregular, and X, Y, and Data are all 2D arrays. """