Customization reference¶
Every decoration in AcadGIS follows the same pattern, so you can dial in as much or as little as you want:
| You pass | Meaning |
|---|---|
True / False |
on with defaults / off |
"rose" (a string) |
a style shortcut, e.g. north_arrow="rose" |
{...} (a dict) |
full control — every option below |
[a, b, c] (a list) |
per‑panel in study_area — one value per map |
So in study_area, graticule=False turns the grid off everywhere, graticule={'grid': False}
configures all panels, and graticule=[True, True, {'grid': False}] sets each panel independently.
Everything here is reachable through a single import acadgis as agis — no matplotlib imports.
Grid & ticks (graticule)¶
Independent control of the grid lines and the degree ticks/labels. Pass as graticule={...} in
plot() / study_area() (or a per‑panel list).
| Option | Values | Default | Notes |
|---|---|---|---|
grid |
True / False |
True |
draw grid lines. False keeps ticks, drops lines |
grid_color |
colour | #9aa0a6 |
grid line colour |
grid_lw |
number | 0.5 |
grid line width |
grid_alpha |
0–1 |
0.55 |
grid line opacity |
grid_style |
'-','--',':','-.', dash tuple |
'-' |
grid line dash |
square |
True / False |
True |
equal interval on both axes (square cells) |
interval |
degrees | auto | spacing for both axes |
x_interval / y_interval |
degrees | auto | per‑axis spacing (overrides interval) |
n |
int | 5 |
target number of divisions when auto |
ticks |
True / False |
True |
draw tick marks + labels |
tick_dir |
'in','out','inout' |
'out' |
tick direction (like QGIS/Excel) |
tick_len / tick_width |
number | 3.5 / 0.8 |
tick mark size |
tick_color |
colour | #333 |
tick mark colour |
minor |
True / False |
False |
minor ticks between majors |
minor_n |
int | 2 |
minor subdivisions |
sides |
subset of 'lrtb' or 'all' |
'lb' |
which sides get labels |
tick_sides |
subset of 'lrtb' or 'all' |
= sides |
which sides get tick marks |
fontsize |
number | 8 |
label size |
label_color |
colour | #333 |
label colour |
bold / italic |
True / False |
False |
label weight/style |
font |
font family | default | label font |
rotate_x / rotate_y |
degrees | 0 |
label rotation (rotate_y=90 = vertical latitude) |
# grid OFF, keep ticks, on all four sides, vertical latitude labels
agis.study_area(..., graticule={'grid': False, 'sides': 'all', 'rotate_y': 90})
# dashed teal square grid, 1° spacing, ticks pointing inward, with minor ticks
agis.plot(gdf, graticule={'grid_color': '#1b9aaa', 'grid_style': '--', 'grid_lw': 0.8,
'interval': 1.0, 'tick_dir': 'in', 'minor': True})
# bold labels, custom font, coarser ticks on just the focus map (per-panel list)
agis.study_area(..., graticule=[True, True, {'interval': 0.3, 'bold': True}])
# fully off
agis.study_area(..., graticule=False)
North arrow (north_arrow)¶
| Option | Values | Default | Notes |
|---|---|---|---|
style |
classic,minimal,pointer,rose |
classic |
arrow design |
size |
number | 0.12 |
height as a fraction of the axes |
color |
colour | theme | fill colour |
edge |
colour | none | outline colour for the arrow shapes |
label |
text | "N" |
the label |
label_color |
colour | = color |
label colour |
label_size |
number | auto | label font size |
rotation |
degrees | 0 |
rotate the whole arrow (e.g. declination) |
coords |
'axes' / 'data' |
'axes' |
placement system |
loc |
(x,y) |
(0.92, 0.88) |
position: axes fraction 0–1, or (lon,lat) if coords='data' |
agis.plot(gdf, north_arrow="rose") # style shortcut
agis.plot(gdf, north_arrow={'style': 'rose', 'size': 0.16, 'color': '#1b9aaa',
'edge': '#06222b', 'label_color': '#e63946', 'rotation': 12})
agis.plot(gdf, north_arrow={'style': 'pointer', 'coords': 'data', 'loc': (92.3, 25.0)})
agis.study_area(..., north_arrow=[True, False, {'style': 'minimal'}]) # per panel
agis.plot(gdf, north_arrow=False) # off
Scale bar (scale_bar)¶
| Option | Values | Default | Notes |
|---|---|---|---|
style |
bar,simple,stepped,double,ticks |
bar |
QGIS‑style bars |
length_km |
number | auto | real length; auto‑rounded if omitted |
units |
km,mi |
km |
label units |
size |
number | 1.0 |
scales bar + label |
color |
colour | theme | fill / line |
edge |
colour | = color |
outline |
text_color |
colour | = color |
label colour |
divisions |
int | 4 |
segments for stepped/double/ticks |
coords |
'axes' / 'data' |
'axes' |
placement system |
loc |
(x,y) |
(0.07, 0.07) |
bar's left end: axes fraction or (lon,lat) |
fontsize |
number | auto | label size |
agis.plot(gdf, scale_bar="stepped")
agis.plot(gdf, scale_bar={'style': 'double', 'divisions': 5, 'color': '#0b3b34',
'text_color': '#e63946', 'length_km': 100})
agis.plot(gdf, scale_bar={'style': 'ticks', 'coords': 'data', 'loc': (88.2, 21.4)})
agis.plot(gdf, scale_bar=False)
Region highlight (highlight_*)¶
The marked region on each parent panel. By default a single indicator (no more double box).
| Option | Values | Default | Notes |
|---|---|---|---|
highlight_style |
overlay,rect,circle |
overlay |
fill+border / rectangle / circle |
highlight_color |
colour | red | fill colour |
highlight_edge |
colour / 'none' |
= colour | border colour |
highlight_alpha |
0–1 |
0.30 |
fill opacity (0 = no fill) |
highlight_width |
number | 2.0 |
border thickness (0 = no border) |
agis.study_area(..., highlight_style='overlay', highlight_color='#2d6a4f',
highlight_edge='#3ad29f', highlight_width=3) # glowing border
agis.study_area(..., highlight_style='circle', highlight_color='#2b6cb0')
agis.study_area(..., highlight_style='overlay', highlight_alpha=0, highlight_width=0) # hide it
Connectors¶
Built‑in linking between panels, plus a wrapped agis.connect() for hand‑placed lines.
Built‑in (in study_area):
| Option | Values | Default | Notes |
|---|---|---|---|
links |
True/False |
True |
draw connector lines |
link_color |
colour | = highlight | line colour |
link_width |
number | 1.6 |
line width |
link_style |
'-','--',':','-.', dash tuple |
'-' |
line dash |
box |
True/False |
False |
draw a focus box on the parent (opt‑in) |
Custom — agis.connect(fig, a, xy_a, b, xy_b, ...):
| Arg | Values | Notes |
|---|---|---|
a, b |
panels | e.g. fig.panels[0], fig.panels[1] |
xy_a, xy_b |
(x,y) |
endpoints |
a_coords,b_coords |
'data','axes','figure' |
data=lon/lat · axes=panel 0–1 corner · figure=whole fig |
color,width,style,alpha |
— | line styling |
arrow |
True/False |
arrowhead at the b end |
fig = agis.study_area(..., links=False, box=False)
p1, p2, p3 = fig.panels[:3]
# a wedge: two lines from a panel's corners to a map point
for corner in [(1, 1), (1, 0)]:
agis.connect(fig, p2, corner, p1, (-4.0, 57.0),
a_coords='axes', b_coords='data', style=(0, (6, 3)))
# an arrowed connector between two map points
agis.connect(fig, p3, (0, 0.5), p2, (-4.2, 56.1),
a_coords='axes', b_coords='data', arrow=True, color='#e63946')
Zoom (zoom, agis.zoom_axes)¶
Zoom each map independently. > 1 zooms in, < 1 zooms out (use 0.1 steps as you like).
agis.study_area(..., zoom=[1.0, 1.3, 1.6]) # per-panel factor
agis.zoom_axes(ax, 1.5) # zoom one map in 1.5x
agis.zoom_axes(ax, 0.8, center=(90.4, 23.6)) # zoom out about a lon/lat
Oversized‑country callouts (agis.callout)¶
The Alaska/Hawaii pattern — show a far‑flung part in its own framed box, placed anywhere.
| Option | Values | Default | Notes |
|---|---|---|---|
loc |
(x0,y0,w,h) |
(0.02,0.02,0.28,0.28) |
box position+size (axes fraction) |
color / palette / terrain |
— | — | fill: single colour, AcadGIS palette, or relief |
cmap |
colormap | terrain |
terrain colormap |
edge / lw / facecolor |
— | #333/1.0/white |
the callout frame |
zoom |
number | 1.0 |
extra zoom inside the box |
title / title_size |
— | — | callout label |
usa = agis.load_boundaries("USA", "state")
ax = agis.plot(usa, palette="vibrant", scale_bar=False, north_arrow=False)
ax.set_xlim(-125, -66); ax.set_ylim(24, 50) # CONUS only
agis.callout(ax, usa[usa.NAME_1=="Alaska"], loc=(0.005,0.02,0.26,0.26),
palette="vibrant", title="Alaska")
agis.callout(ax, usa[usa.NAME_1=="Hawaii"], loc=(0.28,0.02,0.15,0.18),
palette="vibrant", title="Hawaii")
Layout & panel sizes¶
Keep the template defaults, then tweak any panel.
| Option | Values | Default | Notes |
|---|---|---|---|
template |
single,two,cascade,series,grid |
cascade |
preset layout |
uniform_panels |
True/False |
True |
equal panel boxes |
panel_scale |
{index_or_role: factor} |
— | resize specific panels |
gap |
number or (w,h) |
— | easy spacing between maps |
width_ratios / height_ratios |
list | template | manual column/row sizes |
wspace / hspace |
number | template | manual gaps |
figsize |
(w,h) |
template | whole‑figure size |
panel_scale keys accept an index (0,1,2,…, negatives ok) or a role:
country/first · region/state/second · detail/focus/last/terrain.
agis.study_area(..., panel_scale={'detail': 1.5}) # focus map 1.5x bigger
agis.study_area(..., panel_scale={2: 0.7}, gap=0.30) # panel 2 smaller, wider gaps
agis.study_area(..., width_ratios=[1, 2.4], height_ratios=[1, 1.3]) # manual
Titles inside or outside (title_inside)¶
| Option | Values | Default | Notes |
|---|---|---|---|
title_inside |
True/False or per‑panel list |
False |
move the map title inside the panel |
title_loc |
(x,y) |
(0.03, 0.96) |
inside position (axes fraction) |
title_box |
True/False |
True |
white background behind the title |
suptitle |
text | — | the figure title (always outside, on top) |
agis.study_area(..., title_inside=True) # all inside
agis.study_area(..., title_inside=[False, False, True], # only the focus
title_loc=(0.5, 0.97), title_box=False)
Colorbar (terrain panel) — colorbar¶
| Key | Values | Default | Notes |
|---|---|---|---|
loc |
right,bottom,inside |
right |
position (doesn't shrink the map) |
length |
0–1 |
0.72 |
bar length (fraction of the side) |
size |
0–1 |
0.03 |
bar thickness |
pad |
number | 0.02 |
gap from the map |
label |
text | "Elevation (m)" |
colorbar label |
show |
True/False |
True |
show/hide |
agis.study_area(..., terrain=True,
colorbar={'loc': 'bottom', 'length': 0.6, 'pad': 0.05, 'label': 'Elevation (m)'})
Standalone relief() exposes the same via legend_loc / legend_length / legend_size /
legend_pad / legend_label.
Sea / ocean (sea, agis.add_sea)¶
Show the ocean around a coastal country with one argument — no extra imports (geopandas/shapely are wrapped inside). The country's own detailed coast bounds the sea, so there are no coastline slivers; landlocked countries draw nothing.
agis.plot(gdf, sea=True) # bundled 110 m, offline
agis.plot(gdf, sea="#9ecae9") # just the colour
agis.plot(gdf, sea={"source": "ne10m", "pad": 0.35,
"labels": {"Bay of Bengal": (91.2, 21.2)}}) # crisp coast
agis.study_area(..., sea=[{"source": "ne10m"}, None, None]) # per panel
agis.add_sea(ax, country=…, …) options:
| Option | Values | Default | Notes |
|---|---|---|---|
source |
auto · ne10m · ocean |
auto |
110 m bundled · 10 m land (crisp) · 10 m ocean polygon |
color |
colour | #9ecae9 |
ocean fill |
extent / pad |
(minx,miny,maxx,maxy) / number |
view | frame; pad reveals more ocean |
background |
colour | white |
land/neighbour background |
neighbours |
True/False |
False |
fill neighbour land vs. leave white |
coastline |
True/False |
False |
draw the country coastline |
labels |
{"Bay of Bengal": (lon,lat), …} |
— | sea labels |
Data
source="ne10m"/"ocean" download Natural Earth 10 m (~3 MB) once and cache it
in ~/.acadgis/cache; source="auto" is fully offline.
Per‑panel pattern (recap)¶
Anywhere study_area takes a decoration, a list sets it per map (country → … → focus):
agis.study_area("Bangladesh",
steps=[("division","Dhaka"), ("district","Madaripur")],
template="cascade", terrain=True,
graticule=[True, True, {'grid': False, 'sides': 'all'}],
north_arrow=[True, False, {'style': 'rose'}],
scale_bar=[False, True, {'style': 'double'}],
title_inside=[False, False, True],
zoom=[1.0, 1.2, 1.4],
)
Layers — raster · vector · basemap · topography¶
Every layer is an add_*(ax, …) overlay, so it composes with plot() and any
study_area panel. Rasters are reprojected to lon/lat automatically.
Z‑order ladder (defaults, so layers stack predictably):
sea 0 · basemap/raster 1 · land polygons 5 · rivers/roads 6 · points/labels 8.
add_raster — any GeoTIFF¶
Three modes — continuous, categorical, RGB. area clips to a geometry. (needs acadgis[terrain])
# continuous (NDVI / climate / elevation)
agis.add_raster(ax, "ndvi.tif", area=gdf, cmap="YlGn", vmin=0, vmax=1,
colorbar=True, colorbar_label="NDVI", opacity=1.0)
# categorical (land cover) — classes = {value: (colour, label)}
agis.add_raster(ax, "landcover.tif", area=gdf, categorical=True,
classes={1: ("#4a90d9", "Water"), 2: ("#2a9d4a", "Forest")},
legend=True, legend_loc="lower left", legend_title="Land cover")
# true-colour
agis.add_raster(ax, "scene_rgb.tif", rgb=True)
add_layer — any vector, with label control¶
Auto‑detects polygon / line / point. labels=: None/False hide · "one"/1
single · an int top‑N · True/"all" every feature.
agis.add_layer(ax, "roads.geojson", color="#555", linewidth=0.6) # lines
agis.add_layer(ax, sites_gdf, color="#c0392b", marker="^", markersize=55, # points
labels="all", label_field="name", label_size=8,
label="Field sites", legend=True)
agis.add_layer(ax, regions, facecolor="none", edgecolor="#333") # polygons
add_basemap / add_satellite — XYZ tiles¶
Styles: satellite · osm · light · dark · terrain · toner. Set the map
extent first, then call it. (needs acadgis[basemap])
add_topography — DEM hillshade¶
agis.add_topography(ax, area=(91.7, 21.9, 92.5, 23.2), # name / bbox / GeoDataFrame
cmap="terrain", hillshade=True,
colorbar=True, colorbar_label="Elevation (m)", max_size=900)
add_cities / add_roads — curated context¶
agis.add_cities(ax, area=gdf, top=8, labels=5) # Natural Earth places, ranked
agis.add_roads(ax, area=gdf, classes=("motorway", "trunk", "primary")) # OpenStreetMap
add_landcover / add_ndvi — curated raster data (no GeoTIFF needed)¶
Fetch a real global dataset for an area automatically and render it.
# ESA WorldCover 10 m land cover (public COGs, windowed remote read) + class legend
agis.add_landcover(ax, area, year=2021)
# Sentinel-2 NDVI — least-cloudy scene in a date window, computed (NIR-Red)/(NIR+Red)
agis.add_ndvi(ax, area, start="2023-11-01", end="2024-03-01", max_cloud=10,
cmap="RdYlGn")
# the chosen scene date is on ax._acadgis_ndvi_date
Area & extras
area may be a country/region name, a (minx, miny, maxx, maxy) bbox, or a
GeoDataFrame (clips to the polygon). Both need pip install "acadgis[terrain]"
and network access.
Thematic map types¶
The full standard catalogue (0.2.0). Choropleth (choropleth()) and graduated
symbols (points(size_by=)) shipped earlier; these complete it.
Interpolated fields — isopleth & isolines¶
# sparse stations -> smooth grid (numpy Gaussian kernel; clip= masks the ocean)
Z, ext = agis.interpolate_field(lon, lat, temp, bbox=(-125, 24, -66, 50),
clip=usa, bw=6) # bw in degrees: bigger = smoother
agis.add_isopleth(ax, (Z, ext), cmap="RdYlBu_r", levels=14,
colorbar=True, colorbar_label="Temperature (°C)") # filled
agis.add_contours(ax, (Z, ext), levels=12, colors="#c1121f",
labels=True, fmt="%d°", fontsize=6) # isolines
# both also accept a bare 2-D array (+ extent=), a DEM, or a GeoTIFF path
agis.add_contours(ax, agis.load_dem(area), levels=15, fmt="%d m")
Heat map (density)¶
agis.add_heatmap(ax, lon, lat, kind="kde", weights=pop, colorbar=True) # smooth
agis.add_heatmap(ax, lon, lat, kind="hexbin", gridsize=120, bins="log") # dense events
# kind="auto" picks KDE for sparse data, hexbin for large point sets
Dot-density¶
agis.dot_density(ax, states, "population", per=100000, # 1 dot = 100 000
color="#1d3557", size=1.6, seed=0)
Bivariate choropleth¶
agis.bivariate(gdf, "income", "education", # terciles × terciles
xlabel="Income", ylabel="Education") # 3×3 palette + 2-D legend
# custom palette: a 3×3 list of colours via palette=
Cartograms¶
agis.cartogram(gdf, "population", kind="dorling", # circles ∝ value
labels="NAME_1", cmap="viridis")
agis.cartogram(gdf, "population", kind="noncontig", # regions scaled in place
cmap="YlOrRd", colorbar=True) # ghost outlines underneath
One engine, three maps
interpolate_field is shared: the same (Z, extent) grid renders as a
filled isopleth, labelled isolines, or an imshow heat surface.
Connectors (study_area links)¶
links= accepts True/False or a dict for full connector control:
agis.study_area("Bangladesh", [("division", "Dhaka"), ("district", "Gazipur")],
template="series",
links={
"single": True, # one line per hop (default: two corner lines)
"shrink": (10, -18), # trim/stretch each end, in points
# positive = shrink · negative = stretch past the end
"arrow": True, # arrowhead at the destination (deeper) end
"arrow_size": 16, # or arrow="->" / "wedge" / any matplotlib arrowstyle
"dots": True, # endpoint markers …
"dot_size": 10, # … enlarged
"dot_color": "#b30000",
"alpha": 0.9,
"pad": 0.25, # padding of the (invisible) locator box the
# corner anchors sit on — bigger = wider spread
"anchors": [("r", (0.0, 0.5))],
# where each line attaches:
# source = a corner/edge name tl · tr · bl · br · t · b · l · r · c
# or an explicit (lon, lat) point on the source panel
# target = (x, y) axes fraction on the destination panel
# a list applies to every hop; use {hop_index: [...]} per hop
"color": "#ff0000", "width": 2.2, "style": "-", "box": False,
})
For arbitrary extra lines (arrows, panel-to-panel annotations) use
agis.connect(fig, axA, (lon, lat), axB, (x, y), b_coords="axes", arrow=True).
Per-panel layers — sea, rivers, labels¶
sea, rivers and labels are scalar (all panels) or a per-panel list
[country, …, focus] — turn each on/off exactly where you want it:
agis.study_area("Bangladesh", [("division", "Dhaka"), ("district", "Gazipur")],
template="series",
sea=[True, False, False], # ocean only on the country panel
# sea=True · a colour · {"source": "ne10m", "color": "#a9d3e8"} · False
rivers=[{"color": "#2b7bba", "scale": "10m"}, # NE rivers on the first two panels
{"color": "#2b7bba", "scale": "10m"}, False],
# rivers=True · a colour · {"source": "osm"} (dense OpenStreetMap) · False
labels=[False, True, False], # region names only on the division
scale_bar=[False, True, True], # decorations are per-panel too
north_arrow=[False, {"style": "rose"}, {"style": "minimal"}],
graticule={"grid": True, "sides": "lb", "tick_dir": "in", "fontsize": 6})
Extras
add_raster/add_topography need pip install "acadgis[terrain]";
add_basemap/add_satellite need pip install "acadgis[basemap]".
add_cities/add_roads download from Natural Earth / OpenStreetMap and cache
in ~/.acadgis/cache.