or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

basemap-integration.mdcoordinate-transformation.mdindex.mdplace-mapping.mdtile-operations.md

tile-operations.mddocs/

0

# Tile Operations

1

2

Core functionality for downloading, caching, and processing map tiles from web services. These functions provide direct access to tile data for custom applications and analysis workflows.

3

4

## Capabilities

5

6

### Image Tile Retrieval

7

8

Download map tiles for specified geographic bounds and return as numpy arrays with extent information for direct use in applications.

9

10

```python { .api }

11

def bounds2img(w, s, e, n, zoom='auto', source=None, ll=False,

12

wait=0, max_retries=2, n_connections=1, use_cache=True,

13

zoom_adjust=None):

14

"""

15

Download tiles for bounding box and return as image array with extent.

16

17

Parameters:

18

- w: float - West edge coordinate

19

- s: float - South edge coordinate

20

- e: float - East edge coordinate

21

- n: float - North edge coordinate

22

- zoom: int or 'auto' - Zoom level (calculated automatically if 'auto')

23

- source: TileProvider, str, or None - Tile source (defaults to OpenStreetMap HOT)

24

- ll: bool - If True, coordinates are lon/lat (EPSG:4326), otherwise Web Mercator (EPSG:3857)

25

- wait: int - Seconds to wait between failed requests and retries

26

- max_retries: int - Maximum number of retries for failed requests

27

- n_connections: int - Number of parallel connections (default 1, max recommended 16)

28

- use_cache: bool - Whether to cache downloaded tiles

29

- zoom_adjust: int - Adjustment to automatically calculated zoom level

30

31

Returns:

32

tuple: (img: ndarray, extent: tuple)

33

- img: 3D array (height, width, bands) of RGB values

34

- extent: (minX, maxX, minY, maxY) bounding box in Web Mercator

35

"""

36

```

37

38

**Usage Examples:**

39

40

```python

41

import contextily as ctx

42

import matplotlib.pyplot as plt

43

44

# Download tiles for NYC area (lon/lat coordinates)

45

west, south, east, north = -74.1, 40.7, -73.9, 40.8 # NYC bounds

46

img, extent = ctx.bounds2img(west, south, east, north, zoom=12, ll=True)

47

48

# Display the downloaded image

49

fig, ax = plt.subplots(figsize=(10, 8))

50

ax.imshow(img, extent=extent)

51

ax.set_title("NYC Basemap")

52

plt.show()

53

54

# Use different tile provider

55

img, extent = ctx.bounds2img(west, south, east, north,

56

source=ctx.providers.Stamen.Toner,

57

zoom=10, ll=True)

58

59

# High resolution with parallel downloads (be respectful of tile servers)

60

img, extent = ctx.bounds2img(west, south, east, north,

61

zoom=15, n_connections=2, ll=True)

62

63

# Web Mercator coordinates (ll=False, default)

64

w_merc, s_merc, e_merc, n_merc = -8238310, 4969450, -8235310, 4972450

65

img, extent = ctx.bounds2img(w_merc, s_merc, e_merc, n_merc, zoom=14)

66

```

67

68

### Raster File Output

69

70

Download map tiles and save directly to geospatial raster files with proper georeferencing for use in GIS applications.

71

72

```python { .api }

73

def bounds2raster(w, s, e, n, path, zoom='auto', source=None, ll=False,

74

wait=0, max_retries=2, n_connections=1, use_cache=True):

75

"""

76

Download tiles for bounding box and write to raster file in Web Mercator CRS.

77

78

Parameters:

79

- w: float - West edge coordinate

80

- s: float - South edge coordinate

81

- e: float - East edge coordinate

82

- n: float - North edge coordinate

83

- path: str - Output raster file path

84

- zoom: int or 'auto' - Zoom level (calculated automatically if 'auto')

85

- source: TileProvider, str, or None - Tile source (defaults to OpenStreetMap HOT)

86

- ll: bool - If True, coordinates are lon/lat, otherwise Web Mercator

87

- wait: int - Seconds to wait between failed requests and retries

88

- max_retries: int - Maximum number of retries for failed requests

89

- n_connections: int - Number of parallel connections for downloading

90

- use_cache: bool - Whether to cache downloaded tiles

91

92

Returns:

93

tuple: (img: ndarray, extent: tuple)

94

- img: 3D array (height, width, bands) of RGB values

95

- extent: (minX, maxX, minY, maxY) bounding box in Web Mercator

96

"""

97

```

