Mahmudm commited on
Commit
928c17e
·
verified ·
1 Parent(s): 730ca0c

Update ash_animator/basemaps.py

Browse files
Files changed (1) hide show
  1. ash_animator/basemaps.py +39 -81
ash_animator/basemaps.py CHANGED
@@ -1,36 +1,6 @@
1
-
2
- # import contextily as ctx
3
- # from mpl_toolkits.basemap import Basemap
4
- # import cartopy.crs as ccrs
5
- # import cartopy.feature as cfeature
6
-
7
- # def draw_etopo_basemap(ax, mode="basemap", zoom=7):
8
- # try:
9
- # if mode == "stock":
10
- # ax.stock_img()
11
- # elif mode == "contextily":
12
- # extent = ax.get_extent(ccrs.PlateCarree())
13
- # ax.set_extent(extent, crs=ccrs.PlateCarree())
14
- # ctx.add_basemap(ax, crs=ccrs.PlateCarree(), source=ctx.providers.CartoDB.Voyager, zoom=zoom)
15
- # elif mode == "basemap":
16
- # extent = ax.get_extent(ccrs.PlateCarree())
17
- # m = Basemap(projection='cyl',
18
- # llcrnrlon=extent[0], urcrnrlon=extent[1],
19
- # llcrnrlat=extent[2], urcrnrlat=extent[3],
20
- # resolution='h', ax=ax)
21
- # m.shadedrelief()
22
- # m.drawcoastlines(linewidth=0.5)
23
- # m.drawcountries(linewidth=0.7)
24
- # m.drawmapboundary()
25
- # else:
26
- # raise ValueError(f"Unsupported basemap mode: {mode}")
27
- # except Exception as e:
28
- # print(f"[Relief Error - {mode} mode]:", e)
29
- # ax.add_feature(cfeature.LAND)
30
- # ax.add_feature(cfeature.OCEAN)
31
-
32
  import os
33
  import hashlib
 
34
  import contextily as ctx
35
  from mpl_toolkits.basemap import Basemap
36
  import cartopy.crs as ccrs
@@ -38,41 +8,33 @@ import cartopy.feature as cfeature
38
  from PIL import Image
39
  import matplotlib.pyplot as plt
40
 
41
- # Define cache directories
42
- # Optional: Set tile cache directory (must be done before contextily downloads tiles)
43
- os.environ["XDG_CACHE_HOME"] = os.path.expanduser("~/.contextily_cache")
44
-
45
- CTX_TILE_CACHE_DIR = os.path.expanduser("~/.contextily_cache")
46
- BASEMAP_TILE_CACHE_DIR = os.path.expanduser("~/.basemap_cache")
47
-
48
- os.makedirs(CTX_TILE_CACHE_DIR, exist_ok=True)
49
- os.makedirs(BASEMAP_TILE_CACHE_DIR, exist_ok=True)
50
-
51
- def draw_etopo_basemap(ax, mode="basemap", zoom=11):
52
  """
53
- Draws a high-resolution basemap background on the provided Cartopy GeoAxes.
54
-
55
- Parameters
56
- ----------
57
- ax : matplotlib.axes._subplots.AxesSubplot
58
- The matplotlib Axes object (with Cartopy projection) to draw the map background on.
59
-
60
- mode : str, optional
61
- The basemap mode to use:
62
- - "stock": Default stock image from Cartopy.
63
- - "contextily": Web tile background (CartoDB Voyager), with caching.
64
- - "basemap": High-resolution shaded relief using Basemap, with caching.
65
- Default is "basemap".
66
-
67
- zoom : int, optional
68
- Tile zoom level (only for "contextily"). Higher = more detail. Default is 7.
69
-
70
- Notes
71
- -----
72
- - Uses high resolution for Basemap (resolution='h') and saves figure at 300 DPI.
73
- - Cached images are reused using extent-based hashing to avoid re-rendering.
74
- - Basemap is deprecated; Cartopy with web tiles is recommended for new projects.
75
  """
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
76
  try:
77
  if mode == "stock":
78
  ax.stock_img()
@@ -84,43 +46,39 @@ def draw_etopo_basemap(ax, mode="basemap", zoom=11):
84
  ax,
85
  crs=ccrs.PlateCarree(),
86
  source=ctx.providers.CartoDB.Voyager,
87
- zoom=zoom
88
  )
89
 
90
  elif mode == "basemap":
91
  extent = ax.get_extent(crs=ccrs.PlateCarree())
92
-
93
- # Create a hash key for this extent
94
  extent_str = f"{extent[0]:.4f}_{extent[1]:.4f}_{extent[2]:.4f}_{extent[3]:.4f}"
95
  cache_key = hashlib.md5(extent_str.encode()).hexdigest()
96
- cache_file = os.path.join(BASEMAP_TILE_CACHE_DIR, f"{cache_key}_highres.png")
97
 
98
- if os.path.exists(cache_file):
99
  img = Image.open(cache_file)
