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

place-mapping.mddocs/

0

# Place-based Mapping

1

2

Geocoding and mapping functionality for location-based visualizations. These capabilities combine geocoding services with tile downloading to create maps from place names and addresses.

3

4

## Capabilities

5

6

### Place Class

7

8

Geocode locations by name and automatically retrieve corresponding map tiles with integrated plotting capabilities for location-based visualizations.

9

10

```python { .api }

11

class Place:

12

"""

13

Geocode a place by name and get its map.

14

15

Parameters:

16

- search: str - Location to be searched (city, address, landmark, etc.)

17

- zoom: int or None - Zoom level for map detail (auto-calculated if None)

18

- path: str or None - Path to save raster file (no file saved if None)

19

- zoom_adjust: int or None - Adjustment to auto-calculated zoom level

20

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

21

- geocoder: geopy.geocoders object - Geocoding service (defaults to Nominatim)

22

23

Attributes:

24

- geocode: geopy object - Geocoding result with full location data

25

- s, n, e, w: float - Bounding box edges (south, north, east, west)

26

- im: ndarray - Image array of the retrieved map

27

- bbox: list - Bounding box [minX, minY, maxX, maxY] in lon/lat

28

- bbox_map: tuple - Bounding box in Web Mercator coordinates

29

- place: str - Formatted place name from geocoding result

30

- search: str - Original search string

31

- latitude, longitude: float - Center coordinates of the place

32

- zoom: int - Zoom level used for tile retrieval

33

- n_tiles: int - Number of tiles downloaded for the map

34

"""

35

36

def __init__(self, search, zoom=None, path=None, zoom_adjust=None,

37

source=None, geocoder=None): ...

38

39

def plot(self, ax=None, zoom='auto', interpolation='bilinear',

40

attribution=None):

41

"""

42

Plot the Place object on matplotlib axes.

43

44

Parameters:

45

- ax: AxesSubplot or None - Matplotlib axes (creates new figure if None)

46

- zoom: int or 'auto' - Zoom level (ignored, uses Place's zoom)

47

- interpolation: str - Image interpolation method ('bilinear', 'nearest', etc.)

48

- attribution: str or None - Attribution text (defaults to source attribution)

49

50

Returns:

51

AxesSubplot - Matplotlib axes containing the map

52

"""

53

```

54

55

**Usage Examples:**

56

57

```python

58

import contextily as ctx

59

import matplotlib.pyplot as plt

60

61

# Basic place geocoding and mapping

62

place = ctx.Place("Central Park, New York")

63

print(f"Found: {place.place}")

64

print(f"Coordinates: {place.latitude:.4f}, {place.longitude:.4f}")

65

print(f"Zoom level: {place.zoom}, Tiles: {place.n_tiles}")

66

67

# Display the map

68

place.plot()

69

plt.show()

70

71

# Custom zoom level

72

place_detailed = ctx.Place("Times Square, NYC", zoom=16)

73

place_detailed.plot()

74

plt.show()

75

76

# Save map to file while creating Place

77

place_saved = ctx.Place("Golden Gate Bridge",

78

path="golden_gate.tiff",

79

zoom=14)

80

81

# Use different tile provider

82

place_satellite = ctx.Place("Yellowstone National Park",

83

source=ctx.providers.ESRI.WorldImagery,

84

zoom=10)

85

place_satellite.plot()

86

plt.show()

87

88

# International locations

89

place_international = ctx.Place("Eiffel Tower, Paris, France")

90

print(f"Bbox: {place_international.bbox}") # [lon_min, lat_min, lon_max, lat_max]

91

place_international.plot()

92

plt.show()

93

```

94

95

### Advanced Place Usage

96

97

```python

98

import contextily as ctx

99

import geopy

100

101

# Custom geocoder configuration

102

from geopy.geocoders import Nominatim

103

custom_geocoder = Nominatim(user_agent="my_app_v1.0", timeout=10)

104

105

place = ctx.Place("1600 Pennsylvania Avenue, Washington DC",

106

geocoder=custom_geocoder,

107

zoom=15)

108

109

# Access detailed geocoding information

110

print(f"Full address: {place.geocode.address}")

111

print(f"Raw data: {place.geocode.raw}")

112

113

# Fine-tune zoom level

114

place_adjusted = ctx.Place("Statue of Liberty",

115

zoom_adjust=2) # 2 levels more detailed

116

117

# Plot on existing axes

118

fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(15, 6))

119

120

place1 = ctx.Place("San Francisco")

121

place1.plot(ax=ax1)

122

123

place2 = ctx.Place("Los Angeles")

124

place2.plot(ax=ax2)

125

126

plt.suptitle("California Cities")

127

plt.show()

128

```

