Coverage for pyguymer3/geo/_add_bathymetry.py: 3%
38 statements
« prev ^ index » next coverage.py v7.10.3, created at 2025-08-16 08:31 +0000
« prev ^ index » next coverage.py v7.10.3, created at 2025-08-16 08:31 +0000
1#!/usr/bin/env python3
3# Define function ...
4def _add_bathymetry(
5 ax,
6 /,
7 *,
8 debug = __debug__,
9 fov = None,
10 onlyValid = False,
11 repair = False,
12 resolution = "10m",
13):
14 """Add bathymetry to a Cartopy axis.
16 Parameters
17 ----------
18 axis : cartopy.mpl.geoaxes.GeoAxesSubplot
19 the axis to add the bathymetry to
20 debug : bool, optional
21 print debug messages
22 fov : None or shapely.geometry.polygon.Polygon, optional
23 clip the plotted shapes to the provided field-of-view to work around
24 occaisional MatPlotLib or Cartopy plotting errors when shapes much
25 larger than the field-of-view are plotted
26 onlyValid : bool, optional
27 only add valid Polygons (checks for validity can take a while, if being
28 being called often)
29 repair : bool, optional
30 attempt to repair invalid Polygons
31 resolution : str, optional
32 the resolution of the bathymetry
34 Notes
35 -----
36 This function uses `CSS4 named colours
37 <https://matplotlib.org/stable/gallery/color/named_colors.html>`_ .
39 Copyright 2017 Thomas Guymer [1]_
41 References
42 ----------
43 .. [1] PyGuymer3, https://github.com/Guymer/PyGuymer3
44 """
46 # Import standard modules ...
47 import pathlib
48 import urllib
50 # Import special modules ...
51 try:
52 import cartopy
53 cartopy.config.update(
54 {
55 "cache_dir" : pathlib.PosixPath("~/.local/share/cartopy_cache").expanduser(),
56 }
57 )
58 except:
59 raise Exception("\"cartopy\" is not installed; run \"pip install --user Cartopy\"") from None
60 try:
61 import matplotlib
62 matplotlib.rcParams.update(
63 {
64 "backend" : "Agg", # NOTE: See https://matplotlib.org/stable/gallery/user_interfaces/canvasagg.html
65 "figure.dpi" : 300,
66 "figure.figsize" : (9.6, 7.2), # NOTE: See https://github.com/Guymer/misc/blob/main/README.md#matplotlib-figure-sizes
67 "font.size" : 8,
68 }
69 )
70 except:
71 raise Exception("\"matplotlib\" is not installed; run \"pip install --user matplotlib\"") from None
73 # Import sub-functions ...
74 from .extract_polys import extract_polys
76 # **************************************************************************
78 # Create suitable colour map ...
79 cmap = matplotlib.colors.LinearSegmentedColormap.from_list(
80 "bathymetry",
81 [
82 matplotlib.colors.to_rgba(matplotlib.colors.CSS4_COLORS["lightblue"]),
83 matplotlib.colors.to_rgba(matplotlib.colors.CSS4_COLORS["darkblue"]),
84 ]
85 )
87 # Define depths ...
88 depths = [
89 ( 0, "bathymetry_L_0" ),
90 ( 200, "bathymetry_K_200" ),
91 ( 1000, "bathymetry_J_1000" ),
92 ( 2000, "bathymetry_I_2000" ),
93 ( 3000, "bathymetry_H_3000" ),
94 ( 4000, "bathymetry_G_4000" ),
95 ( 5000, "bathymetry_F_5000" ),
96 ( 6000, "bathymetry_E_6000" ),
97 ( 7000, "bathymetry_D_7000" ),
98 ( 8000, "bathymetry_C_8000" ),
99 ( 9000, "bathymetry_B_9000" ),
100 (10000, "bathymetry_A_10000"),
101 ]
103 # Loop over depths ...
104 for depth, name in depths:
105 # Create suitable colour ...
106 facecolor = cmap(float(depth) / 10000.0)
107 if debug:
108 print(f"INFO: \"{name}\" is ({facecolor[0]:.6f},{facecolor[1]:.6f},{facecolor[2]:.6f},{facecolor[3]:.6f}).")
110 # Find file containing the shapes ...
111 try:
112 sfile = cartopy.io.shapereader.natural_earth(
113 resolution = resolution,
114 category = "physical",
115 name = name,
116 )
117 except urllib.error.HTTPError:
118 continue
119 if debug:
120 print(f"INFO: \"{name}\" is \"{sfile}\".")
122 # Loop over records ...
123 for record in cartopy.io.shapereader.Reader(sfile).records():
124 # Skip bad records ...
125 if not hasattr(record, "geometry"):
126 continue
128 # Create a list of Polygons to plot (taking in to account if the
129 # user provided a field-of-view to clip them by) ...
130 polys = []
131 for poly in extract_polys(
132 record.geometry,
133 onlyValid = onlyValid,
134 repair = repair,
135 ):
136 if fov is None:
137 polys.append(poly)
138 continue
139 if poly.disjoint(fov):
140 continue
141 polys.append(poly.intersection(fov))
143 # Plot geometry ...
144 ax.add_geometries(
145 polys,
146 cartopy.crs.PlateCarree(),
147 edgecolor = "none",
148 facecolor = facecolor,
149 )