AcadGIS — Quickstart¶
Every map is shown twice: first a one-liner, then the same map fully customized — every relevant parameter set and commented, so you can copy a line and tweak it. AcadGIS 0.1.2.
In [1]:
Copied!
import acadgis as agis
print('AcadGIS', agis.__version__)
import acadgis as agis
print('AcadGIS', agis.__version__)
AcadGIS 0.2.0
In [12]:
Copied!
world = agis.load_world()
world = agis.load_world()
In [13]:
Copied!
agis.plot(world, column='CONTINENT', palette='vibrant', legend=True,
title='World — by continent',
graticule={'grid': False, 'sides': 'lb'},
north_arrow=False, scale_bar=False);
agis.plot(world, column='CONTINENT', palette='vibrant', legend=True,
title='World — by continent',
graticule={'grid': False, 'sides': 'lb'},
north_arrow=False, scale_bar=False);
In [14]:
Copied!
agis.plot(world, palette='pastel', title='World — ocean effect',
sea={'source': 'auto', 'color': '#a9d3e8', 'set_view': False},
graticule={'grid': False, 'sides': 'lb'},
north_arrow=False, scale_bar=False);
agis.plot(world, palette='pastel', title='World — ocean effect',
sea={'source': 'auto', 'color': '#a9d3e8', 'set_view': False},
graticule={'grid': False, 'sides': 'lb'},
north_arrow=False, scale_bar=False);
In [15]:
Copied!
rng = agis.np.random.default_rng(7)
w = world.copy(); w['index'] = rng.uniform(0, 100, len(w)).round(1)
fig, ax = agis.plt.subplots(figsize=(14, 7)); ax.set_facecolor('#0b1b2a')
w.plot(ax=ax, column='index', cmap='inferno', edgecolor='white', linewidth=0.2,
legend=True, legend_kwds={'label': 'Index', 'shrink': 0.6})
ax.set_title('World — choropleth heatmap (synthetic index)', fontsize=14, fontweight='bold')
ax.set_xticks([]); ax.set_yticks([]); agis.show()
rng = agis.np.random.default_rng(7)
w = world.copy(); w['index'] = rng.uniform(0, 100, len(w)).round(1)
fig, ax = agis.plt.subplots(figsize=(14, 7)); ax.set_facecolor('#0b1b2a')
w.plot(ax=ax, column='index', cmap='inferno', edgecolor='white', linewidth=0.2,
legend=True, legend_kwds={'label': 'Index', 'shrink': 0.6})
ax.set_title('World — choropleth heatmap (synthetic index)', fontsize=14, fontweight='bold')
ax.set_xticks([]); ax.set_yticks([]); agis.show()
In [16]:
Copied!
w = world.copy()
lat = w.geometry.representative_point().y
w['greenness'] = (1 - (lat.abs() / 90)).clip(0, 1).round(2)
fig, ax = agis.plt.subplots(figsize=(14, 7)); ax.set_facecolor('#cfe0ea')
w.plot(ax=ax, column='greenness', cmap='YlGn', edgecolor='#7f8c8d', linewidth=0.2,
legend=True, legend_kwds={'label': 'Greenness (synthetic)', 'shrink': 0.6})
ax.set_title('World — vegetation effect (greenness by latitude)', fontsize=14, fontweight='bold')
ax.set_xticks([]); ax.set_yticks([]); agis.show()
w = world.copy()
lat = w.geometry.representative_point().y
w['greenness'] = (1 - (lat.abs() / 90)).clip(0, 1).round(2)
fig, ax = agis.plt.subplots(figsize=(14, 7)); ax.set_facecolor('#cfe0ea')
w.plot(ax=ax, column='greenness', cmap='YlGn', edgecolor='#7f8c8d', linewidth=0.2,
legend=True, legend_kwds={'label': 'Greenness (synthetic)', 'shrink': 0.6})
ax.set_title('World — vegetation effect (greenness by latitude)', fontsize=14, fontweight='bold')
ax.set_xticks([]); ax.set_yticks([]); agis.show()
In [17]:
Copied!
# --- sparse synthetic samples (replace with your own lon, lat, value) ---
rng = agis.np.random.default_rng(3)
n = 70
slon = rng.uniform(-170, 170, n)
slat = rng.uniform(-55, 78, n)
sval = agis.np.cos(agis.np.radians(slat)) + rng.normal(0, 0.25, n)
# --- regular grid covering the world ---
gx, gy = agis.np.meshgrid(agis.np.linspace(-180, 180, 320),
agis.np.linspace(-58, 84, 170))
# --- Gaussian-kernel interpolation (numpy only, no SciPy) ---
bw = 20.0 # bandwidth in degrees: bigger = smoother
dx = gx[..., None] - slon
dy = gy[..., None] - slat
wts = agis.np.exp(-(dx * dx + dy * dy) / (2 * bw * bw))
gz = (wts * sval).sum(-1) / (wts.sum(-1) + 1e-9)
# --- mask grid cells that fall in the ocean (outside any country) -> NaN ---
pts = agis.gpd.GeoDataFrame(geometry=agis.gpd.points_from_xy(gx.ravel(), gy.ravel()), crs=4326)
on_land = agis.gpd.sjoin(pts, world[['geometry']], predicate='within',
how='left')['index_right'].notna().values
gz = gz.ravel(); gz[~on_land] = agis.np.nan; gz = gz.reshape(gx.shape)
# --- draw the field + country outlines ---
fig, ax = agis.plt.subplots(figsize=(13, 7)); ax.set_facecolor('#aac9e0')
im = ax.imshow(gz, extent=(-180, 180, -58, 84), origin='lower',
cmap='jet', aspect='auto') # try 'turbo', 'RdYlBu_r', 'viridis'
world.boundary.plot(ax=ax, color='white', linewidth=0.25)
fig.colorbar(im, ax=ax, shrink=0.6, label='Interpolated value')
ax.set_xlabel('Longitude'); ax.set_ylabel('Latitude')
ax.set_title('World — interpolated gradient (clipped to land)', fontsize=14, fontweight='bold')
agis.show()
# --- sparse synthetic samples (replace with your own lon, lat, value) ---
rng = agis.np.random.default_rng(3)
n = 70
slon = rng.uniform(-170, 170, n)
slat = rng.uniform(-55, 78, n)
sval = agis.np.cos(agis.np.radians(slat)) + rng.normal(0, 0.25, n)
# --- regular grid covering the world ---
gx, gy = agis.np.meshgrid(agis.np.linspace(-180, 180, 320),
agis.np.linspace(-58, 84, 170))
# --- Gaussian-kernel interpolation (numpy only, no SciPy) ---
bw = 20.0 # bandwidth in degrees: bigger = smoother
dx = gx[..., None] - slon
dy = gy[..., None] - slat
wts = agis.np.exp(-(dx * dx + dy * dy) / (2 * bw * bw))
gz = (wts * sval).sum(-1) / (wts.sum(-1) + 1e-9)
# --- mask grid cells that fall in the ocean (outside any country) -> NaN ---
pts = agis.gpd.GeoDataFrame(geometry=agis.gpd.points_from_xy(gx.ravel(), gy.ravel()), crs=4326)
on_land = agis.gpd.sjoin(pts, world[['geometry']], predicate='within',
how='left')['index_right'].notna().values
gz = gz.ravel(); gz[~on_land] = agis.np.nan; gz = gz.reshape(gx.shape)
# --- draw the field + country outlines ---
fig, ax = agis.plt.subplots(figsize=(13, 7)); ax.set_facecolor('#aac9e0')
im = ax.imshow(gz, extent=(-180, 180, -58, 84), origin='lower',
cmap='jet', aspect='auto') # try 'turbo', 'RdYlBu_r', 'viridis'
world.boundary.plot(ax=ax, color='white', linewidth=0.25)
fig.colorbar(im, ax=ax, shrink=0.6, label='Interpolated value')
ax.set_xlabel('Longitude'); ax.set_ylabel('Latitude')
ax.set_title('World — interpolated gradient (clipped to land)', fontsize=14, fontweight='bold')
agis.show()
In [18]:
Copied!
rng = agis.np.random.default_rng(11)
w = world.copy()
w['value'] = rng.uniform(5, 37, len(w)).round(1)
w.loc[w.sample(frac=0.12, random_state=1).index, 'value'] = agis.np.nan # some no-data
fig, ax = agis.plt.subplots(figsize=(14, 7.5)); ax.set_facecolor('#26303b')
w.plot(ax=ax, column='value', cmap='RdYlGn_r', # try 'OrRd', 'viridis'
scheme='user_defined', classification_kwds={'bins': [10, 15, 20, 25, 37]},
edgecolor='#26303b', linewidth=0.4, legend=True,
legend_kwds={'loc': 'lower left', 'fontsize': 8},
missing_kwds={'color': 'white', 'label': 'No data'})
# --- annotate a few countries with a leader line ---
for name in ['United States', 'Brazil', 'China', 'India', 'Australia']:
r = w[w['NAME_0'] == name]
if r.empty or agis.pd.isna(r['value'].iloc[0]):
continue
p = r.geometry.representative_point().iloc[0]
ax.annotate(f"{name} {r['value'].iloc[0]:g}", xy=(p.x, p.y),
xytext=(p.x + 18, p.y + 14), color='white', fontsize=8,
arrowprops=dict(arrowstyle='-', color='white', lw=0.6))
ax.set_xlim(-180, 180); ax.set_ylim(-60, 88)
ax.set_title('World — classed choropleth with labels', color='white', fontsize=14, fontweight='bold')
ax.set_xticks([]); ax.set_yticks([]); agis.show()
rng = agis.np.random.default_rng(11)
w = world.copy()
w['value'] = rng.uniform(5, 37, len(w)).round(1)
w.loc[w.sample(frac=0.12, random_state=1).index, 'value'] = agis.np.nan # some no-data
fig, ax = agis.plt.subplots(figsize=(14, 7.5)); ax.set_facecolor('#26303b')
w.plot(ax=ax, column='value', cmap='RdYlGn_r', # try 'OrRd', 'viridis'
scheme='user_defined', classification_kwds={'bins': [10, 15, 20, 25, 37]},
edgecolor='#26303b', linewidth=0.4, legend=True,
legend_kwds={'loc': 'lower left', 'fontsize': 8},
missing_kwds={'color': 'white', 'label': 'No data'})
# --- annotate a few countries with a leader line ---
for name in ['United States', 'Brazil', 'China', 'India', 'Australia']:
r = w[w['NAME_0'] == name]
if r.empty or agis.pd.isna(r['value'].iloc[0]):
continue
p = r.geometry.representative_point().iloc[0]
ax.annotate(f"{name} {r['value'].iloc[0]:g}", xy=(p.x, p.y),
xytext=(p.x + 18, p.y + 14), color='white', fontsize=8,
arrowprops=dict(arrowstyle='-', color='white', lw=0.6))
ax.set_xlim(-180, 180); ax.set_ylim(-60, 88)
ax.set_title('World — classed choropleth with labels', color='white', fontsize=14, fontweight='bold')
ax.set_xticks([]); ax.set_yticks([]); agis.show()
In [3]:
Copied!
Path = agis.plt.matplotlib.path.Path
Line2D = agis.plt.Line2D
# reach matplotlib helpers through agis — no separate import
rng = agis.np.random.default_rng(7)
world = agis.load_world()
# teardrop map-pin marker (tip points down)
pin = Path([(0,-1.0),(-0.86,0.05),(-0.7,1.0),(0,1.0),(0.7,1.0),(0.86,0.05),(0,-1.0)],
[Path.MOVETO,Path.CURVE4,Path.CURVE4,Path.CURVE4,Path.CURVE4,Path.CURVE4,Path.CURVE4])
# category -> (colour, [region centres (lon, lat, spread, count)])
CATS = {
'English': ('#f4d03f', [(-98,39,9,140),(-1.5,53,3,60),(-100,56,8,40),(134,-25,9,50),(172,-42,2,15),(78,22,7,60)]),
'Spanish': ('#e74c3c', [(-102,23,5,70),(-74,4,4,40),(-76,-10,3,30),(-64,-36,5,50),(-4,40,3,40),(-71,-35,2,20)]),
'Portuguese': ('#e67e22', [(-50,-12,8,90),(-8.2,39.6,1.5,18),(18,-12,4,20)]),
'French': ('#5dade2', [(2.4,47,3,55),(-5,12,6,40),(-72,47,2,18),(23,-2,6,30)]),
'German': ('#1f9e54', [(10,51,3,55),(14,47.5,1.5,15)]),
'Russian': ('#9b59b6', [(55,57,14,110),(30,50,3,25)]),
'Arabic': ('#16a085', [(30,27,3,40),(45,24,5,45),(2,34,4,35),(44,33,2,20)]),
'Chinese': ('#e84393', [(112,33,7,130),(114,23,3,30)]),
'Japanese': ('#5d6d7e', [(138,37,3,45),(127,37,1.5,18)]),
}
fig, ax = agis.plt.subplots(figsize=(14, 7))
fig.patch.set_facecolor('#e9eef2'); ax.set_facecolor('#dfe6ec')
world.plot(ax=ax, color='#c9d2da', edgecolor='white', linewidth=0.4, zorder=1)
handles = []
for name, (col, regs) in CATS.items():
xs = agis.np.concatenate([x + rng.normal(0, s, n) for x, y, s, n in regs])
ys = agis.np.concatenate([y + rng.normal(0, s * 0.8, n) for x, y, s, n in regs])
ax.scatter(xs, ys, marker=pin, s=70, c=col, edgecolor='#33373b',
linewidth=0.3, alpha=0.95, zorder=3)
handles.append(Line2D([0],[0], marker='o', color='none', markerfacecolor=col,
markeredgecolor='#33373b', markersize=8, label=name))
leg = ax.legend(handles=handles, loc='lower left', fontsize=8, title='Language',
framealpha=0.9, facecolor='#2c3e50', labelcolor='white')
leg.get_title().set_color('white')
ax.set_xlim(-180, 180); ax.set_ylim(-58, 82); ax.set_xticks([]); ax.set_yticks([])
ax.set_title('World — categorical point markers (pins by group)', fontsize=14, fontweight='bold')
agis.show()
Path = agis.plt.matplotlib.path.Path
Line2D = agis.plt.Line2D
# reach matplotlib helpers through agis — no separate import
rng = agis.np.random.default_rng(7)
world = agis.load_world()
# teardrop map-pin marker (tip points down)
pin = Path([(0,-1.0),(-0.86,0.05),(-0.7,1.0),(0,1.0),(0.7,1.0),(0.86,0.05),(0,-1.0)],
[Path.MOVETO,Path.CURVE4,Path.CURVE4,Path.CURVE4,Path.CURVE4,Path.CURVE4,Path.CURVE4])
# category -> (colour, [region centres (lon, lat, spread, count)])
CATS = {
'English': ('#f4d03f', [(-98,39,9,140),(-1.5,53,3,60),(-100,56,8,40),(134,-25,9,50),(172,-42,2,15),(78,22,7,60)]),
'Spanish': ('#e74c3c', [(-102,23,5,70),(-74,4,4,40),(-76,-10,3,30),(-64,-36,5,50),(-4,40,3,40),(-71,-35,2,20)]),
'Portuguese': ('#e67e22', [(-50,-12,8,90),(-8.2,39.6,1.5,18),(18,-12,4,20)]),
'French': ('#5dade2', [(2.4,47,3,55),(-5,12,6,40),(-72,47,2,18),(23,-2,6,30)]),
'German': ('#1f9e54', [(10,51,3,55),(14,47.5,1.5,15)]),
'Russian': ('#9b59b6', [(55,57,14,110),(30,50,3,25)]),
'Arabic': ('#16a085', [(30,27,3,40),(45,24,5,45),(2,34,4,35),(44,33,2,20)]),
'Chinese': ('#e84393', [(112,33,7,130),(114,23,3,30)]),
'Japanese': ('#5d6d7e', [(138,37,3,45),(127,37,1.5,18)]),
}
fig, ax = agis.plt.subplots(figsize=(14, 7))
fig.patch.set_facecolor('#e9eef2'); ax.set_facecolor('#dfe6ec')
world.plot(ax=ax, color='#c9d2da', edgecolor='white', linewidth=0.4, zorder=1)
handles = []
for name, (col, regs) in CATS.items():
xs = agis.np.concatenate([x + rng.normal(0, s, n) for x, y, s, n in regs])
ys = agis.np.concatenate([y + rng.normal(0, s * 0.8, n) for x, y, s, n in regs])
ax.scatter(xs, ys, marker=pin, s=70, c=col, edgecolor='#33373b',
linewidth=0.3, alpha=0.95, zorder=3)
handles.append(Line2D([0],[0], marker='o', color='none', markerfacecolor=col,
markeredgecolor='#33373b', markersize=8, label=name))
leg = ax.legend(handles=handles, loc='lower left', fontsize=8, title='Language',
framealpha=0.9, facecolor='#2c3e50', labelcolor='white')
leg.get_title().set_color('white')
ax.set_xlim(-180, 180); ax.set_ylim(-58, 82); ax.set_xticks([]); ax.set_yticks([])
ax.set_title('World — categorical point markers (pins by group)', fontsize=14, fontweight='bold')
agis.show()
1 · A styled map — simple¶
In [3]:
Copied!
## 1 · A styled map — simple
gdf = agis.load_boundaries('Bangladesh', 'district')
agis.plot(gdf, palette='spectral', title='Bangladesh — districts');
## 1 · A styled map — simple
gdf = agis.load_boundaries('Bangladesh', 'district')
agis.plot(gdf, palette='spectral', title='Bangladesh — districts');
1 · The same map — fully customized¶
Every plot() knob, each commented.
In [4]:
Copied!
agis.plot(gdf, palette='vibrant', pad=0,
north_arrow='rose', scale_bar='double',
graticule={'grid': False, 'sides': 'all'},
sea={'source': 'ne10m',
'extent': (87.8, 20.3, 92.9, 26.8),
'color': '#9ecae9',
'labels': {'Bay of Bengal': (91.0, 21.0)}},
title='Bangladesh — Bay of Bengal (ne10m)');
agis.plot(gdf, palette='vibrant', pad=0,
north_arrow='rose', scale_bar='double',
graticule={'grid': False, 'sides': 'all'},
sea={'source': 'ne10m',
'extent': (87.8, 20.3, 92.9, 26.8),
'color': '#9ecae9',
'labels': {'Bay of Bengal': (91.0, 21.0)}},
title='Bangladesh — Bay of Bengal (ne10m)');
In [6]:
Copied!
ax = agis.plot(
gdf,
# ---- COLOURS ----
palette='spectral', # classic · earth · ocean · pastel · slate · spectral · vibrant
# theme='academic', # academic · atlas · mono · nature · ocean · viridis (instead of palette)
title='Bangladesh — districts (fully customized)',
# ---- HIGHLIGHT (one or more regions) ----
highlight='Madaripur', # a name, or a list of names
highlight_style='rect', # fill · overlay · rect · circle
highlight_color='#e63946', # fill colour (any hex/name)
highlight_edge='#2708F1', # border colour
highlight_width=2.5, # border thickness
highlight_alpha=0.25, # fill opacity (used by overlay/rect/circle)
labels=False, # True = draw region-name labels
legend=False, # True = categorical legend
figsize=(9, 9), pad=0.05, # figure size · margin around the data
# ---- NORTH ARROW (bool | "style" | dict) ----
north_arrow={
'style': 'minimal', # classic · minimal · pointer · rose
'size': 0.13, # height as fraction of the axes
'color': '#0b3b34', # fill
'edge': '#06222b', # outline colour
'label': 'N', # label text
'label_color': '#0b3b34', # label colour (default = color)
'label_size': None, # label font size (default auto)
'rotation': 0, # degrees (e.g. declination)
'coords': 'axes', # 'axes' (0–1) · 'data' (lon,lat)
'loc': (0.9, 0.86)}, # position per coords
# ---- SCALE BAR (bool | "style" | dict) ----
scale_bar={
'style': 'stepped', # bar · simple · stepped · double · ticks
'divisions': 4, # segments (stepped/double/ticks)
'length_km': None, # real length (auto if None)
'units': 'km', # km · mi
'color': '#0b3b34', # fill/line
'edge': '#0b3b34', # outline (default = color)
'text_color': '#0b3b34', # label colour
'size': 1.0, # scales bar + label
'coords': 'axes', # 'axes' (0–1) · 'data' (lon,lat)
'loc': (0.07, 0.07), # left end per coords
'fontsize': None}, # label size (auto if None)
# ---- GRID + TICKS (bool | dict | per-panel list) ----
graticule={
'grid': False, # True/False — grid lines
'grid_color': '#9aa0a6', 'grid_lw': 0.5, 'grid_alpha': 0.55,
'grid_style': '-', # '-' · '--' · ':' · '-.' · dash tuple (0,(6,3))
'square': True, # equal interval both axes (square cells)
'interval': None, # degrees; or 'x_interval'/'y_interval'; or 'n': 6 (auto count)
'ticks': True, # tick marks + labels
'tick_dir': 'in', # in · out · inout
'tick_len': 3.5, 'tick_width': 0.8,
'minor': False, 'minor_n': 2, # minor ticks
'sides': 'all', # 'lb' (default) · 'all' · any of 'l','r','t','b'
'tick_sides': None, # tick-mark sides (default = sides)
'fontsize': 7, 'label_color': '#333',
'bold': False, 'italic': False, 'font': None,
'rotate_x': 0, 'rotate_y': 0}, # 90 = vertical latitude labels
border='solid', # solid · checker · none
# ---- SEA / OCEAN (bool | "#colour" | dict) ----
sea={
'source': 'ne10m', # auto (110m, offline) · ne10m (crisp) · ocean (10m ocean polygon)
'color': '#9ecae9', # ocean fill
'extent': (87.8, 20.3, 92.9, 26.8), # (minx,miny,maxx,maxy); or omit + use 'pad'
'pad': 0.0, # extend view into the ocean (fraction <1, else degrees)
'background': 'white', # land/neighbour background
'neighbours': False, # True = fill neighbour land
'neighbour_color': '#eeeae1',
'coastline': False, # draw the country coastline
'coastline_color': '#5a8fb0',
'labels': {'Bay of Bengal': (91.0, 21.0)}}, # {name: (lon,lat)}
)
ax = agis.plot(
gdf,
# ---- COLOURS ----
palette='spectral', # classic · earth · ocean · pastel · slate · spectral · vibrant
# theme='academic', # academic · atlas · mono · nature · ocean · viridis (instead of palette)
title='Bangladesh — districts (fully customized)',
# ---- HIGHLIGHT (one or more regions) ----
highlight='Madaripur', # a name, or a list of names
highlight_style='rect', # fill · overlay · rect · circle
highlight_color='#e63946', # fill colour (any hex/name)
highlight_edge='#2708F1', # border colour
highlight_width=2.5, # border thickness
highlight_alpha=0.25, # fill opacity (used by overlay/rect/circle)
labels=False, # True = draw region-name labels
legend=False, # True = categorical legend
figsize=(9, 9), pad=0.05, # figure size · margin around the data
# ---- NORTH ARROW (bool | "style" | dict) ----
north_arrow={
'style': 'minimal', # classic · minimal · pointer · rose
'size': 0.13, # height as fraction of the axes
'color': '#0b3b34', # fill
'edge': '#06222b', # outline colour
'label': 'N', # label text
'label_color': '#0b3b34', # label colour (default = color)
'label_size': None, # label font size (default auto)
'rotation': 0, # degrees (e.g. declination)
'coords': 'axes', # 'axes' (0–1) · 'data' (lon,lat)
'loc': (0.9, 0.86)}, # position per coords
# ---- SCALE BAR (bool | "style" | dict) ----
scale_bar={
'style': 'stepped', # bar · simple · stepped · double · ticks
'divisions': 4, # segments (stepped/double/ticks)
'length_km': None, # real length (auto if None)
'units': 'km', # km · mi
'color': '#0b3b34', # fill/line
'edge': '#0b3b34', # outline (default = color)
'text_color': '#0b3b34', # label colour
'size': 1.0, # scales bar + label
'coords': 'axes', # 'axes' (0–1) · 'data' (lon,lat)
'loc': (0.07, 0.07), # left end per coords
'fontsize': None}, # label size (auto if None)
# ---- GRID + TICKS (bool | dict | per-panel list) ----
graticule={
'grid': False, # True/False — grid lines
'grid_color': '#9aa0a6', 'grid_lw': 0.5, 'grid_alpha': 0.55,
'grid_style': '-', # '-' · '--' · ':' · '-.' · dash tuple (0,(6,3))
'square': True, # equal interval both axes (square cells)
'interval': None, # degrees; or 'x_interval'/'y_interval'; or 'n': 6 (auto count)
'ticks': True, # tick marks + labels
'tick_dir': 'in', # in · out · inout
'tick_len': 3.5, 'tick_width': 0.8,
'minor': False, 'minor_n': 2, # minor ticks
'sides': 'all', # 'lb' (default) · 'all' · any of 'l','r','t','b'
'tick_sides': None, # tick-mark sides (default = sides)
'fontsize': 7, 'label_color': '#333',
'bold': False, 'italic': False, 'font': None,
'rotate_x': 0, 'rotate_y': 0}, # 90 = vertical latitude labels
border='solid', # solid · checker · none
# ---- SEA / OCEAN (bool | "#colour" | dict) ----
sea={
'source': 'ne10m', # auto (110m, offline) · ne10m (crisp) · ocean (10m ocean polygon)
'color': '#9ecae9', # ocean fill
'extent': (87.8, 20.3, 92.9, 26.8), # (minx,miny,maxx,maxy); or omit + use 'pad'
'pad': 0.0, # extend view into the ocean (fraction <1, else degrees)
'background': 'white', # land/neighbour background
'neighbours': False, # True = fill neighbour land
'neighbour_color': '#eeeae1',
'coastline': False, # draw the country coastline
'coastline_color': '#5a8fb0',
'labels': {'Bay of Bengal': (91.0, 21.0)}}, # {name: (lon,lat)}
)
In [7]:
Copied!
ind = agis.load_boundaries('India', 'state')
ax = agis.plot(
ind,
# ---- COLOURS ----
palette='vibrant', # classic · earth · ocean · pastel · slate · spectral · vibrant
title='India — surrounding seas (West Bengal highlighted)',
# ---- HIGHLIGHT ----
highlight='West Bengal', # state name (or a list)
highlight_style='overlay', # fill · overlay · rect · circle
highlight_color='#e63946', # fill
highlight_edge='#2708F1', # border colour
highlight_width=2.5, # border thickness
highlight_alpha=0.25, # fill opacity (overlay/rect/circle)
labels=True, legend=False,
figsize=(11, 11), pad=0,
# ---- NORTH ARROW ----
north_arrow={'style': 'pointer', # classic · minimal · pointer · rose
'size': 0.12, 'color': '#0b3b34', 'edge': '#06222b',
'coords': 'axes', 'loc': (0.92, 0.90)},
# ---- SCALE BAR ----
scale_bar={'style': 'bar', # bar · simple · stepped · double · ticks
'divisions': 4, 'color': '#0b3b34', 'text_color': '#0b3b34',
'units': 'km'}, # km · mi
# ---- GRID + TICKS ----
graticule={'grid': False, # grid lines on/off
'sides': 'all', # 'lb' · 'all' · any of l/r/t/b
'tick_dir': 'in', # in · out · inout
'fontsize': 7},
border='solid', # solid · checker · none
# ---- SEA / OCEAN ----
sea={'source': 'ne10m', # auto · ne10m · ocean
'extent': (66.0, 5.0, 98.5, 37.5),
'color': '#9ecae9',
'labels': {'Arabian Sea': (68.5, 15.5),
'Bay of Bengal': (89.5, 13.5),
'Indian Ocean': (80.0, 7.0)}},
)
ind = agis.load_boundaries('India', 'state')
ax = agis.plot(
ind,
# ---- COLOURS ----
palette='vibrant', # classic · earth · ocean · pastel · slate · spectral · vibrant
title='India — surrounding seas (West Bengal highlighted)',
# ---- HIGHLIGHT ----
highlight='West Bengal', # state name (or a list)
highlight_style='overlay', # fill · overlay · rect · circle
highlight_color='#e63946', # fill
highlight_edge='#2708F1', # border colour
highlight_width=2.5, # border thickness
highlight_alpha=0.25, # fill opacity (overlay/rect/circle)
labels=True, legend=False,
figsize=(11, 11), pad=0,
# ---- NORTH ARROW ----
north_arrow={'style': 'pointer', # classic · minimal · pointer · rose
'size': 0.12, 'color': '#0b3b34', 'edge': '#06222b',
'coords': 'axes', 'loc': (0.92, 0.90)},
# ---- SCALE BAR ----
scale_bar={'style': 'bar', # bar · simple · stepped · double · ticks
'divisions': 4, 'color': '#0b3b34', 'text_color': '#0b3b34',
'units': 'km'}, # km · mi
# ---- GRID + TICKS ----
graticule={'grid': False, # grid lines on/off
'sides': 'all', # 'lb' · 'all' · any of l/r/t/b
'tick_dir': 'in', # in · out · inout
'fontsize': 7},
border='solid', # solid · checker · none
# ---- SEA / OCEAN ----
sea={'source': 'ne10m', # auto · ne10m · ocean
'extent': (66.0, 5.0, 98.5, 37.5),
'color': '#9ecae9',
'labels': {'Arabian Sea': (68.5, 15.5),
'Bay of Bengal': (89.5, 13.5),
'Indian Ocean': (80.0, 7.0)}},
)
In [8]:
Copied!
jp = agis.load_boundaries('Japan', 'state') # prefectures
ax = agis.plot(
jp,
palette='ocean', # classic · earth · ocean · pastel · slate · spectral · vibrant
title='Japan — capital (Tokyo) highlighted',
# ---- HIGHLIGHT the Tokyo prefecture ----
highlight='Tokyo',
highlight_style='fill', # fill · overlay · rect · circle
highlight_color='#e63946',
highlight_edge='#2708F1',
highlight_width=2.5,
highlight_alpha=0.25,
labels=False, legend=False,
figsize=(10, 11), pad=0,
north_arrow={'style': 'classic', 'size': 0.12, 'color': '#0b3b34',
'edge': '#06222b', 'loc': (0.92, 0.92)},
scale_bar={'style': 'double', 'divisions': 4, 'color': '#0b3b34',
'text_color': '#0b3b34', 'units': 'km'},
graticule={'grid': False, 'sides': 'lb', 'tick_dir': 'in', 'fontsize': 7},
border='solid',
sea={'source': 'ne10m',
'extent': (127.0, 29.0, 147.0, 46.0),
'color': '#9ecae9',
'labels': {'Sea of Japan': (133.0, 40.5),
'Pacific Ocean': (143.5, 34.0)}},
)
agis.points(ax, {'Tokyo': (139.69, 35.69)}, color='#b30000', size=45, label=True)
jp = agis.load_boundaries('Japan', 'state') # prefectures
ax = agis.plot(
jp,
palette='ocean', # classic · earth · ocean · pastel · slate · spectral · vibrant
title='Japan — capital (Tokyo) highlighted',
# ---- HIGHLIGHT the Tokyo prefecture ----
highlight='Tokyo',
highlight_style='fill', # fill · overlay · rect · circle
highlight_color='#e63946',
highlight_edge='#2708F1',
highlight_width=2.5,
highlight_alpha=0.25,
labels=False, legend=False,
figsize=(10, 11), pad=0,
north_arrow={'style': 'classic', 'size': 0.12, 'color': '#0b3b34',
'edge': '#06222b', 'loc': (0.92, 0.92)},
scale_bar={'style': 'double', 'divisions': 4, 'color': '#0b3b34',
'text_color': '#0b3b34', 'units': 'km'},
graticule={'grid': False, 'sides': 'lb', 'tick_dir': 'in', 'fontsize': 7},
border='solid',
sea={'source': 'ne10m',
'extent': (127.0, 29.0, 147.0, 46.0),
'color': '#9ecae9',
'labels': {'Sea of Japan': (133.0, 40.5),
'Pacific Ocean': (143.5, 34.0)}},
)
agis.points(ax, {'Tokyo': (139.69, 35.69)}, color='#b30000', size=45, label=True)
In [9]:
Copied!
jp = agis.load_boundaries('Japan', 'state')
ax = agis.plot(
jp, palette='ocean',
title='Japan — synthetic sampling data (bubble style)',
highlight='Tokyo', highlight_style='fill', highlight_color='#e63946',
highlight_edge='#2708F1', highlight_width=2.5, highlight_alpha=0.25,
labels=False, legend=False, figsize=(10, 11), pad=0,
north_arrow={'style': 'classic', 'size': 0.12, 'color': '#0b3b34',
'edge': '#06222b', 'loc': (0.92, 0.92)},
scale_bar={'style': 'double', 'divisions': 4, 'color': '#0b3b34',
'text_color': '#0b3b34', 'units': 'km'},
graticule={'grid': False, 'sides': 'lb', 'tick_dir': 'in', 'fontsize': 7},
border='solid',
sea={'source': 'ne10m', 'extent': (127.0, 29.0, 147.0, 46.0), 'color': '#9ecae9',
'labels': {'Sea of Japan': (133.0, 40.5), 'Pacific Ocean': (143.5, 34.0)}},
)
# --- synthetic sample points ON land ---
rng = agis.np.random.default_rng(7)
xs = rng.uniform(129, 146, 600); ys = rng.uniform(31, 46, 600)
pts = agis.gpd.GeoSeries(agis.gpd.points_from_xy(xs, ys), crs=4326)
on = pts[pts.within(jp.union_all())].iloc[:28] # keep 28 on-land points
df = agis.pd.DataFrame({'name': [f'S{i+1}' for i in range(len(on))],
'lon': on.x.values, 'lat': on.y.values,
'value': rng.gamma(2.2, 16, len(on)).round(1)})
# --- eye-catching bubbles: colour + size by value ---
agis.points(ax, df,
value='value', # colour by value (colorbar)
size_by='value', # bubble size by value
cmap='plasma', # try magma · viridis · turbo · YlOrRd
size_range=(40, 750), # min/max bubble size
edgecolor='white', linewidth=0.8,
legend=True, legend_label='Index')
jp = agis.load_boundaries('Japan', 'state')
ax = agis.plot(
jp, palette='ocean',
title='Japan — synthetic sampling data (bubble style)',
highlight='Tokyo', highlight_style='fill', highlight_color='#e63946',
highlight_edge='#2708F1', highlight_width=2.5, highlight_alpha=0.25,
labels=False, legend=False, figsize=(10, 11), pad=0,
north_arrow={'style': 'classic', 'size': 0.12, 'color': '#0b3b34',
'edge': '#06222b', 'loc': (0.92, 0.92)},
scale_bar={'style': 'double', 'divisions': 4, 'color': '#0b3b34',
'text_color': '#0b3b34', 'units': 'km'},
graticule={'grid': False, 'sides': 'lb', 'tick_dir': 'in', 'fontsize': 7},
border='solid',
sea={'source': 'ne10m', 'extent': (127.0, 29.0, 147.0, 46.0), 'color': '#9ecae9',
'labels': {'Sea of Japan': (133.0, 40.5), 'Pacific Ocean': (143.5, 34.0)}},
)
# --- synthetic sample points ON land ---
rng = agis.np.random.default_rng(7)
xs = rng.uniform(129, 146, 600); ys = rng.uniform(31, 46, 600)
pts = agis.gpd.GeoSeries(agis.gpd.points_from_xy(xs, ys), crs=4326)
on = pts[pts.within(jp.union_all())].iloc[:28] # keep 28 on-land points
df = agis.pd.DataFrame({'name': [f'S{i+1}' for i in range(len(on))],
'lon': on.x.values, 'lat': on.y.values,
'value': rng.gamma(2.2, 16, len(on)).round(1)})
# --- eye-catching bubbles: colour + size by value ---
agis.points(ax, df,
value='value', # colour by value (colorbar)
size_by='value', # bubble size by value
cmap='plasma', # try magma · viridis · turbo · YlOrRd
size_range=(40, 750), # min/max bubble size
edgecolor='white', linewidth=0.8,
legend=True, legend_label='Index')
In [10]:
Copied!
uk = agis.load_boundaries('United Kingdom', 'state')
uk['NAME_1'] = uk['NAME_1'].astype(str)
uk.loc[uk['GID_1'] == 'GBR.1_1', 'NAME_1'] = 'England' # name England
uk = uk[uk['NAME_1'] != 'NA'].copy() # drop the unnamed stray fragment
ax = agis.plot(
uk,
palette='earth', # classic · earth · ocean · pastel · slate · spectral · vibrant
title='United Kingdom — capital highlighted (London)',
labels=True, legend=False,
figsize=(9, 11), pad=0,
north_arrow={'style': 'classic', 'size': 0.12, 'color': '#0b3b34',
'edge': '#06222b', 'loc': (0.9, 0.93)},
scale_bar={'style': 'double', 'divisions': 4, 'color': '#0b3b34',
'text_color': '#0b3b34', 'units': 'km'},
graticule={'grid': False, 'sides': 'all', 'tick_dir': 'in', 'fontsize': 7},
border='solid',
sea={'source': 'ne10m',
'extent': (-11.0, 49.0, 3.0, 61.5),
'color': '#9ecae9',
'labels': {'Atlantic Ocean': (-9.0, 56.0),
'North Sea': (2.0, 56.5),
'English Channel': (-2.0, 49.6),
'Irish Sea': (-5.2, 53.8)}},
)
# CAPITAL HIGHLIGHT — red square marker + label
agis.points(ax, {'London': (-0.118, 51.509)},
color='#d7263d', size=90, marker='s', label=True)
uk = agis.load_boundaries('United Kingdom', 'state')
uk['NAME_1'] = uk['NAME_1'].astype(str)
uk.loc[uk['GID_1'] == 'GBR.1_1', 'NAME_1'] = 'England' # name England
uk = uk[uk['NAME_1'] != 'NA'].copy() # drop the unnamed stray fragment
ax = agis.plot(
uk,
palette='earth', # classic · earth · ocean · pastel · slate · spectral · vibrant
title='United Kingdom — capital highlighted (London)',
labels=True, legend=False,
figsize=(9, 11), pad=0,
north_arrow={'style': 'classic', 'size': 0.12, 'color': '#0b3b34',
'edge': '#06222b', 'loc': (0.9, 0.93)},
scale_bar={'style': 'double', 'divisions': 4, 'color': '#0b3b34',
'text_color': '#0b3b34', 'units': 'km'},
graticule={'grid': False, 'sides': 'all', 'tick_dir': 'in', 'fontsize': 7},
border='solid',
sea={'source': 'ne10m',
'extent': (-11.0, 49.0, 3.0, 61.5),
'color': '#9ecae9',
'labels': {'Atlantic Ocean': (-9.0, 56.0),
'North Sea': (2.0, 56.5),
'English Channel': (-2.0, 49.6),
'Irish Sea': (-5.2, 53.8)}},
)
# CAPITAL HIGHLIGHT — red square marker + label
agis.points(ax, {'London': (-0.118, 51.509)},
color='#d7263d', size=90, marker='s', label=True)
In [7]:
Copied!
bd = agis.load_boundaries('Bangladesh', 'division')
ax = agis.plot(
bd,
# ---- COLOURS ----
palette='spectral', # classic · earth · ocean · pastel · slate · spectral · vibrant
title='Bangladesh — divisions (Dhaka highlighted)',
# ---- HIGHLIGHT ----
highlight='Dhaka', # region name (or a list of names)
highlight_style='circle', # fill · overlay · rect · circle
highlight_color='#e63946', # fill colour
highlight_edge='#1d3557', # border colour
highlight_width=2.5, # border thickness
highlight_alpha=0.22, # fill opacity (overlay/rect/circle)
labels=False, legend=False,
figsize=(8.5, 9.5), pad=0,
# ---- NORTH ARROW ----
north_arrow={'style': 'rose', # classic · minimal · pointer · rose
'size': 0.11, 'color': '#0b3b34', 'edge': '#06222b',
'coords': 'axes', 'loc': (0.92, 0.90)},
# ---- SCALE BAR ----
scale_bar={'style': 'double', # bar · simple · stepped · double · ticks
'divisions': 4, 'color': '#0b3b34', 'text_color': '#0b3b34',
'units': 'km'}, # km · mi
# ---- GRID + TICKS ----
graticule={'grid': False, # grid lines on/off
'sides': 'all', # 'lb' · 'all' · any of l/r/t/b
'tick_dir': 'in', # in · out · inout
'fontsize': 7},
border='solid', # solid · checker · none
# ---- SEA / OCEAN ----
sea={'source': 'ne10m', # auto · ne10m · ocean
'extent': (87.0, 19.5, 93.5, 27.0), # (lon_min, lat_min, lon_max, lat_max)
'color': '#9ecae9',
'labels': {'Bay of Bengal': (90.6, 20.4)}},
)
agis.show()
bd = agis.load_boundaries('Bangladesh', 'division')
ax = agis.plot(
bd,
# ---- COLOURS ----
palette='spectral', # classic · earth · ocean · pastel · slate · spectral · vibrant
title='Bangladesh — divisions (Dhaka highlighted)',
# ---- HIGHLIGHT ----
highlight='Dhaka', # region name (or a list of names)
highlight_style='circle', # fill · overlay · rect · circle
highlight_color='#e63946', # fill colour
highlight_edge='#1d3557', # border colour
highlight_width=2.5, # border thickness
highlight_alpha=0.22, # fill opacity (overlay/rect/circle)
labels=False, legend=False,
figsize=(8.5, 9.5), pad=0,
# ---- NORTH ARROW ----
north_arrow={'style': 'rose', # classic · minimal · pointer · rose
'size': 0.11, 'color': '#0b3b34', 'edge': '#06222b',
'coords': 'axes', 'loc': (0.92, 0.90)},
# ---- SCALE BAR ----
scale_bar={'style': 'double', # bar · simple · stepped · double · ticks
'divisions': 4, 'color': '#0b3b34', 'text_color': '#0b3b34',
'units': 'km'}, # km · mi
# ---- GRID + TICKS ----
graticule={'grid': False, # grid lines on/off
'sides': 'all', # 'lb' · 'all' · any of l/r/t/b
'tick_dir': 'in', # in · out · inout
'fontsize': 7},
border='solid', # solid · checker · none
# ---- SEA / OCEAN ----
sea={'source': 'ne10m', # auto · ne10m · ocean
'extent': (87.0, 19.5, 93.5, 27.0), # (lon_min, lat_min, lon_max, lat_max)
'color': '#9ecae9',
'labels': {'Bay of Bengal': (90.6, 20.4)}},
)
agis.show()
In [8]:
Copied!
ax = agis.plot(
bd, # same data, restyled (no reload needed)
# ---- COLOURS ----
palette='ocean', # cool blues & greens
title='Bangladesh — Bay of Bengal coast (Dhaka)',
# ---- HIGHLIGHT (translucent overlay) ----
highlight='Dhaka',
highlight_style='overlay', # fill · overlay · rect · circle
highlight_color='#ffb703', # warm accent over the cool map
highlight_edge='#fb8500',
highlight_width=2.0,
highlight_alpha=0.38,
labels=False, legend=False,
figsize=(8.5, 9.5), pad=0,
# ---- NORTH ARROW (minimal pointer, top-left) ----
north_arrow={'style': 'pointer', 'size': 0.09, 'color': '#22333b',
'coords': 'axes', 'loc': (0.07, 0.92)},
# ---- SCALE BAR (stepped) ----
scale_bar={'style': 'stepped', 'divisions': 3, 'color': '#22333b',
'text_color': '#22333b', 'units': 'km', 'loc': (0.66, 0.04)},
# ---- GRID + TICKS (grid ON, ticks pointing out) ----
graticule={'grid': True, 'grid_color': '#9fb3c8', 'grid_alpha': 0.4,
'sides': 'lb', 'tick_dir': 'out', 'fontsize': 7},
border='solid',
# ---- SEA / OCEAN (ocean polygon + land-tinted neighbours) ----
sea={'source': 'ocean', # auto · ne10m · ocean
'extent': (87.0, 19.5, 93.5, 27.0),
'color': '#cfe8f3',
'background': '#eceee9', # tints non-sea, non-country land (neighbours)
'labels': {'Bay of Bengal': (90.6, 20.4)}},
)
agis.show()
ax = agis.plot(
bd, # same data, restyled (no reload needed)
# ---- COLOURS ----
palette='ocean', # cool blues & greens
title='Bangladesh — Bay of Bengal coast (Dhaka)',
# ---- HIGHLIGHT (translucent overlay) ----
highlight='Dhaka',
highlight_style='overlay', # fill · overlay · rect · circle
highlight_color='#ffb703', # warm accent over the cool map
highlight_edge='#fb8500',
highlight_width=2.0,
highlight_alpha=0.38,
labels=False, legend=False,
figsize=(8.5, 9.5), pad=0,
# ---- NORTH ARROW (minimal pointer, top-left) ----
north_arrow={'style': 'pointer', 'size': 0.09, 'color': '#22333b',
'coords': 'axes', 'loc': (0.07, 0.92)},
# ---- SCALE BAR (stepped) ----
scale_bar={'style': 'stepped', 'divisions': 3, 'color': '#22333b',
'text_color': '#22333b', 'units': 'km', 'loc': (0.66, 0.04)},
# ---- GRID + TICKS (grid ON, ticks pointing out) ----
graticule={'grid': True, 'grid_color': '#9fb3c8', 'grid_alpha': 0.4,
'sides': 'lb', 'tick_dir': 'out', 'fontsize': 7},
border='solid',
# ---- SEA / OCEAN (ocean polygon + land-tinted neighbours) ----
sea={'source': 'ocean', # auto · ne10m · ocean
'extent': (87.0, 19.5, 93.5, 27.0),
'color': '#cfe8f3',
'background': '#eceee9', # tints non-sea, non-country land (neighbours)
'labels': {'Bay of Bengal': (90.6, 20.4)}},
)
agis.show()
In [11]:
Copied!
ind = agis.load_boundaries('India', 'state')
ax = agis.plot(
ind, # same data, restyled (no reload needed)
# ---- COLOURS ----
palette='ocean', # cool blues & greens
title='India — states in context (West Bengal)',
# ---- HIGHLIGHT (translucent overlay) ----
highlight='West Bengal',
highlight_style='overlay', # fill · overlay · rect · circle
highlight_color='#ffb703', # warm accent over the cool map
highlight_edge='#fb8500',
highlight_width=2.0,
highlight_alpha=0.38,
labels=False, legend=False,
figsize=(10, 10), pad=0,
# ---- NORTH ARROW (minimal pointer, top-left) ----
north_arrow={'style': 'pointer', 'size': 0.09, 'color': '#22333b',
'coords': 'axes', 'loc': (0.07, 0.92)},
# ---- SCALE BAR (stepped) ----
scale_bar={'style': 'stepped', 'divisions': 3, 'color': '#22333b',
'text_color': '#22333b', 'units': 'km', 'loc': (0.66, 0.04)},
# ---- GRID + TICKS (grid ON, ticks pointing out) ----
graticule={'grid': True, 'grid_color': '#9fb3c8', 'grid_alpha': 0.4,
'sides': 'lb', 'tick_dir': 'out', 'fontsize': 7},
border='solid',
# ---- SEA / OCEAN (ocean polygon + land-tinted neighbours) ----
sea={'source': 'ocean', # auto · ne10m · ocean
'extent': (66.0, 5.0, 98.5, 37.5),
'color': '#cfe8f3',
'background': '#eceee9', # tints non-sea, non-country land (neighbours)
'labels': {'Arabian Sea': (68.5, 15.5), 'Bay of Bengal': (89.5, 13.5), 'Indian Ocean': (80.0, 7.0)}},
)
agis.show()
ind = agis.load_boundaries('India', 'state')
ax = agis.plot(
ind, # same data, restyled (no reload needed)
# ---- COLOURS ----
palette='ocean', # cool blues & greens
title='India — states in context (West Bengal)',
# ---- HIGHLIGHT (translucent overlay) ----
highlight='West Bengal',
highlight_style='overlay', # fill · overlay · rect · circle
highlight_color='#ffb703', # warm accent over the cool map
highlight_edge='#fb8500',
highlight_width=2.0,
highlight_alpha=0.38,
labels=False, legend=False,
figsize=(10, 10), pad=0,
# ---- NORTH ARROW (minimal pointer, top-left) ----
north_arrow={'style': 'pointer', 'size': 0.09, 'color': '#22333b',
'coords': 'axes', 'loc': (0.07, 0.92)},
# ---- SCALE BAR (stepped) ----
scale_bar={'style': 'stepped', 'divisions': 3, 'color': '#22333b',
'text_color': '#22333b', 'units': 'km', 'loc': (0.66, 0.04)},
# ---- GRID + TICKS (grid ON, ticks pointing out) ----
graticule={'grid': True, 'grid_color': '#9fb3c8', 'grid_alpha': 0.4,
'sides': 'lb', 'tick_dir': 'out', 'fontsize': 7},
border='solid',
# ---- SEA / OCEAN (ocean polygon + land-tinted neighbours) ----
sea={'source': 'ocean', # auto · ne10m · ocean
'extent': (66.0, 5.0, 98.5, 37.5),
'color': '#cfe8f3',
'background': '#eceee9', # tints non-sea, non-country land (neighbours)
'labels': {'Arabian Sea': (68.5, 15.5), 'Bay of Bengal': (89.5, 13.5), 'Indian Ocean': (80.0, 7.0)}},
)
agis.show()
In [13]:
Copied!
usa = agis.load_boundaries('USA', 'state')
usa = usa[~usa['NAME_1'].isin(['Alaska', 'Hawaii'])].reset_index(drop=True) # contiguous 48 + DC
ax = agis.plot(
usa, # same data, restyled (no reload needed)
# ---- COLOURS ----
palette='ocean', # cool blues & greens
title='United States — coastal context (California)',
# ---- HIGHLIGHT (translucent overlay) ----
highlight='California',
highlight_style='overlay', # fill · overlay · rect · circle
highlight_color='#ffb703', # warm accent over the cool map
highlight_edge='#fb8500',
highlight_width=2.0,
highlight_alpha=0.38,
labels=False, legend=False,
figsize=(13, 7.5), pad=0,
# ---- NORTH ARROW (minimal pointer, top-left) ----
north_arrow={'style': 'pointer', 'size': 0.09, 'color': '#22333b',
'coords': 'axes', 'loc': (0.07, 0.92)},
# ---- SCALE BAR (stepped) ----
scale_bar={'style': 'stepped', 'divisions': 3, 'color': '#22333b',
'text_color': '#22333b', 'units': 'km', 'loc': (0.66, 0.04)},
# ---- GRID + TICKS (grid ON, ticks pointing out) ----
graticule={'grid': True, 'grid_color': '#9fb3c8', 'grid_alpha': 0.4,
'sides': 'lb', 'tick_dir': 'out', 'fontsize': 7},
border='solid',
# ---- SEA / OCEAN (ocean polygon + land-tinted neighbours) ----
sea={'source': 'ocean', # auto · ne10m · ocean
'extent': (-128, 22, -64, 51),
'color': '#cfe8f3',
'background': '#eceee9', # tints non-sea, non-country land (neighbours)
'labels': {'Pacific Ocean': (-126, 38), 'Atlantic Ocean': (-69, 38), 'Gulf of Mexico': (-92, 25.5)}},
)
agis.show()
usa = agis.load_boundaries('USA', 'state')
usa = usa[~usa['NAME_1'].isin(['Alaska', 'Hawaii'])].reset_index(drop=True) # contiguous 48 + DC
ax = agis.plot(
usa, # same data, restyled (no reload needed)
# ---- COLOURS ----
palette='ocean', # cool blues & greens
title='United States — coastal context (California)',
# ---- HIGHLIGHT (translucent overlay) ----
highlight='California',
highlight_style='overlay', # fill · overlay · rect · circle
highlight_color='#ffb703', # warm accent over the cool map
highlight_edge='#fb8500',
highlight_width=2.0,
highlight_alpha=0.38,
labels=False, legend=False,
figsize=(13, 7.5), pad=0,
# ---- NORTH ARROW (minimal pointer, top-left) ----
north_arrow={'style': 'pointer', 'size': 0.09, 'color': '#22333b',
'coords': 'axes', 'loc': (0.07, 0.92)},
# ---- SCALE BAR (stepped) ----
scale_bar={'style': 'stepped', 'divisions': 3, 'color': '#22333b',
'text_color': '#22333b', 'units': 'km', 'loc': (0.66, 0.04)},
# ---- GRID + TICKS (grid ON, ticks pointing out) ----
graticule={'grid': True, 'grid_color': '#9fb3c8', 'grid_alpha': 0.4,
'sides': 'lb', 'tick_dir': 'out', 'fontsize': 7},
border='solid',
# ---- SEA / OCEAN (ocean polygon + land-tinted neighbours) ----
sea={'source': 'ocean', # auto · ne10m · ocean
'extent': (-128, 22, -64, 51),
'color': '#cfe8f3',
'background': '#eceee9', # tints non-sea, non-country land (neighbours)
'labels': {'Pacific Ocean': (-126, 38), 'Atlantic Ocean': (-69, 38), 'Gulf of Mexico': (-92, 25.5)}},
)
agis.show()
In [15]:
Copied!
cn = agis.load_boundaries('China', 'province')
ax = agis.plot(
cn,
# ---- COLOURS ----
palette='ocean', # classic · earth · ocean · pastel · slate · spectral · vibrant
title='China — provinces & seas (Guangdong highlighted)',
# ---- HIGHLIGHT ----
highlight='Guangdong', # region name (or a list of names)
highlight_style='circle', # fill · overlay · rect · circle
highlight_color='#e63946', # fill colour
highlight_edge='#1d3557', # border colour
highlight_width=2.5, # border thickness
highlight_alpha=0.22, # fill opacity (overlay/rect/circle)
labels=False, legend=False,
figsize=(12, 8.5), pad=0,
# ---- NORTH ARROW ----
north_arrow={'style': 'rose', # classic · minimal · pointer · rose
'size': 0.11, 'color': '#0b3b34', 'edge': '#06222b',
'coords': 'axes', 'loc': (0.92, 0.90)},
# ---- SCALE BAR ----
scale_bar={'style': 'double', # bar · simple · stepped · double · ticks
'divisions': 4, 'color': '#0b3b34', 'text_color': '#0b3b34',
'units': 'km'}, # km · mi
# ---- GRID + TICKS ----
graticule={'grid': False, # grid lines on/off
'sides': 'all', # 'lb' · 'all' · any of l/r/t/b
'tick_dir': 'in', # in · out · inout
'fontsize': 7},
border='solid', # solid · checker · none
# ---- SEA / OCEAN ----
sea={'source': 'ne10m', # auto · ne10m · ocean
'extent': (72, 15, 137, 55), # (lon_min, lat_min, lon_max, lat_max)
'color': '#9ecae9',
'labels': {'South China Sea': (112, 16), 'East China Sea': (126, 28.5), 'Yellow Sea': (123, 36)}},
)
agis.show()
cn = agis.load_boundaries('China', 'province')
ax = agis.plot(
cn,
# ---- COLOURS ----
palette='ocean', # classic · earth · ocean · pastel · slate · spectral · vibrant
title='China — provinces & seas (Guangdong highlighted)',
# ---- HIGHLIGHT ----
highlight='Guangdong', # region name (or a list of names)
highlight_style='circle', # fill · overlay · rect · circle
highlight_color='#e63946', # fill colour
highlight_edge='#1d3557', # border colour
highlight_width=2.5, # border thickness
highlight_alpha=0.22, # fill opacity (overlay/rect/circle)
labels=False, legend=False,
figsize=(12, 8.5), pad=0,
# ---- NORTH ARROW ----
north_arrow={'style': 'rose', # classic · minimal · pointer · rose
'size': 0.11, 'color': '#0b3b34', 'edge': '#06222b',
'coords': 'axes', 'loc': (0.92, 0.90)},
# ---- SCALE BAR ----
scale_bar={'style': 'double', # bar · simple · stepped · double · ticks
'divisions': 4, 'color': '#0b3b34', 'text_color': '#0b3b34',
'units': 'km'}, # km · mi
# ---- GRID + TICKS ----
graticule={'grid': False, # grid lines on/off
'sides': 'all', # 'lb' · 'all' · any of l/r/t/b
'tick_dir': 'in', # in · out · inout
'fontsize': 7},
border='solid', # solid · checker · none
# ---- SEA / OCEAN ----
sea={'source': 'ne10m', # auto · ne10m · ocean
'extent': (72, 15, 137, 55), # (lon_min, lat_min, lon_max, lat_max)
'color': '#9ecae9',
'labels': {'South China Sea': (112, 16), 'East China Sea': (126, 28.5), 'Yellow Sea': (123, 36)}},
)
agis.show()
In [16]:
Copied!
kr = agis.load_boundaries('South Korea', 'province')
ax = agis.plot(
kr,
# ---- COLOURS ----
palette='spectral', # classic · earth · ocean · pastel · slate · spectral · vibrant
title='South Korea — provinces & seas (Seoul highlighted)',
# ---- HIGHLIGHT ----
highlight='Seoul', # region name (or a list of names)
highlight_style='circle', # fill · overlay · rect · circle
highlight_color='#e63946', # fill colour
highlight_edge='#1d3557', # border colour
highlight_width=2.5, # border thickness
highlight_alpha=0.22, # fill opacity (overlay/rect/circle)
labels=False, legend=False,
figsize=(9, 8.5), pad=0,
# ---- NORTH ARROW ----
north_arrow={'style': 'rose', # classic · minimal · pointer · rose
'size': 0.11, 'color': '#0b3b34', 'edge': '#06222b',
'coords': 'axes', 'loc': (0.92, 0.90)},
# ---- SCALE BAR ----
scale_bar={'style': 'double', # bar · simple · stepped · double · ticks
'divisions': 4, 'color': '#0b3b34', 'text_color': '#0b3b34',
'units': 'km'}, # km · mi
# ---- GRID + TICKS ----
graticule={'grid': False, # grid lines on/off
'sides': 'all', # 'lb' · 'all' · any of l/r/t/b
'tick_dir': 'in', # in · out · inout
'fontsize': 7},
border='solid', # solid · checker · none
# ---- SEA / OCEAN ----
sea={'source': 'ne10m', # auto · ne10m · ocean
'extent': (123.5, 32.5, 132.5, 39.2), # (lon_min, lat_min, lon_max, lat_max)
'color': '#9ecae9',
'labels': {'Yellow Sea': (124.2, 36.3), 'East Sea': (131.2, 37.4), 'Korea Strait': (128.8, 33.7)}},
)
agis.show()
kr = agis.load_boundaries('South Korea', 'province')
ax = agis.plot(
kr,
# ---- COLOURS ----
palette='spectral', # classic · earth · ocean · pastel · slate · spectral · vibrant
title='South Korea — provinces & seas (Seoul highlighted)',
# ---- HIGHLIGHT ----
highlight='Seoul', # region name (or a list of names)
highlight_style='circle', # fill · overlay · rect · circle
highlight_color='#e63946', # fill colour
highlight_edge='#1d3557', # border colour
highlight_width=2.5, # border thickness
highlight_alpha=0.22, # fill opacity (overlay/rect/circle)
labels=False, legend=False,
figsize=(9, 8.5), pad=0,
# ---- NORTH ARROW ----
north_arrow={'style': 'rose', # classic · minimal · pointer · rose
'size': 0.11, 'color': '#0b3b34', 'edge': '#06222b',
'coords': 'axes', 'loc': (0.92, 0.90)},
# ---- SCALE BAR ----
scale_bar={'style': 'double', # bar · simple · stepped · double · ticks
'divisions': 4, 'color': '#0b3b34', 'text_color': '#0b3b34',
'units': 'km'}, # km · mi
# ---- GRID + TICKS ----
graticule={'grid': False, # grid lines on/off
'sides': 'all', # 'lb' · 'all' · any of l/r/t/b
'tick_dir': 'in', # in · out · inout
'fontsize': 7},
border='solid', # solid · checker · none
# ---- SEA / OCEAN ----
sea={'source': 'ne10m', # auto · ne10m · ocean
'extent': (123.5, 32.5, 132.5, 39.2), # (lon_min, lat_min, lon_max, lat_max)
'color': '#9ecae9',
'labels': {'Yellow Sea': (124.2, 36.3), 'East Sea': (131.2, 37.4), 'Korea Strait': (128.8, 33.7)}},
)
agis.show()
In [18]:
Copied!
np = agis.np
# Shared demo data ------------------------------------------------------------
usa = agis.load_boundaries("USA", "state")
usa = usa[~usa["NAME_1"].isin(["Alaska", "Hawaii"])].reset_index(drop=True)
rng = np.random.default_rng(7)
area_km2 = usa.to_crs(6933).area / 1e6
usa["pop"] = (area_km2 * rng.uniform(15, 300, len(usa))).astype(int) # synthetic
usa["income"] = rng.uniform(35, 95, len(usa)).round(1) # synthetic
usa["education"] = (0.55 * (usa["income"] - 35) / 60 + 0.45 * rng.uniform(0, 1, len(usa))).round(3)
print("states:", len(usa))
np = agis.np
# Shared demo data ------------------------------------------------------------
usa = agis.load_boundaries("USA", "state")
usa = usa[~usa["NAME_1"].isin(["Alaska", "Hawaii"])].reset_index(drop=True)
rng = np.random.default_rng(7)
area_km2 = usa.to_crs(6933).area / 1e6
usa["pop"] = (area_km2 * rng.uniform(15, 300, len(usa))).astype(int) # synthetic
usa["income"] = rng.uniform(35, 95, len(usa)).round(1) # synthetic
usa["education"] = (0.55 * (usa["income"] - 35) / 60 + 0.45 * rng.uniform(0, 1, len(usa))).round(3)
print("states:", len(usa))
states: 49
In [19]:
Copied!
# 1 · CHOROPLETH — regions shaded by a value (shipped since 0.1.0).
agis.choropleth(
usa, usa[["NAME_1", "income"]], # boundaries + a data table
on="NAME_1", value="income", # join key + value column (fuzzy matching built in)
palette="viridis", # any matplotlib cmap
scheme="quantiles", k=5, # classed: quantiles · equal_interval · natural_breaks
legend_label="Median income (k$, synthetic)",
title="Choropleth — income by state",
north_arrow=False, scale_bar=False, graticule=False, figsize=(11, 6.5),
)
agis.show()
# 1 · CHOROPLETH — regions shaded by a value (shipped since 0.1.0).
agis.choropleth(
usa, usa[["NAME_1", "income"]], # boundaries + a data table
on="NAME_1", value="income", # join key + value column (fuzzy matching built in)
palette="viridis", # any matplotlib cmap
scheme="quantiles", k=5, # classed: quantiles · equal_interval · natural_breaks
legend_label="Median income (k$, synthetic)",
title="Choropleth — income by state",
north_arrow=False, scale_bar=False, graticule=False, figsize=(11, 6.5),
)
agis.show()
In [20]:
Copied!
# 2 · GRADUATED SYMBOLS — circle size ∝ value (shipped since 0.1.0).
cap = {"Sacramento": (-121.49, 38.58), "Austin": (-97.74, 30.27), "Albany": (-73.76, 42.65),
"Tallahassee": (-84.28, 30.44), "Springfield": (-89.65, 39.80),
"Columbus": (-82.99, 39.96), "Denver": (-104.99, 39.74), "Phoenix": (-112.07, 33.45),
"Atlanta": (-84.39, 33.75), "Boston": (-71.06, 42.36)}
vals = rng.uniform(1, 40, len(cap)).round(1)
ax = agis.plot(usa, palette="pastel", graticule=False, north_arrow=False,
scale_bar=False, figsize=(11, 6.5), title="Graduated symbols — city index")
agis.points(ax, cap, value=vals, size_by=vals, size_range=(40, 900),
cmap="plasma", edgecolor="white", legend=True, legend_label="Index")
agis.show()
# 2 · GRADUATED SYMBOLS — circle size ∝ value (shipped since 0.1.0).
cap = {"Sacramento": (-121.49, 38.58), "Austin": (-97.74, 30.27), "Albany": (-73.76, 42.65),
"Tallahassee": (-84.28, 30.44), "Springfield": (-89.65, 39.80),
"Columbus": (-82.99, 39.96), "Denver": (-104.99, 39.74), "Phoenix": (-112.07, 33.45),
"Atlanta": (-84.39, 33.75), "Boston": (-71.06, 42.36)}
vals = rng.uniform(1, 40, len(cap)).round(1)
ax = agis.plot(usa, palette="pastel", graticule=False, north_arrow=False,
scale_bar=False, figsize=(11, 6.5), title="Graduated symbols — city index")
agis.points(ax, cap, value=vals, size_by=vals, size_range=(40, 900),
cmap="plasma", edgecolor="white", legend=True, legend_label="Index")
agis.show()
In [21]:
Copied!
# 4 · ISOPLETH — sparse stations -> smooth filled surface, clipped to land.
BB = (-125, 24, -66, 50)
slon = rng.uniform(BB[0], BB[2], 55); slat = rng.uniform(BB[1], BB[3], 55)
temp = 30 - 0.7 * (slat - 24) + 4 * np.sin(slon / 8) + rng.normal(0, 1.2, 55) # °C
Z, ext = agis.interpolate_field(slon, slat, temp, bbox=BB,
clip=usa, # mask cells outside the land
bw=6) # bandwidth (deg): bigger = smoother
fig, ax = agis.plt.subplots(figsize=(12, 7))
agis.add_isopleth(ax, (Z, ext), cmap="RdYlBu_r", levels=14,
colorbar=True, colorbar_label="Temperature (°C, synthetic)")
usa.boundary.plot(ax=ax, color="white", linewidth=0.5, zorder=2)
ax.scatter(slon, slat, s=10, c="k", zorder=4, label="stations")
ax.set_xlim(BB[0], BB[2]); ax.set_ylim(BB[1], BB[3])
ax.legend(loc="lower left", fontsize=8)
ax.set_title("Isopleth — interpolated temperature field", fontsize=13, fontweight="bold")
ax.set_xticks([]); ax.set_yticks([]); agis.show()
# 4 · ISOPLETH — sparse stations -> smooth filled surface, clipped to land.
BB = (-125, 24, -66, 50)
slon = rng.uniform(BB[0], BB[2], 55); slat = rng.uniform(BB[1], BB[3], 55)
temp = 30 - 0.7 * (slat - 24) + 4 * np.sin(slon / 8) + rng.normal(0, 1.2, 55) # °C
Z, ext = agis.interpolate_field(slon, slat, temp, bbox=BB,
clip=usa, # mask cells outside the land
bw=6) # bandwidth (deg): bigger = smoother
fig, ax = agis.plt.subplots(figsize=(12, 7))
agis.add_isopleth(ax, (Z, ext), cmap="RdYlBu_r", levels=14,
colorbar=True, colorbar_label="Temperature (°C, synthetic)")
usa.boundary.plot(ax=ax, color="white", linewidth=0.5, zorder=2)
ax.scatter(slon, slat, s=10, c="k", zorder=4, label="stations")
ax.set_xlim(BB[0], BB[2]); ax.set_ylim(BB[1], BB[3])
ax.legend(loc="lower left", fontsize=8)
ax.set_title("Isopleth — interpolated temperature field", fontsize=13, fontweight="bold")
ax.set_xticks([]); ax.set_yticks([]); agis.show()
In [22]:
Copied!
# 5 · ISOLINES — the same field as labelled contour lines.
fig, ax = agis.plt.subplots(figsize=(12, 7))
usa.plot(ax=ax, color="#eef2f5", edgecolor="#aab4bd", linewidth=0.5, zorder=1)
agis.add_contours(ax, (Z, ext), levels=12, colors="#c1121f", linewidths=0.9,
labels=True, fmt="%d°", fontsize=6)
# also works straight off a DEM or GeoTIFF: agis.add_contours(ax, agis.load_dem(area))
ax.set_xlim(BB[0], BB[2]); ax.set_ylim(BB[1], BB[3])
ax.set_title("Isolines — isotherms with inline labels", fontsize=13, fontweight="bold")
ax.set_xticks([]); ax.set_yticks([]); agis.show()
# 5 · ISOLINES — the same field as labelled contour lines.
fig, ax = agis.plt.subplots(figsize=(12, 7))
usa.plot(ax=ax, color="#eef2f5", edgecolor="#aab4bd", linewidth=0.5, zorder=1)
agis.add_contours(ax, (Z, ext), levels=12, colors="#c1121f", linewidths=0.9,
labels=True, fmt="%d°", fontsize=6)
# also works straight off a DEM or GeoTIFF: agis.add_contours(ax, agis.load_dem(area))
ax.set_xlim(BB[0], BB[2]); ax.set_ylim(BB[1], BB[3])
ax.set_title("Isolines — isotherms with inline labels", fontsize=13, fontweight="bold")
ax.set_xticks([]); ax.set_yticks([]); agis.show()
In [23]:
Copied!
# 6 · DOT-DENSITY — 1 dot = `per` units, scattered inside each region.
ind = agis.load_boundaries("India", "state")
ind["pop"] = (ind.to_crs(6933).area / 1e6 * rng.uniform(80, 1200, len(ind))).astype(int)
fig, ax = agis.plt.subplots(figsize=(9, 10))
ind.plot(ax=ax, color="#f7f3ea", edgecolor="#9aa7b1", linewidth=0.5, zorder=1)
agis.dot_density(ax, ind, "pop", per=200000, # 1 dot = 200 000 (synthetic)
color="#1d3557", size=1.4, alpha=0.55, seed=0)
ax.set_title("Dot-density — India (1 dot = 200k, synthetic)", fontsize=13, fontweight="bold")
ax.set_xticks([]); ax.set_yticks([]); agis.show()
# 6 · DOT-DENSITY — 1 dot = `per` units, scattered inside each region.
ind = agis.load_boundaries("India", "state")
ind["pop"] = (ind.to_crs(6933).area / 1e6 * rng.uniform(80, 1200, len(ind))).astype(int)
fig, ax = agis.plt.subplots(figsize=(9, 10))
ind.plot(ax=ax, color="#f7f3ea", edgecolor="#9aa7b1", linewidth=0.5, zorder=1)
agis.dot_density(ax, ind, "pop", per=200000, # 1 dot = 200 000 (synthetic)
color="#1d3557", size=1.4, alpha=0.55, seed=0)
ax.set_title("Dot-density — India (1 dot = 200k, synthetic)", fontsize=13, fontweight="bold")
ax.set_xticks([]); ax.set_yticks([]); agis.show()
In [27]:
Copied!
# FULLY CUSTOMIZED — every parameter.
fig, ax = agis.plt.subplots(figsize=(9, 10))
ind.plot(ax=ax, color="#10151c", edgecolor="#3b4a5a", linewidth=0.5) # dark base
agis.dot_density(
ax, ind, "pop",
per=150000, # 1 dot = 150 000 units — the key knob
color="#ffd166", # any colour; try "#e63946" or "#4cc9f0"
size=1.8, # dot size (points²)
alpha=0.75, # overlap darkening
seed=42, # deterministic layout — same seed, same dots
max_dots=200000, # safety guard: raises before an accidental million-dot plot
zorder=6,
)
ax.set_facecolor("#10151c"); ax.figure.patch.set_facecolor("#10151c")
ax.set_title("dot_density — fully customized (1 dot = 150k)", color="white",
fontsize=13, fontweight="bold")
ax.set_xticks([]); ax.set_yticks([]); agis.show()
# FULLY CUSTOMIZED — every parameter.
fig, ax = agis.plt.subplots(figsize=(9, 10))
ind.plot(ax=ax, color="#10151c", edgecolor="#3b4a5a", linewidth=0.5) # dark base
agis.dot_density(
ax, ind, "pop",
per=150000, # 1 dot = 150 000 units — the key knob
color="#ffd166", # any colour; try "#e63946" or "#4cc9f0"
size=1.8, # dot size (points²)
alpha=0.75, # overlap darkening
seed=42, # deterministic layout — same seed, same dots
max_dots=200000, # safety guard: raises before an accidental million-dot plot
zorder=6,
)
ax.set_facecolor("#10151c"); ax.figure.patch.set_facecolor("#10151c")
ax.set_title("dot_density — fully customized (1 dot = 150k)", color="white",
fontsize=13, fontweight="bold")
ax.set_xticks([]); ax.set_yticks([]); agis.show()
In [28]:
Copied!
# VARIANT — two variables as two dot colours (classic demographic style).
ind["urban"] = (ind["pop"] * rng.uniform(0.2, 0.6, len(ind))).astype(int)
ind["rural"] = ind["pop"] - ind["urban"]
fig, ax = agis.plt.subplots(figsize=(9, 10))
ind.plot(ax=ax, color="#f7f3ea", edgecolor="#9aa7b1", linewidth=0.5)
agis.dot_density(ax, ind, "rural", per=200000, color="#2a9d8f", size=1.5, seed=1)
agis.dot_density(ax, ind, "urban", per=200000, color="#e76f51", size=1.5, seed=2)
ax.legend(handles=[agis.plt.Line2D([0], [0], marker="o", color="none", markersize=6,
markerfacecolor=c, label=l)
for c, l in [("#2a9d8f", "Rural"), ("#e76f51", "Urban")]],
loc="lower right", fontsize=8, title="1 dot = 200k")
ax.set_title("dot_density — two variables", fontsize=13, fontweight="bold")
ax.set_xticks([]); ax.set_yticks([]); agis.show()
# VARIANT — two variables as two dot colours (classic demographic style).
ind["urban"] = (ind["pop"] * rng.uniform(0.2, 0.6, len(ind))).astype(int)
ind["rural"] = ind["pop"] - ind["urban"]
fig, ax = agis.plt.subplots(figsize=(9, 10))
ind.plot(ax=ax, color="#f7f3ea", edgecolor="#9aa7b1", linewidth=0.5)
agis.dot_density(ax, ind, "rural", per=200000, color="#2a9d8f", size=1.5, seed=1)
agis.dot_density(ax, ind, "urban", per=200000, color="#e76f51", size=1.5, seed=2)
ax.legend(handles=[agis.plt.Line2D([0], [0], marker="o", color="none", markersize=6,
markerfacecolor=c, label=l)
for c, l in [("#2a9d8f", "Rural"), ("#e76f51", "Urban")]],
loc="lower right", fontsize=8, title="1 dot = 200k")
ax.set_title("dot_density — two variables", fontsize=13, fontweight="bold")
ax.set_xticks([]); ax.set_yticks([]); agis.show()
In [24]:
Copied!
# 7 · BIVARIATE — two variables at once (terciles × terciles, 3×3 palette).
ax = agis.bivariate(
usa, "income", "education",
xlabel="Income", ylabel="Education", # 2-D legend axis labels
# palette=my_3x3_colours, # customize the 3×3 matrix
title="Bivariate — income × education (synthetic)", figsize=(12, 7),
)
agis.show()
# 7 · BIVARIATE — two variables at once (terciles × terciles, 3×3 palette).
ax = agis.bivariate(
usa, "income", "education",
xlabel="Income", ylabel="Education", # 2-D legend axis labels
# palette=my_3x3_colours, # customize the 3×3 matrix
title="Bivariate — income × education (synthetic)", figsize=(12, 7),
)
agis.show()
In [25]:
Copied!
# 8 · CARTOGRAMS — regions resized by value.
# Dorling: circles ∝ value, pushed apart so they never overlap.
ax = agis.cartogram(usa, "pop", kind="dorling", cmap="viridis",
labels="NAME_1", label_size=5,
title="Cartogram (Dorling) — circles ∝ population", figsize=(12, 7.5))
agis.show()
# 8 · CARTOGRAMS — regions resized by value.
# Dorling: circles ∝ value, pushed apart so they never overlap.
ax = agis.cartogram(usa, "pop", kind="dorling", cmap="viridis",
labels="NAME_1", label_size=5,
title="Cartogram (Dorling) — circles ∝ population", figsize=(12, 7.5))
agis.show()
In [26]:
Copied!
# Non-contiguous: each state scaled in place (ghost outlines underneath).
ax = agis.cartogram(usa, "pop", kind="noncontig", cmap="YlOrRd",
colorbar=True, colorbar_label="Population (synthetic)",
title="Cartogram (non-contiguous) — area ∝ population", figsize=(12, 7))
agis.show()
# Non-contiguous: each state scaled in place (ghost outlines underneath).
ax = agis.cartogram(usa, "pop", kind="noncontig", cmap="YlOrRd",
colorbar=True, colorbar_label="Population (synthetic)",
title="Cartogram (non-contiguous) — area ∝ population", figsize=(12, 7))
agis.show()
In [29]:
Copied!
fig = agis.study_area('India', [('state', 'Uttarakhand')], template='two',
links={'show': False}, zoom=[1.0, 1.0],
highlight_style='fill', # overlay · rect · circle · fill
highlight_color="#ff0000",
highlight_edge="#010101", # border colour (defaults to highlight_color)
highlight_alpha=0.35, # fill opacity (overlay / rect / circle)
highlight_width=2.2,
terrain=True,
#sea=[{'source': 'ne10m', 'color': '#a9d3e8'}, False],
) # links off
p = agis.load_boundaries('India', 'state')
p = p[p['NAME_1'] == 'Uttarakhand'].geometry.representative_point().iloc[0]
agis.connect(fig, fig.panels[0], (p.x, p.y), # from Uttarakhand in the country panel
fig.panels[1], (0.0, 0.5), # to the state panel (left-middle)
b_coords='axes', color="#000000", width=2.0, arrow=True) # ← arrowhead
agis.show()
fig = agis.study_area('India', [('state', 'Uttarakhand')], template='two',
links={'show': False}, zoom=[1.0, 1.0],
highlight_style='fill', # overlay · rect · circle · fill
highlight_color="#ff0000",
highlight_edge="#010101", # border colour (defaults to highlight_color)
highlight_alpha=0.35, # fill opacity (overlay / rect / circle)
highlight_width=2.2,
terrain=True,
#sea=[{'source': 'ne10m', 'color': '#a9d3e8'}, False],
) # links off
p = agis.load_boundaries('India', 'state')
p = p[p['NAME_1'] == 'Uttarakhand'].geometry.representative_point().iloc[0]
agis.connect(fig, fig.panels[0], (p.x, p.y), # from Uttarakhand in the country panel
fig.panels[1], (0.0, 0.5), # to the state panel (left-middle)
b_coords='axes', color="#000000", width=2.0, arrow=True) # ← arrowhead
agis.show()
In [32]:
Copied!
# ★ THE COMPLETE REFERENCE — every study_area() option, with every sub-option.
fig = agis.study_area(
'India',
[('state', 'Uttarakhand')], # zoom chain: (level, name); last entry = the detail panel
template='two', # single · two · cascade · series · grid
terrain=False, # True -> the detail panel becomes a shaded-relief DEM
suptitle='India — Uttarakhand (every option)',
# ═══════════ HIGHLIGHT — marks the child region in each context panel ═══════════
highlight_style='overlay', # overlay · rect · circle · fill
highlight_color='#d6263b',
highlight_edge='#7a0d18', # border colour (defaults to highlight_color)
highlight_alpha=0.35, # fill opacity (overlay / rect / circle)
highlight_width=2.2, # border thickness
# ═══════════ CONNECTORS — links = True/False, or a dict for full control ═══════════
links={
'single': True, # one line per hop (default: two corner lines)
'shrink': (6, -14), # (start, end) in POINTS: +shrink · -STRETCH past the end
'dots': True, # endpoint markers …
'dot_size': 9, 'dot_color': '#b30000', # … enlarged & coloured
'anchors': [('r', (0.0, 0.5))], # WHERE lines attach:
# source = corner/edge name tl·tr·bl·br·t·b·l·r·c OR an explicit (lon, lat) point
# target = (x, y) axes fraction on the destination panel
# a list applies to every hop; a dict {hop_index: [...]} sets each hop
'pad': 0.18, # padding of the (invisible) locator box the corners sit on
'alpha': 0.95,
'color': '#d6263b', 'width': 1.8, # line colour & width
'style': '-', # '-' · '--' · ':' · '-.'
'box': False, # also draw the locator rectangle
# 'show': False, # hide all connectors
},
# ═══════════ GRID & TICKS — graticule (scalar for all panels, or a per-panel list) ═══════════
graticule={
'grid': True, # draw grid lines (False = keep ticks/labels only)
'grid_color': '#9fb3c8', 'grid_lw': 0.5, 'grid_alpha': 0.35,
'grid_style': '--', # '-' · '--' · ':' · '-.'
'interval': None, # degree spacing (None = auto); or x_interval / y_interval / n
'sides': 'lb', # which sides get labels: 'lb' · 'all' · any of l/r/t/b
'ticks': True, 'labels': True, # tick marks / degree labels on-off
'tick_dir': 'in', # 'in' · 'out' · 'inout'
'tick_len': 4, 'tick_width': 0.8, 'tick_color': '#333',
'minor': True, 'minor_n': 4, # minor ticks between majors
'fontsize': 6, 'label_color': '#333',
'bold': False, 'italic': False, # rotate_x / rotate_y rotate the labels
},
graticule_interval=None, # shortcut for the degree spacing (scalar or per-panel list)
# ═══════════ NORTH ARROW — True/False · a style string · a dict (scalar or per-panel list) ═══════════
north_arrow={
'style': 'rose', # classic · minimal · pointer · rose
'size': 0.11, # arrow height as a fraction of the axes
'color': '#0b3b34', 'edge': '#06222b',
'label': 'N', 'label_color': '#0b3b34', 'label_size': 10,
'loc': (0.92, 0.90), 'coords': 'axes', # 'axes' fraction, or 'data' -> (lon, lat)
'rotation': 0,
},
# ═══════════ SCALE BAR — True/False · a style string · a dict (scalar or per-panel list) ═══════════
scale_bar={
'style': 'double', # bar · simple · stepped · double · ticks
'units': 'km', # km · mi
'divisions': 4, # segments for stepped / double / ticks
'color': '#0b3b34', 'edge': '#0b3b34', 'text_color': '#0b3b34',
'size': 1.0, # scales the bar length
'loc': (0.07, 0.06), 'coords': 'axes',
# 'length_km': 100, # force an exact length (auto if omitted)
},
# ═══════════ LAYERS — each is a scalar OR a per-panel list [country, detail] ═══════════
sea=[{'source': 'ne10m', 'color': '#a9d3e8'}, False], # ocean on the country panel only
# sea=True · a colour · {'source':'auto'/'ne10m'/'ocean', 'extent', 'labels', …} · False
#rivers=[{'color': '#2b7bba', 'scale': '10m'}, False], # NE rivers on country; off on detail
# rivers=True · a colour · {'source':'osm'} (dense OSM) · {'scale':'10m'} · False
labels=[False, False], # region-name labels per panel (True / False)
# ═══════════ COLOURS & TITLES ═══════════
palette='ocean', # context-panel fills
detail_palette='vibrant', # deepest-panel fill
cmap='terrain', # colormap used when terrain=True
title_inside=False, # move panel titles inside the map (scalar or list)
title_loc=(0.03, 0.96), title_box=True,
# ═══════════ SIZING ═══════════
uniform_panels=False, # keep panel boxes the SAME size (no shrink-to-aspect).
# NOTE: a ~square country in a tall/narrow panel gets its LATITUDE range stretched to
# fill the box — that adds an ocean band below the country. Two clean fixes:
# • zoom in on that panel (below) — keeps both panels the same size, or
# • uniform_panels=False — shrinks each panel to its own shape (no band, sizes differ).
figsize=(13, 6.5),
gap=0.1, # spacing between panels (scalar, or (wgap, hgap))
# width_ratios=[1, 1.4], height_ratios=None, wspace=…, hspace=…, # fine-grained sizing
# panel_scale={'detail': 1.2}, # enlarge/shrink specific panels by index or role
zoom=[1.0, 1.0], # per-panel zoom (>1 in, <1 out). Country panel zoomed
# in to crop the ocean band; detail panel left as-is.
download=True,
)
agis.show()
# ★ THE COMPLETE REFERENCE — every study_area() option, with every sub-option.
fig = agis.study_area(
'India',
[('state', 'Uttarakhand')], # zoom chain: (level, name); last entry = the detail panel
template='two', # single · two · cascade · series · grid
terrain=False, # True -> the detail panel becomes a shaded-relief DEM
suptitle='India — Uttarakhand (every option)',
# ═══════════ HIGHLIGHT — marks the child region in each context panel ═══════════
highlight_style='overlay', # overlay · rect · circle · fill
highlight_color='#d6263b',
highlight_edge='#7a0d18', # border colour (defaults to highlight_color)
highlight_alpha=0.35, # fill opacity (overlay / rect / circle)
highlight_width=2.2, # border thickness
# ═══════════ CONNECTORS — links = True/False, or a dict for full control ═══════════
links={
'single': True, # one line per hop (default: two corner lines)
'shrink': (6, -14), # (start, end) in POINTS: +shrink · -STRETCH past the end
'dots': True, # endpoint markers …
'dot_size': 9, 'dot_color': '#b30000', # … enlarged & coloured
'anchors': [('r', (0.0, 0.5))], # WHERE lines attach:
# source = corner/edge name tl·tr·bl·br·t·b·l·r·c OR an explicit (lon, lat) point
# target = (x, y) axes fraction on the destination panel
# a list applies to every hop; a dict {hop_index: [...]} sets each hop
'pad': 0.18, # padding of the (invisible) locator box the corners sit on
'alpha': 0.95,
'color': '#d6263b', 'width': 1.8, # line colour & width
'style': '-', # '-' · '--' · ':' · '-.'
'box': False, # also draw the locator rectangle
# 'show': False, # hide all connectors
},
# ═══════════ GRID & TICKS — graticule (scalar for all panels, or a per-panel list) ═══════════
graticule={
'grid': True, # draw grid lines (False = keep ticks/labels only)
'grid_color': '#9fb3c8', 'grid_lw': 0.5, 'grid_alpha': 0.35,
'grid_style': '--', # '-' · '--' · ':' · '-.'
'interval': None, # degree spacing (None = auto); or x_interval / y_interval / n
'sides': 'lb', # which sides get labels: 'lb' · 'all' · any of l/r/t/b
'ticks': True, 'labels': True, # tick marks / degree labels on-off
'tick_dir': 'in', # 'in' · 'out' · 'inout'
'tick_len': 4, 'tick_width': 0.8, 'tick_color': '#333',
'minor': True, 'minor_n': 4, # minor ticks between majors
'fontsize': 6, 'label_color': '#333',
'bold': False, 'italic': False, # rotate_x / rotate_y rotate the labels
},
graticule_interval=None, # shortcut for the degree spacing (scalar or per-panel list)
# ═══════════ NORTH ARROW — True/False · a style string · a dict (scalar or per-panel list) ═══════════
north_arrow={
'style': 'rose', # classic · minimal · pointer · rose
'size': 0.11, # arrow height as a fraction of the axes
'color': '#0b3b34', 'edge': '#06222b',
'label': 'N', 'label_color': '#0b3b34', 'label_size': 10,
'loc': (0.92, 0.90), 'coords': 'axes', # 'axes' fraction, or 'data' -> (lon, lat)
'rotation': 0,
},
# ═══════════ SCALE BAR — True/False · a style string · a dict (scalar or per-panel list) ═══════════
scale_bar={
'style': 'double', # bar · simple · stepped · double · ticks
'units': 'km', # km · mi
'divisions': 4, # segments for stepped / double / ticks
'color': '#0b3b34', 'edge': '#0b3b34', 'text_color': '#0b3b34',
'size': 1.0, # scales the bar length
'loc': (0.07, 0.06), 'coords': 'axes',
# 'length_km': 100, # force an exact length (auto if omitted)
},
# ═══════════ LAYERS — each is a scalar OR a per-panel list [country, detail] ═══════════
sea=[{'source': 'ne10m', 'color': '#a9d3e8'}, False], # ocean on the country panel only
# sea=True · a colour · {'source':'auto'/'ne10m'/'ocean', 'extent', 'labels', …} · False
#rivers=[{'color': '#2b7bba', 'scale': '10m'}, False], # NE rivers on country; off on detail
# rivers=True · a colour · {'source':'osm'} (dense OSM) · {'scale':'10m'} · False
labels=[False, False], # region-name labels per panel (True / False)
# ═══════════ COLOURS & TITLES ═══════════
palette='ocean', # context-panel fills
detail_palette='vibrant', # deepest-panel fill
cmap='terrain', # colormap used when terrain=True
title_inside=False, # move panel titles inside the map (scalar or list)
title_loc=(0.03, 0.96), title_box=True,
# ═══════════ SIZING ═══════════
uniform_panels=False, # keep panel boxes the SAME size (no shrink-to-aspect).
# NOTE: a ~square country in a tall/narrow panel gets its LATITUDE range stretched to
# fill the box — that adds an ocean band below the country. Two clean fixes:
# • zoom in on that panel (below) — keeps both panels the same size, or
# • uniform_panels=False — shrinks each panel to its own shape (no band, sizes differ).
figsize=(13, 6.5),
gap=0.1, # spacing between panels (scalar, or (wgap, hgap))
# width_ratios=[1, 1.4], height_ratios=None, wspace=…, hspace=…, # fine-grained sizing
# panel_scale={'detail': 1.2}, # enlarge/shrink specific panels by index or role
zoom=[1.0, 1.0], # per-panel zoom (>1 in, <1 out). Country panel zoomed
# in to crop the ocean band; detail panel left as-is.
download=True,
)
agis.show()
In [2]:
Copied!
# SERIES (1×3) — arrows for connectors, clean middle grid, no title overlap.
fig = agis.study_area(
'Bangladesh',
[('division', 'Dhaka'), ('district', 'Gazipur')],
template='series',
suptitle='Bangladesh — Dhaka — Gazipur (series customized)',
# HIGHLIGHT
highlight_style='overlay', highlight_color='#f03805',
highlight_edge='#7a1c03', highlight_alpha=0.35, highlight_width=2.0,
# CONNECTORS — arrow into each next panel (needs a KERNEL RESTART to take effect)
links={'single': True, 'shrink': (8, -14),
'arrow': True, 'arrow_size': 16, # arrowhead at the destination end
'color': '#ff0000', 'width': 2.0, 'style': '-'},
# GRID & TICKS — 'interval' sets the degree spacing (density); 'lb' keeps it clean
graticule=[
{'grid': True, 'sides': 'lb', 'tick_dir': 'in', 'tick_len': 5,
'grid_style': '--', 'grid_alpha': 0.35, 'fontsize': 6}, # country
{'grid': False, 'sides': 'lb', 'tick_dir': 'out', 'tick_len': 4,
'interval': 0.5, 'fontsize': 6}, # division: 0.5° spacing
{'grid': True, 'sides': 'lb', 'grid_alpha': 0.25, 'fontsize': 6}, # district
],
north_arrow=[False, {'style': 'rose'}, {'style': 'minimal'}],
scale_bar=[False, {'style': 'stepped'}, {'style': 'double', 'units': 'km'}],
sea=[{'source': 'ne10m', 'color': '#a9d3e8'}, False, False],
labels=[False, True, False],
palette='ocean', detail_palette='vibrant',
figsize=(15, 5.2), gap=0.25,
)
fig.subplots_adjust(top=0.82) # ← push panels down so the suptitle clears the panel titles
agis.show()
# SERIES (1×3) — arrows for connectors, clean middle grid, no title overlap.
fig = agis.study_area(
'Bangladesh',
[('division', 'Dhaka'), ('district', 'Gazipur')],
template='series',
suptitle='Bangladesh — Dhaka — Gazipur (series customized)',
# HIGHLIGHT
highlight_style='overlay', highlight_color='#f03805',
highlight_edge='#7a1c03', highlight_alpha=0.35, highlight_width=2.0,
# CONNECTORS — arrow into each next panel (needs a KERNEL RESTART to take effect)
links={'single': True, 'shrink': (8, -14),
'arrow': True, 'arrow_size': 16, # arrowhead at the destination end
'color': '#ff0000', 'width': 2.0, 'style': '-'},
# GRID & TICKS — 'interval' sets the degree spacing (density); 'lb' keeps it clean
graticule=[
{'grid': True, 'sides': 'lb', 'tick_dir': 'in', 'tick_len': 5,
'grid_style': '--', 'grid_alpha': 0.35, 'fontsize': 6}, # country
{'grid': False, 'sides': 'lb', 'tick_dir': 'out', 'tick_len': 4,
'interval': 0.5, 'fontsize': 6}, # division: 0.5° spacing
{'grid': True, 'sides': 'lb', 'grid_alpha': 0.25, 'fontsize': 6}, # district
],
north_arrow=[False, {'style': 'rose'}, {'style': 'minimal'}],
scale_bar=[False, {'style': 'stepped'}, {'style': 'double', 'units': 'km'}],
sea=[{'source': 'ne10m', 'color': '#a9d3e8'}, False, False],
labels=[False, True, False],
palette='ocean', detail_palette='vibrant',
figsize=(15, 5.2), gap=0.25,
)
fig.subplots_adjust(top=0.82) # ← push panels down so the suptitle clears the panel titles
agis.show()
Ignoring fixed x limits to fulfill fixed data aspect with adjustable data limits. Ignoring fixed y limits to fulfill fixed data aspect with adjustable data limits. Ignoring fixed x limits to fulfill fixed data aspect with adjustable data limits. Ignoring fixed y limits to fulfill fixed data aspect with adjustable data limits. Ignoring fixed y limits to fulfill fixed data aspect with adjustable data limits.
In [19]:
Copied!
agis.study_area(
'USA', steps=[('state','California'),('district','Mariposa')],
template='series', # flat 3-across strip
terrain=True, cmap='terrain', # shaded relief on the focus panel
uniform_panels=True, # keep all three panel boxes equal
highlight_style='rect', # rectangle indicator (overlay|rect|circle)
highlight_color='#e63946', highlight_edge='#7a0c18', # red box, dark edge
highlight_alpha=0.22, highlight_width=2.2, # light fill, firm border
palette='vibrant', detail_palette='earth', # context vs detail colours
links=True, link_color='#e63946', link_width=1.6, box=False, # built-in connectors
north_arrow={'style':'classic','size':0.13,'color':'#1d3557','edge':'#0b1b2b'},
scale_bar=[False, True, {'style':'stepped','divisions':4,'color':'#1d3557'}], # per panel
graticule=[True, True, {'grid':True,'grid_style':':','grid_alpha':0.4,
'sides':'all','interval':0.3,'tick_dir':'in','fontsize':7}], # finer on focus
colorbar={'loc':'bottom','length':0.6,'pad':0.06,'label':'Elevation (m)'},
figsize=(18, 6.5),
suptitle='United States → California → Mariposa (Sierra Nevada)',
);
agis.study_area(
'USA', steps=[('state','California'),('district','Mariposa')],
template='series', # flat 3-across strip
terrain=True, cmap='terrain', # shaded relief on the focus panel
uniform_panels=True, # keep all three panel boxes equal
highlight_style='rect', # rectangle indicator (overlay|rect|circle)
highlight_color='#e63946', highlight_edge='#7a0c18', # red box, dark edge
highlight_alpha=0.22, highlight_width=2.2, # light fill, firm border
palette='vibrant', detail_palette='earth', # context vs detail colours
links=True, link_color='#e63946', link_width=1.6, box=False, # built-in connectors
north_arrow={'style':'classic','size':0.13,'color':'#1d3557','edge':'#0b1b2b'},
scale_bar=[False, True, {'style':'stepped','divisions':4,'color':'#1d3557'}], # per panel
graticule=[True, True, {'grid':True,'grid_style':':','grid_alpha':0.4,
'sides':'all','interval':0.3,'tick_dir':'in','fontsize':7}], # finer on focus
colorbar={'loc':'bottom','length':0.6,'pad':0.06,'label':'Elevation (m)'},
figsize=(18, 6.5),
suptitle='United States → California → Mariposa (Sierra Nevada)',
);
In [18]:
Copied!
fig = agis.study_area(
'Bangladesh',
steps=[('division', 'Dhaka'), ('district', 'Madaripur')],
template='cascade', # single | two | cascade | series | grid
terrain=True, cmap='gist_earth', # shaded relief on the focus map
palette='vibrant', detail_palette='earth', # context fill | mid-panel fill
# --- glowing overlay highlight (fill + border) on each parent panel ---
highlight_style='overlay', # overlay | rect | circle
highlight_color='#7be0c6', # soft mint fill
highlight_edge='#3ad29f', # brighter mint border = the 'glow'
highlight_alpha=0.16, # fill opacity (0 = no fill)
highlight_width=2.6, # border thickness
# --- built-in connectors OFF (we draw custom wedges below) ---
links=False, box=False,
# --- grid OFF, keep degree ticks on all four sides, pointing inward ---
graticule={'grid': False, 'sides': 'all', 'tick_dir': 'in',
'tick_len': 4, 'fontsize': 7, 'label_color': '#0b3b34','interval': 0.5},
# --- compass rose, lower-data-green, dark edge ---
north_arrow={'style': 'rose', 'size': 0.13, 'color': '#0b3b34',
'edge': '#06222b', 'label_color': '#0b3b34',
'loc': (0.9, 0.86)},
# --- double scale bar, 4 divisions, km ---
scale_bar={'style': 'double', 'divisions': 4, 'color': '#0b3b34',
'text_color': '#0b3b34', 'units': 'km'},
# --- layout: equal boxes, focus map enlarged, comfortable gaps ---
uniform_panels=True, panel_scale={'detail': 1.45}, gap=0.16,
zoom=[1.0, 1.1, 1.0], # per-panel zoom (country, division, district)
figsize=(15, 9),
suptitle='Bangladesh \u2192 Dhaka \u2192 Madaripur (fully customized)',
)
# --- custom wedge connectors (only `import acadgis as agis` needed) ---
# Two lines fan from the focus panel's left corners to Madaripur's spot on
# the division map, and one from the division panel up to Dhaka on the
# country map -- a classic 'where am I' wedge.
p1, p2, p3 = fig.panels[:3] # country, division, district panels
for corner in [(0.0, 1.0), (0.0, 0.0)]: # top-left, bottom-left
agis.connect(fig, p3, corner, p2, (90.2, 23.2), # -> Madaripur (lon, lat)
a_coords='axes', b_coords='data', # axes corner -> map point
color='#1b9aaa', style=(0, (6, 3)), width=1.4)
agis.connect(fig, p2, (0.5, 1.0), p1, (90.4, 23.8), # division top -> Dhaka
a_coords='axes', b_coords='data',
color='#1b9aaa', style=(0, (6, 3)), width=1.4)
agis.show()
fig = agis.study_area(
'Bangladesh',
steps=[('division', 'Dhaka'), ('district', 'Madaripur')],
template='cascade', # single | two | cascade | series | grid
terrain=True, cmap='gist_earth', # shaded relief on the focus map
palette='vibrant', detail_palette='earth', # context fill | mid-panel fill
# --- glowing overlay highlight (fill + border) on each parent panel ---
highlight_style='overlay', # overlay | rect | circle
highlight_color='#7be0c6', # soft mint fill
highlight_edge='#3ad29f', # brighter mint border = the 'glow'
highlight_alpha=0.16, # fill opacity (0 = no fill)
highlight_width=2.6, # border thickness
# --- built-in connectors OFF (we draw custom wedges below) ---
links=False, box=False,
# --- grid OFF, keep degree ticks on all four sides, pointing inward ---
graticule={'grid': False, 'sides': 'all', 'tick_dir': 'in',
'tick_len': 4, 'fontsize': 7, 'label_color': '#0b3b34','interval': 0.5},
# --- compass rose, lower-data-green, dark edge ---
north_arrow={'style': 'rose', 'size': 0.13, 'color': '#0b3b34',
'edge': '#06222b', 'label_color': '#0b3b34',
'loc': (0.9, 0.86)},
# --- double scale bar, 4 divisions, km ---
scale_bar={'style': 'double', 'divisions': 4, 'color': '#0b3b34',
'text_color': '#0b3b34', 'units': 'km'},
# --- layout: equal boxes, focus map enlarged, comfortable gaps ---
uniform_panels=True, panel_scale={'detail': 1.45}, gap=0.16,
zoom=[1.0, 1.1, 1.0], # per-panel zoom (country, division, district)
figsize=(15, 9),
suptitle='Bangladesh \u2192 Dhaka \u2192 Madaripur (fully customized)',
)
# --- custom wedge connectors (only `import acadgis as agis` needed) ---
# Two lines fan from the focus panel's left corners to Madaripur's spot on
# the division map, and one from the division panel up to Dhaka on the
# country map -- a classic 'where am I' wedge.
p1, p2, p3 = fig.panels[:3] # country, division, district panels
for corner in [(0.0, 1.0), (0.0, 0.0)]: # top-left, bottom-left
agis.connect(fig, p3, corner, p2, (90.2, 23.2), # -> Madaripur (lon, lat)
a_coords='axes', b_coords='data', # axes corner -> map point
color='#1b9aaa', style=(0, (6, 3)), width=1.4)
agis.connect(fig, p2, (0.5, 1.0), p1, (90.4, 23.8), # division top -> Dhaka
a_coords='axes', b_coords='data',
color='#1b9aaa', style=(0, (6, 3)), width=1.4)
agis.show()
In [3]:
Copied!
# CASCADE (2 stacked + 1 tall) — fully customized; boxed connectors.
fig = agis.study_area(
'India',
[('state', 'Uttarakhand'), ('district', 'Dehradun')],
template='cascade',
suptitle='India — Uttarakhand → Dehradun (cascade, fully customized)',
# HIGHLIGHT — rectangular locator
highlight_style='fill', highlight_color="#ff1900",
highlight_edge="#ff0090", highlight_alpha=0.16, highlight_width=1.8,
# CONNECTORS — dashed, drawing the locator box + big dots
links={'shrink': (4, -8), 'dots': True, 'dot_size': 7, 'dot_color': '#1d3557',
'box': True, 'color': '#1d3557', 'width': 1.4, 'style': '--', 'pad': 0.20},
# GRID & TICKS — scalar (all panels)
graticule=[
{'grid': True, 'sides': 'lb', 'tick_dir': 'in', 'tick_len': 5,
'grid_style': '--', 'grid_alpha': 0.35, 'fontsize': 6}, # country
{'grid': False, 'sides': 'lb', 'tick_dir': 'out', 'tick_len': 4,
'interval': 0.5, 'fontsize': 6}, # division: 0.5° spacing
{'grid': True, 'sides': 'all', 'grid_alpha': 0.25, 'fontsize': 6}, # district
],
# DECORATIONS
north_arrow={'style': 'classic', 'size': 0.10, 'color': '#1d3557'},
scale_bar={'style': 'ticks', 'divisions': 4, 'units': 'km', 'color': '#1d3557'},
# LAYERS — rivers on every panel; no sea (inland); labels on the state panel
#rivers={'color': '#3a7bd5', 'scale': '10m'},
labels=[False, True, False],
sea=False,
palette='spectral', detail_palette='pastel',
figsize=(12, 8), gap=(0.16, 0.20),
title_inside=[False, False, True], # tuck the detail-panel title inside the map
)
agis.show()
# CASCADE (2 stacked + 1 tall) — fully customized; boxed connectors.
fig = agis.study_area(
'India',
[('state', 'Uttarakhand'), ('district', 'Dehradun')],
template='cascade',
suptitle='India — Uttarakhand → Dehradun (cascade, fully customized)',
# HIGHLIGHT — rectangular locator
highlight_style='fill', highlight_color="#ff1900",
highlight_edge="#ff0090", highlight_alpha=0.16, highlight_width=1.8,
# CONNECTORS — dashed, drawing the locator box + big dots
links={'shrink': (4, -8), 'dots': True, 'dot_size': 7, 'dot_color': '#1d3557',
'box': True, 'color': '#1d3557', 'width': 1.4, 'style': '--', 'pad': 0.20},
# GRID & TICKS — scalar (all panels)
graticule=[
{'grid': True, 'sides': 'lb', 'tick_dir': 'in', 'tick_len': 5,
'grid_style': '--', 'grid_alpha': 0.35, 'fontsize': 6}, # country
{'grid': False, 'sides': 'lb', 'tick_dir': 'out', 'tick_len': 4,
'interval': 0.5, 'fontsize': 6}, # division: 0.5° spacing
{'grid': True, 'sides': 'all', 'grid_alpha': 0.25, 'fontsize': 6}, # district
],
# DECORATIONS
north_arrow={'style': 'classic', 'size': 0.10, 'color': '#1d3557'},
scale_bar={'style': 'ticks', 'divisions': 4, 'units': 'km', 'color': '#1d3557'},
# LAYERS — rivers on every panel; no sea (inland); labels on the state panel
#rivers={'color': '#3a7bd5', 'scale': '10m'},
labels=[False, True, False],
sea=False,
palette='spectral', detail_palette='pastel',
figsize=(12, 8), gap=(0.16, 0.20),
title_inside=[False, False, True], # tuck the detail-panel title inside the map
)
agis.show()
In [5]:
Copied!
fig = agis.study_area(
'United States',
[('state', 'California'), ('county', 'Los Angeles')], # zoom chain (level, name); last entry = deepest panel
template='cascade', # country -> state -> district (2 stacked panels + 1 tall detail)
suptitle='United States — California → Los Angeles (cascade)',
# ---- HIGHLIGHT (each context panel marks its child region) ----
highlight_style='rect', # overlay · rect · circle
highlight_color='#d6263b',
highlight_alpha=0.15,
highlight_width=1.8,
# ---- CONNECTORS (link each level to the next) ----
links=True,
link_color='#d6263b',
link_width=1.5,
link_style='-', # '-' solid · '--' dashed · ':' dotted
box=False, # draw a locator box around each region
# ---- COLOURS ----
palette='spectral', # context-panel fills
detail_palette='pastel', # deepest-panel fill
# ---- DECORATIONS (scalar = all panels, or a [list] per panel) ----
north_arrow={'style': 'rose'},
scale_bar=[False, True, True],
graticule={'grid': True, 'sides': 'lb', 'grid_alpha': 0.25, 'fontsize': 6},
figsize=(12, 8),
)
fig.panels[0].set_xlim(-128, -66); fig.panels[0].set_ylim(23, 51) # crop the lower-48 overview (connectors re-anchor via transData)
agis.show()
fig = agis.study_area(
'United States',
[('state', 'California'), ('county', 'Los Angeles')], # zoom chain (level, name); last entry = deepest panel
template='cascade', # country -> state -> district (2 stacked panels + 1 tall detail)
suptitle='United States — California → Los Angeles (cascade)',
# ---- HIGHLIGHT (each context panel marks its child region) ----
highlight_style='rect', # overlay · rect · circle
highlight_color='#d6263b',
highlight_alpha=0.15,
highlight_width=1.8,
# ---- CONNECTORS (link each level to the next) ----
links=True,
link_color='#d6263b',
link_width=1.5,
link_style='-', # '-' solid · '--' dashed · ':' dotted
box=False, # draw a locator box around each region
# ---- COLOURS ----
palette='spectral', # context-panel fills
detail_palette='pastel', # deepest-panel fill
# ---- DECORATIONS (scalar = all panels, or a [list] per panel) ----
north_arrow={'style': 'rose'},
scale_bar=[False, True, True],
graticule={'grid': True, 'sides': 'lb', 'grid_alpha': 0.25, 'fontsize': 6},
figsize=(12, 8),
)
fig.panels[0].set_xlim(-128, -66); fig.panels[0].set_ylim(23, 51) # crop the lower-48 overview (connectors re-anchor via transData)
agis.show()
Ignoring fixed y limits to fulfill fixed data aspect with adjustable data limits. Ignoring fixed x limits to fulfill fixed data aspect with adjustable data limits. Ignoring fixed y limits to fulfill fixed data aspect with adjustable data limits. Ignoring fixed x limits to fulfill fixed data aspect with adjustable data limits.
In [6]:
Copied!
fig = agis.study_area(
'China',
[('province', 'Guangdong'), ('district', 'Shenzhen')], # zoom chain (level, name); last entry = deepest panel
template='cascade', # country -> state -> district (2 stacked panels + 1 tall detail)
suptitle='China — Guangdong → Shenzhen (cascade)',
# ---- HIGHLIGHT (each context panel marks its child region) ----
highlight_style='rect', # overlay · rect · circle
highlight_color='#d6263b',
highlight_alpha=0.15,
highlight_width=1.8,
# ---- CONNECTORS (link each level to the next) ----
links=True,
link_color='#d6263b',
link_width=1.5,
link_style='-', # '-' solid · '--' dashed · ':' dotted
box=False, # draw a locator box around each region
# ---- COLOURS ----
palette='spectral', # context-panel fills
detail_palette='pastel', # deepest-panel fill
# ---- DECORATIONS (scalar = all panels, or a [list] per panel) ----
north_arrow={'style': 'rose'},
scale_bar=True,
graticule={'grid': True, 'sides': 'lb', 'grid_alpha': 0.25, 'fontsize': 6},
figsize=(12, 8),
)
agis.show()
fig = agis.study_area(
'China',
[('province', 'Guangdong'), ('district', 'Shenzhen')], # zoom chain (level, name); last entry = deepest panel
template='cascade', # country -> state -> district (2 stacked panels + 1 tall detail)
suptitle='China — Guangdong → Shenzhen (cascade)',
# ---- HIGHLIGHT (each context panel marks its child region) ----
highlight_style='rect', # overlay · rect · circle
highlight_color='#d6263b',
highlight_alpha=0.15,
highlight_width=1.8,
# ---- CONNECTORS (link each level to the next) ----
links=True,
link_color='#d6263b',
link_width=1.5,
link_style='-', # '-' solid · '--' dashed · ':' dotted
box=False, # draw a locator box around each region
# ---- COLOURS ----
palette='spectral', # context-panel fills
detail_palette='pastel', # deepest-panel fill
# ---- DECORATIONS (scalar = all panels, or a [list] per panel) ----
north_arrow={'style': 'rose'},
scale_bar=True,
graticule={'grid': True, 'sides': 'lb', 'grid_alpha': 0.25, 'fontsize': 6},
figsize=(12, 8),
)
agis.show()
In [7]:
Copied!
fig = agis.study_area(
'South Korea',
[('province', 'Gyeonggi-do'), ('district', 'Suwon')], # zoom chain (level, name); last entry = deepest panel
template='cascade', # country -> state -> district (2 stacked panels + 1 tall detail)
suptitle='South Korea — Gyeonggi-do → Suwon (cascade)',
# ---- HIGHLIGHT (each context panel marks its child region) ----
highlight_style='rect', # overlay · rect · circle
highlight_color='#d6263b',
highlight_alpha=0.15,
highlight_width=1.8,
# ---- CONNECTORS (link each level to the next) ----
links=True,
link_color='#d6263b',
link_width=1.5,
link_style='-', # '-' solid · '--' dashed · ':' dotted
box=False, # draw a locator box around each region
# ---- COLOURS ----
palette='spectral', # context-panel fills
detail_palette='pastel', # deepest-panel fill
# ---- DECORATIONS (scalar = all panels, or a [list] per panel) ----
north_arrow={'style': 'rose'},
scale_bar=True,
graticule={'grid': True, 'sides': 'lb', 'grid_alpha': 0.25, 'fontsize': 6},
figsize=(12, 8),
)
agis.show()
fig = agis.study_area(
'South Korea',
[('province', 'Gyeonggi-do'), ('district', 'Suwon')], # zoom chain (level, name); last entry = deepest panel
template='cascade', # country -> state -> district (2 stacked panels + 1 tall detail)
suptitle='South Korea — Gyeonggi-do → Suwon (cascade)',
# ---- HIGHLIGHT (each context panel marks its child region) ----
highlight_style='rect', # overlay · rect · circle
highlight_color='#d6263b',
highlight_alpha=0.15,
highlight_width=1.8,
# ---- CONNECTORS (link each level to the next) ----
links=True,
link_color='#d6263b',
link_width=1.5,
link_style='-', # '-' solid · '--' dashed · ':' dotted
box=False, # draw a locator box around each region
# ---- COLOURS ----
palette='spectral', # context-panel fills
detail_palette='pastel', # deepest-panel fill
# ---- DECORATIONS (scalar = all panels, or a [list] per panel) ----
north_arrow={'style': 'rose'},
scale_bar=True,
graticule={'grid': True, 'sides': 'lb', 'grid_alpha': 0.25, 'fontsize': 6},
figsize=(12, 8),
)
agis.show()
In [20]:
Copied!
fig = agis.study_area(
'Bangladesh',
[('division', 'Dhaka'), ('district', 'Gazipur'), ('upazila', 'Sreepur')],
template='grid',
suptitle='Bangladesh — Dhaka → Gazipur → Sreepur (grid)',
highlight_style='overlay', highlight_color='#9c2f2f',
highlight_edge='#5a1414', highlight_alpha=0.30, highlight_width=1.8,
# CONNECTORS — single arrows, NO dots (now follow the drill-down chain)
links={'single': True, 'arrow': True, 'arrow_size': 14,
'color': '#9c2f2f', 'width': 1.6}, # ← dots removed; add 'dots': True only if you want them
graticule={'grid': True, 'sides': 'lb', 'tick_dir': 'in', 'grid_alpha': 0.25, 'fontsize': 6},
north_arrow={'style': 'minimal'},
scale_bar=[{'style': 'bar'}, {'style': 'stepped'}, {'style': 'double'}, {'style': 'ticks'}],
sea=[{'source': 'ne10m', 'color': '#a9d3e8'}, False, False, False],
labels=[False, False, True, False],
palette='earth', detail_palette='spectral',
figsize=(11, 10), gap=(0.16, 0.18),
)
agis.show()
fig = agis.study_area(
'Bangladesh',
[('division', 'Dhaka'), ('district', 'Gazipur'), ('upazila', 'Sreepur')],
template='grid',
suptitle='Bangladesh — Dhaka → Gazipur → Sreepur (grid)',
highlight_style='overlay', highlight_color='#9c2f2f',
highlight_edge='#5a1414', highlight_alpha=0.30, highlight_width=1.8,
# CONNECTORS — single arrows, NO dots (now follow the drill-down chain)
links={'single': True, 'arrow': True, 'arrow_size': 14,
'color': '#9c2f2f', 'width': 1.6}, # ← dots removed; add 'dots': True only if you want them
graticule={'grid': True, 'sides': 'lb', 'tick_dir': 'in', 'grid_alpha': 0.25, 'fontsize': 6},
north_arrow={'style': 'minimal'},
scale_bar=[{'style': 'bar'}, {'style': 'stepped'}, {'style': 'double'}, {'style': 'ticks'}],
sea=[{'source': 'ne10m', 'color': '#a9d3e8'}, False, False, False],
labels=[False, False, True, False],
palette='earth', detail_palette='spectral',
figsize=(11, 10), gap=(0.16, 0.18),
)
agis.show()
Ignoring fixed x limits to fulfill fixed data aspect with adjustable data limits. Ignoring fixed x limits to fulfill fixed data aspect with adjustable data limits. Ignoring fixed x limits to fulfill fixed data aspect with adjustable data limits. Ignoring fixed x limits to fulfill fixed data aspect with adjustable data limits.
2 · Study-area locator — simple¶
2 · The same locator — fully customized¶
Templates, colours, glowing highlight, custom connectors, per-map decorations, layout sizing and per-map zoom.
In [13]:
Copied!
gdf = agis.load_boundaries('Bangladesh', 'district')
PALETTES = ['classic', 'earth', 'ocean', 'pastel', 'slate', 'spectral', 'vibrant']
THEMES = ['academic', 'atlas', 'mono', 'nature', 'ocean', 'viridis']
# accent per theme (echoes each theme's highlight colour)
th_accent = {'academic': '#1d4ed8', 'atlas': '#9e0142', 'mono': '#000000',
'nature': '#bf360c', 'ocean': '#d7263d', 'viridis': '#440154'}
fig, axes = agis.plt.subplots(2, 3, figsize=(16, 10), facecolor='white')
for ax, t in zip(axes.flat, THEMES):
agis.plot(
gdf, theme=t, ax=ax,
title=t.capitalize(), # theme name as panel title
highlight='Sylhet', # one region outlined in every look
figsize=(5, 5), pad=0.04,
# rose arrow tinted to the theme accent, top-right of each panel
north_arrow={'style': 'rose', 'size': 0.12, 'color': th_accent[t],
'edge': th_accent[t], 'loc': (0.9, 0.85)},
# stepped scale bar in the theme accent, bottom-left
scale_bar={'style': 'stepped', 'divisions': 4, 'color': th_accent[t],
'text_color': th_accent[t], 'units': 'km',
'loc': (0.06, 0.06)},
# degree ticks all sides, no grid lines so each theme's fill reads cleanly
graticule={'grid': False, 'sides': 'all', 'tick_dir': 'in',
'tick_len': 3, 'fontsize': 6},
border='solid',
)
fig.suptitle('AcadGIS themes — Bangladesh districts', fontsize=16, weight='bold')
fig.subplots_adjust(left=0.03, right=0.985, top=0.93, bottom=0.04,
wspace=0.16, hspace=0.16)
agis.show()
gdf = agis.load_boundaries('Bangladesh', 'district')
PALETTES = ['classic', 'earth', 'ocean', 'pastel', 'slate', 'spectral', 'vibrant']
THEMES = ['academic', 'atlas', 'mono', 'nature', 'ocean', 'viridis']
# accent per theme (echoes each theme's highlight colour)
th_accent = {'academic': '#1d4ed8', 'atlas': '#9e0142', 'mono': '#000000',
'nature': '#bf360c', 'ocean': '#d7263d', 'viridis': '#440154'}
fig, axes = agis.plt.subplots(2, 3, figsize=(16, 10), facecolor='white')
for ax, t in zip(axes.flat, THEMES):
agis.plot(
gdf, theme=t, ax=ax,
title=t.capitalize(), # theme name as panel title
highlight='Sylhet', # one region outlined in every look
figsize=(5, 5), pad=0.04,
# rose arrow tinted to the theme accent, top-right of each panel
north_arrow={'style': 'rose', 'size': 0.12, 'color': th_accent[t],
'edge': th_accent[t], 'loc': (0.9, 0.85)},
# stepped scale bar in the theme accent, bottom-left
scale_bar={'style': 'stepped', 'divisions': 4, 'color': th_accent[t],
'text_color': th_accent[t], 'units': 'km',
'loc': (0.06, 0.06)},
# degree ticks all sides, no grid lines so each theme's fill reads cleanly
graticule={'grid': False, 'sides': 'all', 'tick_dir': 'in',
'tick_len': 3, 'fontsize': 6},
border='solid',
)
fig.suptitle('AcadGIS themes — Bangladesh districts', fontsize=16, weight='bold')
fig.subplots_adjust(left=0.03, right=0.985, top=0.93, bottom=0.04,
wspace=0.16, hspace=0.16)
agis.show()
In [16]:
Copied!
usa = agis.load_boundaries('USA', 'state')
from acadgis.decorations import north_arrow, scale_bar
# a few CONUS state capitals (lon, lat) for the points overlay
caps = {
'Washington, D.C.': (-77.04, 38.91),
'Austin': (-97.74, 30.27),
'Sacramento': (-121.49, 38.58),
'Denver': (-104.99, 39.74),
'Saint Paul': (-93.09, 44.94),
'Tallahassee': (-84.28, 30.44),
}
# --- 1) styled base map (categorical: one palette colour per state) ---
ax = agis.plot(
usa,
palette='vibrant', # classic earth ocean pastel slate spectral vibrant
title='United States — a states poster (fully customized)',
highlight=['Texas', 'California'], # outline a couple of states
labels=False, # per-state name labels (off — too busy at this scale)
legend=False, # categorical legend
figsize=(15, 9), pad=0.02, # poster size + tight margin around the data
border='solid', # solid | checker | none
north_arrow=False, # drawn after the CONUS zoom (below)
scale_bar=False, # ditto
# grid OFF, keep inward degree ticks/labels on all four sides
graticule={'grid': False, 'sides': 'all', 'tick_dir': 'in',
'tick_len': 4, 'fontsize': 7, 'label_color': '#34403d'},
)
# --- 2) zoom the parent map to the continental US ---
ax.set_xlim(-125, -66) # lon: west coast -> east coast
ax.set_ylim(24, 50) # lat: south Texas/Florida -> northern border
# --- 3) compass rose, placed by axes fraction (top-right) ---
# drawn AFTER the zoom so it sits over CONUS, not the AK/HI frame
north_arrow(ax, style='rose', size=0.12, color='#0b3b34',
edge='#06222b', label='N', label_color='#e63946',
label_size=13, coords='axes', loc=(0.965, 0.86))
# --- 4) double scale bar, lower-right, labelled in miles ---
# length_km is the real bar length; with units='mi' the label is
# converted, so 500*1.609344 km draws a clean '500 mi' bar
scale_bar(ax, style='double', divisions=5, length_km=500 * 1.609344,
units='mi', color='#0b3b34', edge='#0b3b34', text_color='#0b3b34',
size=1.0, coords='axes', loc=(0.66, 0.07))
# --- 5) Alaska & Hawaii as framed callouts (the US-map convention) ---
agis.callout(ax, usa[usa.NAME_1 == 'Alaska'], loc=(0.005, 0.04, 0.27, 0.27),
palette='vibrant', # per-region palette fill
edge='#0b3b34', lw=1.3, facecolor='white', # the frame
pad=0.04, zoom=1.0, title='Alaska', title_size=9)
agis.callout(ax, usa[usa.NAME_1 == 'Hawaii'], loc=(0.285, 0.04, 0.15, 0.18),
palette='vibrant', edge='#0b3b34', lw=1.3, facecolor='white',
pad=0.04, zoom=1.0, title='Hawaii', title_size=9)
# --- 6) a few state capitals on the CONUS map ---
agis.points(ax, caps, color='#e63946', size=42, marker='*',
edgecolor='white', linewidth=0.7,
fontsize=8, text_color='#0b3b34', dy=0.5, halo=True)
agis.show()
usa = agis.load_boundaries('USA', 'state')
from acadgis.decorations import north_arrow, scale_bar
# a few CONUS state capitals (lon, lat) for the points overlay
caps = {
'Washington, D.C.': (-77.04, 38.91),
'Austin': (-97.74, 30.27),
'Sacramento': (-121.49, 38.58),
'Denver': (-104.99, 39.74),
'Saint Paul': (-93.09, 44.94),
'Tallahassee': (-84.28, 30.44),
}
# --- 1) styled base map (categorical: one palette colour per state) ---
ax = agis.plot(
usa,
palette='vibrant', # classic earth ocean pastel slate spectral vibrant
title='United States — a states poster (fully customized)',
highlight=['Texas', 'California'], # outline a couple of states
labels=False, # per-state name labels (off — too busy at this scale)
legend=False, # categorical legend
figsize=(15, 9), pad=0.02, # poster size + tight margin around the data
border='solid', # solid | checker | none
north_arrow=False, # drawn after the CONUS zoom (below)
scale_bar=False, # ditto
# grid OFF, keep inward degree ticks/labels on all four sides
graticule={'grid': False, 'sides': 'all', 'tick_dir': 'in',
'tick_len': 4, 'fontsize': 7, 'label_color': '#34403d'},
)
# --- 2) zoom the parent map to the continental US ---
ax.set_xlim(-125, -66) # lon: west coast -> east coast
ax.set_ylim(24, 50) # lat: south Texas/Florida -> northern border
# --- 3) compass rose, placed by axes fraction (top-right) ---
# drawn AFTER the zoom so it sits over CONUS, not the AK/HI frame
north_arrow(ax, style='rose', size=0.12, color='#0b3b34',
edge='#06222b', label='N', label_color='#e63946',
label_size=13, coords='axes', loc=(0.965, 0.86))
# --- 4) double scale bar, lower-right, labelled in miles ---
# length_km is the real bar length; with units='mi' the label is
# converted, so 500*1.609344 km draws a clean '500 mi' bar
scale_bar(ax, style='double', divisions=5, length_km=500 * 1.609344,
units='mi', color='#0b3b34', edge='#0b3b34', text_color='#0b3b34',
size=1.0, coords='axes', loc=(0.66, 0.07))
# --- 5) Alaska & Hawaii as framed callouts (the US-map convention) ---
agis.callout(ax, usa[usa.NAME_1 == 'Alaska'], loc=(0.005, 0.04, 0.27, 0.27),
palette='vibrant', # per-region palette fill
edge='#0b3b34', lw=1.3, facecolor='white', # the frame
pad=0.04, zoom=1.0, title='Alaska', title_size=9)
agis.callout(ax, usa[usa.NAME_1 == 'Hawaii'], loc=(0.285, 0.04, 0.15, 0.18),
palette='vibrant', edge='#0b3b34', lw=1.3, facecolor='white',
pad=0.04, zoom=1.0, title='Hawaii', title_size=9)
# --- 6) a few state capitals on the CONUS map ---
agis.points(ax, caps, color='#e63946', size=42, marker='*',
edgecolor='white', linewidth=0.7,
fontsize=8, text_color='#0b3b34', dy=0.5, halo=True)
agis.show()