129

130

### Place Data Access

131

132

```python

133

import contextily as ctx

134

import numpy as np

135

136

# Create place and access data

137

place = ctx.Place("Grand Canyon National Park")

138

139

# Geographic information

140

print(f"Center: ({place.latitude}, {place.longitude})")

141

print(f"Bounding box (lon/lat): {place.bbox}")

142

print(f"Bounding box (Web Mercator): {place.bbox_map}")

143

144

# Image data

145

print(f"Image shape: {place.im.shape}") # (height, width, bands)

146

print(f"Image data type: {place.im.dtype}")

147

148

# Use image data directly

149

import matplotlib.pyplot as plt

150

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

151

ax.imshow(place.im, extent=place.bbox_map)

152

ax.set_title(place.place)

153

plt.show()

154

155

# Combine with other geospatial data

156

# Convert to same coordinate system as needed

157

extent_4326 = place.bbox # Already in WGS84

158

extent_3857 = place.bbox_map # Web Mercator

159

```

160

161

### Deprecated Plot Function

162

163

```python { .api }

164

def plot_map(place, bbox=None, title=None, ax=None, axis_off=True,

165

latlon=True, attribution=None):

166

"""

167

Plot map of given place (deprecated).

168

169

Parameters:

170

- place: Place instance or ndarray - Place object or image array to plot

171

- bbox: tuple or None - Bounding box for display extent

172

- title: str or None - Plot title

173

- ax: AxesSubplot or None - Matplotlib axes (creates new if None)

174

- axis_off: bool - Whether to turn off axis border and ticks

175

- latlon: bool - Whether bbox is in lat/lon coordinates

176

- attribution: str or None - Attribution text

177

178

Returns:

179

AxesSubplot - Matplotlib axes containing the plot

180

181

Note: This function is deprecated. Use add_basemap or Place.plot instead.

182

"""

183

```

184

185

**Migration from plot_map:**

186

187

```python

188

import contextily as ctx

189

import warnings

190

191

# Old deprecated approach (avoid)

192

place = ctx.Place("Boston")

193

with warnings.catch_warnings():

194

warnings.simplefilter("ignore", DeprecationWarning)

195

ax = ctx.plot_map(place)

196

197

# New recommended approach

198

place = ctx.Place("Boston")

199

ax = place.plot() # Preferred method

200

```

201

202

## Geocoding Customization

203

204

### Alternative Geocoding Services

205

206

```python

207

import contextily as ctx

208

from geopy.geocoders import GoogleV3, Bing, ArcGIS

209

210

# Google Geocoding (requires API key)

211

google_geocoder = GoogleV3(api_key="your_api_key")

212

place_google = ctx.Place("Space Needle", geocoder=google_geocoder)

213

214

# Bing Geocoding (requires API key)

215

bing_geocoder = Bing(api_key="your_api_key")

216

place_bing = ctx.Place("Pike Place Market", geocoder=bing_geocoder)

217

218

# ArcGIS Geocoding (free, rate limited)

219

arcgis_geocoder = ArcGIS(timeout=10)

220

place_arcgis = ctx.Place("Mount Rainier", geocoder=arcgis_geocoder)

221

222

# Compare results

223

places = [place_google, place_bing, place_arcgis]

224

fig, axes = plt.subplots(1, 3, figsize=(18, 6))

225

226

for i, place in enumerate(places):

227

place.plot(ax=axes[i])

228

axes[i].set_title(f"{place.search} via {type(place.geocode.geocoder).__name__}")

229

230

plt.show()

231

```

232

233

### Handling Geocoding Errors

234

235