98

99

**Usage Examples:**

100

101

```python

102

import contextily as ctx

103

104

# Download and save basemap for analysis area

105

west, south, east, north = -122.5, 37.7, -122.3, 37.9 # San Francisco

106

img, extent = ctx.bounds2raster(west, south, east, north,

107

'sf_basemap.tiff', zoom=13, ll=True)

108

109

# High-resolution satellite imagery

110

img, extent = ctx.bounds2raster(west, south, east, north,

111

'sf_satellite.tiff',

112

source=ctx.providers.ESRI.WorldImagery,

113

zoom=16, ll=True)

114

115

# Use the saved raster in other applications

116

import rasterio

117

with rasterio.open('sf_basemap.tiff') as src:

118

print(f"CRS: {src.crs}") # EPSG:3857

119

print(f"Bounds: {src.bounds}")

120

basemap_data = src.read()

121

```

122

123

### Tile Count Estimation

124

125

Calculate the number of tiles required for a given area and zoom level to estimate download time and data usage.

126

127

```python { .api }

128

def howmany(w, s, e, n, zoom, verbose=True, ll=False):

129

"""

130

Calculate number of tiles required for bounding box and zoom level.

131

132

Parameters:

133

- w: float - West edge coordinate

134

- s: float - South edge coordinate

135

- e: float - East edge coordinate

136

- n: float - North edge coordinate

137

- zoom: int - Zoom level (integer value required)

138

- verbose: bool - Whether to print informative message

139

- ll: bool - If True, coordinates are lon/lat, otherwise Web Mercator

140

141

Returns:

142

int - Number of tiles required

143

"""

144

```

145

146

**Usage Examples:**

147

148

```python

149

import contextily as ctx

150

151

# Check tile count before downloading

152

west, south, east, north = -74.1, 40.7, -73.9, 40.8 # NYC

153

tile_count = ctx.howmany(west, south, east, north, zoom=15, ll=True)

154

# Output: "Using zoom level 15, this will download 64 tiles"

155

156

# Estimate for different zoom levels

157

for zoom in range(10, 17):

158

count = ctx.howmany(west, south, east, north, zoom, verbose=False, ll=True)

159

print(f"Zoom {zoom}: {count} tiles")

160

161

# Auto-calculated zoom estimation

162

count = ctx.howmany(west, south, east, north, zoom='auto', ll=True)

163

```

164

165

### Cache Management

166

167

Control tile caching behavior for performance optimization and storage management.

168

169

```python { .api }

170

def set_cache_dir(path):

171

"""

172

Set custom cache directory for tile downloads.

173

174

Parameters:

175

- path: str - Path to cache directory

176

177

Returns:

178

None

179

"""

180

```

181

182

**Usage Examples:**

183

184

```python

185

import contextily as ctx

186

import os

187

188

# Set persistent cache directory

189

cache_dir = os.path.expanduser('~/contextily_cache')

190

ctx.set_cache_dir(cache_dir)

191

192

# Now all tile downloads use persistent cache

193

img, extent = ctx.bounds2img(-74.1, 40.7, -73.9, 40.8, zoom=12, ll=True)

194

195

# Disable caching for specific downloads

196

img, extent = ctx.bounds2img(-74.1, 40.7, -73.9, 40.8,

197

zoom=12, ll=True, use_cache=False)

198

```

199

200

## Tile Sources and Providers

201

202

### Default Provider

203

204

```python

205

# Default source is OpenStreetMap Humanitarian tiles

206

img, extent = ctx.bounds2img(w, s, e, n, zoom=12, ll=True)

207

# Equivalent to:

208

img, extent = ctx.bounds2img(w, s, e, n, zoom=12, ll=True,

209

source=ctx.providers.OpenStreetMap.HOT)

210

```

211

212

### Popular Providers

213

214

```python

215

# Satellite imagery

216

img, extent = ctx.bounds2img(w, s, e, n, zoom=14, ll=True,

217

source=ctx.providers.ESRI.WorldImagery)

218

219

# Terrain map

220

img, extent = ctx.bounds2img(w, s, e, n, zoom=12, ll=True,

221

source=ctx.providers.Stamen.Terrain)

222

223

# High contrast

224

img, extent = ctx.bounds2img(w, s, e, n, zoom=11, ll=True,

225

source=ctx.providers.Stamen.Toner)

226

```

227

228

### Custom Tile URLs

229

230

