Coverage for pyguymer3/geo/_add_bathymetry.py: 2%

43 statements  

« prev     ^ index     » next       coverage.py v7.9.2, created at 2025-07-08 18:47 +0000

1#!/usr/bin/env python3 

2 

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. 

15 

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 

33 

34 Notes 

35 ----- 

36 This function uses `CSS4 named colours 

37 <https://matplotlib.org/stable/gallery/color/named_colors.html>`_ . 

38 

39 Copyright 2017 Thomas Guymer [1]_ 

40 

41 References 

42 ---------- 

43 .. [1] PyGuymer3, https://github.com/Guymer/PyGuymer3 

44 """ 

45 

46 # Import standard modules ... 

47 import os 

48 import urllib 

49 

50 # Import special modules ... 

51 try: 

52 import cartopy 

53 cartopy.config.update( 

54 { 

55 "cache_dir" : os.path.expanduser("~/.local/share/cartopy_cache"), 

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 

72 try: 

73 import shapely 

74 import shapely.geometry 

75 except: 

76 raise Exception("\"shapely\" is not installed; run \"pip install --user Shapely\"") from None 

77 

78 # Import sub-functions ... 

79 from .extract_polys import extract_polys 

80 

81 # ************************************************************************** 

82 

83 # Create suitable colour map ... 

84 cmap = matplotlib.colors.LinearSegmentedColormap.from_list( 

85 "bathymetry", 

86 [ 

87 matplotlib.colors.to_rgba(matplotlib.colors.CSS4_COLORS["lightblue"]), 

88 matplotlib.colors.to_rgba(matplotlib.colors.CSS4_COLORS["darkblue"]), 

89 ] 

90 ) 

91 

92 # Define depths ... 

93 depths = [ 

94 ( 0, "bathymetry_L_0" ), 

95 ( 200, "bathymetry_K_200" ), 

96 ( 1000, "bathymetry_J_1000" ), 

97 ( 2000, "bathymetry_I_2000" ), 

98 ( 3000, "bathymetry_H_3000" ), 

99 ( 4000, "bathymetry_G_4000" ), 

100 ( 5000, "bathymetry_F_5000" ), 

101 ( 6000, "bathymetry_E_6000" ), 

102 ( 7000, "bathymetry_D_7000" ), 

103 ( 8000, "bathymetry_C_8000" ), 

104 ( 9000, "bathymetry_B_9000" ), 

105 (10000, "bathymetry_A_10000"), 

106 ] 

107 

108 # Loop over depths ... 

109 for depth, name in depths: 

110 # Create suitable colour ... 

111 facecolor = cmap(float(depth) / 10000.0) 

112 if debug: 

113 print(f"INFO: \"{name}\" is ({facecolor[0]:.6f},{facecolor[1]:.6f},{facecolor[2]:.6f},{facecolor[3]:.6f}).") 

114 

115 # Find file containing the shapes ... 

116 try: 

117 sfile = cartopy.io.shapereader.natural_earth( 

118 resolution = resolution, 

119 category = "physical", 

120 name = name, 

121 ) 

122 except urllib.error.HTTPError: 

123 continue 

124 if debug: 

125 print(f"INFO: \"{name}\" is \"{sfile}\".") 

126 

127 # Loop over records ... 

128 for record in cartopy.io.shapereader.Reader(sfile).records(): 

129 # Skip bad records ... 

130 if not hasattr(record, "geometry"): 

131 continue 

132 

133 # Create a list of Polygons to plot (taking in to account if the 

134 # user provided a field-of-view to clip them by) ... 

135 polys = [] 

136 for poly in extract_polys( 

137 record.geometry, 

138 onlyValid = onlyValid, 

139 repair = repair, 

140 ): 

141 if fov is None: 

142 polys.append(poly) 

143 continue 

144 if poly.disjoint(fov): 

145 continue 

146 polys.append(poly.intersection(fov)) 

147 

148 # Plot geometry ... 

149 ax.add_geometries( 

150 polys, 

151 cartopy.crs.PlateCarree(), 

152 edgecolor = "none", 

153 facecolor = facecolor, 

154 )