Skip to content

Themes

Themes control all colours and stroke widths used by the Canvas.

Default theme example

Built-in themes

Default

from econ_viz import Canvas, themes

cvs = Canvas(x_max=20, y_max=15, theme=themes.default)

The default theme draws from a colour-blind-friendly colour cycle (thriveth, 2014), exposed as themes.COLORBLIND_CYCLE_HEX and themes.COLORBLIND_CYCLE_RGB. Economics teaching relies heavily on graphs, so colour alone should not carry meaning for students with impaired vision (Kugler & Andrews, 1996).

Nord

cvs = Canvas(x_max=20, y_max=15, theme=themes.nord)

The Nord theme uses the Nord colour palette — cool blues and muted tones suitable for academic presentations.

Nord theme example

Paper

cvs = Canvas(x_max=20, y_max=15, theme=themes.paper)

The paper theme uses thinner lines, smaller markers, and restrained typography on a transparent background — suitable for print and journal figures where ink and space are at a premium.

Paper theme example

Monochrome

cvs = Canvas(x_max=20, y_max=15, theme=themes.monochrome)

The monochrome theme drops colour entirely — every element is a shade of gray — and instead distinguishes curves, budget lines, and rays by line style, and markers by shape. Suitable for black-and-white printing or figures viewed by colour-blind readers without relying on colour at all.

Monochrome theme example

Presentation

cvs = Canvas(x_max=20, y_max=15, theme=themes.presentation)

The presentation theme uses larger text, thicker lines, and bigger markers for visibility on a projector screen or in a lecture hall.

Presentation theme example

Dark

cvs = Canvas(x_max=20, y_max=15, theme=themes.dark)

The dark theme uses a dark background with light foreground colours, suitable for dark-mode slides or websites.

Dark theme example

Custom theme

Pass any field to the constructor to override just that value; everything else keeps the built-in default:

from econ_viz import Theme

my_theme = Theme(
    name="custom",
    axis_color="#333333",
    label_color="#333333",
    ic_color="#2563eb",
    ic_linewidth=1.5,
    budget_color="#dc2626",
    eq_color="#16a34a",
    eq_markersize=6.0,
)

cvs = Canvas(x_max=20, y_max=15, theme=my_theme)

Every line, marker, fill, label, and legend a diagram draws also has a composite default -- theme.ic_stroke, theme.eq_marker, theme.point_label, and so on -- built from the fields above. To change one of these as a whole (for example, giving the core segment of an Edgeworth box its own arrowhead, not just its own colour), subclass Theme and override the property:

from econ_viz import ArrowStyle, Stroke, Theme

class MyTheme(Theme):
    @property
    def core_stroke(self) -> Stroke:
        return Stroke(width=3.0, color="#C0392B", arrow=ArrowStyle.TRIANGLE)

cvs = EdgeworthBox(..., theme=MyTheme(name="my-theme"))

Passing an explicit argument to a method (add_core(stroke=...)) still wins over the theme, and the theme still wins over the built-in default -- the same precedence a settings file follows.

Theme fields

Field Description
name Theme identifier
axis_color Colour of axis spines and arrow tips
label_color Colour of axis and origin labels
ic_color, ic_linewidth Indifference-curve stroke colour and width
secondary_ic_color, secondary_ic_linewidth, secondary_ic_opacity Subdued curves shown beside a highlighted focal utility level
path_color, path_linewidth PCC / ICC path stroke colour and width
budget_color, budget_linewidth Budget-line stroke colour and width
budget_fill_alpha Opacity of the feasible-set shading
eq_color, eq_markersize Equilibrium marker colour and size
ray_color, ray_linewidth Expansion-path ray colour and width
kink_color Kink-point marker colour
sub_effect_color, inc_effect_color Substitution- / income-effect arrow colours
effect_arrow_linewidth Effect-arrow width
compensated_budget_color, compensated_budget_linewidth, compensated_budget_linestyle Compensated budget line in a decomposition
subsistence_color, subsistence_linewidth Stone-Geary subsistence reference lines
contract_color, contract_linewidth Edgeworth contract curve
core_color, core_linewidth Edgeworth core segment
price_color, price_linewidth Edgeworth price line
walrasian_color, walrasian_markersize Edgeworth Walrasian equilibrium marker
axis_stroke, drop_stroke, projection_stroke, guide_stroke, box_stroke Lines with no separate colour/width fields of their own

Style properties

Every property below is a Stroke, Marker, Label, Fill, or Legend, built from the fields above. Overriding one in a subclass changes every diagram that doesn't pass its own explicit argument for that role; the settings file sets the same properties from [stroke.<name>], [marker.<name>], [label.<name>], and [fill.<name>] sections.

Kind Properties
Stroke ic_stroke, secondary_ic_stroke, budget_stroke, ray_stroke, path_stroke, compensated_budget_stroke, final_budget_stroke, substitution_stroke, income_stroke, subsistence_stroke, contract_stroke, core_stroke, price_stroke, axis_stroke, drop_stroke, projection_stroke, guide_stroke, box_stroke
Marker eq_marker, point_marker, kink_marker, bliss_marker, path_marker, core_marker, endowment_marker, walrasian_marker
Label axis_label, origin_label, title_label, box_label, effect_label, point_label, bundle_label, bliss_label, ic_label, edgeworth_label
Fill budget_fill
Legend legend

Comments