```python

231

# Custom tile server

232

custom_url = "https://tiles.example.com/{z}/{x}/{y}.png"

233

img, extent = ctx.bounds2img(w, s, e, n, zoom=12, ll=True, source=custom_url)

234

235

# TileProvider object

236

from xyzservices import TileProvider

237

provider = TileProvider(

238

url="https://server.arcgisonline.com/ArcGIS/rest/services/World_Street_Map/MapServer/tile/{z}/{y}/{x}",

239

attribution="© Esri"

240

)

241

img, extent = ctx.bounds2img(w, s, e, n, zoom=12, ll=True, source=provider)

242

```

243

244

## Performance and Rate Limiting

245

246

### Parallel Downloads

247

248

```python

249

# Single connection (default, most respectful)

250

img, extent = ctx.bounds2img(w, s, e, n, zoom=14, ll=True, n_connections=1)

251

252

# Multiple connections (check provider's terms of service)

253

# OpenStreetMap allows max 2 connections

254

img, extent = ctx.bounds2img(w, s, e, n, zoom=14, ll=True, n_connections=2)

255

256

# Higher concurrency for servers that allow it

257

img, extent = ctx.bounds2img(w, s, e, n, zoom=12, ll=True, n_connections=8)

258

```

259

260

### Rate Limiting and Retries

261

262

```python

263

# Handle rate-limited APIs

264

img, extent = ctx.bounds2img(w, s, e, n, zoom=14, ll=True,

265

wait=1, # Wait 1 second between retries

266

max_retries=5) # Try up to 5 times

267

268

# Disable retries for fast failure

269

img, extent = ctx.bounds2img(w, s, e, n, zoom=12, ll=True, max_retries=0)

270

```

271

272

### Memory Management

273

274

```python

275

# Disable caching for memory-constrained environments

276

img, extent = ctx.bounds2img(w, s, e, n, zoom=15, ll=True,

277

use_cache=False, n_connections=4)

278

279

# Process large areas in chunks

280

def download_large_area(w, s, e, n, zoom, chunk_size=0.01):

281

"""Download large area in smaller chunks to manage memory."""

282

chunks = []

283

for lat in np.arange(s, n, chunk_size):

284

for lon in np.arange(w, e, chunk_size):

285

chunk_w, chunk_s = lon, lat

286

chunk_e, chunk_n = min(lon + chunk_size, e), min(lat + chunk_size, n)

287

img, extent = ctx.bounds2img(chunk_w, chunk_s, chunk_e, chunk_n,

288

zoom=zoom, ll=True, use_cache=False)

289

chunks.append((img, extent))

290

return chunks

291

```

292

293

## Error Handling

294

295

### Common Error Scenarios

296

297

```python

298

import contextily as ctx

299

import requests

300

301

try:

302

img, extent = ctx.bounds2img(w, s, e, n, zoom=18, ll=True)

303

except requests.HTTPError as e:

304

if "404" in str(e):

305

print("Tiles not available at this zoom level")

306

else:

307

print(f"HTTP error: {e}")

308

except ValueError as e:

309

print(f"Invalid parameters: {e}")

310

except Exception as e:

311

print(f"Download failed: {e}")

312

313

# Validate zoom level for provider

314

try:

315

# Some providers have max zoom limits

316

img, extent = ctx.bounds2img(w, s, e, n, zoom=20, ll=True,

317

source=ctx.providers.OpenStreetMap.HOT)

318

except ValueError as e:

319

print(f"Zoom level error: {e}")

320

# Retry with lower zoom

321

img, extent = ctx.bounds2img(w, s, e, n, zoom=18, ll=True)

322

```

323

324

### Graceful Fallbacks

325

326

```python

327

def robust_tile_download(w, s, e, n, zoom=12, ll=True):

328

"""Download tiles with fallback providers."""

329

providers_to_try = [

330

ctx.providers.OpenStreetMap.HOT,

331

ctx.providers.CartoDB.Positron,

332

ctx.providers.Stamen.Toner

333

]

334

335

for provider in providers_to_try:

336

try:

337

return ctx.bounds2img(w, s, e, n, zoom=zoom, ll=ll, source=provider)

338

except Exception as e:

339

print(f"Provider {provider} failed: {e}")

340

continue

341

342

raise Exception("All tile providers failed")

343

344

# Usage

345

img, extent = robust_tile_download(-74.1, 40.7, -73.9, 40.8, zoom=12)

346

```