```python

236

import contextily as ctx

237

from geopy.exc import GeopyError, GeocoderTimedOut

238

239

def safe_place_creation(search_term, **kwargs):

240

"""Create Place with error handling."""

241

try:

242

return ctx.Place(search_term, **kwargs)

243

except GeopyError as e:

244

print(f"Geocoding failed for '{search_term}': {e}")

245

return None

246

except GeocoderTimedOut:

247

print(f"Geocoding timed out for '{search_term}'")

248

return None

249

except Exception as e:

250

print(f"Place creation failed for '{search_term}': {e}")

251

return None

252

253

# Usage with error handling

254

places = []

255

search_terms = [

256

"New York City",

257

"Invalid Location XYZ123", # Will fail

258

"London, England"

259

]

260

261

for term in search_terms:

262

place = safe_place_creation(term, zoom=10)

263

if place:

264

places.append(place)

265

266

# Plot successful results

267

if places:

268

fig, axes = plt.subplots(1, len(places), figsize=(5*len(places), 5))

269

if len(places) == 1:

270

axes = [axes]

271

272

for ax, place in zip(axes, places):

273

place.plot(ax=ax)

274

```

275

276

## Batch Processing

277

278

### Multiple Locations

279

280

```python

281

import contextily as ctx

282

import matplotlib.pyplot as plt

283

284

def create_place_grid(locations, cols=3):

285

"""Create a grid plot of multiple places."""

286

n_places = len(locations)

287

rows = (n_places + cols - 1) // cols

288

289

fig, axes = plt.subplots(rows, cols, figsize=(5*cols, 5*rows))

290

axes = np.array(axes).flatten() if n_places > 1 else [axes]

291

292

places = []

293

for i, location in enumerate(locations):

294

try:

295

place = ctx.Place(location, zoom=12)

296

place.plot(ax=axes[i])

297

places.append(place)

298

except Exception as e:

299

axes[i].text(0.5, 0.5, f"Failed to load\n{location}",

300

ha='center', va='center', transform=axes[i].transAxes)

301

print(f"Failed to create place for {location}: {e}")

302

303

# Hide unused subplots

304

for i in range(len(locations), len(axes)):

305

axes[i].set_visible(False)

306

307

plt.tight_layout()

308

return places

309

310

# Example usage

311

major_cities = [

312

"New York City",

313

"Los Angeles",

314

"Chicago",

315

"Houston",

316

"Phoenix",

317

"Philadelphia"

318

]

319

320

places = create_place_grid(major_cities, cols=3)

321

plt.show()

322

```

323

324

### Route Visualization

325

326

```python

327

import contextily as ctx

328

import matplotlib.pyplot as plt

329

import numpy as np

330

331

def create_route_map(start_location, end_location, zoom=10):

332

"""Create a map showing route between two locations."""

333

334

# Geocode start and end points

335

start_place = ctx.Place(start_location)

336

end_place = ctx.Place(end_location)

337

338

# Calculate combined bounding box

339

all_lons = [start_place.longitude, end_place.longitude]

340

all_lats = [start_place.latitude, end_place.latitude]

341

342

bbox_combined = [

343

min(all_lons) - 0.1, # west

344

min(all_lats) - 0.1, # south

345

max(all_lons) + 0.1, # east

346

max(all_lats) + 0.1 # north

347

]

348

349

# Download map for combined area

350

img, extent = ctx.bounds2img(*bbox_combined, zoom=zoom, ll=True)

351

352

# Create plot

353

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

354

ax.imshow(img, extent=extent)

355

356

# Convert coordinates to Web Mercator for plotting

357

import mercantile as mt

358

start_x, start_y = mt.xy(start_place.longitude, start_place.latitude)

359

end_x, end_y = mt.xy(end_place.longitude, end_place.latitude)

360

361

# Plot points and line

362

ax.scatter([start_x], [start_y], c='green', s=100, label=start_location, zorder=5)

363

ax.scatter([end_x], [end_y], c='red', s=100, label=end_location, zorder=5)

364

ax.plot([start_x, end_x], [start_y, end_y], 'b--', linewidth=2, alpha=0.7, zorder=4)

365

366

ax.legend()

367

ax.set_title(f"Route: {start_location} to {end_location}")

368

plt.show()

369

370

return start_place, end_place

371

372

# Example usage

373

start, end = create_route_map("San Francisco", "Los Angeles")

374

```

375

376

## Integration with Other Libraries

