Cleopatra — Package Scope#
This document defines what Cleopatra is and is not, so that any contributor (human or LLM) can decide whether a proposed feature belongs here before writing it. If a request falls outside this scope, it should be declined or redirected, not implemented.
One-sentence scope#
Cleopatra is a high-level, matplotlib-only convenience layer for visualizing in-memory NumPy data — 2D/3D raster arrays, unstructured meshes, point clouds, vector fields, polygons, lines, and statistical distributions — with sensible scientific defaults, a shared colour-mapping/colorbar pipeline, and animation export.
Audience and design center#
- Users: scientific / research users working with geospatial and raster data who want a one-call plot with good defaults over raw matplotlib.
- Inputs: plain
numpyarrays (and array-likes). The user brings the data already loaded into memory. - Outputs: matplotlib
Figure/Axes/ artist objects (returned, not hidden), plus animations exported to GIF/MP4/MOV/AVI. - Backend: matplotlib only. Cleopatra never changes the active backend on
import;
config.Config.set_matplotlib_backend()is opt-in.
In scope#
The glyph family (data → matplotlib artist + colorbar)#
All glyphs share a Glyph base class providing the figure/axes lifecycle,
colour norms (linear, power, sym-lognorm, boundary-norm, midpoint),
colorbars, ticks, classification, and animation.
| Module | Class | Visualizes |
|---|---|---|
array_glyph |
ArrayGlyph, FacetGrid |
2D/3D NumPy raster arrays; cell-value display, point overlays, RGB, faceting, animation |
mesh_glyph |
MeshGlyph |
UGRID-style unstructured meshes via triangulation (tripcolor/tricontourf), wireframe outlines, contour labels, animation |
statistical_glyph |
StatisticalGlyph |
Histograms (1D/2D), boxplots, multiboxplots, strip plots |
scatter_glyph |
ScatterGlyph |
2D point clouds; colour + independent size encoding, size legend |
vector_glyph |
VectorGlyph |
2D vector fields as arrows, wind barbs, or streamlines; magnitude colouring |
flow_glyph |
FlowGlyph |
Magnitude-coloured, width-scaled flow polylines |
line_glyph |
LineGlyph |
Line, bar, and fill-between (band) plots |
polygon_glyph |
PolygonGlyph |
Filled / outlined polygon collections, value-coloured |
kde_glyph |
KDEGlyph |
2D Gaussian kernel-density contours (NumPy-only, no scipy) |
Supporting utilities#
colors(Colors): convert hex ↔ RGB-255 ↔ RGB-normalized, extract colour ramps from images, build matplotlib colormaps.styles: predefined line/marker styles,Scaletransforms,ColorScaleenum,MidpointNormalize, value→size mapping, classification (classify: quantiles, equal-interval, percentiles, std-mean, Fisher-Jenks/natural-breaks — all NumPy-native), and reusable legend builders (disjoint/size/width/ histogram/colorbar).tiles(optionalcleopatra[tiles]extra): fetch + stitch XYZ web-tile basemaps; reprojection helpers.reference(uses thecleopatra[tiles]extra for relief decoding / reprojection): fetch + draw fixed public reference-basemap data under your plot — Natural Earth vector layers (add_features) and a global hypsometric relief raster (add_relief), thecartopyax.coastlines()/GeoAxes.stock_img()niche. It acquires only fixed public datasets that cleopatra re-hosts as dependency-light artifacts (gzipped GeoJSON / PNG); it reads no user files and never imports GDAL/geopandas.tilesandreferenceare cleopatra's only networked features.projection: lightweight axes-frame / coordinate helpers.animation: turn a matplotlibFuncAnimationinto a saved file, GIF bytes, or an embeddable IPython image (via ffmpeg).config(Config): opt-in matplotlib-backend selection; notebook detection.
What new work generally belongs here#
- New glyph types or plot kinds that follow the "NumPy in → matplotlib
Figure/Axes out" contract and reuse the shared
Glyphpipeline. - New colour scales, classification schemes, legends, or styling that plug into the existing scalar-mapping pipeline.
- New animation export targets or colour-conversion helpers.
- Better defaults, customization knobs, and matplotlib-composition support
(shared axes,
add_colorbar=False, passing in existingax/fig).
Out of scope (decline or redirect)#
- Non-matplotlib backends / engines: Plotly, Bokeh, Altair, pyvista, datashader, OpenGL, web/JS rendering. Cleopatra is matplotlib-only.
- Data I/O and formats: reading/writing user GeoTIFF, NetCDF,
shapefiles, GeoJSON, CSV, databases. Users bring NumPy arrays already;
file/raster I/O of user data belongs in sibling packages (e.g.
pyramids), not here. The deliberate exception is thetiles/referencebasemap helpers, which fetch a handful of fixed public reference datasets (never user data) that cleopatra re-hosts as dependency-light artifacts — see "Supporting utilities". - GIS / geoprocessing: reprojection of user data, clipping, resampling,
zonal stats, CRS management beyond what the optional
tilesbasemap needs. - Interactive / GUI apps: dashboards, widget servers, event callbacks, click-to-edit tooling, real-time streaming.
- Numerical / statistical modelling: curve fitting, regression, ML, forecasting, hypothesis tests — Cleopatra displays results, it doesn't compute models. (KDE is the deliberate, self-contained exception.)
- Heavy new hard dependencies: keep the core to
numpy+matplotlib(plusffmpeg-python,hpc-utils). Anything bigger must be an optional extra liketiles, and only with strong justification. - 3D rendering (mplot3d surfaces/volumes), networked data sources other
than the
tiles/referencebasemap helpers, and general-purpose plotting that matplotlib already does well without added value.
Boundary heuristic for a feature request#
Ask, in order:
- Input — does it start from in-memory NumPy data (not a file/CRS/URL)?
(The
tiles/referencebasemap helpers are the deliberate exception: they acquire fixed public reference data, never user files.) - Output — does it produce a matplotlib
Figure/Axes/artist (or an animation of one)? - Reuse — can it build on
Glyphand the shared colour/colorbar/legend pipeline rather than a parallel stack? - Dependencies — does it stay within numpy + matplotlib, or fit cleanly as an optional extra?
If all four are "yes," it likely belongs in Cleopatra. If any is "no," it
probably belongs in a different package (data I/O → pyramids; modelling →
elsewhere) and should be declined here.