Theming
ds.theme() registers a global Altair theme, so every chart you build afterwards inherits
perceptually uniform palettes and publication-ready styling. Call it once; override per chart with
ordinary Altair encodings. Calling it again replaces the theme entirely.
Before and after
Section titled “Before and after”The same Altair code, with exactly one line added - ds.theme():
import altair as altimport dysonsphere as dsfrom vega_datasets import data
ds.theme()
cars = ds.ensure_polars(data.cars()).drop_nulls(["Miles_per_Gallon", "Horsepower"])
chart = ( alt.Chart(cars) .mark_point() .encode( x=alt.X("Horsepower:Q"), y=alt.Y("Miles_per_Gallon:Q", title="Miles per gallon"), color=alt.Color("Origin:N"), ))ds.theme()Dark mode
Section titled “Dark mode”Dark-background figures keep getting more common: notebooks render inline charts against the
dark editor themes most IDEs default to, and dark or black slide backgrounds are increasingly
the norm in scientific and industrial presentations alike. ds.theme(darkmode=True) inverts the
axis, label, and text ink while keeping palette colors intact - one flag, same chart code:
import altair as altimport dysonsphere as dsfrom vega_datasets import data
# darkmode=True inverts the ink; chartFill auto-resolves to black.ds.theme(darkmode=True, transparent=False)
cars = ds.ensure_polars(data.cars()).drop_nulls(["Miles_per_Gallon", "Horsepower"])
chart = ( alt.Chart(cars) .mark_point() .encode( x=alt.X("Horsepower:Q"), y=alt.Y("Miles_per_Gallon:Q", title="Miles per gallon"), color=alt.Color("Origin:N"), ))chartFilldarkmode=True - black chartFillThese two pin transparent=False, so each bakes its own contrasting chartFill background
(auto: white, black in darkmode). Ordinarily dysonsphere draws transparent instead, letting the
page or slide provide the ground - every chart on this site swaps ink with the site’s light/dark
toggle, which is this same darkmode flag at work.
Palettes
Section titled “Palettes”Pass palette= to set the categorical color scheme - any palette name from ds.colors (browse
them all in the Palettes gallery):
import altair as altimport dysonsphere as dsfrom vega_datasets import data
ds.theme(palette="blues", xLabelAngle=-45)
barley = data.barley()
chart = ( alt.Chart(barley) .mark_bar() .encode( x=alt.X("variety:N", sort="-y", title="Variety"), y=alt.Y("mean(yield):Q", title="Mean yield (bu/acre)"), color=alt.Color("variety:N", legend=None), ))Per-type palettes
Section titled “Per-type palettes”palette sets the master categorical scheme. To recolor just one channel, use the per-type keys:
categoryPalette, divergingPalette, heatmapPalette, ordinalPalette, rampPalette. Here only
the continuous heatmap is restyled:
import altair as altimport dysonsphere as dsfrom vega_datasets import data
# Per-type palettes: heatmapPalette styles only continuous heatmaps, leaving the# categorical palette untouched. Any name from ds.colors works.ds.theme(heatmapPalette="lagoon")
cars = ds.ensure_polars(data.cars()).drop_nulls(["Miles_per_Gallon", "Horsepower"])
chart = ( alt.Chart(cars) .mark_rect() .encode( x=alt.X("Horsepower:Q", bin=alt.Bin(maxbins=12)), y=alt.Y("Miles_per_Gallon:Q", bin=alt.Bin(maxbins=12), title="Miles per gallon"), color=alt.Color("count():Q", title="Cars"), ))Style presets
Section titled “Style presets”Named presets are selected with style=. One ships built in - "notebook", a big-screen
exploration look (900 x 900 px, 18 pt type, dark, transparent) for working inline in a notebook
before you produce the print-scale figure:
ds.theme(style="notebook") # explore at screen scaleds.theme() # back to publication defaultsA dysonsphere.toml config file can customise the preset or add your own named styles -
ds.theme(style="poster") picks up a [poster] section from your config. See the
configuration guide for the full file format, search paths, and merge
order; ds.create_config() scaffolds a starter file.
Frame and grid
Section titled “Frame and grid”closed=True draws a full frame around the plot (all four spines):
import altair as altimport dysonsphere as dsfrom vega_datasets import data
# closed=True draws a full frame around the plot (all four spines).ds.theme(closed=True)
cars = ds.ensure_polars(data.cars()).drop_nulls(["Miles_per_Gallon", "Horsepower"])
chart = ( alt.Chart(cars) .mark_point() .encode( x=alt.X("Horsepower:Q"), y=alt.Y("Miles_per_Gallon:Q", title="Miles per gallon"), ))grid=True adds grid lines - solid by default; dashedGrid=True dashes them:
import altair as altimport dysonsphere as dsfrom vega_datasets import data
# grid=True draws grid lines; dashedGrid=False makes them solid instead of dashed.ds.theme(grid=True)
stocks = data.stocks()
chart = ( alt.Chart(stocks) .mark_line() .encode( x=alt.X("date:T", title=None), y=alt.Y("price:Q", title="Price (USD)"), color=alt.Color("symbol:N", title="Symbol"), ))Rounded marks
Section titled “Rounded marks”cornerRadius=True rounds bar tips (and rects and arcs) by a size derived from the chart
dimensions; pass a float for explicit pixels.
import altair as altimport dysonsphere as dsfrom vega_datasets import data
# cornerRadius=True rounds bar tips (and rects/arcs) by a size derived from the# chart dimensions; pass a float for explicit pixels.ds.theme(palette="blues", xLabelAngle=-45, cornerRadius=True)
barley = data.barley()
chart = ( alt.Chart(barley) .mark_bar() .encode( x=alt.X("variety:N", sort="-y", title="Variety"), y=alt.Y("mean(yield):Q", title="Mean yield (bu/acre)"), color=alt.Color("variety:N", legend=None), ))Label angles
Section titled “Label angles”xLabelAngle / yLabelAngle rotate axis labels (in degrees); alignment is derived from the sign,
so crowded categories stay legible.
import altair as altimport dysonsphere as dsfrom vega_datasets import data
# Angle crowded categorical labels; alignment follows the sign automatically.ds.theme(palette="blues", xLabelAngle=-45)
barley = data.barley()
chart = ( alt.Chart(barley) .mark_bar() .encode( x=alt.X("variety:N", sort="-y", title=None), y=alt.Y("mean(yield):Q", title="Mean yield (bu/acre)"), color=alt.Color("variety:N", legend=None), ))Inward ticks
Section titled “Inward ticks”inwardTicks=True points tick marks into the plot area (physics-journal style) and defaults the
frame to closed:
import altair as altimport dysonsphere as dsfrom vega_datasets import data
# inwardTicks=True points tick marks into the plot (physics-journal style);# it also defaults the frame to closed.ds.theme(inwardTicks=True)
cars = ds.ensure_polars(data.cars()).drop_nulls(["Miles_per_Gallon", "Horsepower"])
chart = ( alt.Chart(cars) .mark_point() .encode( x=alt.X("Horsepower:Q"), y=alt.Y("Miles_per_Gallon:Q", title="Miles per gallon"), ))More knobs
Section titled “More knobs”The theme exposes dozens of parameters - axisOffset, tickSize, inwardTicks, fontSize /
secondaryFontSize / smallestFontSize, markSize, markStrokeWidth, bandPadding, sigFigs,
and the axis-element toggles (xAxis, xTicks, xLabels, and their y counterparts). The
configuration guide’s key reference documents every one
of them, with defaults - and each is equally valid as a theme() keyword or a dysonsphere.toml
entry.