100
  ax.imshow(img, extent=extent, transform=ccrs.PlateCarree())
101
  else:
102
- # Create a high-resolution temporary figure
103
  temp_fig, temp_ax = plt.subplots(figsize=(12, 9),
104
  subplot_kw={'projection': ccrs.PlateCarree()})
105
  temp_ax.set_extent(extent, crs=ccrs.PlateCarree())
106
-
107
  m = Basemap(projection='cyl',
108
  llcrnrlon=extent[0], urcrnrlon=extent[1],
109
  llcrnrlat=extent[2], urcrnrlat=extent[3],
110
- resolution='f', ax=temp_ax) # 'h' = high resolution
111
-
112
  m.shadedrelief()
113
- # m.drawcoastlines(linewidth=0.1)
114
- # m.drawcountries(linewidth=0.1)
115
- # m.drawmapboundary()
116
 
117
- # Save high-DPI figure for clarity
118
- temp_fig.savefig(cache_file, dpi=300, bbox_inches='tight', pad_inches=0)
 
 
 
119
  plt.close(temp_fig)
120
 
121
- # Load and display the cached image
122
- img = Image.open(cache_file)
123
- ax.imshow(img, extent=extent, transform=ccrs.PlateCarree())
 
124
 
125
  else:
126
  raise ValueError(f"Unsupported basemap mode: {mode}")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  import os
2
  import hashlib
3
+ import tempfile
4
  import contextily as ctx
5
  from mpl_toolkits.basemap import Basemap
6
  import cartopy.crs as ccrs
 
8
  from PIL import Image
9
  import matplotlib.pyplot as plt
10
 
11
+ def get_safe_dir(name):
 
 
 
 
 
 
 
 
 
 
12
  """
13
+ Returns the first writable directory from a list of fallback options.
14
+ Returns None if all fail.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
15
  """
16
+ fallback_paths = [
17
+ os.path.join("/code", name),
18
+ os.path.join(tempfile.gettempdir(), name),
19
+ os.path.expanduser(f"~/.{name}")
20
+ ]
21
+ for path in fallback_paths:
22
+ try:
23
+ os.makedirs(path, exist_ok=True)
24
+ return path
25
+ except PermissionError:
26
+ continue
27
+ return None
28
+
29
+ # Define and validate cache directories
30
+ CTX_TILE_CACHE_DIR = get_safe_dir("contextily_cache")
31
+ BASEMAP_TILE_CACHE_DIR = get_safe_dir("basemap_cache")
32
+
33
+ # Set environment variable only if safe
34
+ if CTX_TILE_CACHE_DIR:
35
+ os.environ["XDG_CACHE_HOME"] = CTX_TILE_CACHE_DIR
36
+
37
+ def draw_etopo_basemap(ax, mode="basemap", zoom=11):
38
  try:
39
  if mode == "stock":
40
  ax.stock_img()
 
46
  ax,
47
  crs=ccrs.PlateCarree(),
48
  source=ctx.providers.CartoDB.Voyager,
49
+ zoom=zoom
50
  )
51
 
52
  elif mode == "basemap":
53
  extent = ax.get_extent(crs=ccrs.PlateCarree())
 
 
54
  extent_str = f"{extent[0]:.4f}_{extent[1]:.4f}_{extent[2]:.4f}_{extent[3]:.4f}"
55
  cache_key = hashlib.md5(extent_str.encode()).hexdigest()
56
+ cache_file = os.path.join(BASEMAP_TILE_CACHE_DIR, f"{cache_key}_highres.png") if BASEMAP_TILE_CACHE_DIR else None
57
 
58
+ if cache_file and os.path.exists(cache_file):
59
  img = Image.open(cache_file)
60
  ax.imshow(img, extent=extent, transform=ccrs.PlateCarree())
61
  else:
 
62
  temp_fig, temp_ax = plt.subplots(figsize=(12, 9),
63
  subplot_kw={'projection': ccrs.PlateCarree()})
64
  temp_ax.set_extent(extent, crs=ccrs.PlateCarree())
 
65
  m = Basemap(projection='cyl',
66
  llcrnrlon=extent[0], urcrnrlon=extent[1],
67
  llcrnrlat=extent[2], urcrnrlat=extent[3],
68
+ resolution='f', ax=temp_ax)
 
69
  m.shadedrelief()
 
 
 
70
 
71
+ if cache_file:
72
+ try:
73
+ temp_fig.savefig(cache_file, dpi=300, bbox_inches='tight', pad_inches=0)
74
+ except Exception as e:
75
+ print(f"[Cache Save Failed]: {e}")
76
  plt.close(temp_fig)
77
 
78
+ # Display image only if it was saved
79
+ if cache_file and os.path.exists(cache_file):
80
+ img = Image.open(cache_file)
81
+ ax.imshow(img, extent=extent, transform=ccrs.PlateCarree())
82
 
83
  else:
84
  raise ValueError(f"Unsupported basemap mode: {mode}")