377

378

### GeoPandas Integration

379

380

```python

381

import contextily as ctx

382

import geopandas as gpd

383

import matplotlib.pyplot as plt

384

385

# Create place and convert to GeoDataFrame

386

place = ctx.Place("Washington DC", zoom=12)

387

388

# Create point geometry for the place center

389

from shapely.geometry import Point

390

point = Point(place.longitude, place.latitude)

391

gdf = gpd.GeoDataFrame([{'name': place.place, 'geometry': point}], crs='EPSG:4326')

392

393

# Convert to Web Mercator for basemap overlay

394

gdf_3857 = gdf.to_crs(epsg=3857)

395

396

# Plot with basemap

397

ax = gdf_3857.plot(figsize=(10, 8), color='red', markersize=100)

398

ctx.add_basemap(ax, source=ctx.providers.OpenStreetMap.HOT)

399

plt.title(f"Location: {place.place}")

400

plt.show()

401

```

402

403

### Folium Integration

404

405

```python

406

import contextily as ctx

407

import folium

408

409

# Geocode location

410

place = ctx.Place("Central Park, NYC")

411

412

# Create folium map centered on the place

413

m = folium.Map(

414

location=[place.latitude, place.longitude],

415

zoom_start=place.zoom

416

)

417

418

# Add marker

419

folium.Marker(

420

[place.latitude, place.longitude],

421

popup=place.place,

422

tooltip=f"Zoom: {place.zoom}, Tiles: {place.n_tiles}"

423

).add_to(m)

424

425

# Add bounding box

426

folium.Rectangle(

427

bounds=[[place.bbox[1], place.bbox[0]], [place.bbox[3], place.bbox[2]]],

428

color='red',

429

fill=False

430

).add_to(m)

431

432

# Display map

433

m.save('place_map.html')

434

```

435

436

## Performance and Caching

437

438

### Optimizing Place Creation

439

440

```python

441

import contextily as ctx

442

443

# Set persistent cache for place images

444

ctx.set_cache_dir('~/contextily_places_cache')

445

446

# Reuse geocoding results

447

class PlaceCache:

448

def __init__(self):

449

self.geocode_cache = {}

450

451

def get_place(self, search, **kwargs):

452

if search in self.geocode_cache:

453

# Reuse geocoding result

454

cached_geocode = self.geocode_cache[search]

455

place = ctx.Place.__new__(ctx.Place)

456

place.geocode = cached_geocode

457

place.search = search

458

# Initialize other attributes...

459

place._get_map()

460

return place

461

else:

462

# Create new place and cache geocoding

463

place = ctx.Place(search, **kwargs)

464

self.geocode_cache[search] = place.geocode

465

return place

466

467

# Usage

468

cache = PlaceCache()

469

place1 = cache.get_place("Paris, France") # First time: geocodes

470

place2 = cache.get_place("Paris, France") # Second time: uses cache

471

```

472

473

### Bulk Location Processing

474

475

```python

476

import contextily as ctx

477

from concurrent.futures import ThreadPoolExecutor

478

import time

479

480

def create_place_safe(location_data):

481

"""Thread-safe place creation."""

482

location, zoom = location_data

483

try:

484

place = ctx.Place(location, zoom=zoom)

485

return place

486

except Exception as e:

487

print(f"Failed to create place for {location}: {e}")

488

return None

489

490

def batch_create_places(locations, max_workers=3):

491

"""Create multiple places in parallel (be respectful of geocoding services)."""

492

location_data = [(loc, 10) for loc in locations]

493

494

places = []

495

with ThreadPoolExecutor(max_workers=max_workers) as executor:

496

results = executor.map(create_place_safe, location_data)

497

places = [place for place in results if place is not None]

498

499

return places

500

501

# Example usage (be mindful of geocoding service rate limits)

502

locations = ["New York", "Boston", "Philadelphia", "Washington DC"]

503

places = batch_create_places(locations, max_workers=2)

504

505

# Plot results

506

if places:

507

fig, axes = plt.subplots(2, 2, figsize=(12, 12))

508

axes = axes.flatten()

509

510

for i, place in enumerate(places[:4]):

511

place.plot(ax=axes[i])

512

513

plt.tight_layout()

514

plt.show()

515

```