AcadGIS 0.1.4 — layer gallery (manual check)¶
Every layer we built, each on the region that shows it best, eye-catching colours, fully commented. 10 layer functions in 0.1.4:
| # | function | what | region here |
|---|---|---|---|
| 1 | plot + highlight_style |
styled admin map, highlight a region | 🇧🇷 Brazil |
| 2 | add_basemap / add_satellite |
XYZ tiles (6 styles) | 🇦🇪 Dubai |
| 3 | add_topography |
DEM hillshade + hypsometry | 🇨🇭 Swiss Alps |
| 4 | add_landcover |
ESA WorldCover 10 m (curated) | 🇨🇭 Switzerland |
| 5 | add_ndvi |
Sentinel-2 NDVI (curated) | 🇪🇬 Nile / Luxor |
| 6 | add_raster (rgb) |
any GeoTIFF — true colour | 🇮🇹 Venice |
| 7 | add_layer |
any vector (poly/line/point) + labels | 🇯🇵 Japan |
| 8 | add_cities |
Natural Earth places, ranked | 🇪🇺 Europe |
| 9 | add_roads |
OpenStreetMap roads | 🇫🇷 Paris |
Continuous & categorical add_raster are also exercised by §3–5 (which call it internally). Network is needed for §2–6, §8–9. Only import acadgis as agis is needed (§6 adds rioxarray/requests for the demo fetch).
Bonus — 🇧🇩 Bangladesh field-research set (§10–13): your-own-data raster (numpy → GeoTIFF), categorical with custom classes, study sites over satellite, and a composed divisions + rivers + cities map.
import acadgis as agis
print("AcadGIS", agis.__version__)
AcadGIS 0.1.4
1 · plot() + highlight_style — 🇧🇷 Brazil¶
# plot() + highlight_style — Brazil (big, colourful states).
br = agis.load_boundaries("Brazil", "state") # 27 states (GADM adm1)
agis.plot(
br,
palette="vibrant", # eye-catching qualitative palette
title="Brazil — states (Amazonas highlighted)",
highlight="Amazonas", # name (or a list of names)
highlight_style="overlay", # fill · overlay · rect · circle
highlight_color="#ffd000", highlight_edge="#b30000",
highlight_alpha=0.45, highlight_width=2.2,
graticule={"grid": True, "sides": "lb", "grid_alpha": 0.25, "fontsize": 7},
north_arrow={"style": "rose"}, scale_bar={"style": "double"},
figsize=(9, 9),
)
agis.show()
2 · add_basemap / add_satellite — 🇦🇪 Dubai¶
# add_satellite — Palm Jumeirah, Dubai (iconic from space).
DUBAI = (55.10, 25.05, 55.185, 25.135) # (minx, miny, maxx, maxy)
fig, ax = agis.plt.subplots(figsize=(9, 8))
ax.set_xlim(DUBAI[0], DUBAI[2]); ax.set_ylim(DUBAI[1], DUBAI[3])
agis.add_satellite(ax) # = add_basemap(style="satellite")
ax.set_title("add_satellite — Palm Jumeirah, Dubai", fontsize=12, fontweight="bold")
ax.set_xticks([]); ax.set_yticks([]); agis.show()
# All six basemap styles over the same spot.
styles = ["satellite", "osm", "light", "dark", "terrain", "toner"]
fig, axes = agis.plt.subplots(2, 3, figsize=(13, 7))
for sty, ax in zip(styles, axes.ravel()):
ax.set_xlim(DUBAI[0], DUBAI[2]); ax.set_ylim(DUBAI[1], DUBAI[3])
agis.add_basemap(ax, style=sty)
ax.set_title(sty, fontsize=9, fontweight="bold"); ax.set_xticks([]); ax.set_yticks([])
fig.suptitle("add_basemap — 6 tile styles", fontsize=13, fontweight="bold")
agis.show()
3 · add_topography — 🇨🇭 Swiss Alps¶
# add_topography — Swiss Alps (dramatic relief).
ALPS = (7.55, 45.85, 8.25, 46.45) # Jungfrau / Interlaken
fig, ax = agis.plt.subplots(figsize=(9, 8))
ax.set_xlim(ALPS[0], ALPS[2]); ax.set_ylim(ALPS[1], ALPS[3])
agis.add_topography(
ax, area=ALPS,
cmap="terrain", hillshade=True, # hypsometric tint + shaded relief
colorbar=True, colorbar_label="Elevation (m)",
max_size=900, # DEM resolution cap (speed vs detail)
)
ax.set_title("add_topography — Swiss Alps (Jungfrau)", fontsize=12, fontweight="bold")
agis.show()
4 · add_landcover — 🇨🇭 Switzerland¶
# add_landcover — Switzerland (forest, grassland, snow, water, built-up).
CH = (7.2, 46.0, 9.2, 47.3) # central Switzerland (multi-tile merge)
fig, ax = agis.plt.subplots(figsize=(10, 8))
ax.set_xlim(CH[0], CH[2]); ax.set_ylim(CH[1], CH[3])
agis.add_landcover(ax, CH, year=2021) # real ESA WorldCover 10 m + class legend
ax.set_title("add_landcover — Switzerland (ESA WorldCover 10 m)", fontsize=12, fontweight="bold")
ax.set_xticks([]); ax.set_yticks([]); agis.show()
5 · add_ndvi — 🇪🇬 Nile at Luxor¶
# add_ndvi — the Nile at Luxor (green crops as a ribbon through desert).
LUXOR = (32.55, 25.60, 32.95, 25.95)
fig, ax = agis.plt.subplots(figsize=(8.5, 8))
ax.set_xlim(LUXOR[0], LUXOR[2]); ax.set_ylim(LUXOR[1], LUXOR[3])
agis.add_ndvi(ax, LUXOR, start="2023-01-01", end="2024-12-31", # least-cloudy scene in window
max_cloud=5, cmap="RdYlGn")
ax.set_title(f"add_ndvi — Nile at Luxor (Sentinel-2 {ax._acadgis_ndvi_date})",
fontsize=12, fontweight="bold")
ax.set_xticks([]); ax.set_yticks([]); agis.show()
6 · add_raster (rgb) — 🇮🇹 Venice true colour¶
# add_raster (rgb=True) — Venice true-colour from a Sentinel-2 "visual" COG.
import requests, rioxarray
from rasterio.warp import transform_bounds
VENICE = (12.30, 45.40, 12.42, 45.47)
body = {"collections": ["sentinel-2-l2a"], "bbox": list(VENICE),
"datetime": "2023-04-01T00:00:00Z/2024-09-30T00:00:00Z",
"query": {"eo:cloud_cover": {"lt": 5}}, "limit": 40}
feats = requests.post("https://earth-search.aws.element84.com/v1/search",
json=body, timeout=60).json()["features"]
feats.sort(key=lambda f: f["properties"]["eo:cloud_cover"])
href = feats[0]["assets"]["visual"]["href"] # 3-band true-colour COG (UTM)
date = feats[0]["properties"]["datetime"][:10]
da = rioxarray.open_rasterio(href)
bx = transform_bounds("EPSG:4326", da.rio.crs, *VENICE)
da = da.rio.clip_box(*bx) # windowed read of just Venice
fig, ax = agis.plt.subplots(figsize=(9, 8))
agis.add_raster(ax, da, rgb=True) # generic add_raster, RGB mode
ax.set_title(f"add_raster (rgb) — Venice true colour, S-2 {date}", fontsize=12, fontweight="bold")
ax.set_xticks([]); ax.set_yticks([]); agis.show()
7 · add_layer — 🇯🇵 Japan (polygons + lines + points)¶
# add_layer — Japan: prefectures (polygons) + rivers (lines) + cities (points).
jp = agis.load_boundaries("Japan", "province") # 47 prefectures
fig, ax = agis.plt.subplots(figsize=(9, 9))
agis.plot(jp, ax=ax, palette="pastel", graticule=False, north_arrow=False, scale_bar=False)
agis.add_layer(ax, agis.load_rivers(scale="10m"), area=jp, # any vector -> lines
color="#2b7bba", linewidth=0.8, label="Rivers")
agis.add_layer(ax, agis.load_places(), area=jp, # points + labels
labels=5, label_field="name", rank_field="pop", # label the 5 biggest
color="#c0392b", markersize=40, label_size=8, label="Cities")
ax.set_xlim(128, 146); ax.set_ylim(30.5, 46) # main islands (skip far Ryukyu/Ogasawara)
ax.set_title("add_layer — Japan: prefectures + rivers + cities", fontsize=12, fontweight="bold")
ax.legend(loc="upper left", fontsize=8); agis.show()
8 · add_cities — 🇪🇺 Europe¶
# add_cities — Europe (ranked by population, label control).
EUR = (-10, 36, 28, 60)
fig, ax = agis.plt.subplots(figsize=(11, 9))
ax.set_xlim(EUR[0], EUR[2]); ax.set_ylim(EUR[1], EUR[3])
agis.add_basemap(ax, style="light", alpha=0.9)
agis.add_cities(ax, top=25, labels=12, # show 25 biggest, label the top 12
color="#d1495b", markersize=30, label_color="#111", label_size=8)
ax.set_title("add_cities — Europe (top 25, labelled top 12)", fontsize=12, fontweight="bold")
ax.set_xticks([]); ax.set_yticks([]); agis.show()
9 · add_roads — 🇫🇷 Paris¶
# add_roads — Paris (radial boulevards), OSM widths by class.
PARIS = (2.24, 48.81, 2.43, 48.91)
fig, ax = agis.plt.subplots(figsize=(9, 8.5))
ax.set_xlim(PARIS[0], PARIS[2]); ax.set_ylim(PARIS[1], PARIS[3])
agis.add_basemap(ax, style="light")
agis.add_roads(ax, classes=("motorway", "trunk", "primary", "secondary"),
color="#e63946", by_class=True) # width scales with road class
agis.add_cities(ax, top=1, labels="one", color="#111", label_color="#111", markersize=45)
ax.set_title("add_roads — Paris (OSM, by class)", fontsize=12, fontweight="bold")
ax.set_xticks([]); ax.set_yticks([]); agis.show()
🇧🇩 Bonus — Bangladesh field-research set¶
Practical patterns: your own raster (numpy → GeoTIFF), study sites over satellite, and a composed thematic map.
10 · add_raster — your own data (continuous field)¶
# add_raster — bring your OWN data: build a raster from a numpy array.
import numpy as np, rasterio, tempfile, os
from rasterio.transform import from_bounds
bd0 = agis.load_boundaries("Bangladesh", "country")
bd1 = agis.load_boundaries("Bangladesh", "division")
w, s, e, n = bd0.total_bounds
W = H = 480
LON, LAT = np.meshgrid(np.linspace(w, e, W), np.linspace(n, s, H))
# a smooth synthetic field (swap in any (H,W) array — model output, interpolation, …)
field = np.clip(0.55 + 0.25*np.cos(np.radians((LAT-23)*6)) + 0.20*np.sin(np.radians((LON-90)*5))
+ 0.18*np.exp(-(((LON-89.5)**2+(LAT-24.8)**2)/1.2))
- 0.22*np.exp(-(((LON-90.4)**2+(LAT-23.8)**2)/0.25)), 0, 1).astype("float32")
tif = os.path.join(tempfile.gettempdir(), "bd_field.tif")
with rasterio.open(tif, "w", driver="GTiff", height=H, width=W, count=1, dtype="float32",
crs="EPSG:4326", transform=from_bounds(w, s, e, n, W, H), nodata=-9999) as d:
d.write(field, 1)
fig, ax = agis.plt.subplots(figsize=(8, 9))
agis.add_raster(ax, tif, area=bd0, cmap="YlGn", vmin=0, vmax=1,
colorbar=True, colorbar_label="value (your raster)")
agis.add_layer(ax, bd1, facecolor="none", edgecolor="#555", linewidth=0.6)
ax.set_xlim(w, e); ax.set_ylim(s, n)
ax.set_title("add_raster — your own data (continuous field)", fontsize=12, fontweight="bold")
agis.show()
11 · add_raster — categorical (your own classes)¶
# add_raster — categorical with your OWN classes={value:(colour, label)}.
lc = np.full((H, W), 3, "uint8") # 3 cropland
lc[field > 0.72] = 4 # 4 forest
lc[(field > 0.45) & (field <= 0.55)] = 5 # 5 wetland
lc[field < 0.32] = 1 # 1 water
lc[np.exp(-(((LON-90.4)**2+(LAT-23.8)**2)/0.18)) > 0.5] = 2 # 2 built-up
lctif = os.path.join(tempfile.gettempdir(), "bd_lc.tif")
with rasterio.open(lctif, "w", driver="GTiff", height=H, width=W, count=1, dtype="uint8",
crs="EPSG:4326", transform=from_bounds(w, s, e, n, W, H), nodata=0) as d:
d.write(lc, 1)
CLASSES = {1: ("#4a90d9", "Water"), 2: ("#d1495b", "Built-up"), 3: ("#e9d8a6", "Cropland"),
4: ("#2a9d4a", "Forest"), 5: ("#76c893", "Wetland")}
fig, ax = agis.plt.subplots(figsize=(8, 9))
agis.add_raster(ax, lctif, area=bd0, categorical=True, classes=CLASSES, legend=True)
agis.add_layer(ax, bd1, facecolor="none", edgecolor="#333", linewidth=0.5)
ax.set_xlim(w, e); ax.set_ylim(s, n)
ax.set_title("add_raster — categorical (your own classes)", fontsize=12, fontweight="bold")
agis.show()
12 · add_basemap + field study sites — Gazipur¶
# add_basemap + study sites — the field-research workflow (sites over satellite).
gz = agis.load_boundaries("Bangladesh", "district", within="Dhaka")
gz = gz[gz["NAME_2"] == "Gazipur"]
gw, gs2, ge, gn = gz.total_bounds
rng = np.random.default_rng(3)
xs = gw + (ge - gw) * rng.uniform(.25, .75, 7)
ys = gs2 + (gn - gs2) * rng.uniform(.30, .75, 7)
sites = agis.gpd.GeoDataFrame({"id": [f"S{i+1}" for i in range(7)],
"geometry": agis.gpd.points_from_xy(xs, ys)}, crs="EPSG:4326")
fig, ax = agis.plt.subplots(figsize=(8.5, 8))
ax.set_xlim(gw - .03, ge + .03); ax.set_ylim(gs2 - .03, gn + .03)
agis.add_satellite(ax)
agis.add_layer(ax, gz, facecolor="none", edgecolor="#ffd000", linewidth=2.2)
agis.add_layer(ax, sites, color="#ff2e63", markersize=85, edgecolor="white",
labels="all", label_field="id", label_color="white", label_size=8,
label="Field sites", legend=True)
ax.set_title("add_basemap (satellite) + field sites — Gazipur", fontsize=12, fontweight="bold")
ax.set_xticks([]); ax.set_yticks([]); agis.show()
13 · add_layer — composed thematic map (Bangladesh)¶
# add_layer — composed thematic map: divisions + rivers + ranked cities.
fig, ax = agis.plt.subplots(figsize=(8.5, 9))
agis.plot(bd1, ax=ax, palette="pastel", graticule=False, north_arrow=False, scale_bar=False)
agis.add_layer(ax, agis.load_rivers(scale="10m"), area=bd0, color="#2b7bba",
linewidth=0.9, label="Rivers")
agis.add_cities(ax, area=bd0, top=6, labels="all", color="#111", marker="s",
markersize=45, label_color="#111")
ax.set_xlim(w, e); ax.set_ylim(s, n)
ax.legend(loc="upper left", fontsize=8)
ax.set_title("add_layer — Bangladesh: divisions + rivers + cities", fontsize=12, fontweight="bold")
agis.show()
🇧🇩 Real-data Bangladesh trio¶
The same curated layers as §3–5, here on Bangladesh: real land cover & NDVI over Dhaka, and topography over the Chittagong Hill Tracts.
14 · add_landcover — Dhaka (real ESA WorldCover)¶
# add_landcover — real ESA WorldCover 10 m for Dhaka (urban core in red).
DHK = (90.28, 23.62, 90.55, 23.95)
dhk = agis.load_boundaries("Bangladesh", "district", within="Dhaka")
fig, ax = agis.plt.subplots(figsize=(8.5, 8))
ax.set_xlim(DHK[0], DHK[2]); ax.set_ylim(DHK[1], DHK[3])
agis.add_landcover(ax, DHK, year=2021) # real 10 m land cover + class legend
agis.add_layer(ax, dhk, facecolor="none", edgecolor="#111", linewidth=0.7)
ax.set_title("add_landcover — Dhaka (ESA WorldCover 10 m)", fontsize=12, fontweight="bold")
ax.set_xticks([]); ax.set_yticks([]); agis.show()
15 · add_ndvi — Dhaka (real Sentinel-2)¶
# add_ndvi — real Sentinel-2 NDVI for Dhaka.
fig, ax = agis.plt.subplots(figsize=(8.5, 8))
ax.set_xlim(DHK[0], DHK[2]); ax.set_ylim(DHK[1], DHK[3])
agis.add_ndvi(ax, DHK, start="2024-01-01", end="2024-04-01", max_cloud=8, cmap="RdYlGn")
agis.add_layer(ax, dhk, facecolor="none", edgecolor="#111", linewidth=0.7)
ax.set_title(f"add_ndvi — Dhaka (Sentinel-2 {ax._acadgis_ndvi_date})",
fontsize=12, fontweight="bold")
ax.set_xticks([]); ax.set_yticks([]); agis.show()
16 · add_topography — Chittagong Hill Tracts¶
# add_topography — Chittagong Hill Tracts (Bangladesh's hill country).
CHT = (91.7, 21.9, 92.5, 23.2)
fig, ax = agis.plt.subplots(figsize=(8, 8.5))
ax.set_xlim(CHT[0], CHT[2]); ax.set_ylim(CHT[1], CHT[3])
agis.add_topography(ax, area=CHT, cmap="terrain", hillshade=True,
colorbar=True, colorbar_label="Elevation (m)", max_size=900)
ax.set_title("add_topography — Chittagong Hill Tracts", fontsize=12, fontweight="bold")
agis.show()