bharat-choropleth
bharat-choropleth creates dependency-free, accessible static SVG
choropleths from TopoJSON. It is a Python sibling to the repository’s React,
plain-JavaScript, and Flutter renderers, intended for reports, generated web
pages, and notebooks that should not need a browser or JavaScript runtime.
It includes no boundaries. Pass a mapping or path to your own TopoJSON and
retain the source attribution and licence for any boundary bundle you use.
The repository’s prepared bundles are under data/generated
and their notices are documented in data/ATTRIBUTION.md.
Install
pip install bharat-choropleth
# Only when you need a Matplotlib axes rather than SVG:
pip install 'bharat-choropleth[matplotlib]'
# Only when you need interactive state-to-district controls in Jupyter:
pip install 'bharat-choropleth[notebook]'
Generate an SVG
from bharat_choropleth import render_svg
values = {
"in-cs-30-goa": 6,
"in-cs-24-gujarat": 7,
"in-cs-27-maharashtra": 41,
}
svg = render_svg(
"data/generated/current-2019-states/states.topo.json",
values,
object_name="states",
title="Example state metric",
description="A static map. Regions without a supplied value are marked as no data.",
)
open("states.svg", "w", encoding="utf-8").write(svg)
render_svg returns a complete <svg> element with a title, optional
description, per-region accessible labels, an even-odd fill rule, and a
lower-to-higher legend. Features with missing, invalid, or non-finite values
receive the distinct no-data colour; they are never treated as low values.
Decode once, render repeatedly
from bharat_choropleth import decode_topology, render_svg
states = decode_topology("states.topo.json", object_name="states")
svg = render_svg(states, {"in-cs-30-goa": 6})
The decoder understands TopoJSON’s quantized delta arcs, reversed arc indexes, holes, polygons, and multi-polygons. Every part is retained—an archipelago is rendered as separate islands, never as a fabricated enclosing polygon.
Optional Matplotlib
from bharat_choropleth.matplotlib import render_matplotlib
ax = render_matplotlib("states.topo.json", values, object_name="states")
ax.figure.savefig("states.png", dpi=180, bbox_inches="tight")
The Matplotlib adapter is an extra, so importing bharat_choropleth does not
pull in Matplotlib or any other rendering dependency.
Jupyter drill-down
Install the notebook extra for an ipywidgets state selector and lazy
district loader, with an optional third level below it. The control updates its
inline SVG when a region is selected; it has no browser-map or JavaScript
runtime dependency.
from pathlib import Path
from bharat_choropleth.notebook import notebook_drilldown
root = Path.cwd()
states = root / "data/generated/current-2019-states/states.topo.json"
district_dir = root / "data/generated/current-2019-districts/districts"
map_control = notebook_drilldown(
states,
{"in-cs-30-goa": 6, "in-cs-31-lakshadweep": 43},
district_loader=lambda state_id: district_dir / f"{state_id}.topo.json",
states_object_name="states",
)
map_control.widget # Display this as the last Jupyter cell expression.
Pass district_values as either a {state_id: {district_id: value}} mapping
or a state_id -> {district_id: value} callable to colour the district view.
Add sub_district_loader for a third level — tehsils, taluks, mandals and
blocks — and a district selector appears beside the state one. It follows the
same contract as the JavaScript, React and Flutter packages: return None for
a district with no sub-district level and it stays a leaf, keeping the district
view rather than opening an empty one, and is not offered again. Back then
steps one level at a time rather than returning straight to the national map.
sub_district_dir = root / "data/generated/current-2019-subdistricts/subdistricts"
def load_sub_districts(district_id):
path = sub_district_dir / f"{district_id}.topo.json"
return path if path.exists() else None # three districts genuinely have none
map_control = notebook_drilldown(
states,
{"in-cs-30-goa": 6, "in-cs-31-lakshadweep": 43},
district_loader=lambda state_id: district_dir / f"{state_id}.topo.json",
sub_district_loader=load_sub_districts,
states_object_name="states",
)
sub_district_values takes the same two shapes as district_values, keyed by
district id. Omit sub_district_loader and the control stays state-to-district
with no district selector shown at all.
API
| Item | Purpose |
|---|---|
load_topology(source) |
Load a TopoJSON mapping or JSON file path. |
decode_topology(source, object_name=...) |
Decode Polygon/MultiPolygon areas into immutable Feature objects. |
ColorScale.fit(values) |
Fit the shared low-to-high colour ramp to finite values. |
render_svg(source, values, ...) |
Create a complete static, accessible SVG string. |
bharat_choropleth.matplotlib.render_matplotlib(...) |
Optional static Matplotlib renderer. |
bharat_choropleth.notebook.notebook_drilldown(...) |
Optional ipywidgets state-to-district-to-sub-district SVG control. |
Develop and package
python -m unittest discover -s tests -v
python -m build
twine check dist/*
Publishing to PyPI is intentionally a separate, identity-bound action:
python -m twine upload --repository testpypi dist/* # optional first check
python -m twine upload dist/*
Never commit a PyPI token or generated third-party boundary data without first checking its redistribution conditions.
Metadata
Release files for bharat-choropleth 0.2.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| bharat_choropleth-0.2.0.tar.gz | 18.8 kB | Without provenance | Details for bharat_choropleth-0.2.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| bharat_choropleth-0.2.0-py3-none-any.whl | Python 3 | none | any | Details for bharat_choropleth-0.2.0-py3-none-any.whl |
Total release size: 35.5 kB
Release files / bharat_choropleth-0.2.0.tar.gz
| Download URL | bharat_choropleth-0.2.0.tar.gz |
|---|---|
| Size | 18.8 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
d257e701bc036101cde6fd06661c15059212b40b204f92dbcde4c5c9c83ceeec
|
|
BLAKE2b-256 checksum How to use checksums |
5e75dc8c0995d6294ffe1efd29cfd66d893eaf19698c12e53f68e4a2b430bdd1
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.12
|
Release files / bharat_choropleth-0.2.0-py3-none-any.whl
| Download URL | bharat_choropleth-0.2.0-py3-none-any.whl |
|---|---|
| Size | 16.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
c998226a443ab6bc5dd22d91a23f304aae5dc66e331bf7bf6e6ef64fc437e5e4
|
|
BLAKE2b-256 checksum How to use checksums |
9a4944c45feef00e5c4bef31cb9c831a4981ec36fd6cc56921371c642159f404
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.12
|
Security for bharat-choropleth 0.2.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.